Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1528,8 +1528,13 @@ 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); + // (X | Y) - Y --> (X | Y) ^ Y + // (Y | X) - Y --> (Y | X) ^ Y + if (match(Op0, m_c_Or(m_Specific(Op1), m_Value()))) + return BinaryOperator::CreateXor(Op0, 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); Index: llvm/test/Transforms/InstCombine/sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/sub.ll +++ llvm/test/Transforms/InstCombine/sub.ll @@ -1267,6 +1267,51 @@ ret <2 x i32> %res } +define i32 @test70(i32 %A) { +; CHECK-LABEL: @test70( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -124 +; CHECK-NEXT: ret i32 [[TMP1]] +; + %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: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[D:%.*]] = and i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: ret i32 [[D]] +; + %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: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[D:%.*]] = and i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: ret i32 [[D]] +; + %C = or i32 %B, %A + %D = sub i32 %C, %B + ret i32 %D +} + +define i32 @test73(i32 %A, i32 %B) { +; CHECK-LABEL: @test73( +; CHECK-NEXT: [[C:%.*]] = or i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[D:%.*]] = xor i32 [[C]], [[B]] +; CHECK-NEXT: [[E:%.*]] = mul i32 [[C]], [[D]] +; CHECK-NEXT: ret i32 [[E]] +; + %C = or i32 %A, %B + %D = sub i32 %C, %B + %E = mul i32 %C, %D + ret i32 %E +} + define i32 @nsw_inference1(i32 %x, i32 %y) { ; CHECK-LABEL: @nsw_inference1( ; CHECK-NEXT: [[X2:%.*]] = or i32 [[X:%.*]], 1024