diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 553435c937a70..2fb60ef11499c 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -939,12 +939,11 @@ Instruction *InstCombinerImpl::foldBinOpShiftWithShift(BinaryOperator &I) { m_OneUse(m_Shift(m_Value(Y), m_Value(Shift))))) return nullptr; if (!match(I.getOperand(1 - ShOpnum), - m_BinOp(m_Value(ShiftedX), m_Value(Mask)))) + m_c_BinOp(m_CombineAnd( + m_OneUse(m_Shift(m_Value(X), m_Specific(Shift))), + m_Value(ShiftedX)), + m_Value(Mask)))) return nullptr; - - if (!match(ShiftedX, m_OneUse(m_Shift(m_Value(X), m_Specific(Shift))))) - return nullptr; - // Make sure we are matching instruction shifts and not ConstantExpr auto *IY = dyn_cast(I.getOperand(ShOpnum)); auto *IX = dyn_cast(ShiftedX); diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll index 5a0890e918ef0..5a58995f6c315 100644 --- a/llvm/test/Transforms/InstCombine/and-xor-or.ll +++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll @@ -388,10 +388,9 @@ define i8 @xor_shl(i8 %x, i8 %y, i8 %zarg, i8 %shamt) { ; CHECK-LABEL: define {{[^@]+}}@xor_shl ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[ZARG:%.*]], i8 [[SHAMT:%.*]]) { ; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG]] -; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X]], [[SHAMT]] -; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y]], [[SHAMT]] -; CHECK-NEXT: [[A:%.*]] = xor i8 [[Z]], [[SX]] -; CHECK-NEXT: [[R:%.*]] = xor i8 [[A]], [[SY]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], [[SHAMT]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[TMP2]], [[Z]] ; CHECK-NEXT: ret i8 [[R]] ; %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization @@ -406,10 +405,9 @@ define i8 @and_lshr(i8 %x, i8 %y, i8 %zarg, i8 %shamt) { ; CHECK-LABEL: define {{[^@]+}}@and_lshr ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[ZARG:%.*]], i8 [[SHAMT:%.*]]) { ; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG]] -; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X]], [[SHAMT]] -; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y]], [[SHAMT]] -; CHECK-NEXT: [[A:%.*]] = and i8 [[Z]], [[SX]] -; CHECK-NEXT: [[R:%.*]] = and i8 [[SY]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], [[SHAMT]] +; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], [[Z]] ; CHECK-NEXT: ret i8 [[R]] ; %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization @@ -435,6 +433,51 @@ define i8 @or_lshr(i8 %x, i8 %y, i8 %z, i8 %shamt) { ret i8 %r } +define i8 @or_lshr_commuted1(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: define {{[^@]+}}@or_lshr_commuted1 +; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[SHAMT:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], [[SHAMT]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[TMP2]], [[Z]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = lshr i8 %x, %shamt + %sy = lshr i8 %y, %shamt + %a = or i8 %z, %sx + %r = or i8 %sy, %a + ret i8 %r +} + +define i8 @or_lshr_commuted2(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: define {{[^@]+}}@or_lshr_commuted2 +; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[SHAMT:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], [[SHAMT]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[TMP2]], [[Z]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = lshr i8 %x, %shamt + %sy = lshr i8 %y, %shamt + %a = or i8 %z, %sx + %r = or i8 %a, %sy + ret i8 %r +} + +define i8 @or_lshr_commuted3(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: define {{[^@]+}}@or_lshr_commuted3 +; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[SHAMT:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], [[SHAMT]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[TMP2]], [[Z]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = lshr i8 %x, %shamt + %sy = lshr i8 %y, %shamt + %a = or i8 %sx, %z + %r = or i8 %a, %sy + ret i8 %r +} + define i8 @xor_lshr(i8 %x, i8 %y, i8 %z, i8 %shamt) { ; CHECK-LABEL: define {{[^@]+}}@xor_lshr ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[SHAMT:%.*]]) {