Teach ScalarEvolution to recognize x^-1 in the case where non-demanded
authorDan Gohman <gohman@apple.com>
Mon, 18 May 2009 16:29:04 +0000 (16:29 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 18 May 2009 16:29:04 +0000 (16:29 +0000)
bits have been stripped out by instcombine.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72010 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/and-xor.ll [new file with mode: 0644]

index 3480a317c061e213480ef911903f8b3c48f36903..3ecb30232c6aa235503e21c40e2497f8c56c8b5c 100644 (file)
@@ -2203,6 +2203,19 @@ SCEVHandle ScalarEvolution::createSCEV(Value *V) {
       // If the RHS of xor is -1, then this is a not operation.
       if (CI->isAllOnesValue())
         return getNotSCEV(getSCEV(U->getOperand(0)));
+
+      // Model xor(and(x, C), C) as and(~x, C), if C is a low-bits mask.
+      // This is a variant of the check for xor with -1, and it handles
+      // the case where instcombine has trimmed non-demanded bits out
+      // of an xor with -1.
+      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(U->getOperand(0)))
+        if (ConstantInt *LCI = dyn_cast<ConstantInt>(BO->getOperand(1)))
+          if (BO->getOpcode() == Instruction::And &&
+              LCI->getValue() == CI->getValue())
+            if (const SCEVZeroExtendExpr *Z =
+                  dyn_cast<SCEVZeroExtendExpr>(getSCEV(U->getOperand(0))))
+              return getZeroExtendExpr(getNotSCEV(Z->getOperand()),
+                                       U->getType());
     }
     break;
 
diff --git a/test/Analysis/ScalarEvolution/and-xor.ll b/test/Analysis/ScalarEvolution/and-xor.ll
new file mode 100644 (file)
index 0000000..94cca83
--- /dev/null
@@ -0,0 +1,8 @@
+; RUN: llvm-as < %s | opt -scalar-evolution -analyze -disable-output \
+; RUN:   | grep {\\-->  (zext} | count 2
+
+define i32 @foo(i32 %x) {
+  %n = and i32 %x, 255
+  %y = xor i32 %n, 255
+  ret i32 %y
+}