Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -766,6 +766,13 @@ if (Op0 == Op1) return Constant::getNullValue(Op0->getType()); + // if (X == Y) + // X - Y -> 0 + Optional Imp = + isImpliedByDomCondition(CmpInst::ICMP_EQ, Op0, Op1, Q.CxtI, Q.DL); + if (Imp) + return Constant::getNullValue(Op0->getType()); + // Is this a negation? if (match(Op0, m_Zero())) { // 0 - X -> 0 if the sub is NUW. @@ -2480,6 +2487,13 @@ if (Op0 == Op1) return Constant::getNullValue(Op0->getType()); + // if (A == B) + // A ^ B -> 0 + Optional Imp = + isImpliedByDomCondition(CmpInst::ICMP_EQ, Op0, Op1, Q.CxtI, Q.DL); + if (Imp) + return Constant::getNullValue(Op0->getType()); + // A ^ ~A = ~A ^ A = -1 if (match(Op0, m_Not(m_Specific(Op1))) || match(Op1, m_Not(m_Specific(Op0)))) return Constant::getAllOnesValue(Op0->getType()); Index: llvm/test/Transforms/InstSimplify/domcondition.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstSimplify/domcondition.ll @@ -0,0 +1,75 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instsimplify -S | FileCheck %s + +define i32 @xor_domcondition(i32 %x, i32 %y) { +; CHECK-LABEL: @xor_domcondition( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.true: +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: ret i32 0 +; +entry: + %cmp = icmp eq i32 %x, %y + br i1 %cmp, label %cond.true, label %cond.end + +cond.true: + %xor = xor i32 %x, %y + %mul = mul i32 %xor, %x + br label %cond.end + +cond.end: + %cond = phi i32 [ %mul, %cond.true ], [ 0, %entry ] + ret i32 %cond +} + +define i32 @xor_domcondition_negative(i32 %x, i32 %y) { +; CHECK-LABEL: @xor_domcondition_negative( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.true: +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: ret i32 0 +; +entry: + %cmp = icmp ne i32 %x, %y + br i1 %cmp, label %cond.true, label %cond.end + +cond.true: + %xor = xor i32 %x, %y + %mul = mul i32 %xor, %x + br label %cond.end + +cond.end: + %cond = phi i32 [ %mul, %cond.true ], [ 0, %entry ] + ret i32 %cond +} + + +define i32 @sub_domcondition(i32 %x, i32 %y) { +; CHECK-LABEL: @sub_domcondition( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.true: +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: ret i32 0 +; +entry: + %cmp = icmp eq i32 %x, %y + br i1 %cmp, label %cond.true, label %cond.end + +cond.true: + %xor = xor i32 %x, %y + %mul = mul i32 %xor, %x + br label %cond.end + +cond.end: + %cond = phi i32 [ %mul, %cond.true ], [ 0, %entry ] + ret i32 %cond +}