Skip to content

Commit fe97f95

Browse files
committed
[InstCombine] propagate "exact" through folds of div
These folds were added recently with: 6b869be 8da2fa8 ...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
1 parent 2639caf commit fe97f95

File tree

2 files changed

+27
-21
lines changed

2 files changed

+27
-21
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -827,28 +827,34 @@ static Instruction *foldIDivShl(BinaryOperator &I,
827827
Type *Ty = I.getType();
828828

829829
// With appropriate no-wrap constraints, remove a common factor in the
830-
// dividend and divisor that is disguised as a left-shift.
830+
// dividend and divisor that is disguised as a left-shifted value.
831831
Value *X, *Y, *Z;
832-
if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
833-
match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
834-
// Both operands must have the matching no-wrap for this kind of division.
835-
auto *Mul = cast<OverflowingBinaryOperator>(Op0);
836-
auto *Shl = cast<OverflowingBinaryOperator>(Op1);
837-
bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
838-
bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
839-
840-
// (X * Y) u/ (X << Z) --> Y u>> Z
841-
if (!IsSigned && HasNUW)
842-
return BinaryOperator::CreateLShr(Y, Z);
843-
844-
// (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
845-
if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
846-
Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
847-
return BinaryOperator::CreateSDiv(Y, Shl);
848-
}
832+
if (!match(Op1, m_Shl(m_Value(X), m_Value(Z))) ||
833+
!match(Op0, m_c_Mul(m_Specific(X), m_Value(Y))))
834+
return nullptr;
835+
836+
// Both operands must have the matching no-wrap for this kind of division.
837+
Instruction *Ret = nullptr;
838+
auto *Mul = cast<OverflowingBinaryOperator>(Op0);
839+
auto *Shl = cast<OverflowingBinaryOperator>(Op1);
840+
bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
841+
bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
842+
843+
// (X * Y) u/ (X << Z) --> Y u>> Z
844+
if (!IsSigned && HasNUW)
845+
Ret = BinaryOperator::CreateLShr(Y, Z);
846+
847+
// (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
848+
if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
849+
Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
850+
Ret = BinaryOperator::CreateSDiv(Y, Shl);
849851
}
850852

851-
return nullptr;
853+
if (!Ret)
854+
return nullptr;
855+
856+
Ret->setIsExact(I.isExact());
857+
return Ret;
852858
}
853859

854860
/// This function implements the transforms common to both integer division

llvm/test/Transforms/InstCombine/div-shift.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) {
314314
define i5 @sdiv_mul_shl_nsw_exact_commute1(i5 %x, i5 %y, i5 %z) {
315315
; CHECK-LABEL: @sdiv_mul_shl_nsw_exact_commute1(
316316
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]]
317-
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]]
317+
; CHECK-NEXT: [[D:%.*]] = sdiv exact i5 [[Y:%.*]], [[TMP1]]
318318
; CHECK-NEXT: ret i5 [[D]]
319319
;
320320
%m1 = mul nsw i5 %y, %x
@@ -453,7 +453,7 @@ define i5 @udiv_mul_shl_nuw(i5 %x, i5 %y, i5 %z) {
453453

454454
define i5 @udiv_mul_shl_nuw_exact_commute1(i5 %x, i5 %y, i5 %z) {
455455
; CHECK-LABEL: @udiv_mul_shl_nuw_exact_commute1(
456-
; CHECK-NEXT: [[D:%.*]] = lshr i5 [[Y:%.*]], [[Z:%.*]]
456+
; CHECK-NEXT: [[D:%.*]] = lshr exact i5 [[Y:%.*]], [[Z:%.*]]
457457
; CHECK-NEXT: ret i5 [[D]]
458458
;
459459
%m1 = mul nuw i5 %y, %x

0 commit comments

Comments
 (0)