[llvm-commits] [PATCH, instcombine] X ^ Y -> X or Y

Shuxin Yang shuxin.llvm at gmail.com
Tue Dec 4 14:07:31 PST 2012


Hi,

   For rdar://12329730, last piece.

   This change attempts to simplify (X^Y) -> X or Y in the user's 
context if we know that
  only bits from X or Y are demanded.

    A minimized case is provided bellow. This change will simplify 
"t>>9" into "var1 >>9".

==============================
unsigned foo (unsigned val1, unsigned val2) {
     unsigned t = val1 ^ 1234;
     return (t >> 16) | t; // NOTE: t is used more than once.
}
===============================

   Note that if the "t" were used only once, the expression would be 
finally optimized as well.
However, with with this change, the optimization will take place earlier.

   The change to test39 at shift.ll is not obvious.  We can verify the 
correctness by
starting tmp4 with value {b7, b6, ... b0} (NOTE: tmp4 is of type i8).

Thank you for review
Shuxin

  test39 WAS:
========
define i8 @test39(i32 %a0) {
entry:
   %tmp4 = trunc i32 %a0 to i8
   %tmp5 = shl i8 %tmp4, 5
   %tmp49 = shl i8 %tmp4, 6
   %tmp50 = and i8 %tmp49, 64
   %tmp51 = xor i8 %tmp50, %tmp5
   %tmp53 = lshr i8 %tmp51, 7
   %tmp54 = shl nuw nsw i8 %tmp53, 4
   %tmp551 = or i8 %tmp54, %tmp51
   ret i8 %tmp551
}

  IS:
===
define i8 @test39(i32 %a0) {
entry:
   %tmp4 = trunc i32 %a0 to i8
   %tmp5 = shl i8 %tmp4, 5
   %tmp49 = shl i8 %tmp4, 6
   %tmp50 = and i8 %tmp49, 64
   %tmp51 = xor i8 %tmp50, %tmp5
   %0 = shl i8 %tmp4, 2  ; **** diff **
   %tmp54 = and i8 %0, 16 ; **** diff **
   %tmp551 = or i8 %tmp54, %tmp51
   ret i8 %tmp551
}


-------------- next part --------------
Index: test/Transforms/InstCombine/xor2.ll
===================================================================
--- test/Transforms/InstCombine/xor2.ll	(revision 169286)
+++ test/Transforms/InstCombine/xor2.ll	(working copy)
@@ -66,3 +66,19 @@
 ; CHECK: lshr i32 %val1, 8
 ; CHECK: ret
 }
+
+; defect-1 in rdar://12329730
+; Simplify (X^Y) -> X or Y in the user's context if we know that 
+; only bits from X or Y are demanded.
+; e.g. the "x ^ 1234" can be optimized into x in the context of "t >> 16".
+;  Put in other word, t >> 16 -> x >> 16.
+; unsigned foo(unsigned x) { nsigned t = x ^ 1234; ;  return (t >> 16) + t;}
+define i32 @test6(i32 %x) {
+  %xor = xor i32 %x, 1234
+  %shr = lshr i32 %xor, 16
+  %add = add i32 %shr, %xor
+  ret i32 %add
+; CHECK: @test6
+; CHECK: lshr i32 %x, 16
+; CHECK: ret
+}
Index: test/Transforms/InstCombine/shift.ll
===================================================================
--- test/Transforms/InstCombine/shift.ll	(revision 169286)
+++ test/Transforms/InstCombine/shift.ll	(working copy)
@@ -523,9 +523,9 @@
   %tmp51 = xor i8 %tmp50, %tmp5
   %tmp52 = and i8 %tmp51, -128
   %tmp53 = lshr i8 %tmp52, 7
-; CHECK: lshr i8 %tmp51, 7
   %tmp54 = mul i8 %tmp53, 16
-; CHECK: shl nuw nsw i8 %tmp53, 4
+; CHECK: %0 = shl i8 %tmp4, 2
+; CHECK: %tmp54 = and i8 %0, 16
   %tmp55 = xor i8 %tmp54, %tmp51
 ; CHECK: ret i8 %tmp551
   ret i8 %tmp55
Index: test/Transforms/InstCombine/2010-11-01-lshr-mask.ll
===================================================================
--- test/Transforms/InstCombine/2010-11-01-lshr-mask.ll	(revision 169286)
+++ test/Transforms/InstCombine/2010-11-01-lshr-mask.ll	(working copy)
@@ -5,8 +5,8 @@
 define i32 @main(i32 %argc) nounwind ssp {
 entry:
   %tmp3151 = trunc i32 %argc to i8
-; CHECK: %tmp3162 = shl i8 %tmp3151, 5
-; CHECK: and i8 %tmp3162, 64
+; CHECK: %0 = shl i8 %tmp3151, 5
+; CHECK: and i8 %0, 64
 ; CHECK-NOT: shl
 ; CHECK-NOT: shr
   %tmp3161 = or i8 %tmp3151, -17
Index: lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp	(revision 169286)
+++ lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp	(working copy)
@@ -200,8 +200,21 @@
       if ((DemandedMask & (~LHSKnownZero) & RHSKnownOne) == 
           (DemandedMask & (~LHSKnownZero)))
         return I->getOperand(1);
+    } else if (I->getOpcode() == Instruction::Xor) {
+      // 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.
+      
+      ComputeMaskedBits(I->getOperand(1), RHSKnownZero, RHSKnownOne, Depth+1);
+      ComputeMaskedBits(I->getOperand(0), LHSKnownZero, LHSKnownOne, Depth+1);
+      
+      // If all of the demanded bits are known zero on one side, return the
+      // other. 
+      if ((DemandedMask & RHSKnownZero) == DemandedMask)
+        return I->getOperand(0);
+      if ((DemandedMask & LHSKnownZero) == DemandedMask)
+        return I->getOperand(1);
     }
-    
+
     // Compute the KnownZero/KnownOne bits to simplify things downstream.
     ComputeMaskedBits(I, KnownZero, KnownOne, Depth);
     return 0;


More information about the llvm-commits mailing list