[llvm-commits] [PATCH] InstCombine enhancement

Shuxin Yang shuxin.llvm at gmail.com
Mon Nov 26 13:32:08 PST 2012


Hi, dear all:

      This change is trying to catch this optimization opportunity (one 
of the two defects reported in rdar://12329730):

    -----------------------------------------------------
           ((X^C1) >> C2) ^ C3  => (X>>C2) ^ ((C1>>C2)^C3)
      where the subexpression "X ^ C1" has more than one uses, and
      "(X^C1) >> C2" has single use.
   ------------------------------------------------------

     If the "X ^ C1" has only one use,  InstCombine will distribute the 
">>" operation
in the "X^C1 >> C2", and the entire expression would be eventually 
optimized;
however, if "X ^ C1" has multiple uses,  InstCombine would give up.

Thanks
Shuxin








-------------- next part --------------
Index: test/Transforms/InstCombine/xor2.ll
===================================================================
--- test/Transforms/InstCombine/xor2.ll	(revision 168597)
+++ test/Transforms/InstCombine/xor2.ll	(working copy)
@@ -51,3 +51,18 @@
 ; CHECK: %1 = ashr i32 %A, %B
 ; CHECK: ret i32 %1
 }
+
+; defect-2 in rdar://12329730
+; (X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3)
+;   where the "X" has more than one use
+define i32 @test5(i32 %val1) {
+test5:
+  %xor = xor i32 %val1, 1234
+  %shr = lshr i32 %xor, 8
+  %xor1 = xor i32 %shr, 1
+  %add = add i32 %xor1, %xor
+  ret i32 %add
+; CHECK: @test5
+; CHECK: lshr i32 %val1, 8
+; CHECK: ret
+}
Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp	(revision 168597)
+++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp	(working copy)
@@ -2159,6 +2159,26 @@
             I.setOperand(1, NewRHS);
             return &I;
           }
+        } else if (Op0I->getOpcode() == Instruction::LShr) {
+          // ((X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3)
+          BinaryOperator *E1; // E1 = "X ^ C1"
+          ConstantInt *C1;
+          if (Op0I->hasOneUse() &&
+              (E1 = dyn_cast<BinaryOperator>(Op0I->getOperand(0))) &&
+              E1->getOpcode() == Instruction::Xor &&
+              (C1 = dyn_cast<ConstantInt>(E1->getOperand(1)))) {
+            // fold (C1 >> C2) ^ C3
+            ConstantInt *C2 = Op0CI, *C3 = RHS;
+            APInt FoldConst = C1->getValue().lshr(C2->getValue());
+            FoldConst ^= C3->getValue();
+            // prepare the two operands
+            Value *Opnd0 = Builder->CreateLShr(E1->getOperand(0), C2);
+            Opnd0->takeName(Op0I);
+            cast<Instruction>(Opnd0)->setDebugLoc(I.getDebugLoc());
+            Value *FoldVal = ConstantInt::get(Opnd0->getType(), FoldConst);
+
+            return BinaryOperator::CreateXor(Opnd0, FoldVal);
+          }
         }
       }
     }


More information about the llvm-commits mailing list