Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -916,6 +916,37 @@ return false; } +bool checkIfValIsNegative(Value *Val, Value *&NegOfVal, + InstCombiner::BuilderTy *Builder) { + Value *X = nullptr, *Y = nullptr, *Z = nullptr; + ConstantInt *C1 = nullptr, *C2 = nullptr; + + // XOR(OR(Z, NOT(C)), C)) == NOT(AND(Z, C)) + // ADD(NOT(Z & C), 1)) == NEG(AND(Z, C)) + if (match(Val, m_Add(m_Value(X), m_One())) && + match(X, m_Xor(m_Value(Y), m_ConstantInt(C1))) && + match(Y, m_Or(m_Value(Z), m_ConstantInt(C2))) && + C1->getValue() == ~C2->getValue()) { + NegOfVal = Builder->CreateAnd(Z, C1); + return true; + } + + // XOR(AND(Z, ~C), (~C + 1)) == NEG(OR(Z, C)) if C is odd + if (match(Val, m_Xor(m_Value(Y), m_ConstantInt(C1))) && + match(Y, m_And(m_Value(Z), m_ConstantInt(C2))) && + C1->getValue() == C2->getValue() + 1 && + !C1->getValue().countTrailingZeros()) { + NegOfVal = Builder->CreateOr(Z, ConstantExpr::getNot(C2)); + return true; + } + + // TODO: Check for other patterns [visitXorInst's DeMorgan's Law conversion] + // ADD(XOR(AND(Z, ~C), ~C) + 1)== NEG(OR(Z, C)) if C is even + + NegOfVal = nullptr; + return false; +} + Instruction *InstCombiner::visitAdd(BinaryOperator &I) { bool Changed = SimplifyAssociativeOrCommutative(I); Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); @@ -1022,6 +1053,12 @@ if (Value *V = dyn_castNegVal(RHS)) return BinaryOperator::CreateSub(LHS, V); + Value *NegVal = nullptr; + if (LHS->hasOneUse() && checkIfValIsNegative(LHS, NegVal, Builder)) + return BinaryOperator::CreateSub(RHS, NegVal); + + if (RHS->hasOneUse() && checkIfValIsNegative(RHS, NegVal, Builder)) + return BinaryOperator::CreateSub(LHS, NegVal); { Constant *C2; Index: test/Transforms/InstCombine/add2.ll =================================================================== --- test/Transforms/InstCombine/add2.ll +++ test/Transforms/InstCombine/add2.ll @@ -76,3 +76,54 @@ ; CHECK-NEXT: %add = sub <2 x i64> , %A ; CHECK-NEXT: ret <2 x i64> %add } + +define i32 @test9(i32 %x) { + %and = and i32 %x, 1431655765 + %neg = xor i32 %and, -1 + %add = add nsw i32 %neg, 1 + %add1 = add nsw i32 %x, %add + ret i32 %add1 +; CHECK-LABEL: @test9( +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %x, -1431655766 +; CHECK-NEXT: ret i32 [[AND]] +} + +define i32 @test10(i32 %x) { + %shr = ashr i32 %x, 3 + %and = and i32 %shr, 1431655765 + %neg = xor i32 %and, -1 + %add = add nsw i32 %neg, 1 + %add1 = add nsw i32 %x, %add + ret i32 %add1 +; CHECK-LABEL: @test10( +; CHECK-NEXT: [[SHR:%[a-z0-9]+]] = ashr i32 %x, 3 +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 [[SHR]], 1431655765 +; CHECK-NEXT: [[SUB:%[a-z0-9]+]] = sub i32 %x, %0 +; CHECK-NEXT: ret i32 [[SUB]] +} + +define i32 @test11(i32 %x) { + %or = or i32 %x, 1431655765 + %neg = xor i32 %or, -1 + %add = add nsw i32 %neg, 1 + %add1 = add nsw i32 %x, %add + ret i32 %add1 +; CHECK-LABEL: @test11( +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, 1431655765 +; CHECK-NEXT: [[SUB:%[a-z0-9]+]] = sub i32 %x, %0 +; CHECK-NEXT: ret i32 [[SUB]] +} + +define i32 @test12(i32 %x) { + %shr = ashr i32 %x, 3 + %or = or i32 %shr, 1431655765 + %neg = xor i32 %or, -1 + %add = add nsw i32 %neg, 1 + %add1 = add nsw i32 %x, %add + ret i32 %add1 +; CHECK-LABEL: @test12( +; CHECK-NEXT: [[SHR:%[a-z0-9]+]] = ashr i32 %x, 3 +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = or i32 [[SHR]], 1431655765 +; CHECK-NEXT: [[SUB:%[a-z0-9]+]] = sub i32 %x, %0 +; CHECK-NEXT: ret i32 [[SUB]] +}