Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -916,6 +916,33 @@ return false; } +// Checks for NOT and NEG patterns +Value *checkIfValIsNegative(Value *Val, InstCombiner::BuilderTy *Builder) { + Value *X = nullptr, *Y = nullptr, *Z = nullptr; + ConstantInt *C1 = nullptr, *C2 = nullptr; + + // ADd(XOR(OR(Z, NOT(C)), 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()) { + return Builder->CreateAnd(Z, C1); + } + + // 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()) { + return Builder->CreateOr(Z, ConstantExpr::getNot(C2)); + } + + // 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 + + return nullptr; +} + Instruction *InstCombiner::visitAdd(BinaryOperator &I) { bool Changed = SimplifyAssociativeOrCommutative(I); Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); @@ -1022,6 +1049,11 @@ if (Value *V = dyn_castNegVal(RHS)) return BinaryOperator::CreateSub(LHS, V); + if (Value *NegVal = checkIfValIsNegative(LHS, Builder)) + return BinaryOperator::CreateSub(RHS, NegVal); + + if (Value *NegVal = checkIfValIsNegative(RHS, 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, [[AND]] +; 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, [[AND]] +; 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, [[AND]] +; CHECK-NEXT: ret i32 [[SUB]] +}