[llvm-commits] [llvm] r43777 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/phi-merge.ll

Chris Lattner sabre at nondot.org
Tue Nov 6 13:52:08 PST 2007


Author: lattner
Date: Tue Nov  6 15:52:06 2007
New Revision: 43777

URL: http://llvm.org/viewvc/llvm-project?rev=43777&view=rev
Log:
Implement PR1777 by detecting dependent phis that
all compute the same value.

Added:
    llvm/trunk/test/Transforms/InstCombine/phi-merge.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=43777&r1=43776&r2=43777&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue Nov  6 15:52:06 2007
@@ -8551,6 +8551,34 @@
   return false;
 }
 
+/// PHIsEqualValue - Return true if this phi node is always equal to
+/// NonPhiInVal.  This happens with mutually cyclic phi nodes like:
+///   z = some value; x = phi (y, z); y = phi (x, z)
+static bool PHIsEqualValue(PHINode *PN, Value *NonPhiInVal, 
+                           SmallPtrSet<PHINode*, 16> &ValueEqualPHIs) {
+  // See if we already saw this PHI node.
+  if (!ValueEqualPHIs.insert(PN))
+    return true;
+  
+  // Don't scan crazily complex things.
+  if (ValueEqualPHIs.size() == 16)
+    return false;
+ 
+  // Scan the operands to see if they are either phi nodes or are equal to
+  // the value.
+  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
+    Value *Op = PN->getIncomingValue(i);
+    if (PHINode *OpPN = dyn_cast<PHINode>(Op)) {
+      if (!PHIsEqualValue(OpPN, NonPhiInVal, ValueEqualPHIs))
+        return false;
+    } else if (Op != NonPhiInVal)
+      return false;
+  }
+  
+  return true;
+}
+
+
 // PHINode simplification
 //
 Instruction *InstCombiner::visitPHINode(PHINode &PN) {
@@ -8592,6 +8620,40 @@
     }
   }
 
+  // We sometimes end up with phi cycles that non-obviously end up being the
+  // same value, for example:
+  //   z = some value; x = phi (y, z); y = phi (x, z)
+  // where the phi nodes don't necessarily need to be in the same block.  Do a
+  // quick check to see if the PHI node only contains a single non-phi value, if
+  // so, scan to see if the phi cycle is actually equal to that value.
+  {
+    unsigned InValNo = 0, NumOperandVals = PN.getNumIncomingValues();
+    // Scan for the first non-phi operand.
+    while (InValNo != NumOperandVals && 
+           isa<PHINode>(PN.getIncomingValue(InValNo)))
+      ++InValNo;
+
+    if (InValNo != NumOperandVals) {
+      Value *NonPhiInVal = PN.getOperand(InValNo);
+      
+      // Scan the rest of the operands to see if there are any conflicts, if so
+      // there is no need to recursively scan other phis.
+      for (++InValNo; InValNo != NumOperandVals; ++InValNo) {
+        Value *OpVal = PN.getIncomingValue(InValNo);
+        if (OpVal != NonPhiInVal && !isa<PHINode>(OpVal))
+          break;
+      }
+      
+      // If we scanned over all operands, then we have one unique value plus
+      // phi values.  Scan PHI nodes to see if they all merge in each other or
+      // the value.
+      if (InValNo == NumOperandVals) {
+        SmallPtrSet<PHINode*, 16> ValueEqualPHIs;
+        if (PHIsEqualValue(&PN, NonPhiInVal, ValueEqualPHIs))
+          return ReplaceInstUsesWith(PN, NonPhiInVal);
+      }
+    }
+  }
   return 0;
 }
 

Added: llvm/trunk/test/Transforms/InstCombine/phi-merge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/phi-merge.ll?rev=43777&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/phi-merge.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/phi-merge.ll Tue Nov  6 15:52:06 2007
@@ -0,0 +1,31 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep {phi i32}
+; PR1777
+
+declare i1 @rrr()
+
+define i1 @zxcv() {
+entry:
+%a = alloca i32
+%i = ptrtoint i32* %a to i32
+%b = call i1 @rrr()
+br i1 %b, label %one, label %two
+
+one:
+%x = phi i32 [%i, %entry], [%y, %two]
+%c = call i1 @rrr()
+br i1 %c, label %two, label %end
+
+two:
+%y = phi i32 [%i, %entry], [%x, %one]
+%d = call i1 @rrr()
+br i1 %d, label %one, label %end
+
+end:
+%f = phi i32 [ %x, %one], [%y, %two]
+; Change the %f to %i, and the optimizer suddenly becomes a lot smarter
+; even though %f must equal %i at this point
+%g = inttoptr i32 %f to i32*
+store i32 10, i32* %g
+%z = call i1 @rrr()
+ret i1 %z
+}





More information about the llvm-commits mailing list