[SCEV] Improve modelling for (null) pointer constants
This is a continuation of D89456.
As it was suggested there, now that SCEV models `PtrToInt`,
we can try to improve SCEV's pointer handling.
In particular, i believe, i will need this in the future
to further fix `SCEVAddExpr`operation type handling.
This removes special handling of `ConstantPointerNull`
from `ScalarEvolution::createSCEV()`, and add constant folding
into `ScalarEvolution::getPtrToIntExpr()`.
This way, `null` constants stay as such in SCEV's,
but gracefully become zero integers when asked.
Reviewed By: Meinersbur
Differential Revision: https://reviews.llvm.org/D98147
GitOrigin-RevId: 61f006ac655431bd44b9e089f74c73bec0c1a48c
diff --git a/lib/Analysis/ScopBuilder.cpp b/lib/Analysis/ScopBuilder.cpp
index 4def171..e12261c 100644
--- a/lib/Analysis/ScopBuilder.cpp
+++ b/lib/Analysis/ScopBuilder.cpp
@@ -1761,6 +1761,11 @@
if (DestAccFunc->isZero())
return true;
+ if (auto *U = dyn_cast<SCEVUnknown>(DestAccFunc)) {
+ if (isa<ConstantPointerNull>(U->getValue()))
+ return true;
+ }
+
auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(SE.getPointerBase(DestAccFunc));
assert(DestPtrSCEV);
DestAccFunc = SE.getMinusSCEV(DestAccFunc, DestPtrSCEV);
@@ -1837,6 +1842,11 @@
if (ArgSCEV->isZero())
continue;
+ if (auto *U = dyn_cast<SCEVUnknown>(ArgSCEV)) {
+ if (isa<ConstantPointerNull>(U->getValue()))
+ return true;
+ }
+
auto *ArgBasePtr = cast<SCEVUnknown>(SE.getPointerBase(ArgSCEV));
addArrayAccess(Stmt, Inst, AccType, ArgBasePtr->getValue(),
ArgBasePtr->getType(), false, {AF}, {nullptr}, CI);
diff --git a/lib/Support/SCEVAffinator.cpp b/lib/Support/SCEVAffinator.cpp
index 9d2e7d9..1691b2a 100644
--- a/lib/Support/SCEVAffinator.cpp
+++ b/lib/Support/SCEVAffinator.cpp
@@ -551,8 +551,15 @@
}
}
- llvm_unreachable(
- "Unknowns SCEV was neither parameter nor a valid instruction.");
+ if (isa<ConstantPointerNull>(Expr->getValue())) {
+ isl::val v{Ctx, 0};
+ isl::space Space{Ctx, 0, NumIterators};
+ isl::local_space ls{Space};
+ return getPWACtxFromPWA(isl::aff(ls, v));
+ }
+
+ llvm_unreachable("Unknowns SCEV was neither a parameter, a constant nor a "
+ "valid instruction.");
}
PWACtx SCEVAffinator::complexityBailout() {
diff --git a/lib/Support/SCEVValidator.cpp b/lib/Support/SCEVValidator.cpp
index 94b5516..0e0ec73 100644
--- a/lib/Support/SCEVValidator.cpp
+++ b/lib/Support/SCEVValidator.cpp
@@ -461,6 +461,11 @@
}
}
+ if (Expr->getType()->isPointerTy()) {
+ if (isa<ConstantPointerNull>(V))
+ return ValidatorResult(SCEVType::INT); // "int"
+ }
+
return ValidatorResult(SCEVType::PARAM, Expr);
}
};
diff --git a/test/Isl/CodeGen/partial_write_impossible_restriction.ll b/test/Isl/CodeGen/partial_write_impossible_restriction.ll
index e4c2ce2..3b17518 100644
--- a/test/Isl/CodeGen/partial_write_impossible_restriction.ll
+++ b/test/Isl/CodeGen/partial_write_impossible_restriction.ll
@@ -7,7 +7,7 @@
;
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
-define void @partial_write_impossible_restriction() {
+define void @partial_write_impossible_restriction(i32* %.pn) {
entry:
br i1 undef, label %invoke.cont258, label %cond.true.i.i.i.i1007
@@ -15,7 +15,6 @@
br label %invoke.cont258
invoke.cont258:
- %.pn = phi i32* [ null, %cond.true.i.i.i.i1007 ], [ null, %entry ]
br label %invoke.cont274
invoke.cont274: ; preds = %invoke.cont258
@@ -49,11 +48,11 @@
; CHECK-LABEL: polly.stmt.cond.false:
-; CHECK: %polly.access..pn2 = getelementptr i32, i32* %.pn, i64 %polly.indvar
-; CHECK: store i32 %cond.in.sroa.speculate.load.cond.false_p_scalar_, i32* %polly.access..pn2, align 4, !alias.scope !0, !noalias !2
+; CHECK: %polly.access..pn{{[0-9]*}} = getelementptr i32, i32* %.pn, i64 %polly.indvar
+; CHECK: store i32 %cond.in.sroa.speculate.load.cond.false_p_scalar_, i32* %polly.access..pn{{[0-9]*}}, align 4, !alias.scope !0, !noalias !2
; CHECK: br label %polly.merge
-; CHECK-LABEL: polly.stmt.cond.false11:
-; CHECK: %polly.access..pn14 = getelementptr i32, i32* %.pn, i64 0
-; CHECK: store i32 %cond.in.sroa.speculate.load.cond.false_p_scalar_13, i32* %polly.access..pn14, align 4, !alias.scope !0, !noalias !2
-; CHECK: br label %polly.stmt.cond.end15
+; CHECK-LABEL: polly.stmt.cond.false{{[0-9]*}}:
+; CHECK: %polly.access..pn{{[0-9]*}} = getelementptr i32, i32* %.pn, i64 0
+; CHECK: store i32 %cond.in.sroa.speculate.load.cond.false_p_scalar_{{[0-9]*}}, i32* %polly.access..pn{{[0-9]*}}, align 4, !alias.scope !0, !noalias !2
+; CHECK: br label %polly.stmt.cond.end{{[0-9]*}}
diff --git a/test/Isl/CodeGen/scev_looking_through_bitcasts.ll b/test/Isl/CodeGen/scev_looking_through_bitcasts.ll
index 1012e23..3521f00 100644
--- a/test/Isl/CodeGen/scev_looking_through_bitcasts.ll
+++ b/test/Isl/CodeGen/scev_looking_through_bitcasts.ll
@@ -31,7 +31,9 @@
}
-; CHECK: polly.stmt.cond.end73.i:
-; CHECK-NEXT: %0 = bitcast %structty** %b.s2a to i8**
-; CHECK-NEXT: store i8* undef, i8** %0
+
+; CHECK: polly.stmt.cond.end73.i:
+; CHECK-NEXT: %scevgep = getelementptr i8, i8* null, i64 %a
+; CHECK-NEXT: %scevgep1 = bitcast i8* %scevgep to %structty*
+; CHECK-NEXT: store %structty* %scevgep1, %structty** %b.s2a, align 8
; CHECK-NEXT: br label %polly.exiting