<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div></div><div><br class=""></div><div>Usage:</div><div><div><font face="Menlo" class="">> for i in `seq 4000 2000 20000`; do echo $i; python genphis.py $i | time opt -instcombine -o /dev/null; done</font></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div><div><font color="#444444" face="Menlo" class="">4000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 0.20 real 0.16 user 0.00 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">6000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 0.37 real 0.32 user 0.00 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">8000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 0.98 real 0.92 user 0.01 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">10000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 2.65 real 2.58 user 0.01 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">12000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 3.79 real 3.71 user 0.02 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">14000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 5.08 real 4.99 user 0.02 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">16000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 6.80 real 6.71 user 0.03 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">18000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 8.41 real 8.31 user 0.03 sys</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class="">20000</font></div></div></div><div class=""><div><div><font color="#444444" face="Menlo" class=""> 10.43 real 10.31 user 0.04 sys</font></div></div></div></blockquote><div class=""><div><br class=""></div><div>Thanks,</div><div>Michael</div><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 9, 2017, at 10:07 PM, Xinliang David Li via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Author: davidxl<br class="">Date: Mon Oct 9 22:07:54 2017<br class="">New Revision: 315272<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=315272&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=315272&view=rev</a><br class="">Log:<br class=""> Renable r314928</div></div></blockquote><blockquote type="cite" class=""><div class=""><div class=""><br class=""> Eliminate inttype phi with inttoptr/ptrtoint.<br class=""><br class=""> This version fixed a bug in finding the matching<br class=""> phi -- the order of the incoming blocks may be <br class=""> different (triggered in self build on Windows).<br class=""> A new test case is added.<br class=""><br class="">Added:<br class=""> llvm/trunk/test/Transforms/InstCombine/intptr1.ll<br class=""> - copied unchanged from r315107, llvm/trunk/test/Transforms/InstCombine/intptr1.ll<br class=""> llvm/trunk/test/Transforms/InstCombine/intptr2.ll<br class=""> - copied unchanged from r315107, llvm/trunk/test/Transforms/InstCombine/intptr2.ll<br class=""> llvm/trunk/test/Transforms/InstCombine/intptr3.ll<br class=""> - copied unchanged from r315107, llvm/trunk/test/Transforms/InstCombine/intptr3.ll<br class=""> llvm/trunk/test/Transforms/InstCombine/intptr4.ll<br class=""> - copied unchanged from r315107, llvm/trunk/test/Transforms/InstCombine/intptr4.ll<br class=""> llvm/trunk/test/Transforms/InstCombine/intptr5.ll<br class=""> - copied unchanged from r315107, llvm/trunk/test/Transforms/InstCombine/intptr5.ll<br class=""> llvm/trunk/test/Transforms/InstCombine/intptr6.ll<br class=""> - copied unchanged from r315107, llvm/trunk/test/Transforms/InstCombine/intptr6.ll<br class=""> llvm/trunk/test/Transforms/InstCombine/intptr7.ll<br class="">Modified:<br class=""> llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h<br class=""> llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp<br class=""><br class="">Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h?rev=315272&r1=315271&r2=315272&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h?rev=315272&r1=315271&r2=315272&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h (original)<br class="">+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h Mon Oct 9 22:07:54 2017<br class="">@@ -670,6 +670,10 @@ private:<br class=""> Instruction *FoldPHIArgGEPIntoPHI(PHINode &PN);<br class=""> Instruction *FoldPHIArgLoadIntoPHI(PHINode &PN);<br class=""> Instruction *FoldPHIArgZextsIntoPHI(PHINode &PN);<br class="">+ /// If an integer typed PHI has only one use which is an IntToPtr operation,<br class="">+ /// replace the PHI with an existing pointer typed PHI if it exists. Otherwise<br class="">+ /// insert a new pointer typed PHI and replace the original one.<br class="">+ Instruction *FoldIntegerTypedPHI(PHINode &PN);<br class=""><br class=""> /// Helper function for FoldPHIArgXIntoPHI() to set debug location for the<br class=""> /// folded operation.<br class=""><br class="">Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp?rev=315272&r1=315271&r2=315272&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp?rev=315272&r1=315271&r2=315272&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp (original)<br class="">+++ llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp Mon Oct 9 22:07:54 2017<br class="">@@ -40,6 +40,238 @@ void InstCombiner::PHIArgMergedDebugLoc(<br class=""> }<br class=""> }<br class=""><br class="">+// Replace Integer typed PHI PN if the PHI's value is used as a pointer value.<br class="">+// If there is an existing pointer typed PHI that produces the same value as PN,<br class="">+// replace PN and the IntToPtr operation with it. Otherwise, synthesize a new<br class="">+// PHI node:<br class="">+//<br class="">+// Case-1:<br class="">+// bb1:<br class="">+// int_init = PtrToInt(ptr_init)<br class="">+// br label %bb2<br class="">+// bb2:<br class="">+// int_val = PHI([int_init, %bb1], [int_val_inc, %bb2]<br class="">+// ptr_val = PHI([ptr_init, %bb1], [ptr_val_inc, %bb2]<br class="">+// ptr_val2 = IntToPtr(int_val)<br class="">+// ...<br class="">+// use(ptr_val2)<br class="">+// ptr_val_inc = ...<br class="">+// inc_val_inc = PtrToInt(ptr_val_inc)<br class="">+//<br class="">+// ==><br class="">+// bb1:<br class="">+// br label %bb2<br class="">+// bb2:<br class="">+// ptr_val = PHI([ptr_init, %bb1], [ptr_val_inc, %bb2]<br class="">+// ...<br class="">+// use(ptr_val)<br class="">+// ptr_val_inc = ...<br class="">+//<br class="">+// Case-2:<br class="">+// bb1:<br class="">+// int_ptr = BitCast(ptr_ptr)<br class="">+// int_init = Load(int_ptr)<br class="">+// br label %bb2<br class="">+// bb2:<br class="">+// int_val = PHI([int_init, %bb1], [int_val_inc, %bb2]<br class="">+// ptr_val2 = IntToPtr(int_val)<br class="">+// ...<br class="">+// use(ptr_val2)<br class="">+// ptr_val_inc = ...<br class="">+// inc_val_inc = PtrToInt(ptr_val_inc)<br class="">+// ==><br class="">+// bb1:<br class="">+// ptr_init = Load(ptr_ptr)<br class="">+// br label %bb2<br class="">+// bb2:<br class="">+// ptr_val = PHI([ptr_init, %bb1], [ptr_val_inc, %bb2]<br class="">+// ...<br class="">+// use(ptr_val)<br class="">+// ptr_val_inc = ...<br class="">+// ...<br class="">+//<br class="">+Instruction *InstCombiner::FoldIntegerTypedPHI(PHINode &PN) {<br class="">+ if (!PN.getType()->isIntegerTy())<br class="">+ return nullptr;<br class="">+ if (!PN.hasOneUse())<br class="">+ return nullptr;<br class="">+<br class="">+ auto *IntToPtr = dyn_cast<IntToPtrInst>(PN.user_back());<br class="">+ if (!IntToPtr)<br class="">+ return nullptr;<br class="">+<br class="">+ // Check if the pointer is actually used as pointer:<br class="">+ auto HasPointerUse = [](Instruction *IIP) {<br class="">+ for (User *U : IIP->users()) {<br class="">+ Value *Ptr = nullptr;<br class="">+ if (LoadInst *LoadI = dyn_cast<LoadInst>(U)) {<br class="">+ Ptr = LoadI->getPointerOperand();<br class="">+ } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {<br class="">+ Ptr = SI->getPointerOperand();<br class="">+ } else if (GetElementPtrInst *GI = dyn_cast<GetElementPtrInst>(U)) {<br class="">+ Ptr = GI->getPointerOperand();<br class="">+ }<br class="">+<br class="">+ if (Ptr && Ptr == IIP)<br class="">+ return true;<br class="">+ }<br class="">+ return false;<br class="">+ };<br class="">+<br class="">+ if (!HasPointerUse(IntToPtr))<br class="">+ return nullptr;<br class="">+<br class="">+ if (DL.getPointerSizeInBits(IntToPtr->getAddressSpace()) !=<br class="">+ DL.getTypeSizeInBits(IntToPtr->getOperand(0)->getType()))<br class="">+ return nullptr;<br class="">+<br class="">+ SmallVector<Value *, 4> AvailablePtrVals;<br class="">+ for (unsigned i = 0; i != PN.getNumIncomingValues(); ++i) {<br class="">+ Value *Arg = PN.getIncomingValue(i);<br class="">+<br class="">+ // First look backward:<br class="">+ if (auto *PI = dyn_cast<PtrToIntInst>(Arg)) {<br class="">+ AvailablePtrVals.emplace_back(PI->getOperand(0));<br class="">+ continue;<br class="">+ }<br class="">+<br class="">+ // Next look forward:<br class="">+ Value *ArgIntToPtr = nullptr;<br class="">+ for (User *U : Arg->users()) {<br class="">+ if (isa<IntToPtrInst>(U) && U->getType() == IntToPtr->getType() &&<br class="">+ (DT.dominates(cast<Instruction>(U), PN.getIncomingBlock(i)) ||<br class="">+ cast<Instruction>(U)->getParent() == PN.getIncomingBlock(i))) {<br class="">+ ArgIntToPtr = U;<br class="">+ break;<br class="">+ }<br class="">+ }<br class="">+<br class="">+ if (ArgIntToPtr) {<br class="">+ AvailablePtrVals.emplace_back(ArgIntToPtr);<br class="">+ continue;<br class="">+ }<br class="">+<br class="">+ // If Arg is defined by a PHI, allow it. This will also create<br class="">+ // more opportunities iteratively.<br class="">+ if (isa<PHINode>(Arg)) {<br class="">+ AvailablePtrVals.emplace_back(Arg);<br class="">+ continue;<br class="">+ }<br class="">+<br class="">+ // For a single use integer load:<br class="">+ auto *LoadI = dyn_cast<LoadInst>(Arg);<br class="">+ if (!LoadI)<br class="">+ return nullptr;<br class="">+<br class="">+ if (!LoadI->hasOneUse())<br class="">+ return nullptr;<br class="">+<br class="">+ // Push the integer typed Load instruction into the available<br class="">+ // value set, and fix it up later when the pointer typed PHI<br class="">+ // is synthesized.<br class="">+ AvailablePtrVals.emplace_back(LoadI);<br class="">+ }<br class="">+<br class="">+ // Now search for a matching PHI<br class="">+ auto *BB = PN.getParent();<br class="">+ assert(AvailablePtrVals.size() == PN.getNumIncomingValues() &&<br class="">+ "Not enough available ptr typed incoming values");<br class="">+ PHINode *MatchingPtrPHI = nullptr;<br class="">+ for (auto II = BB->begin(), EI = BasicBlock::iterator(BB->getFirstNonPHI());<br class="">+ II != EI; II++) {<br class="">+ PHINode *PtrPHI = dyn_cast<PHINode>(II);<br class="">+ if (!PtrPHI || PtrPHI == &PN || PtrPHI->getType() != IntToPtr->getType())<br class="">+ continue;<br class="">+ MatchingPtrPHI = PtrPHI;<br class="">+ for (unsigned i = 0; i != PtrPHI->getNumIncomingValues(); ++i) {<br class="">+ if (AvailablePtrVals[i] !=<br class="">+ PtrPHI->getIncomingValueForBlock(PN.getIncomingBlock(i))) {<br class="">+ MatchingPtrPHI = nullptr;<br class="">+ break;<br class="">+ }<br class="">+ }<br class="">+<br class="">+ if (MatchingPtrPHI)<br class="">+ break;<br class="">+ }<br class="">+<br class="">+ if (MatchingPtrPHI) {<br class="">+ assert(MatchingPtrPHI->getType() == IntToPtr->getType() &&<br class="">+ "Phi's Type does not match with IntToPtr");<br class="">+ // The PtrToCast + IntToPtr will be simplified later<br class="">+ return CastInst::CreateBitOrPointerCast(MatchingPtrPHI,<br class="">+ IntToPtr->getOperand(0)->getType());<br class="">+ }<br class="">+<br class="">+ // If it requires a conversion for every PHI operand, do not do it.<br class="">+ if (std::all_of(AvailablePtrVals.begin(), AvailablePtrVals.end(),<br class="">+ [&](Value *V) {<br class="">+ return (V->getType() != IntToPtr->getType()) ||<br class="">+ isa<IntToPtrInst>(V);<br class="">+ }))<br class="">+ return nullptr;<br class="">+<br class="">+ // If any of the operand that requires casting is a terminator<br class="">+ // instruction, do not do it.<br class="">+ if (std::any_of(AvailablePtrVals.begin(), AvailablePtrVals.end(),<br class="">+ [&](Value *V) {<br class="">+ return (V->getType() != IntToPtr->getType()) &&<br class="">+ isa<TerminatorInst>(V);<br class="">+ }))<br class="">+ return nullptr;<br class="">+<br class="">+ PHINode *NewPtrPHI = PHINode::Create(<br class="">+ IntToPtr->getType(), PN.getNumIncomingValues(), PN.getName() + ".ptr");<br class="">+<br class="">+ InsertNewInstBefore(NewPtrPHI, PN);<br class="">+ SmallDenseMap<Value *, Instruction *> Casts;<br class="">+ for (unsigned i = 0; i != PN.getNumIncomingValues(); ++i) {<br class="">+ auto *IncomingBB = PN.getIncomingBlock(i);<br class="">+ auto *IncomingVal = AvailablePtrVals[i];<br class="">+<br class="">+ if (IncomingVal->getType() == IntToPtr->getType()) {<br class="">+ NewPtrPHI->addIncoming(IncomingVal, IncomingBB);<br class="">+ continue;<br class="">+ }<br class="">+<br class="">+#ifndef NDEBUG<br class="">+ LoadInst *LoadI = dyn_cast<LoadInst>(IncomingVal);<br class="">+ assert((isa<PHINode>(IncomingVal) ||<br class="">+ IncomingVal->getType()->isPointerTy() ||<br class="">+ (LoadI && LoadI->hasOneUse())) &&<br class="">+ "Can not replace LoadInst with multiple uses");<br class="">+#endif<br class="">+ // Need to insert a BitCast.<br class="">+ // For an integer Load instruction with a single use, the load + IntToPtr<br class="">+ // cast will be simplified into a pointer load:<br class="">+ // %v = load i64, i64* %a.ip, align 8<br class="">+ // %v.cast = inttoptr i64 %v to float **<br class="">+ // ==><br class="">+ // %v.ptrp = bitcast i64 * %a.ip to float **<br class="">+ // %v.cast = load float *, float ** %v.ptrp, align 8<br class="">+ Instruction *&CI = Casts[IncomingVal];<br class="">+ if (!CI) {<br class="">+ CI = CastInst::CreateBitOrPointerCast(IncomingVal, IntToPtr->getType(),<br class="">+ IncomingVal->getName() + ".ptr");<br class="">+ if (auto *IncomingI = dyn_cast<Instruction>(IncomingVal)) {<br class="">+ BasicBlock::iterator InsertPos(IncomingI);<br class="">+ InsertPos++;<br class="">+ if (isa<PHINode>(IncomingI))<br class="">+ InsertPos = IncomingI->getParent()->getFirstInsertionPt();<br class="">+ InsertNewInstBefore(CI, *InsertPos);<br class="">+ } else {<br class="">+ auto *InsertBB = &IncomingBB->getParent()->getEntryBlock();<br class="">+ InsertNewInstBefore(CI, *InsertBB->getFirstInsertionPt());<br class="">+ }<br class="">+ }<br class="">+ NewPtrPHI->addIncoming(CI, IncomingBB);<br class="">+ }<br class="">+<br class="">+ // The PtrToCast + IntToPtr will be simplified later<br class="">+ return CastInst::CreateBitOrPointerCast(NewPtrPHI,<br class="">+ IntToPtr->getOperand(0)->getType());<br class="">+}<br class="">+<br class=""> /// If we have something like phi [add (a,b), add(a,c)] and if a/b/c and the<br class=""> /// adds all have a single use, turn this into a phi and a single binop.<br class=""> Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {<br class="">@@ -903,6 +1135,9 @@ Instruction *InstCombiner::visitPHINode(<br class=""> // this PHI only has a single use (a PHI), and if that PHI only has one use (a<br class=""> // PHI)... break the cycle.<br class=""> if (PN.hasOneUse()) {<br class="">+ if (Instruction *Result = FoldIntegerTypedPHI(PN))<br class="">+ return Result;<br class="">+<br class=""> Instruction *PHIUser = cast<Instruction>(PN.user_back());<br class=""> if (PHINode *PU = dyn_cast<PHINode>(PHIUser)) {<br class=""> SmallPtrSet<PHINode*, 16> PotentiallyDeadPHIs;<br class=""><br class="">Added: llvm/trunk/test/Transforms/InstCombine/intptr7.ll<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/intptr7.ll?rev=315272&view=auto" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/intptr7.ll?rev=315272&view=auto</a><br class="">==============================================================================<br class="">--- llvm/trunk/test/Transforms/InstCombine/intptr7.ll (added)<br class="">+++ llvm/trunk/test/Transforms/InstCombine/intptr7.ll Mon Oct 9 22:07:54 2017<br class="">@@ -0,0 +1,58 @@<br class="">+; RUN: opt < %s -instcombine -S | FileCheck %s<br class="">+<br class="">+define void @matching_phi(i64 %a, float* %b, i1 %cond) {<br class="">+; CHECK-LABEL: @matching_phi<br class="">+entry:<br class="">+ %cmp1 = icmp eq i1 %cond, 0<br class="">+ %add.int = add i64 %a, 1<br class="">+ %add = inttoptr i64 %add.int to float *<br class="">+<br class="">+ %addb = getelementptr inbounds float, float* %b, i64 2<br class="">+ %addb.int = ptrtoint float* %addb to i64<br class="">+ br i1 %cmp1, label %A, label %B<br class="">+A:<br class="">+ br label %C<br class="">+B:<br class="">+ store float 1.0e+01, float* %add, align 4<br class="">+ br label %C<br class="">+<br class="">+C:<br class="">+ %a.addr.03 = phi float* [ %addb, %A ], [ %add, %B ]<br class="">+ %b.addr.02 = phi i64 [ %addb.int, %A ], [ %add.int, %B ]<br class="">+ %tmp = inttoptr i64 %b.addr.02 to float*<br class="">+; CHECK: %a.addr.03 = phi<br class="">+; CHECK-NEXT: = load<br class="">+ %tmp1 = load float, float* %tmp, align 4<br class="">+ %mul.i = fmul float %tmp1, 4.200000e+01<br class="">+ store float %mul.i, float* %a.addr.03, align 4<br class="">+ ret void<br class="">+}<br class="">+<br class="">+define void @no_matching_phi(i64 %a, float* %b, i1 %cond) {<br class="">+; CHECK-LABEL: @no_matching_phi<br class="">+entry:<br class="">+ %cmp1 = icmp eq i1 %cond, 0<br class="">+ %add.int = add i64 %a, 1<br class="">+ %add = inttoptr i64 %add.int to float *<br class="">+<br class="">+ %addb = getelementptr inbounds float, float* %b, i64 2<br class="">+ %addb.int = ptrtoint float* %addb to i64<br class="">+ br i1 %cmp1, label %A, label %B<br class="">+A:<br class="">+ br label %C<br class="">+B:<br class="">+ store float 1.0e+01, float* %add, align 4<br class="">+ br label %C<br class="">+<br class="">+C:<br class="">+ %a.addr.03 = phi float* [ %addb, %A ], [ %add, %B ]<br class="">+ %b.addr.02 = phi i64 [ %addb.int, %B ], [ %add.int, %A ]<br class="">+ %tmp = inttoptr i64 %b.addr.02 to float*<br class="">+ %tmp1 = load float, float* %tmp, align 4<br class="">+; CHECK: %a.addr.03 = phi<br class="">+; CHECK-NEXT: %b.addr.02.ptr = phi<br class="">+; CHECK-NEXT: = load<br class="">+ %mul.i = fmul float %tmp1, 4.200000e+01<br class="">+ store float %mul.i, float* %a.addr.03, align 4<br class="">+ ret void<br class="">+}<br class=""><br class=""><br class="">_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits<br class=""></div></div></blockquote></div><br class=""></div></body></html>