Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1528,8 +1528,14 @@ if (Value *V = SimplifyUsingDistributiveLaws(I)) return replaceInstUsesWith(I, V); - // If this is a 'B = x-(-A)', change to B = x+A. Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + Value *X; + // (X | Y) - Y --> (X | Y) ^ Y + // (Y | X) - Y --> (Y | X) ^ Y + if (match(Op0, m_OneUse(m_c_Or(m_Value(X), m_Specific(Op1))))) + return BinaryOperator::CreateXor(Builder.CreateOr(X, Op1), Op1); + + // If this is a 'B = x-(-A)', change to B = x+A. if (Value *V = dyn_castNegVal(Op1)) { BinaryOperator *Res = BinaryOperator::CreateAdd(Op0, V); @@ -1554,7 +1560,7 @@ return BinaryOperator::CreateNot(Op1); // (~X) - (~Y) --> Y - X - Value *X, *Y; + Value *Y; if (match(Op0, m_Not(m_Value(X))) && match(Op1, m_Not(m_Value(Y)))) return BinaryOperator::CreateSub(Y, X); Index: llvm/test/Transforms/InstCombine/sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/sub.ll +++ llvm/test/Transforms/InstCombine/sub.ll @@ -1267,6 +1267,38 @@ ret <2 x i32> %res } +define i32 @test70(i32 %A) { +; CHECK-LABEL: @test70( +; CHECK-NEXT: [[A:%.*]] = and i32 [[TMP1:%.*]], -124 +; CHECK-NEXT: ret i32 [[A]] +; + %B = or i32 %A, 123 + %C = sub i32 %B, 123 + ret i32 %C +} + +define i32 @test71(i32 %A, i32 %B) { +; CHECK-LABEL: @test71( +; CHECK-NEXT: [[A:%.*]] = xor i32 [[TMP1:%.*]], -1 +; CHECK-NEXT: [[B:%.*]] = and i32 [[A]], [[TMP2:%.*]] +; CHECK-NEXT: ret i32 [[B]] +; + %C = or i32 %A, %B + %D = sub i32 %C, %B + ret i32 %D +} + +define i32 @test72(i32 %A, i32 %B) { +; CHECK-LABEL: @test72( +; CHECK-NEXT: [[A:%.*]] = xor i32 [[TMP1:%.*]], -1 +; CHECK-NEXT: [[B:%.*]] = and i32 [[A]], [[TMP2:%.*]] +; CHECK-NEXT: ret i32 [[B]] +; + %C = or i32 %B, %A + %D = sub i32 %C, %B + ret i32 %D +} + define i32 @nsw_inference1(i32 %x, i32 %y) { ; CHECK-LABEL: @nsw_inference1( ; CHECK-NEXT: [[X2:%.*]] = or i32 [[X:%.*]], 1024