[libcxx-commits] [lld] [libc] [clang-tools-extra] [lldb] [libcxxabi] [clang] [flang] [llvm] [SCEVExp] Keep NUW/NSW if both original inc and isomporphic inc agree. (PR #79512)
Florian Hahn via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Feb 1 01:40:58 PST 2024
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/79512
>From 299a055e271264f918321bf7360ee37c6ede8b26 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 23 Jan 2024 13:39:38 +0000
Subject: [PATCH 1/2] [SCEVExp] Keep NUW/NSW if both original inc and
isomporphic inc agree.
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.
---
.../Utils/ScalarEvolutionExpander.cpp | 28 +++++++++++++++++--
.../Transforms/IndVarSimplify/iv-poison.ll | 12 ++++----
2 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index cf8cea937a6bf..902c4db883769 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -1607,11 +1607,35 @@ 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);
+ assert(OrigInc->getType()->getScalarSizeInBits() >=
+ IsomorphicInc->getType()->getScalarSizeInBits()) && "Should only replace an increment with a wider one.");
+ 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.
+ 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');
diff --git a/llvm/test/Transforms/IndVarSimplify/iv-poison.ll b/llvm/test/Transforms/IndVarSimplify/iv-poison.ll
index 38299e0a6b353..383599f614357 100644
--- a/llvm/test/Transforms/IndVarSimplify/iv-poison.ll
+++ b/llvm/test/Transforms/IndVarSimplify/iv-poison.ll
@@ -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:%.*]]
>From d75c570c47b1463d9c677ed9f295ed7aaae17b60 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 1 Feb 2024 09:39:56 +0000
Subject: [PATCH 2/2] !fixup remove extra ) from assert, move to comment.
---
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index e2e086b2a17b8..ed55a13072aaa 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -1611,8 +1611,6 @@ void SCEVExpander::replaceCongruentIVInc(
bool BothHaveNSW = false;
auto *OBOIncV = dyn_cast<OverflowingBinaryOperator>(OrigInc);
auto *OBOIsomorphic = dyn_cast<OverflowingBinaryOperator>(IsomorphicInc);
- assert(OrigInc->getType()->getScalarSizeInBits() >=
- IsomorphicInc->getType()->getScalarSizeInBits()) && "Should only replace an increment with a wider one.");
if (OBOIncV && OBOIsomorphic) {
BothHaveNUW =
OBOIncV->hasNoUnsignedWrap() && OBOIsomorphic->hasNoUnsignedWrap();
@@ -1628,6 +1626,9 @@ void SCEVExpander::replaceCongruentIVInc(
// 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);
More information about the libcxx-commits
mailing list