forked from OSchip/llvm-project
[InstCombine] propagate "exact" through folds of div
These folds were added recently with:6b869be810
8da2fa856f
...but they didn't account for the "exact" attribute, and that can be safely propagated: https://alive2.llvm.org/ce/z/F_WhnR https://alive2.llvm.org/ce/z/ft9Cgr
This commit is contained in:
parent
2639caf560
commit
fe97f95036
|
@ -827,28 +827,34 @@ static Instruction *foldIDivShl(BinaryOperator &I,
|
|||
Type *Ty = I.getType();
|
||||
|
||||
// With appropriate no-wrap constraints, remove a common factor in the
|
||||
// dividend and divisor that is disguised as a left-shift.
|
||||
// dividend and divisor that is disguised as a left-shifted value.
|
||||
Value *X, *Y, *Z;
|
||||
if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
|
||||
match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
|
||||
// Both operands must have the matching no-wrap for this kind of division.
|
||||
auto *Mul = cast<OverflowingBinaryOperator>(Op0);
|
||||
auto *Shl = cast<OverflowingBinaryOperator>(Op1);
|
||||
bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
|
||||
bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
|
||||
if (!match(Op1, m_Shl(m_Value(X), m_Value(Z))) ||
|
||||
!match(Op0, m_c_Mul(m_Specific(X), m_Value(Y))))
|
||||
return nullptr;
|
||||
|
||||
// (X * Y) u/ (X << Z) --> Y u>> Z
|
||||
if (!IsSigned && HasNUW)
|
||||
return BinaryOperator::CreateLShr(Y, Z);
|
||||
// Both operands must have the matching no-wrap for this kind of division.
|
||||
Instruction *Ret = nullptr;
|
||||
auto *Mul = cast<OverflowingBinaryOperator>(Op0);
|
||||
auto *Shl = cast<OverflowingBinaryOperator>(Op1);
|
||||
bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
|
||||
bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
|
||||
|
||||
// (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);
|
||||
}
|
||||
// (X * Y) u/ (X << Z) --> Y u>> Z
|
||||
if (!IsSigned && HasNUW)
|
||||
Ret = BinaryOperator::CreateLShr(Y, Z);
|
||||
|
||||
// (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);
|
||||
Ret = BinaryOperator::CreateSDiv(Y, Shl);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
if (!Ret)
|
||||
return nullptr;
|
||||
|
||||
Ret->setIsExact(I.isExact());
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/// This function implements the transforms common to both integer division
|
||||
|
|
|
@ -314,7 +314,7 @@ define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) {
|
|||
define i5 @sdiv_mul_shl_nsw_exact_commute1(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @sdiv_mul_shl_nsw_exact_commute1(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv exact i5 [[Y:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: ret i5 [[D]]
|
||||
;
|
||||
%m1 = mul nsw i5 %y, %x
|
||||
|
@ -453,7 +453,7 @@ define i5 @udiv_mul_shl_nuw(i5 %x, i5 %y, i5 %z) {
|
|||
|
||||
define i5 @udiv_mul_shl_nuw_exact_commute1(i5 %x, i5 %y, i5 %z) {
|
||||
; CHECK-LABEL: @udiv_mul_shl_nuw_exact_commute1(
|
||||
; CHECK-NEXT: [[D:%.*]] = lshr i5 [[Y:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[D:%.*]] = lshr exact i5 [[Y:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: ret i5 [[D]]
|
||||
;
|
||||
%m1 = mul nuw i5 %y, %x
|
||||
|
|
Loading…
Reference in New Issue