Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1442,13 +1442,13 @@ // (A ^ B) & ((B ^ C) ^ A) -> (A ^ B) & ~C if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A)))) - if (Op1->hasOneUse() || cast(Op1)->hasOneUse()) + if (Op1->hasOneUse() || IsFreeToInvert(C, C->hasOneUse())) return BinaryOperator::CreateAnd(Op0, Builder->CreateNot(C)); // ((A ^ C) ^ B) & (B ^ A) -> (B ^ A) & ~C if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B)))) if (match(Op1, m_Xor(m_Specific(B), m_Specific(A)))) - if (Op0->hasOneUse() || cast(Op0)->hasOneUse()) + if (Op0->hasOneUse() || IsFreeToInvert(C, C->hasOneUse())) return BinaryOperator::CreateAnd(Op1, Builder->CreateNot(C)); // (A | B) & ((~A) ^ B) -> (A & B) @@ -2138,20 +2138,14 @@ } // (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C - // FIXME: The two hasOneUse calls here are the same call, maybe we were - // supposed to check Op1->operand(0)? if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A)))) - if (Op1->hasOneUse() || cast(Op1)->hasOneUse()) - return BinaryOperator::CreateOr(Op0, C); + return BinaryOperator::CreateOr(Op0, C); // ((A ^ C) ^ B) | (B ^ A) -> (B ^ A) | C - // FIXME: The two hasOneUse calls here are the same call, maybe we were - // supposed to check Op0->operand(0)? if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B)))) if (match(Op1, m_Xor(m_Specific(B), m_Specific(A)))) - if (Op0->hasOneUse() || cast(Op0)->hasOneUse()) - return BinaryOperator::CreateOr(Op1, C); + return BinaryOperator::CreateOr(Op1, C); // ((B | C) & A) | B -> B | (A & C) if (match(Op0, m_And(m_Or(m_Specific(Op1), m_Value(C)), m_Value(A)))) Index: test/Transforms/InstCombine/or-xor.ll =================================================================== --- test/Transforms/InstCombine/or-xor.ll +++ test/Transforms/InstCombine/or-xor.ll @@ -316,7 +316,7 @@ ; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 ; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] -; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR1]], [[XOR2]] +; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR1]], 33 ; CHECK-NEXT: [[RES:%.*]] = mul i8 [[OR]], [[XOR2]] ; CHECK-NEXT: ret i8 [[RES]] ; @@ -333,7 +333,7 @@ ; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 ; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] -; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR2]], [[XOR1]] +; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR1]], 33 ; CHECK-NEXT: [[RES:%.*]] = mul i8 [[OR]], [[XOR2]] ; CHECK-NEXT: ret i8 [[RES]] ; Index: test/Transforms/InstCombine/xor2.ll =================================================================== --- test/Transforms/InstCombine/xor2.ll +++ test/Transforms/InstCombine/xor2.ll @@ -330,7 +330,7 @@ ; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 ; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR1]], [[XOR2]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR1]], -34 ; CHECK-NEXT: [[RES:%.*]] = mul i8 [[AND]], [[XOR2]] ; CHECK-NEXT: ret i8 [[RES]] ; @@ -347,7 +347,7 @@ ; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 ; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR2]], [[XOR1]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR1]], -34 ; CHECK-NEXT: [[RES:%.*]] = mul i8 [[AND]], [[XOR2]] ; CHECK-NEXT: ret i8 [[RES]] ;