Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2389,28 +2389,23 @@ return BinaryOperator::CreateAdd(V, NewC); } } + + // (X|C1)^C2 -> X^(C1^C2) iff X&~C1 == 0 + if (match(Op0, m_Or(m_Value(V), m_APInt(C))) && + MaskedValueIsZero(V, *C, 0, &I)) { + Constant *NewC = ConstantInt::get(I.getType(), *C ^ *RHSC); + Worklist.Add(cast(Op0)); + I.setOperand(0, V); + I.setOperand(1, NewC); + return &I; + } } } if (ConstantInt *RHSC = dyn_cast(Op1)) { if (BinaryOperator *Op0I = dyn_cast(Op0)) { if (ConstantInt *Op0CI = dyn_cast(Op0I->getOperand(1))) { - if (Op0I->getOpcode() == Instruction::Or) { - // (X|C1)^C2 -> X^(C1|C2) iff X&~C1 == 0 - if (MaskedValueIsZero(Op0I->getOperand(0), Op0CI->getValue(), - 0, &I)) { - Constant *NewRHS = ConstantExpr::getOr(Op0CI, RHSC); - // Anything in both C1 and C2 is known to be zero, remove it from - // NewRHS. - Constant *CommonBits = ConstantExpr::getAnd(Op0CI, RHSC); - NewRHS = ConstantExpr::getAnd(NewRHS, - ConstantExpr::getNot(CommonBits)); - Worklist.Add(Op0I); - I.setOperand(0, Op0I->getOperand(0)); - I.setOperand(1, NewRHS); - return &I; - } - } else if (Op0I->getOpcode() == Instruction::LShr) { + if (Op0I->getOpcode() == Instruction::LShr) { // ((X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3) // E1 = "X ^ C1" BinaryOperator *E1; Index: test/Transforms/InstCombine/or.ll =================================================================== --- test/Transforms/InstCombine/or.ll +++ test/Transforms/InstCombine/or.ll @@ -143,6 +143,19 @@ ret i16 %D } +define <2 x i16> @test23vec(<2 x i16> %A) { +; CHECK-LABEL: @test23vec( +; CHECK-NEXT: [[B:%.*]] = lshr <2 x i16> [[A:%.*]], +; CHECK-NEXT: [[D:%.*]] = xor <2 x i16> [[B]], +; CHECK-NEXT: ret <2 x i16> [[D]] +; + %B = lshr <2 x i16> %A, + ;; fold or into xor + %C = or <2 x i16> %B, + %D = xor <2 x i16> %C, + ret <2 x i16> %D +} + ; PR1738 define i1 @test24(double %X, double %Y) { ; CHECK-LABEL: @test24( Index: test/Transforms/InstCombine/select-with-bitwise-ops.ll =================================================================== --- test/Transforms/InstCombine/select-with-bitwise-ops.ll +++ test/Transforms/InstCombine/select-with-bitwise-ops.ll @@ -273,9 +273,8 @@ ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[X:%.*]], ; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32> ; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP2]], -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[TMP3]], -; CHECK-NEXT: [[TMP5:%.*]] = xor <2 x i32> [[TMP4]], -; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], +; CHECK-NEXT: ret <2 x i32> [[TMP4]] ; %1 = and <2 x i64> %x, %2 = icmp ne <2 x i64> %1, zeroinitializer @@ -302,9 +301,8 @@ ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[X:%.*]], ; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32> ; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP2]], -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[TMP3]], -; CHECK-NEXT: [[TMP5:%.*]] = xor <2 x i32> [[TMP4]], -; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], +; CHECK-NEXT: ret <2 x i32> [[TMP4]] ; %1 = and <2 x i64> %x, %2 = icmp ne <2 x i64> %1, zeroinitializer @@ -344,10 +342,9 @@ ; CHECK-LABEL: @test67vec( ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i16> [[X:%.*]], ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i16> [[TMP1]], -; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i16> [[TMP2]], -; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i16> [[TMP3]], -; CHECK-NEXT: [[TMP5:%.*]] = zext <2 x i16> [[TMP4]] to <2 x i32> -; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; CHECK-NEXT: [[TMP3:%.*]] = xor <2 x i16> [[TMP2]], +; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i16> [[TMP3]] to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP4]] ; %1 = and <2 x i16> %x, %2 = icmp ne <2 x i16> %1, zeroinitializer