Skip to content

Commit 7f59264

Browse files
authored
[IPSCCP] Intersect attribute info for interprocedural args (#106397)
IPSCCP can currently return worse results than SCCP for arguments that are tracked interprocedurally, because information from attributes is not used for them. Fix this by intersecting in the attribute information when propagating lattice values from calls.
1 parent c7a4efa commit 7f59264

File tree

3 files changed

+41
-28
lines changed

3 files changed

+41
-28
lines changed

llvm/lib/Transforms/Utils/SCCPSolver.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -820,19 +820,21 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
820820
markOverdefined(ValueState[V], V);
821821
}
822822

823-
void trackValueOfArgument(Argument *A) {
823+
ValueLatticeElement getArgAttributeVL(Argument *A) {
824824
if (A->getType()->isIntOrIntVectorTy()) {
825-
if (std::optional<ConstantRange> Range = A->getRange()) {
826-
markConstantRange(ValueState[A], A, *Range);
827-
return;
828-
}
829-
}
830-
if (A->hasNonNullAttr()) {
831-
markNotNull(ValueState[A], A);
832-
return;
825+
if (std::optional<ConstantRange> Range = A->getRange())
826+
return ValueLatticeElement::getRange(*Range);
833827
}
828+
if (A->hasNonNullAttr())
829+
return ValueLatticeElement::getNot(Constant::getNullValue(A->getType()));
834830
// Assume nothing about the incoming arguments without attributes.
835-
markOverdefined(A);
831+
return ValueLatticeElement::getOverdefined();
832+
}
833+
834+
void trackValueOfArgument(Argument *A) {
835+
if (A->getType()->isStructTy())
836+
return (void)markOverdefined(A);
837+
mergeInValue(A, getArgAttributeVL(A));
836838
}
837839

838840
bool isStructLatticeConstant(Function *F, StructType *STy);
@@ -1800,7 +1802,9 @@ void SCCPInstVisitor::handleCallArguments(CallBase &CB) {
18001802
getMaxWidenStepsOpts());
18011803
}
18021804
} else
1803-
mergeInValue(&*AI, getValueState(*CAI), getMaxWidenStepsOpts());
1805+
mergeInValue(&*AI,
1806+
getValueState(*CAI).intersect(getArgAttributeVL(&*AI)),
1807+
getMaxWidenStepsOpts());
18041808
}
18051809
}
18061810
}

llvm/test/Transforms/SCCP/pointer-nonnull.ll

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,22 @@ define internal i1 @ip_test_nonnull_callee(ptr nonnull %p) {
210210
;
211211
; IPSCCP-LABEL: define internal i1 @ip_test_nonnull_callee(
212212
; IPSCCP-SAME: ptr nonnull [[P:%.*]]) {
213-
; IPSCCP-NEXT: [[CMP:%.*]] = icmp ne ptr [[P]], null
214-
; IPSCCP-NEXT: ret i1 [[CMP]]
213+
; IPSCCP-NEXT: ret i1 poison
215214
;
216215
%cmp = icmp ne ptr %p, null
217216
ret i1 %cmp
218217
}
219218

220219
define i1 @ip_test_nonnull_caller(ptr %p) {
221-
; CHECK-LABEL: define i1 @ip_test_nonnull_caller(
222-
; CHECK-SAME: ptr [[P:%.*]]) {
223-
; CHECK-NEXT: [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]])
224-
; CHECK-NEXT: ret i1 [[RES]]
220+
; SCCP-LABEL: define i1 @ip_test_nonnull_caller(
221+
; SCCP-SAME: ptr [[P:%.*]]) {
222+
; SCCP-NEXT: [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]])
223+
; SCCP-NEXT: ret i1 [[RES]]
224+
;
225+
; IPSCCP-LABEL: define i1 @ip_test_nonnull_caller(
226+
; IPSCCP-SAME: ptr [[P:%.*]]) {
227+
; IPSCCP-NEXT: [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]])
228+
; IPSCCP-NEXT: ret i1 true
225229
;
226230
%res = call i1 @ip_test_nonnull_callee(ptr %p)
227231
ret i1 %res

llvm/test/Transforms/SCCP/range-attribute.ll

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,7 @@ define i1 @ip_range_attribute_constant() {
193193

194194
define internal i1 @ip_cmp_attribute_overdefined_callee(i32 range(i32 0, 10) %x) {
195195
; IPSCCP-LABEL: @ip_cmp_attribute_overdefined_callee(
196-
; IPSCCP-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 10
197-
; IPSCCP-NEXT: ret i1 [[CMP]]
196+
; IPSCCP-NEXT: ret i1 poison
198197
;
199198
; SCCP-LABEL: @ip_cmp_attribute_overdefined_callee(
200199
; SCCP-NEXT: ret i1 true
@@ -204,19 +203,21 @@ define internal i1 @ip_cmp_attribute_overdefined_callee(i32 range(i32 0, 10) %x)
204203
}
205204

206205
define i1 @ip_cmp_attribute_overdefined_caller(i32 %x) {
207-
; CHECK-LABEL: @ip_cmp_attribute_overdefined_caller(
208-
; CHECK-NEXT: [[RES:%.*]] = call i1 @ip_cmp_attribute_overdefined_callee(i32 [[X:%.*]])
209-
; CHECK-NEXT: ret i1 [[RES]]
206+
; IPSCCP-LABEL: @ip_cmp_attribute_overdefined_caller(
207+
; IPSCCP-NEXT: [[RES:%.*]] = call i1 @ip_cmp_attribute_overdefined_callee(i32 [[X:%.*]])
208+
; IPSCCP-NEXT: ret i1 true
209+
;
210+
; SCCP-LABEL: @ip_cmp_attribute_overdefined_caller(
211+
; SCCP-NEXT: [[RES:%.*]] = call i1 @ip_cmp_attribute_overdefined_callee(i32 [[X:%.*]])
212+
; SCCP-NEXT: ret i1 [[RES]]
210213
;
211214
%res = call i1 @ip_cmp_attribute_overdefined_callee(i32 %x)
212215
ret i1 %res
213216
}
214217

215218
define internal i1 @ip_cmp_attribute_intersect_callee(i32 range(i32 0, 10) %x) {
216219
; IPSCCP-LABEL: @ip_cmp_attribute_intersect_callee(
217-
; IPSCCP-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
218-
; IPSCCP-NEXT: [[AND:%.*]] = and i1 [[CMP1]], true
219-
; IPSCCP-NEXT: ret i1 [[AND]]
220+
; IPSCCP-NEXT: ret i1 poison
220221
;
221222
; SCCP-LABEL: @ip_cmp_attribute_intersect_callee(
222223
; SCCP-NEXT: [[CMP2:%.*]] = icmp uge i32 [[X:%.*]], 5
@@ -230,9 +231,13 @@ define internal i1 @ip_cmp_attribute_intersect_callee(i32 range(i32 0, 10) %x) {
230231
}
231232

232233
define i1 @ip_cmp_attribute_intersect_caller(i32 range(i32 5, 15) %x) {
233-
; CHECK-LABEL: @ip_cmp_attribute_intersect_caller(
234-
; CHECK-NEXT: [[RES:%.*]] = call i1 @ip_cmp_attribute_intersect_callee(i32 [[X:%.*]])
235-
; CHECK-NEXT: ret i1 [[RES]]
234+
; IPSCCP-LABEL: @ip_cmp_attribute_intersect_caller(
235+
; IPSCCP-NEXT: [[RES:%.*]] = call i1 @ip_cmp_attribute_intersect_callee(i32 [[X:%.*]])
236+
; IPSCCP-NEXT: ret i1 true
237+
;
238+
; SCCP-LABEL: @ip_cmp_attribute_intersect_caller(
239+
; SCCP-NEXT: [[RES:%.*]] = call i1 @ip_cmp_attribute_intersect_callee(i32 [[X:%.*]])
240+
; SCCP-NEXT: ret i1 [[RES]]
236241
;
237242
%res = call i1 @ip_cmp_attribute_intersect_callee(i32 %x)
238243
ret i1 %res

0 commit comments

Comments
 (0)