aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-10-26 01:06:31 +0000
committerChris Lattner <sabre@nondot.org>2009-10-26 01:06:31 +0000
commit863928fc39c7f1ab86779415eb704b2f2474b995 (patch)
tree3b3a61d0d841f735be0cbb4bb83d7b1c7efd3cad
parent1125f58efcfe4e93322f993aa74215e6ffacd8ea (diff)
Implement PR3266 & PR5276, folding:
not (or (icmp, icmp)) -> and(icmp, icmp) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85085 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp51
-rw-r--r--test/Transforms/InstCombine/or.ll17
-rw-r--r--test/Transforms/InstCombine/xor-demorgans.ll12
3 files changed, 61 insertions, 19 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 81423b740b..0285fb5377 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -631,9 +631,32 @@ static inline Value *dyn_castFNegVal(Value *V) {
return 0;
}
-static inline Value *dyn_castNotVal(Value *V) {
+/// isFreeToInvert - Return true if the specified value is free to invert (apply
+/// ~ to). This happens in cases where the ~ can be eliminated.
+static inline bool isFreeToInvert(Value *V) {
+ // ~(~(X)) -> X.
if (BinaryOperator::isNot(V))
- return BinaryOperator::getNotArgument(V);
+ return true;
+
+ // Constants can be considered to be not'ed values.
+ if (isa<ConstantInt>(V))
+ return true;
+
+ // Compares can be inverted if they have a single use.
+ if (CmpInst *CI = dyn_cast<CmpInst>(V))
+ return CI->hasOneUse();
+
+ return false;
+}
+
+static inline Value *dyn_castNotVal(Value *V) {
+ // If this is not(not(x)) don't return that this is a not: we want the two
+ // not's to be folded first.
+ if (BinaryOperator::isNot(V)) {
+ Value *Operand = BinaryOperator::getNotArgument(V);
+ if (!isFreeToInvert(Operand))
+ return Operand;
+ }
// Constants can be considered to be not'ed values...
if (ConstantInt *C = dyn_cast<ConstantInt>(V))
@@ -641,6 +664,8 @@ static inline Value *dyn_castNotVal(Value *V) {
return 0;
}
+
+
// dyn_castFoldableMul - If this value is a multiply that can be folded into
// other computations (because it has a constant operand), return the
// non-constant operand of the multiply, and set CST to point to the multiplier.
@@ -4166,7 +4191,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
if (Instruction *CastOp = dyn_cast<Instruction>(CI->getOperand(0))) {
if ((isa<TruncInst>(CI) || isa<BitCastInst>(CI)) &&
CastOp->getNumOperands() == 2)
- if (ConstantInt *AndCI = dyn_cast<ConstantInt>(CastOp->getOperand(1))) {
+ if (ConstantInt *AndCI =dyn_cast<ConstantInt>(CastOp->getOperand(1))){
if (CastOp->getOpcode() == Instruction::And) {
// Change: and (cast (and X, C1) to T), C2
// into : and (cast X to T), trunc_or_bitcast(C1)&C2
@@ -5064,12 +5089,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
// Is this a ~ operation?
if (Value *NotOp = dyn_castNotVal(&I)) {
- // ~(~X & Y) --> (X | ~Y) - De Morgan's Law
- // ~(~X | Y) === (X & ~Y) - De Morgan's Law
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(NotOp)) {
if (Op0I->getOpcode() == Instruction::And ||
Op0I->getOpcode() == Instruction::Or) {
- if (dyn_castNotVal(Op0I->getOperand(1))) Op0I->swapOperands();
+ // ~(~X & Y) --> (X | ~Y) - De Morgan's Law
+ // ~(~X | Y) === (X & ~Y) - De Morgan's Law
+ if (dyn_castNotVal(Op0I->getOperand(1)))
+ Op0I->swapOperands();
if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) {
Value *NotY =
Builder->CreateNot(Op0I->getOperand(1),
@@ -5078,6 +5104,19 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
return BinaryOperator::CreateOr(Op0NotVal, NotY);
return BinaryOperator::CreateAnd(Op0NotVal, NotY);
}
+
+ // ~(X & Y) --> (~X | ~Y) - De Morgan's Law
+ // ~(X | Y) === (~X & ~Y) - De Morgan's Law
+ if (isFreeToInvert(Op0I->getOperand(0)) &&
+ isFreeToInvert(Op0I->getOperand(1))) {
+ Value *NotX =
+ Builder->CreateNot(Op0I->getOperand(0), "notlhs");
+ Value *NotY =
+ Builder->CreateNot(Op0I->getOperand(1), "notrhs");
+ if (Op0I->getOpcode() == Instruction::And)
+ return BinaryOperator::CreateOr(NotX, NotY);
+ return BinaryOperator::CreateAnd(NotX, NotY);
+ }
}
}
}
diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll
index dbdd08a489..b72480b4f9 100644
--- a/test/Transforms/InstCombine/or.ll
+++ b/test/Transforms/InstCombine/or.ll
@@ -237,4 +237,19 @@ define i1 @test24(double %X, double %Y) {
; CHECK: @test24
; CHECK: %bothcond = fcmp uno double %Y, %X ; <i1> [#uses=1]
; CHECK: ret i1 %bothcond
-} \ No newline at end of file
+}
+
+; PR3266 & PR5276
+define i1 @test25(i32 %A, i32 %B) {
+ %C = icmp eq i32 %A, 0
+ %D = icmp eq i32 %B, 57
+ %E = or i1 %C, %D
+ %F = xor i1 %E, -1
+ ret i1 %F
+
+; CHECK: @test25
+; CHECK: icmp ne i32 %A, 0
+; CHECK-NEXT: icmp ne i32 %B, 57
+; CHECK-NEXT: %F = and i1
+; CHECK-NEXT: ret i1 %F
+}
diff --git a/test/Transforms/InstCombine/xor-demorgans.ll b/test/Transforms/InstCombine/xor-demorgans.ll
deleted file mode 100644
index 3383845fb3..0000000000
--- a/test/Transforms/InstCombine/xor-demorgans.ll
+++ /dev/null
@@ -1,12 +0,0 @@
-; RUN: opt < %s -instcombine -S | not grep {= or}
-; PR3266
-; XFAIL: *
-
-define i1 @foo(i32 %x, i32 %y) nounwind {
-.summary:
- %0 = icmp sgt i32 %x, 4 ; <i1> [#uses=1]
- %1 = icmp sgt i32 %y, 0 ; <i1> [#uses=1]
- %.demorgan = or i1 %1, %0 ; <i1> [#uses=1]
- %2 = xor i1 %.demorgan, true ; <i1> [#uses=1]
- ret i1 %2
-}