diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 37 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/prevent-cmp-merge.ll | 41 |
2 files changed, 61 insertions, 17 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 990305b1d8d..1e6e0727955 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2212,27 +2212,30 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, } break; case Instruction::Xor: - // For the xor case, we can xor two constants together, eliminating - // the explicit xor. - if (Constant *BOC = dyn_cast<Constant>(BO->getOperand(1))) { - return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), - ConstantExpr::getXor(RHS, BOC)); - } else if (RHSV == 0) { - // Replace ((xor A, B) != 0) with (A != B) - return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), - BO->getOperand(1)); + if (BO->hasOneUse()) { + if (Constant *BOC = dyn_cast<Constant>(BO->getOperand(1))) { + // For the xor case, we can xor two constants together, eliminating + // the explicit xor. + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + ConstantExpr::getXor(RHS, BOC)); + } else if (RHSV == 0) { + // Replace ((xor A, B) != 0) with (A != B) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + BO->getOperand(1)); + } } break; case Instruction::Sub: - // Replace ((sub A, B) != C) with (B != A-C) if A & C are constants. - if (ConstantInt *BOp0C = dyn_cast<ConstantInt>(BO->getOperand(0))) { - if (BO->hasOneUse()) + if (BO->hasOneUse()) { + if (ConstantInt *BOp0C = dyn_cast<ConstantInt>(BO->getOperand(0))) { + // Replace ((sub A, B) != C) with (B != A-C) if A & C are constants. return new ICmpInst(ICI.getPredicate(), BO->getOperand(1), - ConstantExpr::getSub(BOp0C, RHS)); - } else if (RHSV == 0) { - // Replace ((sub A, B) != 0) with (A != B) - return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), - BO->getOperand(1)); + ConstantExpr::getSub(BOp0C, RHS)); + } else if (RHSV == 0) { + // Replace ((sub A, B) != 0) with (A != B) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + BO->getOperand(1)); + } } break; case Instruction::Or: diff --git a/llvm/test/Transforms/InstCombine/prevent-cmp-merge.ll b/llvm/test/Transforms/InstCombine/prevent-cmp-merge.ll new file mode 100644 index 00000000000..ab37c7d5623 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/prevent-cmp-merge.ll @@ -0,0 +1,41 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; +; This test makes sure that InstCombine does not replace the sequence of +; xor/sub instruction followed by cmp instruction into a single cmp instruction +; if there is more than one use of xor/sub. + +define zeroext i1 @test1(i32 %lhs, i32 %rhs) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: %xor = xor i32 %lhs, 5 +; CHECK-NEXT: %cmp1 = icmp eq i32 %xor, 10 + + %xor = xor i32 %lhs, 5 + %cmp1 = icmp eq i32 %xor, 10 + %cmp2 = icmp eq i32 %xor, %rhs + %sel = or i1 %cmp1, %cmp2 + ret i1 %sel +} + +define zeroext i1 @test2(i32 %lhs, i32 %rhs) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: %xor = xor i32 %lhs, %rhs +; CHECK-NEXT: %cmp1 = icmp eq i32 %xor, 0 + + %xor = xor i32 %lhs, %rhs + %cmp1 = icmp eq i32 %xor, 0 + %cmp2 = icmp eq i32 %xor, 32 + %sel = xor i1 %cmp1, %cmp2 + ret i1 %sel +} + +define zeroext i1 @test3(i32 %lhs, i32 %rhs) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: %sub = sub nsw i32 %lhs, %rhs +; CHECK-NEXT: %cmp1 = icmp eq i32 %sub, 0 + + %sub = sub nsw i32 %lhs, %rhs + %cmp1 = icmp eq i32 %sub, 0 + %cmp2 = icmp eq i32 %sub, 31 + %sel = or i1 %cmp1, %cmp2 + ret i1 %sel +} |

