<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>