Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2833,6 +2833,23 @@ } } + // (A | B) | (C & D) + //Value *A, *B, *C, *D; + if (match(Op0, m_Or(m_Value(A), m_Value(B))) && + match(Op1, m_And(m_Value(C), m_Value(D)))) { + const APInt *C0, *C1; + // (A | (B & C0)) | (B & C1) -> A | (B & C1|C2) + if(match(B, m_c_And(m_Specific(C), m_APInt(C0))) && match(D, m_APInt(C1))) { + Constant *C01 = ConstantInt::get(Ty, *C0 | *C1); + return BinaryOperator::CreateOr(A, Builder.CreateAnd(C, C01)); + } + // ((B & C0) | A) | (B & C1) -> (B & C1|C2) | A + if(match(A, m_c_And(m_Specific(C), m_APInt(C0))) && match(D, m_APInt(C1))) { + Constant *C01 = ConstantInt::get(Ty, *C0 | *C1); + return BinaryOperator::CreateOr(Builder.CreateAnd(C, C01), B); + } + } + // (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)))) Index: llvm/test/Transforms/InstCombine/and-or.ll =================================================================== --- llvm/test/Transforms/InstCombine/and-or.ll +++ llvm/test/Transforms/InstCombine/and-or.ll @@ -335,3 +335,54 @@ ret i8 %extra_use_of_or } +define i64 @or_or_and(i64 %x) { +; CHECK-LABEL: @or_or_and( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[X:%.*]], 8 +; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[X]], 8 +; CHECK-NEXT: [[SHL3:%.*]] = and i64 [[TMP1]], -72057594037927936 +; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP0]], 71777214277877760 +; CHECK-NEXT: [[OR7:%.*]] = or i64 [[TMP2]], [[SHL3]] +; CHECK-NEXT: ret i64 [[OR7]] +; +entry: + %0 = lshr i64 %x, 8 + %shl = and i64 %0, 71776119061217280 + %1 = shl i64 %x, 8 + %shl3 = and i64 %1, -72057594037927936 + %or = or i64 %shl, %shl3 + %shl6 = and i64 %0, 1095216660480 + %or7 = or i64 %or, %shl6 + ret i64 %or7 +} + +define i64 @or_or_or_and_complex(i64 noundef %i) local_unnamed_addr #0 { +; CHECK-LABEL: @or_or_or_and_complex( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[I:%.*]], 8 +; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[I]], 8 +; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP0]], 71777214294589695 +; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP1]], -71777214294589696 +; CHECK-NEXT: [[OR27:%.*]] = or i64 [[TMP2]], [[TMP3]] +; CHECK-NEXT: ret i64 [[OR27]] +; +entry: + %0 = lshr i64 %i, 8 + %shl = and i64 %0, 71776119061217280 + %1 = shl i64 %i, 8 + %shl3 = and i64 %1, -72057594037927936 + %or = or i64 %shl, %shl3 + %shl6 = and i64 %0, 1095216660480 + %or7 = or i64 %or, %shl6 + %shl10 = and i64 %1, 280375465082880 + %or11 = or i64 %or7, %shl10 + %shl14 = and i64 %0, 16711680 + %or15 = or i64 %or11, %shl14 + %shl18 = and i64 %1, 4278190080 + %or19 = or i64 %or15, %shl18 + %and21 = and i64 %0, 255 + %or23 = or i64 %or19, %and21 + %shl26 = and i64 %1, 65280 + %or27 = or i64 %or23, %shl26 + ret i64 %or27 +} Index: llvm/test/Transforms/InstCombine/or.ll =================================================================== --- llvm/test/Transforms/InstCombine/or.ll +++ llvm/test/Transforms/InstCombine/or.ll @@ -371,8 +371,8 @@ ; PR4216 define i32 @test30(i32 %A) { ; CHECK-LABEL: @test30( -; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], -58312 -; CHECK-NEXT: [[E:%.*]] = or i32 [[D]], 32962 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -58312 +; CHECK-NEXT: [[E:%.*]] = or i32 [[TMP1]], 32962 ; CHECK-NEXT: ret i32 [[E]] ; %B = or i32 %A, 32962 ; 0b1000_0000_1100_0010 @@ -384,10 +384,8 @@ define <2 x i32> @test30vec(<2 x i32> %A) { ; CHECK-LABEL: @test30vec( -; CHECK-NEXT: [[C:%.*]] = and <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[A]], -; CHECK-NEXT: [[D:%.*]] = or <2 x i32> [[B]], -; CHECK-NEXT: [[E:%.*]] = or <2 x i32> [[D]], [[C]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], +; CHECK-NEXT: [[E:%.*]] = or <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i32> [[E]] ; %B = or <2 x i32> %A,