[llvm-commits] [llvm] r63481 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/multi-use-or.ll

Chris Lattner sabre at nondot.org
Sat Jan 31 00:40:04 PST 2009


Author: lattner
Date: Sat Jan 31 02:40:03 2009
New Revision: 63481

URL: http://llvm.org/viewvc/llvm-project?rev=63481&view=rev
Log:
now that all the pieces are in place, teach instcombine's
simplifydemandedbits to simplify instructions with *multiple
uses* in contexts where it can get away with it.  This allows
it to simplify the code in multi-use-or.ll into a single 'add 
double'.

This change is particularly interesting because it will cover
up for some common codegen bugs with large integers created due
to the recent SROA patch.  When working on fixing those bugs,
this should be disabled.


Added:
    llvm/trunk/test/Transforms/InstCombine/multi-use-or.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=63481&r1=63480&r2=63481&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Jan 31 02:40:03 2009
@@ -825,10 +825,68 @@
   Instruction *I = dyn_cast<Instruction>(V);
   if (!I) return 0;        // Only analyze instructions.
   
+  APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0);
+  APInt &RHSKnownZero = KnownZero, &RHSKnownOne = KnownOne;
+
   // If there are multiple uses of this value and we aren't at the root, then
   // we can't do any simplifications of the operands, because DemandedMask
   // only reflects the bits demanded by *one* of the users.
   if (Depth != 0 && !I->hasOneUse()) {
+    // Despite the fact that we can't simplify this instruction in all User's
+    // context, we can at least compute the knownzero/knownone bits, and we can
+    // do simplifications that apply to *just* the one user if we know that
+    // this instruction has a simpler value in that context.
+    if (I->getOpcode() == Instruction::And) {
+      // If either the LHS or the RHS are Zero, the result is zero.
+      ComputeMaskedBits(I->getOperand(1), DemandedMask,
+                        RHSKnownZero, RHSKnownOne, Depth+1);
+      ComputeMaskedBits(I->getOperand(0), DemandedMask & ~RHSKnownZero,
+                        LHSKnownZero, LHSKnownOne, Depth+1);
+      
+      // If all of the demanded bits are known 1 on one side, return the other.
+      // These bits cannot contribute to the result of the 'and' in this
+      // context.
+      if ((DemandedMask & ~LHSKnownZero & RHSKnownOne) == 
+          (DemandedMask & ~LHSKnownZero))
+        return I->getOperand(0);
+      if ((DemandedMask & ~RHSKnownZero & LHSKnownOne) == 
+          (DemandedMask & ~RHSKnownZero))
+        return I->getOperand(1);
+      
+      // If all of the demanded bits in the inputs are known zeros, return zero.
+      if ((DemandedMask & (RHSKnownZero|LHSKnownZero)) == DemandedMask)
+        return Constant::getNullValue(VTy);
+      
+    } else if (I->getOpcode() == Instruction::Or) {
+      // We can simplify (X|Y) -> X or Y in the user's context if we know that
+      // only bits from X or Y are demanded.
+      
+      // If either the LHS or the RHS are One, the result is One.
+      ComputeMaskedBits(I->getOperand(1), DemandedMask, 
+                        RHSKnownZero, RHSKnownOne, Depth+1);
+      ComputeMaskedBits(I->getOperand(0), DemandedMask & ~RHSKnownOne, 
+                        LHSKnownZero, LHSKnownOne, Depth+1);
+      
+      // If all of the demanded bits are known zero on one side, return the
+      // other.  These bits cannot contribute to the result of the 'or' in this
+      // context.
+      if ((DemandedMask & ~LHSKnownOne & RHSKnownZero) == 
+          (DemandedMask & ~LHSKnownOne))
+        return I->getOperand(0);
+      if ((DemandedMask & ~RHSKnownOne & LHSKnownZero) == 
+          (DemandedMask & ~RHSKnownOne))
+        return I->getOperand(1);
+      
+      // If all of the potentially set bits on one side are known to be set on
+      // the other side, just use the 'other' side.
+      if ((DemandedMask & (~RHSKnownZero) & LHSKnownOne) == 
+          (DemandedMask & (~RHSKnownZero)))
+        return I->getOperand(0);
+      if ((DemandedMask & (~LHSKnownZero) & RHSKnownOne) == 
+          (DemandedMask & (~LHSKnownZero)))
+        return I->getOperand(1);
+    }
+    
     // Compute the KnownZero/KnownOne bits to simplify things downstream.
     ComputeMaskedBits(I, DemandedMask, KnownZero, KnownOne, Depth);
     return 0;
@@ -841,8 +899,6 @@
   if (Depth == 0 && !V->hasOneUse())
     DemandedMask = APInt::getAllOnesValue(BitWidth);
   
-  APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0);
-  APInt &RHSKnownZero = KnownZero, &RHSKnownOne = KnownOne;
   switch (I->getOpcode()) {
   default:
     ComputeMaskedBits(I, DemandedMask, RHSKnownZero, RHSKnownOne, Depth);

Added: llvm/trunk/test/Transforms/InstCombine/multi-use-or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/multi-use-or.ll?rev=63481&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/multi-use-or.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/multi-use-or.ll Sat Jan 31 02:40:03 2009
@@ -0,0 +1,24 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {add double .sx, .sy}
+; The 'or' has multiple uses, make sure that this doesn't prevent instcombine
+; from propagating the extends to the truncs.
+
+define double @ScaleObjectAdd(double %sx, double %sy, double %sz) nounwind {
+entry:
+        %sx34 = bitcast double %sx to i64               ; <i64> [#uses=1]
+        %sx3435 = zext i64 %sx34 to i192                ; <i192> [#uses=1]
+        %sy22 = bitcast double %sy to i64               ; <i64> [#uses=1]
+        %sy2223 = zext i64 %sy22 to i192                ; <i192> [#uses=1]
+        %sy222324 = shl i192 %sy2223, 128               ; <i192> [#uses=1]
+        %sy222324.ins = or i192 %sx3435, %sy222324              ; <i192> [#uses=1]
+        
+        
+        %a = trunc i192 %sy222324.ins to i64            ; <i64> [#uses=1]
+        %b = bitcast i64 %a to double           ; <double> [#uses=1]
+        %c = lshr i192 %sy222324.ins, 128               ; <i192> [#uses=1]
+        %d = trunc i192 %c to i64               ; <i64> [#uses=1]
+        %e = bitcast i64 %d to double           ; <double> [#uses=1]
+        %f = add double %b, %e
+
+;        ret double %e
+        ret double %f
+}





More information about the llvm-commits mailing list