llvm.org GIT mirror llvm / 86c9814
indvars: Added getInsertPointForUses to find a valid place to truncate the IV. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135568 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Trick 8 years ago
2 changed file(s) with 71 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
215215 return true;
216216 }
217217
218 /// Determine the insertion point for this user. By default, insert immediately
219 /// before the user. SCEVExpander or LICM will hoist loop invariants out of the
220 /// loop. For PHI nodes, there may be multiple uses, so compute the nearest
221 /// common dominator for the incoming blocks.
222 static Instruction *getInsertPointForUses(Instruction *User, Value *Def,
223 DominatorTree *DT) {
224 PHINode *PHI = dyn_cast(User);
225 if (!PHI)
226 return User;
227
228 Instruction *InsertPt = 0;
229 for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i) {
230 if (PHI->getIncomingValue(i) != Def)
231 continue;
232
233 BasicBlock *InsertBB = PHI->getIncomingBlock(i);
234 if (!InsertPt) {
235 InsertPt = InsertBB->getTerminator();
236 continue;
237 }
238 InsertBB = DT->findNearestCommonDominator(InsertPt->getParent(), InsertBB);
239 InsertPt = InsertBB->getTerminator();
240 }
241 assert(InsertPt && "Missing phi operand");
242 assert(!isa(Def) ||
243 DT->dominates(cast(Def), InsertPt) &&
244 "def does not dominate all uses");
245 return InsertPt;
246 }
247
218248 //===----------------------------------------------------------------------===//
219249 // RewriteNonIntegerIVs and helpers. Prefer integer IVs.
220250 //===----------------------------------------------------------------------===//
696726 // hoist loop invariants out of the loop. For PHI nodes, there may be
697727 // multiple uses, so compute the nearest common dominator for the
698728 // incoming blocks.
699 Instruction *InsertPt = User;
700 if (PHINode *PHI = dyn_cast(InsertPt))
701 for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
702 if (PHI->getIncomingValue(i) == Op) {
703 if (InsertPt == User)
704 InsertPt = PHI->getIncomingBlock(i)->getTerminator();
705 else
706 InsertPt =
707 DT->findNearestCommonDominator(InsertPt->getParent(),
708 PHI->getIncomingBlock(i))
709 ->getTerminator();
710 }
729 Instruction *InsertPt = getInsertPointForUses(User, Op, DT);
711730
712731 // Now expand it into actual Instructions and patch it into place.
713732 Value *NewVal = Rewriter.expandCodeFor(AR, UseTy, InsertPt);
10221041 // This user does not evaluate to a recurence after widening, so don't
10231042 // follow it. Instead insert a Trunc to kill off the original use,
10241043 // eventually isolating the original narrow IV so it can be removed.
1025 Use *U = std::find(DU.NarrowUse->op_begin(), DU.NarrowUse->op_end(),
1026 DU.NarrowDef);
1027 IRBuilder<> Builder(*U);
1044 IRBuilder<> Builder(getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT));
10281045 Value *Trunc = Builder.CreateTrunc(DU.WideDef, DU.NarrowDef->getType());
10291046 DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, Trunc);
10301047 return 0;
349349 exit:
350350 ret void
351351 }
352
353 ; Test a widened IV that is used by a phi on different paths within the loop.
354 ;
355 ; CHECK: for.body:
356 ; CHECK: phi i64
357 ; CHECK: trunc i64
358 ; CHECK: if.then:
359 ; CHECK: for.inc:
360 ; CHECK: phi i32
361 ; CHECK: for.end:
362 define void @phiUsesTrunc() nounwind {
363 entry:
364 br i1 undef, label %for.body, label %for.end
365
366 for.body:
367 %iv = phi i32 [ %inc, %for.inc ], [ 1, %entry ]
368 br i1 undef, label %if.then, label %if.else
369
370 if.then:
371 br i1 undef, label %if.then33, label %for.inc
372
373 if.then33:
374 br label %for.inc
375
376 if.else:
377 br i1 undef, label %if.then97, label %for.inc
378
379 if.then97:
380 %idxprom100 = sext i32 %iv to i64
381 br label %for.inc
382
383 for.inc:
384 %kmin.1 = phi i32 [ %iv, %if.then33 ], [ 0, %if.then ], [ %iv, %if.then97 ], [ 0, %if.else ]
385 %inc = add nsw i32 %iv, 1
386 br i1 undef, label %for.body, label %for.end
387
388 for.end:
389 ret void
390 }