forked from OSchip/llvm-project
[InstCombine] fold sdiv with hidden common factor
(X * Y) s/ (X << Z) --> Y s/ (1 << Z) https://alive2.llvm.org/ce/z/yRSddG issue #58137
This commit is contained in:
parent
241893f99f
commit
8da2fa856f
|
@ -970,12 +970,17 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
|
|||
auto *OBO0 = cast<OverflowingBinaryOperator>(Op0);
|
||||
auto *OBO1 = cast<OverflowingBinaryOperator>(Op1);
|
||||
bool HasNUW = OBO0->hasNoUnsignedWrap() && OBO1->hasNoUnsignedWrap();
|
||||
bool HasNSW = OBO0->hasNoSignedWrap() && OBO1->hasNoSignedWrap();
|
||||
|
||||
// (X * Y) u/ (X << Z) --> Y u>> Z
|
||||
if (!IsSigned && HasNUW)
|
||||
return BinaryOperator::CreateLShr(Y, Z);
|
||||
|
||||
// TODO: Handle signed division.
|
||||
// (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
|
||||
if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
|
||||
Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
|
||||
return BinaryOperator::CreateSDiv(Y, Shl);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -295,11 +295,12 @@ define <2 x i32> @t16(<2 x i32> %x, <2 x i32> %y) {
|
|||
ret <2 x i32> %r
|
||||
}
|
||||
|
||||
; (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
|
||||
|
||||
define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_nsw(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[M2:%.*]] = shl nsw i5 [[X]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: ret i5 [[D]]
|
||||
;
|
||||
%m1 = mul nsw i5 %x, %y
|
||||
|
@ -308,11 +309,12 @@ define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) {
|
|||
ret i5 %d
|
||||
}
|
||||
|
||||
; (Y * Z) s/ (X << Z) --> Y s/ (1 << Z)
|
||||
|
||||
define i5 @sdiv_mul_shl_nsw_commute1(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_nsw_commute1(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[Y:%.*]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[M2:%.*]] = shl nsw i5 [[X]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: ret i5 [[D]]
|
||||
;
|
||||
%m1 = mul nsw i5 %y, %x
|
||||
|
@ -321,6 +323,8 @@ define i5 @sdiv_mul_shl_nsw_commute1(i5 %x, i5 %y, i5 %z) {
|
|||
ret i5 %d
|
||||
}
|
||||
|
||||
; negative test - shl is not commutative
|
||||
|
||||
define i5 @sdiv_mul_shl_nsw_commute2(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_nsw_commute2(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[Y:%.*]], [[X:%.*]]
|
||||
|
@ -334,12 +338,14 @@ define i5 @sdiv_mul_shl_nsw_commute2(i5 %x, i5 %y, i5 %z) {
|
|||
ret i5 %d
|
||||
}
|
||||
|
||||
; extra use is ok
|
||||
|
||||
define i8 @sdiv_mul_shl_nsw_use1(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_nsw_use1(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: call void @use(i8 [[M1]])
|
||||
; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[M1]], [[M2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i8 1, [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[Y]], [[TMP1]]
|
||||
; CHECK-NEXT: ret i8 [[D]]
|
||||
;
|
||||
%m1 = mul nsw i8 %x, %y
|
||||
|
@ -349,12 +355,14 @@ define i8 @sdiv_mul_shl_nsw_use1(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %d
|
||||
}
|
||||
|
||||
; extra use is ok
|
||||
|
||||
define i8 @sdiv_mul_shl_nsw_use2(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_nsw_use2(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: call void @use(i8 [[M2]])
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[M1]], [[M2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i8 1, [[Z]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[Y:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: ret i8 [[D]]
|
||||
;
|
||||
%m1 = mul nsw i8 %x, %y
|
||||
|
@ -364,6 +372,8 @@ define i8 @sdiv_mul_shl_nsw_use2(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %d
|
||||
}
|
||||
|
||||
; negative test - both operands can't have extra uses
|
||||
|
||||
define i8 @sdiv_mul_shl_nsw_use3(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_nsw_use3(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]]
|
||||
|
@ -381,6 +391,8 @@ define i8 @sdiv_mul_shl_nsw_use3(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %d
|
||||
}
|
||||
|
||||
; negative test - shl must be divisor
|
||||
|
||||
define i5 @sdiv_shl_mul_nsw(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @sdiv_shl_mul_nsw(
|
||||
; CHECK-NEXT: [[M1:%.*]] = shl nsw i5 [[Z:%.*]], [[X:%.*]]
|
||||
|
@ -394,6 +406,8 @@ define i5 @sdiv_shl_mul_nsw(i5 %x, i5 %y, i5 %z) {
|
|||
ret i5 %d
|
||||
}
|
||||
|
||||
; negative test - wrong no-wrap
|
||||
|
||||
define i5 @sdiv_mul_shl_missing_nsw1(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_missing_nsw1(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]]
|
||||
|
@ -407,6 +421,8 @@ define i5 @sdiv_mul_shl_missing_nsw1(i5 %x, i5 %y, i5 %z) {
|
|||
ret i5 %d
|
||||
}
|
||||
|
||||
; negative test - wrong no-wrap
|
||||
|
||||
define i5 @sdiv_mul_shl_missing_nsw2(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_missing_nsw2(
|
||||
; CHECK-NEXT: [[M1:%.*]] = mul nuw i5 [[X:%.*]], [[Y:%.*]]
|
||||
|
|
|
@ -39,11 +39,7 @@ define i32 @not_reassociate_or_or_not(i32 %a, i32 %b, i32 %c, i32 %d) {
|
|||
|
||||
define i32 @PR58137(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: @PR58137(
|
||||
; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[A:%.*]], 1
|
||||
; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[MUL]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[MUL2:%.*]] = shl nsw i32 [[A]], 1
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[MUL1]], [[MUL2]]
|
||||
; CHECK-NEXT: ret i32 [[DIV]]
|
||||
; CHECK-NEXT: ret i32 [[B:%.*]]
|
||||
;
|
||||
%mul = mul nsw i32 2, %b
|
||||
%mul1 = mul nsw i32 %mul, %a
|
||||
|
|
Loading…
Reference in New Issue