[SCEVExp] Keep NUW/NSW if both original inc and isomporphic inc agree. (#79512)
We are replacing with a wider increment. If both OrigInc and IsomorphicInc are NUW/NSW, then we can preserve them on the wider increment; the narrower IsomorphicInc would wrap before the wider OrigInc, so the replacement won't make IsomorphicInc's uses more poisonous. PR: https://github.com/llvm/llvm-project/pull/79512
This commit is contained in:
@@ -1604,11 +1604,36 @@ void SCEVExpander::replaceCongruentIVInc(
|
||||
const SCEV *TruncExpr =
|
||||
SE.getTruncateOrNoop(SE.getSCEV(OrigInc), IsomorphicInc->getType());
|
||||
if (OrigInc == IsomorphicInc || TruncExpr != SE.getSCEV(IsomorphicInc) ||
|
||||
!SE.LI.replacementPreservesLCSSAForm(IsomorphicInc, OrigInc) ||
|
||||
!hoistIVInc(OrigInc, IsomorphicInc,
|
||||
!SE.LI.replacementPreservesLCSSAForm(IsomorphicInc, OrigInc))
|
||||
return;
|
||||
|
||||
bool BothHaveNUW = false;
|
||||
bool BothHaveNSW = false;
|
||||
auto *OBOIncV = dyn_cast<OverflowingBinaryOperator>(OrigInc);
|
||||
auto *OBOIsomorphic = dyn_cast<OverflowingBinaryOperator>(IsomorphicInc);
|
||||
if (OBOIncV && OBOIsomorphic) {
|
||||
BothHaveNUW =
|
||||
OBOIncV->hasNoUnsignedWrap() && OBOIsomorphic->hasNoUnsignedWrap();
|
||||
BothHaveNSW =
|
||||
OBOIncV->hasNoSignedWrap() && OBOIsomorphic->hasNoSignedWrap();
|
||||
}
|
||||
|
||||
if (!hoistIVInc(OrigInc, IsomorphicInc,
|
||||
/*RecomputePoisonFlags*/ true))
|
||||
return;
|
||||
|
||||
// We are replacing with a wider increment. If both OrigInc and IsomorphicInc
|
||||
// are NUW/NSW, then we can preserve them on the wider increment; the narrower
|
||||
// IsomorphicInc would wrap before the wider OrigInc, so the replacement won't
|
||||
// make IsomorphicInc's uses more poisonous.
|
||||
assert(OrigInc->getType()->getScalarSizeInBits() >=
|
||||
IsomorphicInc->getType()->getScalarSizeInBits() &&
|
||||
"Should only replace an increment with a wider one.");
|
||||
if (BothHaveNUW || BothHaveNSW) {
|
||||
OrigInc->setHasNoUnsignedWrap(OBOIncV->hasNoUnsignedWrap() || BothHaveNUW);
|
||||
OrigInc->setHasNoSignedWrap(OBOIncV->hasNoSignedWrap() || BothHaveNSW);
|
||||
}
|
||||
|
||||
SCEV_DEBUG_WITH_TYPE(DebugType,
|
||||
dbgs() << "INDVARS: Eliminated congruent iv.inc: "
|
||||
<< *IsomorphicInc << '\n');
|
||||
|
||||
@@ -64,7 +64,7 @@ define i2 @iv_hoist_both_adds_nsw(i2 %arg) {
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV_0:%.*]] = phi i2 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i2 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw nsw i2 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i2 1, [[ARG:%.*]]
|
||||
; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
; CHECK: exit:
|
||||
@@ -92,7 +92,7 @@ define i4 @iv_hoist_both_adds_nsw_extra_use(i4 %arg) {
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw nsw i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 1, [[ARG:%.*]]
|
||||
@@ -124,7 +124,7 @@ define i4 @iv_hoist_both_adds_nsw_extra_use_incs_reordered(i4 %arg) {
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw nsw i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 1, [[ARG:%.*]]
|
||||
@@ -244,7 +244,7 @@ define i2 @iv_hoist_both_adds_nuw(i2 %arg, i2 %start) {
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV_0:%.*]] = phi i2 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add i2 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i2 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i2 [[START]], [[ARG:%.*]]
|
||||
; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
; CHECK: exit:
|
||||
@@ -272,7 +272,7 @@ define i4 @iv_hoist_both_adds_nuw_extra_use(i4 %arg, i4 %start) {
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[ARG:%.*]]
|
||||
@@ -304,7 +304,7 @@ define i4 @iv_hoist_both_adds_nuw_extra_use_incs_reordered(i4 %arg, i4 %start) {
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]])
|
||||
; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[ARG:%.*]]
|
||||
|
||||
Reference in New Issue
Block a user