| File: | src/of_loops.c |
| Warning: | line 349, column 4 Value stored to 'lhs' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /***************************************************************************** |
| 2 | * |
| 3 | * of_loops.c: Loops Optimization |
| 4 | * |
| 5 | * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org). |
| 6 | * |
| 7 | ****************************************************************************/ |
| 8 | /**************************************************************************** |
| 9 | * |
| 10 | * Open Problems: |
| 11 | * |
| 12 | * - after a preheader is created, udInfoBlock() must be modified. |
| 13 | * Solutions: |
| 14 | * a- traverse the flog and check each ud list |
| 15 | * - |
| 16 | * |
| 17 | * - after a preheader is created, there should be a new bit in each |
| 18 | * loop->blockSet, and also loop->blockList(s) should be updated. |
| 19 | * Solutions: |
| 20 | * a- the problem should exist only for nested loops. If loops are |
| 21 | * sorted so that external loops are processed before internal ones, |
| 22 | * then a block > nbits is considered an external block |
| 23 | * b- all the loops that must be still examined are updated. Not so |
| 24 | * hard. A dirty trick could avoid alloc/free of each bitv. |
| 25 | * |
| 26 | ****************************************************************************/ |
| 27 | |
| 28 | #include "debug.h" |
| 29 | #include "flog.h" |
| 30 | #include "loops.h" |
| 31 | #include "of_loops.h" |
| 32 | #include "opttools.h" |
| 33 | #include "store.h" |
| 34 | #include "usedef.h" |
| 35 | |
| 36 | /**************************************************************************** |
| 37 | * |
| 38 | * :: Debug |
| 39 | * |
| 40 | ****************************************************************************/ |
| 41 | |
| 42 | static Bool loopDebug = false((int) 0); |
| 43 | |
| 44 | #define loopDEBUGif (!loopDebug) { } else afprintf DEBUG_IF(loop)if (!loopDebug) { } else afprintf |
| 45 | |
| 46 | /**************************************************************************** |
| 47 | * |
| 48 | * :: Macros |
| 49 | * |
| 50 | ****************************************************************************/ |
| 51 | #define loopDefNo(foam)((foam)->foamGen.hdr.info.defNo) ((foam)->foamGen.hdr.info.defNo) |
| 52 | |
| 53 | /**************************************************************************** |
| 54 | * |
| 55 | * :: Type Definitions |
| 56 | * |
| 57 | ****************************************************************************/ |
| 58 | |
| 59 | struct _InvInfo { |
| 60 | Foam * foamPtr; /* pointer to the definition */ |
| 61 | BBlock block; /* block to which belong */ |
| 62 | }; |
| 63 | |
| 64 | DECLARE_LIST(InvInfo)typedef struct InvInfoListCons { InvInfo first; struct InvInfoListCons *rest; } *InvInfoList; struct InvInfo_listOpsStruct { InvInfoList (*Cons) (InvInfo, InvInfoList); InvInfoList (*Singleton) (InvInfo ); InvInfoList (*List) (int n, ...); InvInfoList (*Listv) (va_list argp); InvInfoList (*ListNull) (InvInfo, ...); Bool (*Equal) (InvInfoList, InvInfoList, Bool (*f) (InvInfo, InvInfo)); InvInfo (*Find) (InvInfoList, InvInfo, Bool(*eq)(InvInfo,InvInfo) , int *); InvInfo (*Match) (InvInfoList, void *, Bool(*match)(InvInfo , void *), int *); InvInfoList (*MatchAll) (InvInfoList, void *, Bool(*match)(InvInfo, void *)); InvInfoList (*FreeCons) ( InvInfoList); void (*Free) (InvInfoList); InvInfoList (*FreeTo ) (InvInfoList, InvInfoList); void (*FreeDeeply) (InvInfoList , void (*f)(InvInfo)); InvInfoList (*FreeDeeplyTo) (InvInfoList , InvInfoList, void (*f) (InvInfo) ); InvInfoList (*FreeIfSat ) (InvInfoList, void (*f)(InvInfo), Bool (*s)(InvInfo)); InvInfo (*Elt) (InvInfoList, Length); InvInfoList (*Drop) (InvInfoList , Length); InvInfoList (*LastCons) (InvInfoList); Length (*_Length ) (InvInfoList); Bool (*IsLength) (InvInfoList, Length); Bool (*IsShorter) (InvInfoList, Length); Bool (*IsLonger) (InvInfoList , Length); InvInfoList (*Copy) (InvInfoList); InvInfoList (*CopyTo ) (InvInfoList, InvInfoList); InvInfoList (*CopyDeeply) (InvInfoList , InvInfo (*)(InvInfo)); InvInfoList (*CopyDeeplyTo) (InvInfoList , InvInfoList, InvInfo (*)(InvInfo)); InvInfoList (*Map) (InvInfo (*f)(InvInfo), InvInfoList); InvInfoList (*NMap) (InvInfo (* f)(InvInfo), InvInfoList); InvInfoList (*Reverse) (InvInfoList ); InvInfoList (*NReverse) (InvInfoList); InvInfoList (*Concat ) (InvInfoList, InvInfoList); InvInfoList (*NConcat) (InvInfoList , InvInfoList); Bool (*Memq) (InvInfoList, InvInfo); Bool (*Member ) (InvInfoList, InvInfo, Bool(*eq)(InvInfo,InvInfo) ); Bool ( *ContainsAllq) (InvInfoList, InvInfoList); Bool (*ContainsAnyq ) (InvInfoList, InvInfoList); Bool (*ContainsAll) (InvInfoList , InvInfoList, Bool (*eq)(InvInfo, InvInfo)); Bool (*ContainsAny ) (InvInfoList, InvInfoList, Bool (*eq)(InvInfo, InvInfo)); int (*Posq) (InvInfoList, InvInfo); int (*Position) (InvInfoList , InvInfo, Bool(*eq)(InvInfo,InvInfo) ); InvInfoList (*NRemove ) (InvInfoList, InvInfo, Bool(*eq)(InvInfo,InvInfo) ); void ( *FillVector) (InvInfo *, InvInfoList); int (*Print) (FILE *, InvInfoList , int (*pr)(FILE *, InvInfo) ); int (*GPrint) (FILE *, InvInfoList , int (*pr)(FILE *, InvInfo), char *l,char *m,char *r); int ( *Format) (OStream, CString, InvInfoList); }; extern struct InvInfo_listOpsStruct const *InvInfo_listPointer; |
| 65 | CREATE_LIST(InvInfo)struct InvInfo_listOpsStruct const *InvInfo_listPointer = (struct InvInfo_listOpsStruct const *) &ptrlistOps; |
| 66 | |
| 67 | /**************************************************************************** |
| 68 | * |
| 69 | * :: Global Data Structures |
| 70 | * |
| 71 | ****************************************************************************/ |
| 72 | |
| 73 | struct { |
| 74 | Foam unit; |
| 75 | FlowGraph flog; |
| 76 | Dominators doms; |
| 77 | |
| 78 | Bitv domExits; |
| 79 | |
| 80 | int numLocs; |
| 81 | int numPars; |
| 82 | |
| 83 | InvInfo * invInfov; |
| 84 | int numInv; |
| 85 | int numDefs; |
| 86 | |
| 87 | } loopInfo; |
| 88 | |
| 89 | /***************************************************************************** |
| 90 | * |
| 91 | * :: Local Prototypes |
| 92 | * |
| 93 | ****************************************************************************/ |
| 94 | |
| 95 | localstatic void loopFindAndMoveInvariantsFrLoop (LoopList); |
| 96 | |
| 97 | localstatic void loopInvariantsFindFrLoop (Loop); |
| 98 | localstatic Bool loopInvariantsFindFrBlock (BBlock, Loop); |
| 99 | |
| 100 | localstatic Bool loopIsInvariantExp (Foam, Loop); |
| 101 | |
| 102 | |
| 103 | localstatic void loopInvariantsFilterFrLoop (Loop); |
| 104 | |
| 105 | localstatic BBlock loopInvariantsMoveFrLoop (Loop); |
| 106 | localstatic Foam loopPreHeaderCodeCreate (Loop); |
| 107 | |
| 108 | localstatic int loopDefinitionsReset (Loop/* , Bitv*/); |
| 109 | |
| 110 | localstatic Bool loopBlockDominatesAllExits (BBlock, BBlockList); |
| 111 | |
| 112 | localstatic Bitv loopFindExitsDominators (Loop); |
| 113 | |
| 114 | localstatic InvInfo loopInvInfoNew (Foam *, BBlock); |
| 115 | |
| 116 | localstatic void loopInvariantsPrintDb (int); |
| 117 | |
| 118 | localstatic void loopUpdate (Loop, BBlock, LoopList); |
| 119 | |
| 120 | /**************************************************************************** |
| 121 | * |
| 122 | * :: Main Entry Points |
| 123 | * |
| 124 | ****************************************************************************/ |
| 125 | |
| 126 | void |
| 127 | loopUnit(Foam foam) |
| 128 | { |
| 129 | int i; |
| 130 | Foam defs = foam->foamUnit.defs, def, prog; |
| 131 | FlowGraph flog; |
| 132 | |
| 133 | loopDebug = 1; |
| 134 | |
| 135 | assert(foamTag(foam) == FOAM_Unit)do { if (!(((foam)->hdr.tag) == FOAM_Unit)) _do_assert(("foamTag(foam) == FOAM_Unit" ),"of_loops.c",135); } while (0); |
| 136 | |
| 137 | loopInfo.unit = foam; |
| 138 | |
| 139 | /* !! No loop optimization for const 0 */ |
| 140 | |
| 141 | for (i = 1; i < foamArgc(defs)((defs)->hdr.argc); i++) { |
| 142 | |
| 143 | def = defs->foamDDef.argv[i]; |
| 144 | |
| 145 | if (foamTag(def->foamDef.rhs)((def->foamDef.rhs)->hdr.tag) != FOAM_Prog) |
| 146 | continue; |
| 147 | |
| 148 | prog = def->foamDef.rhs; |
| 149 | |
| 150 | loopInfo.numLocs = foamDDeclArgc(prog->foamProg.locals)(((prog->foamProg.locals)->hdr.argc) - (1)); |
| 151 | loopInfo.numPars = foamDDeclArgc(prog->foamProg.params)(((prog->foamProg.params)->hdr.argc) - (1)); |
| 152 | |
| 153 | flog = flogFrProg(prog, FLOG_UniqueExit); |
| 154 | |
| 155 | loopInvariantsMoveFrFlog(flog); |
| 156 | |
| 157 | def->foamDef.rhs = flogToProg(flog); |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | |
| 162 | /* !!! There is something that must be changed. Usedef must decide that |
| 163 | * he need a FLOG_Union, not the client. |
| 164 | */ |
| 165 | void |
| 166 | loopInvariantsMoveFrFlog(FlowGraph flog) |
| 167 | { |
| 168 | Dominators doms; |
| 169 | LoopList loops; |
| 170 | |
| 171 | loopInfo.flog = flog; |
| 172 | |
| 173 | /* ----- First step: Build usedef chains ------ */ |
| 174 | |
| 175 | if (!usedefChainsFrFlog(flog, UD_OUTPUT_UdList)) |
| 176 | return; |
| 177 | |
| 178 | /* ----- Second step: Find All the Natural Loops ------ */ |
| 179 | |
| 180 | loops = lpNaturalLoopsFrFlog(flog, &doms); |
| 181 | |
| 182 | if (!loops) { |
| 183 | lpDominatorsFree(doms); |
| 184 | return; |
| 185 | } |
| 186 | |
| 187 | loopInfo.doms = doms; |
| 188 | |
| 189 | /* ----- Third step: unify loops with some header ------ */ |
| 190 | |
| 191 | loops = lpUnifyCommonHeaders(loops); |
| 192 | |
| 193 | /* ----- Fourth step: Optimize each loop ------ */ |
| 194 | |
| 195 | for (; loops; loops = cdr(loops)((loops)->rest)) |
| 196 | loopFindAndMoveInvariantsFrLoop(loops); |
| 197 | |
| 198 | usedefChainsFreeFrFlog(flog); |
| 199 | |
| 200 | } |
| 201 | |
| 202 | |
| 203 | /* Given a loopList , find all the invariant computations for the |
| 204 | * first element, create the preheader and modify the flowgraph, and update |
| 205 | * the dataflow info for the remaining loops. |
| 206 | */ |
| 207 | localstatic void |
| 208 | loopFindAndMoveInvariantsFrLoop(LoopList loops) |
| 209 | { |
| 210 | BBlock preHeader; |
| 211 | Loop loop = car(loops)((loops)->first); |
| 212 | |
| 213 | otProgInfoInit(OT_ASSOCIATION_LIST0x0002, |
| 214 | loopInfo.numLocs, loopInfo.numPars, loopInfo.unit); |
| 215 | |
| 216 | loopInvariantsFindFrLoop(loop); |
| 217 | |
| 218 | assert(loopInfo.numInv)do { if (!(loopInfo.numInv)) _do_assert(("loopInfo.numInv"),"of_loops.c" ,218); } while (0); |
| 219 | |
| 220 | if (loopInfo.numInv == 1) { |
| 221 | otProgInfoFini(); |
| 222 | return; |
| 223 | } |
| 224 | |
| 225 | loopInvariantsFilterFrLoop(loop); |
| 226 | |
| 227 | otProgInfoFini(); |
| 228 | |
| 229 | assert(loopInfo.numInv)do { if (!(loopInfo.numInv)) _do_assert(("loopInfo.numInv"),"of_loops.c" ,229); } while (0); |
| 230 | |
| 231 | if (loopInfo.numInv == 1) return; |
| 232 | |
| 233 | preHeader = loopInvariantsMoveFrLoop(loop); |
| 234 | |
| 235 | if (cdr(loops)((loops)->rest)) |
| 236 | loopUpdate(loop, preHeader, cdr(loops)((loops)->rest)); |
| 237 | |
| 238 | |
| 239 | } |
| 240 | |
| 241 | /**************************************************************************** |
| 242 | * |
| 243 | * :: Find Invariants |
| 244 | * |
| 245 | ****************************************************************************/ |
| 246 | |
| 247 | localstatic void |
| 248 | loopInvariantsFindFrLoop(Loop loop) |
| 249 | { |
| 250 | int numDefs; |
| 251 | Bool changed; |
| 252 | BitvClass class = loop->bitvClass; |
| 253 | |
| 254 | loopInfo.domExits = loopFindExitsDominators(loop); |
| 255 | |
| 256 | /* First: reset all invariant info on definitions */ |
| 257 | |
| 258 | numDefs = loopDefinitionsReset(loop/*, domExits*/); |
| 259 | |
| 260 | loopInfo.numInv = 1; /* NOTE: must start from 1 */ |
| 261 | |
| 262 | if (numDefs == 0) return; /* No potential invariants */ |
| 263 | |
| 264 | do { |
| 265 | changed = false((int) 0); |
| 266 | listIter(BBlock, bb, loop->blockList, {{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (loopInvariantsFindFrBlock(bb, loop)) changed = 1; }; }; } }; } |
| 267 | |
| 268 | /* Consider only blocks which dominates exits */{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (loopInvariantsFindFrBlock(bb, loop)) changed = 1; }; }; } }; } |
| 269 | if (!bitvTest(class, loopInfo.domExits, bb->label)){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (loopInvariantsFindFrBlock(bb, loop)) changed = 1; }; }; } }; } |
| 270 | continue;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (loopInvariantsFindFrBlock(bb, loop)) changed = 1; }; }; } }; } |
| 271 | |
| 272 | if (loopInvariantsFindFrBlock(bb, loop)){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (loopInvariantsFindFrBlock(bb, loop)) changed = 1; }; }; } }; } |
| 273 | changed = true;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (loopInvariantsFindFrBlock(bb, loop)) changed = 1; }; }; } }; } |
| 274 | |
| 275 | }){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (loopInvariantsFindFrBlock(bb, loop)) changed = 1; }; }; } }; }; |
| 276 | |
| 277 | } while (changed); |
| 278 | |
| 279 | /* bitvFree(domExits); */ |
| 280 | |
| 281 | if (loopDebug) loopInvariantsPrintDb(numDefs); |
| 282 | |
| 283 | return; |
| 284 | } |
| 285 | |
| 286 | localstatic void |
| 287 | loopInvariantsPrintDb(int numDefs) |
| 288 | { |
| 289 | int i; |
| 290 | |
| 291 | if (loopInfo.numInv == 0) |
| 292 | fprintf(dbOut, "No invariants found among %d definitions.\n", |
| 293 | numDefs); |
| 294 | else { |
| 295 | fprintf(dbOut, "Found %d invariants among %d definitions.\n", |
| 296 | loopInfo.numInv - 1, numDefs); |
| 297 | |
| 298 | for (i = 1; i < loopInfo.numInv; i++) { |
| 299 | fprintf(dbOut, "Inv %d in block %d: ", i, |
| 300 | loopInfo.invInfov[i]->block->label); |
| 301 | |
| 302 | foamPrintDb(*(loopInfo.invInfov[i]->foamPtr)); |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | } |
| 307 | |
| 308 | #define LOOP_InvState_Unknown0 0 |
| 309 | #define LOOP_InvState_Invalid-1 -1 |
| 310 | #define LOOP_InvState_Valid1 1 |
| 311 | |
| 312 | localstatic Bool |
| 313 | loopInvariantsFindFrBlock(BBlock bb, Loop loop) |
| 314 | { |
| 315 | Foam lhs, rhs, stmt, seq = bb->code; |
| 316 | int i, state; |
| 317 | Bool found = false((int) 0); |
| 318 | InvInfo * invInfov = loopInfo.invInfov; |
| 319 | FoamList defs; |
| 320 | |
| 321 | for (i = 0; i < foamArgc(seq)((seq)->hdr.argc); i++) { |
| 322 | |
| 323 | stmt = seq->foamSeq.argv[i]; |
| 324 | |
| 325 | if (!otIsDef(stmt)(((stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) continue; |
| 326 | |
| 327 | if (loopDefNo(stmt)((stmt)->foamGen.hdr.info.defNo) != LOOP_InvState_Unknown0) |
| 328 | continue; |
| 329 | |
| 330 | defs = (FoamList) otGetVarInfoList(stmt->foamDef.lhs); |
| 331 | |
| 332 | assert(defs)do { if (!(defs)) _do_assert(("defs"),"of_loops.c",332); } while (0); |
| 333 | |
| 334 | if (!listIsSingleton(defs)((defs) && !((defs)->rest))) { |
| 335 | loopDefNo(stmt)((stmt)->foamGen.hdr.info.defNo) = LOOP_InvState_Invalid-1; |
| 336 | continue; |
| 337 | } |
| 338 | |
| 339 | rhs = stmt->foamDef.rhs; |
| 340 | |
| 341 | state = loopIsInvariantExp(rhs, loop); |
| 342 | |
| 343 | if (state == LOOP_InvState_Invalid-1) |
| 344 | loopDefNo(stmt)((stmt)->foamGen.hdr.info.defNo) = LOOP_InvState_Invalid-1; |
| 345 | else if (state != LOOP_InvState_Unknown0) { |
| 346 | |
| 347 | found = true1; |
| 348 | |
| 349 | lhs = stmt->foamDef.lhs; |
Value stored to 'lhs' is never read | |
| 350 | |
| 351 | loopDefNo(stmt)((stmt)->foamGen.hdr.info.defNo) = loopInfo.numInv; |
| 352 | invInfov[loopInfo.numInv] = |
| 353 | loopInvInfoNew(&(seq->foamSeq.argv[i]), bb); |
| 354 | |
| 355 | /* otAddVarInfo(invInfov[loopInfo.numInv], lhs); */ |
| 356 | |
| 357 | loopInfo.numInv += 1; |
| 358 | |
| 359 | /* loopInvalidateNotUniqueDef0(stmt); */ |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | return found; |
| 364 | } |
| 365 | |
| 366 | localstatic int |
| 367 | loopIsInvariantExp(Foam foam, Loop loop) |
| 368 | { |
| 369 | foamIter(foam, arg, {{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { int state = loopIsInvariantExp(*arg, loop); if (state == 0 || state == -1) return state; }; }; } } }; } |
| 370 | int state = loopIsInvariantExp(*arg, loop);{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { int state = loopIsInvariantExp(*arg, loop); if (state == 0 || state == -1) return state; }; }; } } }; } |
| 371 | |
| 372 | if (state == LOOP_InvState_Unknown ||{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { int state = loopIsInvariantExp(*arg, loop); if (state == 0 || state == -1) return state; }; }; } } }; } |
| 373 | state == LOOP_InvState_Invalid){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { int state = loopIsInvariantExp(*arg, loop); if (state == 0 || state == -1) return state; }; }; } } }; } |
| 374 | return state;{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { int state = loopIsInvariantExp(*arg, loop); if (state == 0 || state == -1) return state; }; }; } } }; } |
| 375 | }){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { int state = loopIsInvariantExp(*arg, loop); if (state == 0 || state == -1) return state; }; }; } } }; }; |
| 376 | |
| 377 | if (otIsLocalVar(foam)(((foam)->hdr.tag) == FOAM_Loc || ((foam)->hdr.tag) == FOAM_Par )) { |
| 378 | UdInfoList udInfol = udReachingDefs(foam)((foam)->foamGen.hdr.info.defList); |
| 379 | |
| 380 | /* Has this var a unique reaching def. and is this def marked |
| 381 | * invariant ? |
| 382 | */ |
| 383 | |
| 384 | if (listIsSingleton(udInfol)((udInfol) && !((udInfol)->rest))) { |
| 385 | UdInfo ud = car(udInfol)((udInfol)->first); |
| 386 | |
| 387 | if (!lpIsBlockInLoop(udInfoBlock(ud), loop)(bitvTest((loop)->bitvClass, (loop)->blockSet, (((ud)-> block))->label))) |
| 388 | return LOOP_InvState_Valid1; |
| 389 | |
| 390 | if (loopDefNo(udInfoDef(ud))((((ud)->foam))->foamGen.hdr.info.defNo) == LOOP_InvState_Invalid-1) |
| 391 | return LOOP_InvState_Invalid-1; |
| 392 | |
| 393 | if (loopDefNo(udInfoDef(ud))((((ud)->foam))->foamGen.hdr.info.defNo) == LOOP_InvState_Unknown0) |
| 394 | return LOOP_InvState_Unknown0; |
| 395 | |
| 396 | return LOOP_InvState_Valid1; |
| 397 | } |
| 398 | |
| 399 | listIter(UdInfo, ud, udInfol, {{ { UdInfoList _l0; UdInfo ud; for (_l0 = (udInfol); _l0; _l0 = ((_l0)->rest)) { ud = ((_l0)->first); { { if ((bitvTest ((loop)->bitvClass, (loop)->blockSet, (((ud)->block) )->label))) return -1; }; }; } }; } |
| 400 | if (lpIsBlockInLoop(udInfoBlock(ud), loop)){ { UdInfoList _l0; UdInfo ud; for (_l0 = (udInfol); _l0; _l0 = ((_l0)->rest)) { ud = ((_l0)->first); { { if ((bitvTest ((loop)->bitvClass, (loop)->blockSet, (((ud)->block) )->label))) return -1; }; }; } }; } |
| 401 | return LOOP_InvState_Invalid;{ { UdInfoList _l0; UdInfo ud; for (_l0 = (udInfol); _l0; _l0 = ((_l0)->rest)) { ud = ((_l0)->first); { { if ((bitvTest ((loop)->bitvClass, (loop)->blockSet, (((ud)->block) )->label))) return -1; }; }; } }; } |
| 402 | }){ { UdInfoList _l0; UdInfo ud; for (_l0 = (udInfol); _l0; _l0 = ((_l0)->rest)) { ud = ((_l0)->first); { { if ((bitvTest ((loop)->bitvClass, (loop)->blockSet, (((ud)->block) )->label))) return -1; }; }; } }; }; |
| 403 | |
| 404 | return LOOP_InvState_Valid1; |
| 405 | } |
| 406 | |
| 407 | if (otIsNonLocalVar(foam)(((foam)->hdr.tag) == FOAM_Lex || ((foam)->hdr.tag) == FOAM_Glo )) { |
| 408 | if (otIsConstSyme(foamSyme(foam)((foam)->hdr.syme))) |
| 409 | return LOOP_InvState_Valid1; |
| 410 | else |
| 411 | return LOOP_InvState_Invalid-1; |
| 412 | } |
| 413 | |
| 414 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_Cast) return LOOP_InvState_Valid1; |
| 415 | if (otIsMovableData(foam)) return LOOP_InvState_Valid1; |
| 416 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_RRFmt) return LOOP_InvState_Valid1; |
| 417 | |
| 418 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_BCall && |
| 419 | !foamBValInfo(foam->foamBCall.op)(foamBValInfoTable[(int)(foam->foamBCall.op)-(int)FOAM_BVAL_START ]).hasSideFx) |
| 420 | return LOOP_InvState_Valid1; |
| 421 | |
| 422 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_OCall) |
| 423 | /*!! Could check for non-side-effecting expressions here. */ |
| 424 | return LOOP_InvState_Invalid-1; |
| 425 | |
| 426 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_CCall) { |
| 427 | if (otIsForcer(foam->foamCCall.op)) |
| 428 | return LOOP_InvState_Valid1; |
| 429 | |
| 430 | /*!! Could check for non-side-effecting expressions here. */ |
| 431 | return LOOP_InvState_Invalid-1; |
| 432 | } |
| 433 | |
| 434 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_PCall) |
| 435 | return LOOP_InvState_Invalid-1; |
| 436 | |
| 437 | return LOOP_InvState_Invalid-1; |
| 438 | } |
| 439 | |
| 440 | /* Assign 0 to each def in the blocks in LOOP and build |
| 441 | * association lists: (Var in LOOP) -> (All definition of Var in LOOP) |
| 442 | * Return the number of defs found (== potential invariants) |
| 443 | */ |
| 444 | localstatic int |
| 445 | loopDefinitionsReset(Loop loop /*, Bitv domExits $$*/ ) |
| 446 | { |
| 447 | int numDefs = 0, i; |
| 448 | |
| 449 | listIter(BBlock, bb, loop->blockList, {{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 450 | int i;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 451 | Foam seq = bb->code;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 452 | |
| 453 | /* if (!bitvTest(class, domExits, bb->label)) continue; */{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 454 | |
| 455 | for (i = 0; i < foamArgc(seq); i++) {{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 456 | |
| 457 | Foam stmt = seq->foamSeq.argv[i];{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 458 | |
| 459 | if (otIsDef(stmt)) {{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 460 | loopDefNo(stmt) = 0;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 461 | numDefs++;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 462 | |
| 463 | otAddVarInfo(stmt, stmt->foamDef.lhs);{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 464 | }{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 465 | }{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; } |
| 466 | }){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { int i; Foam seq = bb->code; for (i = 0; i < ((seq)-> hdr.argc); i++) { Foam stmt = seq->foamSeq.argv[i]; if ((( (stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) { ((stmt)->foamGen.hdr.info.defNo) = 0; numDefs++; otAddVarInfo0 ((VarInfo) (stmt), stmt->foamDef.lhs); } } }; }; } }; }; |
| 467 | |
| 468 | if (numDefs) { |
| 469 | loopInfo.invInfov = (InvInfo *) |
| 470 | stoAlloc(OB_Other0, |
| 471 | sizeof(InvInfo) * (numDefs + 1)); |
| 472 | |
| 473 | for (i = 0; i < numDefs + 1; i++) |
| 474 | loopInfo.invInfov[i] = (InvInfo) 0; |
| 475 | } |
| 476 | loopInfo.numDefs = numDefs; |
| 477 | |
| 478 | return numDefs; |
| 479 | } |
| 480 | /**************************************************************************** |
| 481 | * |
| 482 | * :: Filter Invariants |
| 483 | * |
| 484 | ****************************************************************************/ |
| 485 | localstatic Bool loopFilterExp(Foam foam); |
| 486 | /* local void loopInvalidateNotUniqueDef(void);*/ |
| 487 | |
| 488 | localstatic Bool loopFilterDependencies(Foam foam); |
| 489 | localstatic Bool loopIsStillInvariant(Foam foam); |
| 490 | |
| 491 | /* For each invariant x := (exp), check the following conditions: |
| 492 | * |
| 493 | * a) this must be the unique def. for x in LOOP. |
| 494 | * b) all uses of x in LOOP are reached only by this definition. |
| 495 | * |
| 496 | * How: build a vector: var -> invariant. |
| 497 | * (b) It's easy using usedef chains: traverse the loop, for each use look |
| 498 | * at the usedef |
| 499 | */ |
| 500 | localstatic void |
| 501 | loopInvariantsFilterFrLoop(Loop loop) |
| 502 | { |
| 503 | Bool removed = false((int) 0); |
| 504 | BitvClass class = loop->bitvClass; |
| 505 | |
| 506 | /* 1) Check, for each inv x := ..., that all uses of x in LOOP |
| 507 | * can be reached only by the invariant. |
| 508 | */ |
| 509 | |
| 510 | listIter(BBlock, bb, loop->blockList, {{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopFilterExp(bb->code)) removed = 1; }; }; } }; } |
| 511 | |
| 512 | if (!loopFilterExp(bb->code)){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopFilterExp(bb->code)) removed = 1; }; }; } }; } |
| 513 | removed = true;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopFilterExp(bb->code)) removed = 1; }; }; } }; } |
| 514 | |
| 515 | }){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopFilterExp(bb->code)) removed = 1; }; }; } }; }; |
| 516 | |
| 517 | if (!removed) return; |
| 518 | |
| 519 | /* 2) Check if other invariants must be removed |
| 520 | * due to removed invariants. |
| 521 | */ |
| 522 | |
| 523 | |
| 524 | while (removed) { |
| 525 | |
| 526 | removed = false((int) 0); |
| 527 | |
| 528 | listIter(BBlock, bb, loop->blockList, {{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (!loopFilterDependencies(bb->code)) removed = 1; }; } ; } }; } |
| 529 | |
| 530 | /* Consider only blocks which dominates exits */{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (!loopFilterDependencies(bb->code)) removed = 1; }; } ; } }; } |
| 531 | if (!bitvTest(class, loopInfo.domExits, bb->label)){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (!loopFilterDependencies(bb->code)) removed = 1; }; } ; } }; } |
| 532 | continue;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (!loopFilterDependencies(bb->code)) removed = 1; }; } ; } }; } |
| 533 | |
| 534 | if (!loopFilterDependencies(bb->code)){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (!loopFilterDependencies(bb->code)) removed = 1; }; } ; } }; } |
| 535 | removed = true;{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (!loopFilterDependencies(bb->code)) removed = 1; }; } ; } }; } |
| 536 | |
| 537 | }){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!bitvTest(class, loopInfo.domExits, bb->label)) continue ; if (!loopFilterDependencies(bb->code)) removed = 1; }; } ; } }; }; |
| 538 | } |
| 539 | |
| 540 | } |
| 541 | |
| 542 | |
| 543 | /* For each var use, look at the reaching defs: |
| 544 | * is there is an invariant among them, the list must be a singleton |
| 545 | * otherwise invalid invariant. |
| 546 | */ |
| 547 | localstatic Bool |
| 548 | loopFilterExp(Foam foam) |
| 549 | { |
| 550 | UdInfoList udInfol; |
| 551 | Bool removed = false((int) 0); |
| 552 | FoamList defs; |
| 553 | Foam invDef; |
| 554 | |
| 555 | foamIter(foam, arg, {{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 556 | |
| 557 | if (otIsDef(*arg)) {{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 558 | if (!loopFilterExp((*arg)->foamDef.rhs)){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 559 | removed = true;{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 560 | }{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 561 | else{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 562 | if (!loopFilterExp(*arg)){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 563 | removed = true;{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; } |
| 564 | }){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if ((((*arg)->hdr.tag) == FOAM_Set || ((*arg)-> hdr.tag) == FOAM_Def)) { if (!loopFilterExp((*arg)->foamDef .rhs)) removed = 1; } else if (!loopFilterExp(*arg)) removed = 1; }; }; } } }; }; |
| 565 | |
| 566 | if (!otIsVar(foam)(((foam)->hdr.tag) == FOAM_Loc || ((foam)->hdr.tag) == FOAM_Par || ((foam)->hdr.tag) == FOAM_Lex || ((foam)->hdr.tag) == FOAM_Glo)) |
| 567 | return removed; |
| 568 | |
| 569 | /* Take all definition for this var inside the loop */ |
| 570 | defs = (FoamList) otGetVarInfoList(foam); |
| 571 | |
| 572 | if (!defs) return removed; |
| 573 | |
| 574 | if (!listIsSingleton(defs)((defs) && !((defs)->rest))) return removed; |
| 575 | |
| 576 | if (loopDefNo(car(defs))((((defs)->first))->foamGen.hdr.info.defNo) == LOOP_InvState_Invalid-1) return removed; |
| 577 | |
| 578 | if (loopDefNo(car(defs))((((defs)->first))->foamGen.hdr.info.defNo) == LOOP_InvState_Unknown0) { |
| 579 | loopDefNo(car(defs))((((defs)->first))->foamGen.hdr.info.defNo) = LOOP_InvState_Unknown0; |
| 580 | return removed; |
| 581 | } |
| 582 | |
| 583 | /* There is an invariant with this lhs. */ |
| 584 | |
| 585 | /* Is this the only reaching def for foam ? */ |
| 586 | |
| 587 | udInfol = udReachingDefs(foam)((foam)->foamGen.hdr.info.defList); |
| 588 | invDef = car(defs)((defs)->first); |
| 589 | |
| 590 | if (!listIsSingleton(udInfol)((udInfol) && !((udInfol)->rest)) && |
| 591 | udInfoDef(car(udInfol))((((udInfol)->first))->foam)->foamDef.lhs != foam) { |
| 592 | |
| 593 | /* The invariant is marked invalid */ |
| 594 | |
| 595 | loopInfo.invInfov[loopDefNo(invDef)((invDef)->foamGen.hdr.info.defNo)] = (InvInfo) 0; |
| 596 | loopDefNo(invDef)((invDef)->foamGen.hdr.info.defNo) = LOOP_InvState_Invalid-1; |
| 597 | |
| 598 | loopInfo.numInv--; |
| 599 | |
| 600 | loopDEBUGif (!loopDebug) { } else afprintf(dbOut,"* Invariant rejected by loopFilterExp *\n"); |
| 601 | |
| 602 | removed = true1; |
| 603 | |
| 604 | } |
| 605 | |
| 606 | return removed; |
| 607 | |
| 608 | } |
| 609 | |
| 610 | localstatic Bool |
| 611 | loopFilterDependencies(Foam foam) |
| 612 | { |
| 613 | Foam stmt; |
| 614 | int i; |
| 615 | Bool changed = false((int) 0); |
| 616 | |
| 617 | assert(foamTag(foam) == FOAM_Seq)do { if (!(((foam)->hdr.tag) == FOAM_Seq)) _do_assert(("foamTag(foam) == FOAM_Seq" ),"of_loops.c",617); } while (0); |
| 618 | |
| 619 | |
| 620 | for (i = 0; i < foamArgc(foam)((foam)->hdr.argc); i++) { |
| 621 | |
| 622 | stmt = foam->foamSeq.argv[i]; |
| 623 | |
| 624 | if (!otIsDef(stmt)(((stmt)->hdr.tag) == FOAM_Set || ((stmt)->hdr.tag) == FOAM_Def )) continue; |
| 625 | |
| 626 | if (loopDefNo(stmt)((stmt)->foamGen.hdr.info.defNo) == LOOP_InvState_Invalid-1) continue; |
| 627 | |
| 628 | assert(loopDefNo(stmt))do { if (!(((stmt)->foamGen.hdr.info.defNo))) _do_assert(( "loopDefNo(stmt)"),"of_loops.c",628); } while (0); |
| 629 | |
| 630 | /* Found an invariant. Is it still valid ? */ |
| 631 | |
| 632 | if (!loopIsStillInvariant(stmt->foamDef.rhs)) { |
| 633 | |
| 634 | /* The invariant is marked invalid */ |
| 635 | |
| 636 | loopInfo.invInfov[loopDefNo(stmt)((stmt)->foamGen.hdr.info.defNo)] = (InvInfo) 0; |
| 637 | loopDefNo(stmt)((stmt)->foamGen.hdr.info.defNo) = LOOP_InvState_Invalid-1; |
| 638 | |
| 639 | loopInfo.numInv--; |
| 640 | |
| 641 | loopDEBUGif (!loopDebug) { } else afprintf(dbOut,"* Invariant rejected by loopFilterDependencies *\n"); |
| 642 | |
| 643 | changed = true1; |
| 644 | } |
| 645 | |
| 646 | } |
| 647 | |
| 648 | return changed; |
| 649 | } |
| 650 | |
| 651 | |
| 652 | localstatic Bool |
| 653 | loopIsStillInvariant(Foam foam) |
| 654 | { |
| 655 | UdInfoList udInfol; |
| 656 | UdInfo ud; |
| 657 | |
| 658 | foamIter(foam, arg, {{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (!loopIsStillInvariant(*arg)) return ((int) 0); } ; }; } } }; } |
| 659 | |
| 660 | if (!loopIsStillInvariant(*arg)){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (!loopIsStillInvariant(*arg)) return ((int) 0); } ; }; } } }; } |
| 661 | return false;{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (!loopIsStillInvariant(*arg)) return ((int) 0); } ; }; } } }; } |
| 662 | }){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (!loopIsStillInvariant(*arg)) return ((int) 0); } ; }; } } }; }; |
| 663 | |
| 664 | if (!otIsVar(foam)(((foam)->hdr.tag) == FOAM_Loc || ((foam)->hdr.tag) == FOAM_Par || ((foam)->hdr.tag) == FOAM_Lex || ((foam)->hdr.tag) == FOAM_Glo)) |
| 665 | return true1; |
| 666 | |
| 667 | udInfol = udReachingDefs(foam)((foam)->foamGen.hdr.info.defList); |
| 668 | |
| 669 | /* Has this var still a unique reaching def. and is this def marked |
| 670 | * invariant ? |
| 671 | */ |
| 672 | |
| 673 | assert(listIsSingleton(udInfol))do { if (!(((udInfol) && !((udInfol)->rest)))) _do_assert (("listIsSingleton(udInfol)"),"of_loops.c",673); } while (0); |
| 674 | |
| 675 | ud = car(udInfol)((udInfol)->first); |
| 676 | |
| 677 | assert(loopDefNo(udInfoDef(ud)))do { if (!(((((ud)->foam))->foamGen.hdr.info.defNo))) _do_assert (("loopDefNo(udInfoDef(ud))"),"of_loops.c",677); } while (0); |
| 678 | |
| 679 | if (loopDefNo(udInfoDef(ud))((((ud)->foam))->foamGen.hdr.info.defNo) == LOOP_InvState_Invalid-1) |
| 680 | return false((int) 0); |
| 681 | |
| 682 | return true1; |
| 683 | } |
| 684 | |
| 685 | /**************************************************************************** |
| 686 | * |
| 687 | * :: Move Invariants in the Preheader |
| 688 | * |
| 689 | ****************************************************************************/ |
| 690 | |
| 691 | |
| 692 | localstatic BBlock |
| 693 | loopInvariantsMoveFrLoop(Loop loop) |
| 694 | { |
| 695 | int i, j; |
| 696 | BBlock bbPre, bbHeader = loop->header; |
| 697 | Length newLab; |
| 698 | FlowGraph flog = loopInfo.flog; |
| 699 | |
| 700 | Foam newSeq = loopPreHeaderCodeCreate(loop); |
| 701 | |
| 702 | flogFixEntries(flog); /* $$ !! */ |
| 703 | |
| 704 | /* Create a new block with PREHEADER as code .. */ |
| 705 | |
| 706 | newLab = flogReserveLabel(flog)bbufReserve1((flog)->blocks); |
| 707 | |
| 708 | bbPre = bbNew(newSeq, newLab); |
| 709 | |
| 710 | /* Attach it to the graph... */ |
| 711 | flogSetBlock(flog, newLab, bbPre)((flog)->fixedEntries = ((int) 0), bbufSetBlockFn((flog)-> blocks,newLab,bbPre), (bbPre)->graph = (flog)); |
| 712 | |
| 713 | /* .. and set up entry and exit edges */ |
| 714 | |
| 715 | bbufNeed(bbPre->exits, 1); |
| 716 | bbSetExit(bbPre, int0, bbHeader)((bbPre)->graph->fixedEntries = ((int) 0), (bbPre)-> exits->argv[((int) 0)] = (bbHeader)); /* preheader -> header */ |
| 717 | bbSetExitC(bbPre, 1)((bbPre)->exits->pos = (1)); |
| 718 | |
| 719 | bbufNeed(bbPre->entries, bbEntryC(bbHeader)((bbHeader)->entries->pos)); |
| 720 | |
| 721 | /* Modify each entry of bbHeader not from LOOP |
| 722 | * so that now are entries in bbPre |
| 723 | */ |
| 724 | |
| 725 | for (i = 0; i < bbEntryC(bbHeader)((bbHeader)->entries->pos); i++) { |
| 726 | |
| 727 | BBlock entryBlock = bbEntry(bbHeader, i)((bbHeader)->entries->argv[i]); |
| 728 | |
| 729 | if (lpIsBlockInLoop(entryBlock, loop)(bitvTest((loop)->bitvClass, (loop)->blockSet, (entryBlock )->label))) continue; |
| 730 | |
| 731 | for (j = 0; j < bbExitC(entryBlock)((entryBlock)->exits->pos); j++) |
| 732 | if (bbExit(entryBlock, j)((entryBlock)->exits->argv[j]) == bbHeader) |
| 733 | bbSetExit(entryBlock, j, bbPre)((entryBlock)->graph->fixedEntries = ((int) 0), (entryBlock )->exits->argv[j] = (bbPre)); |
| 734 | } |
| 735 | |
| 736 | /* If bbHeader was the first, now bbPre will be the first */ |
| 737 | |
| 738 | if (bbHeader == flog->block0) flog->block0 = bbPre; |
| 739 | |
| 740 | /* NOTE: entries have not been modified, but this isn't important, |
| 741 | * because they have been invalidated. |
| 742 | */ |
| 743 | |
| 744 | return bbPre; |
| 745 | |
| 746 | } |
| 747 | |
| 748 | localstatic Foam |
| 749 | loopPreHeaderCodeCreate(Loop loop) |
| 750 | { |
| 751 | Foam preHeader = foamNewEmpty(FOAM_Seq, loopInfo.numInv); |
| 752 | Foam foam; |
| 753 | InvInfo * invInfov = loopInfo.invInfov; |
| 754 | int j = 0, i; |
| 755 | |
| 756 | for (i = 1; i < loopInfo.numDefs + 1; i++) { |
| 757 | |
| 758 | if (!invInfov[i]) continue; |
| 759 | |
| 760 | foam = *(invInfov[i]->foamPtr); |
| 761 | |
| 762 | assert(loopDefNo(foam) > 0)do { if (!(((foam)->foamGen.hdr.info.defNo) > 0)) _do_assert (("loopDefNo(foam) > 0"),"of_loops.c",762); } while (0); |
| 763 | |
| 764 | *(invInfov[i]->foamPtr) = foamNewNOp()foamNew(FOAM_NOp, (int) 0); |
| 765 | |
| 766 | preHeader->foamSeq.argv[j++] = foam; |
| 767 | } |
| 768 | |
| 769 | assert(j == loopInfo.numInv - 1)do { if (!(j == loopInfo.numInv - 1)) _do_assert(("j == loopInfo.numInv - 1" ),"of_loops.c",769); } while (0); |
| 770 | |
| 771 | /* Add: (Goto the header block) */ |
| 772 | preHeader->foamSeq.argv[j] = foamNewGoto(loop->header->label)foamNew(FOAM_Goto, 1, (AInt)(loop->header->label)); |
| 773 | |
| 774 | if (DEBUG(loop)loopDebug) { |
| 775 | fprintf(dbOut, "New preheader: \n"); |
| 776 | foamPrintDb(preHeader); |
| 777 | } |
| 778 | |
| 779 | return preHeader; |
| 780 | |
| 781 | } |
| 782 | |
| 783 | /**************************************************************************** |
| 784 | * |
| 785 | * :: Updated dflow info and loops |
| 786 | * |
| 787 | ****************************************************************************/ |
| 788 | |
| 789 | localstatic void loopUpdateBlocks (Loop, BBlock, LoopList); |
| 790 | localstatic void loopUpdateDominators (Loop, BBlock); |
| 791 | localstatic void loopUpdateUseDefChains (void); |
| 792 | |
| 793 | /****************************************************************************** |
| 794 | * |
| 795 | * :: Update dflow info and loops |
| 796 | * |
| 797 | *****************************************************************************/ |
| 798 | |
| 799 | localstatic void |
| 800 | loopUpdate(Loop loop, BBlock preHeader, LoopList loops) |
| 801 | { |
| 802 | |
| 803 | loopUpdateBlocks(loop, preHeader, loops); |
| 804 | loopUpdateDominators(loop, preHeader); |
| 805 | loopUpdateUseDefChains(); |
| 806 | } |
| 807 | |
| 808 | |
| 809 | localstatic void |
| 810 | loopUpdateBlocks(Loop loop, BBlock preHeader, LoopList loops) |
| 811 | { |
| 812 | BitvClass oldClass, newClass; |
| 813 | Length newbit = bitvClassSize(loop->bitvClass)((loop->bitvClass)->nbits); |
| 814 | |
| 815 | listIter(Loop, loop0, loops, {{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 816 | oldClass = loop0->bitvClass;{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 817 | newClass = bitvClassCreate(bitvClassSize(oldClass) + 1);{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 818 | |
| 819 | assert(bitvClassSize(newClass) == preHeader->label + 1);{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 820 | |
| 821 | loop0->blockSet ={ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 822 | bitvResize(newClass, oldClass, loop0->blockSet);{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 823 | |
| 824 | loop0->bitvClass = newClass;{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 825 | |
| 826 | if (lpIsBlockInLoop(loop->header, loop0)) {{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 827 | bitvSet(newClass, loop0->blockSet, newbit);{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 828 | listPush(BBlock, preHeader, loop0->blockList);{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 829 | }{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 830 | |
| 831 | bitvClassDestroy(oldClass);{ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; } |
| 832 | }){ { LoopList _l0; Loop loop0; for (_l0 = (loops); _l0; _l0 = ( (_l0)->rest)) { loop0 = ((_l0)->first); { { oldClass = loop0 ->bitvClass; newClass = bitvClassCreate(((oldClass)->nbits ) + 1); do { if (!(((newClass)->nbits) == preHeader->label + 1)) _do_assert(("bitvClassSize(newClass) == preHeader->label + 1" ),"of_loops.c",819); } while (0); loop0->blockSet = bitvResize (newClass, oldClass, loop0->blockSet); loop0->bitvClass = newClass; if ((bitvTest((loop0)->bitvClass, (loop0)-> blockSet, (loop->header)->label))) { bitvSet(newClass, loop0 ->blockSet, newbit); (loop0->blockList = (BBlock_listPointer ->Cons)(preHeader, loop0->blockList)); } bitvClassDestroy (oldClass); }; }; } }; }; |
| 833 | } |
| 834 | |
| 835 | localstatic void |
| 836 | loopUpdateDominators(Loop loop, BBlock preHeader) |
| 837 | { |
| 838 | Dominators doms = loopInfo.doms; |
| 839 | int i; |
| 840 | BitvClass newClass, oldClass; |
| 841 | |
| 842 | oldClass = doms->bitvClass; |
| 843 | newClass = bitvClassCreate(bitvClassSize(oldClass)((oldClass)->nbits) + 1); |
| 844 | |
| 845 | for (i = 0; i < doms->nBlocks; i++) |
| 846 | doms->doms[i] = bitvResize(newClass, oldClass, doms->doms[i]); |
| 847 | |
| 848 | doms->nBlocks += 1; |
| 849 | bitvClassDestroy(doms->bitvClass); |
| 850 | doms->bitvClass = newClass; |
| 851 | |
| 852 | assert(bitvClassSize(newClass) == doms->nBlocks)do { if (!(((newClass)->nbits) == doms->nBlocks)) _do_assert (("bitvClassSize(newClass) == doms->nBlocks"),"of_loops.c" ,852); } while (0); |
| 853 | assert(bitvClassSize(newClass) == bitvClassSize(loop->bitvClass) + 1)do { if (!(((newClass)->nbits) == ((loop->bitvClass)-> nbits) + 1)) _do_assert(("bitvClassSize(newClass) == bitvClassSize(loop->bitvClass) + 1" ),"of_loops.c",853); } while (0); |
| 854 | |
| 855 | /* 1) Each dominator of loop->header become a dominator of preheader.*/ |
| 856 | |
| 857 | flogIter(loopInfo.flog, bb, {{ { int _i; BBlock bb; for (_i = 0; _i < ((loopInfo.flog)-> blocks->pos); _i++) { bb = bbufBlockFn((loopInfo.flog)-> blocks,_i); if (!bb) continue; { { if (bb == preHeader) continue ; if (bitvTest((doms)->bitvClass, (doms)->doms[(loop-> header)->label], (bb)->label)) bitvSet((doms)->bitvClass , (doms)->doms[(preHeader)->label], (bb)->label); }; }; } }; } |
| 858 | |
| 859 | if (bb == preHeader) continue;{ { int _i; BBlock bb; for (_i = 0; _i < ((loopInfo.flog)-> blocks->pos); _i++) { bb = bbufBlockFn((loopInfo.flog)-> blocks,_i); if (!bb) continue; { { if (bb == preHeader) continue ; if (bitvTest((doms)->bitvClass, (doms)->doms[(loop-> header)->label], (bb)->label)) bitvSet((doms)->bitvClass , (doms)->doms[(preHeader)->label], (bb)->label); }; }; } }; } |
| 860 | |
| 861 | if (lpIsDom(doms, bb, loop->header)){ { int _i; BBlock bb; for (_i = 0; _i < ((loopInfo.flog)-> blocks->pos); _i++) { bb = bbufBlockFn((loopInfo.flog)-> blocks,_i); if (!bb) continue; { { if (bb == preHeader) continue ; if (bitvTest((doms)->bitvClass, (doms)->doms[(loop-> header)->label], (bb)->label)) bitvSet((doms)->bitvClass , (doms)->doms[(preHeader)->label], (bb)->label); }; }; } }; } |
| 862 | lpSetDom(doms, bb, preHeader);{ { int _i; BBlock bb; for (_i = 0; _i < ((loopInfo.flog)-> blocks->pos); _i++) { bb = bbufBlockFn((loopInfo.flog)-> blocks,_i); if (!bb) continue; { { if (bb == preHeader) continue ; if (bitvTest((doms)->bitvClass, (doms)->doms[(loop-> header)->label], (bb)->label)) bitvSet((doms)->bitvClass , (doms)->doms[(preHeader)->label], (bb)->label); }; }; } }; } |
| 863 | }){ { int _i; BBlock bb; for (_i = 0; _i < ((loopInfo.flog)-> blocks->pos); _i++) { bb = bbufBlockFn((loopInfo.flog)-> blocks,_i); if (!bb) continue; { { if (bb == preHeader) continue ; if (bitvTest((doms)->bitvClass, (doms)->doms[(loop-> header)->label], (bb)->label)) bitvSet((doms)->bitvClass , (doms)->doms[(preHeader)->label], (bb)->label); }; }; } }; }; |
| 864 | |
| 865 | /* 2) Preheader become dominator of header. */ |
| 866 | |
| 867 | lpSetDom(doms, preHeader, loop->header)bitvSet((doms)->bitvClass, (doms)->doms[(loop->header )->label], (preHeader)->label); |
| 868 | |
| 869 | } |
| 870 | |
| 871 | /* Now this operation is expensive, because all the ud-chains are recomputed |
| 872 | * again. |
| 873 | * ToDo: |
| 874 | * The UdInfo can be a pair (BB, index), where index is such that |
| 875 | * bb->code->foamSeq.argv[index] is the reaching def. |
| 876 | * In such way each (NOp) generated when a def is moved will have a UdInfo |
| 877 | * on it, (new-block, new-index), and the definition can be found |
| 878 | * dereferencing this chains. |
| 879 | */ |
| 880 | localstatic void |
| 881 | loopUpdateUseDefChains() |
| 882 | { |
| 883 | usedefChainsFreeFrFlog(loopInfo.flog); |
| 884 | |
| 885 | flogReuse(loopInfo.flog, FLOG_UniqueExit); |
| 886 | |
| 887 | usedefChainsFrFlog(loopInfo.flog, UD_OUTPUT_UdList); |
| 888 | } |
| 889 | |
| 890 | /**************************************************************************** |
| 891 | * |
| 892 | * :: Utility |
| 893 | * |
| 894 | ****************************************************************************/ |
| 895 | |
| 896 | /* Return a bitv where are on only bits corresponding to blocks in LOOP which |
| 897 | * dominates all the loop exits |
| 898 | */ |
| 899 | localstatic Bitv |
| 900 | loopFindExitsDominators(Loop loop) |
| 901 | { |
| 902 | BitvClass bclass = loop->bitvClass; |
| 903 | Bitv bres = bitvNew(bclass); |
| 904 | BBlockList exitBlocks = lpExitBlocksFrLoop(loop); |
| 905 | |
| 906 | bitvCopy(bclass, bres, loop->blockSet); |
| 907 | |
| 908 | listIter(BBlock, bb, loop->blockList, {{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopBlockDominatesAllExits(bb, exitBlocks)) bitvClear(bclass , bres, bb->label); }; }; } }; } |
| 909 | |
| 910 | if (!loopBlockDominatesAllExits(bb, exitBlocks)){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopBlockDominatesAllExits(bb, exitBlocks)) bitvClear(bclass , bres, bb->label); }; }; } }; } |
| 911 | bitvClear(bclass, bres, bb->label);{ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopBlockDominatesAllExits(bb, exitBlocks)) bitvClear(bclass , bres, bb->label); }; }; } }; } |
| 912 | |
| 913 | }){ { BBlockList _l0; BBlock bb; for (_l0 = (loop->blockList ); _l0; _l0 = ((_l0)->rest)) { bb = ((_l0)->first); { { if (!loopBlockDominatesAllExits(bb, exitBlocks)) bitvClear(bclass , bres, bb->label); }; }; } }; }; |
| 914 | |
| 915 | return bres; |
| 916 | } |
| 917 | |
| 918 | |
| 919 | /* Return true iif BB dominates all the blocks in EXITS */ |
| 920 | |
| 921 | localstatic Bool |
| 922 | loopBlockDominatesAllExits(BBlock bb, BBlockList exits) |
| 923 | { |
| 924 | Dominators doms = loopInfo.doms; |
| 925 | |
| 926 | listIter(BBlock, bbLoopExit, exits, {{ { BBlockList _l0; BBlock bbLoopExit; for (_l0 = (exits); _l0 ; _l0 = ((_l0)->rest)) { bbLoopExit = ((_l0)->first); { { if (!bitvTest((doms)->bitvClass, (doms)->doms[(bbLoopExit )->label], (bb)->label)) return ((int) 0); }; }; } }; } |
| 927 | if (!lpIsDom(doms, bb, bbLoopExit)){ { BBlockList _l0; BBlock bbLoopExit; for (_l0 = (exits); _l0 ; _l0 = ((_l0)->rest)) { bbLoopExit = ((_l0)->first); { { if (!bitvTest((doms)->bitvClass, (doms)->doms[(bbLoopExit )->label], (bb)->label)) return ((int) 0); }; }; } }; } |
| 928 | return false;{ { BBlockList _l0; BBlock bbLoopExit; for (_l0 = (exits); _l0 ; _l0 = ((_l0)->rest)) { bbLoopExit = ((_l0)->first); { { if (!bitvTest((doms)->bitvClass, (doms)->doms[(bbLoopExit )->label], (bb)->label)) return ((int) 0); }; }; } }; } |
| 929 | }){ { BBlockList _l0; BBlock bbLoopExit; for (_l0 = (exits); _l0 ; _l0 = ((_l0)->rest)) { bbLoopExit = ((_l0)->first); { { if (!bitvTest((doms)->bitvClass, (doms)->doms[(bbLoopExit )->label], (bb)->label)) return ((int) 0); }; }; } }; }; |
| 930 | |
| 931 | return true1; |
| 932 | } |
| 933 | |
| 934 | /***************************************************************************** |
| 935 | * |
| 936 | * :: Constructors and Destructors |
| 937 | * |
| 938 | ****************************************************************************/ |
| 939 | |
| 940 | localstatic InvInfo |
| 941 | loopInvInfoNew(Foam * pstmt, BBlock bb) |
| 942 | { |
| 943 | InvInfo invInfo = (InvInfo) stoAlloc(OB_Other0, sizeof(*invInfo)); |
| 944 | |
| 945 | invInfo->foamPtr = pstmt; |
| 946 | invInfo->block = bb; |
| 947 | |
| 948 | return invInfo; |
| 949 | } |