Skip to content

Commit db03d9d

Browse files
committed
Recommit "[Inliner] Propagate callee argument memory access attributes before inlining" (2nd Try)
In the re-commit, just dropping the propagation of `writeonly` as that is the only attribute that can play poorly with call slot optimization (see issue: #95152 for more details). Closes #95888
1 parent 0adecfb commit db03d9d

File tree

5 files changed

+133
-31
lines changed

5 files changed

+133
-31
lines changed

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,83 @@ static bool MayContainThrowingOrExitingCallAfterCB(CallBase *Begin,
13441344
++BeginIt, End->getIterator(), InlinerAttributeWindow + 1);
13451345
}
13461346

1347+
// Add attributes from CB params and Fn attributes that can always be propagated
1348+
// to the corresponding argument / inner callbases.
1349+
static void AddParamAndFnBasicAttributes(const CallBase &CB,
1350+
ValueToValueMapTy &VMap) {
1351+
auto *CalledFunction = CB.getCalledFunction();
1352+
auto &Context = CalledFunction->getContext();
1353+
1354+
// Collect valid attributes for all params.
1355+
SmallVector<AttrBuilder> ValidParamAttrs;
1356+
bool HasAttrToPropagate = false;
1357+
1358+
for (unsigned I = 0, E = CB.arg_size(); I < E; ++I) {
1359+
ValidParamAttrs.emplace_back(AttrBuilder{CB.getContext()});
1360+
// Access attributes can be propagated to any param with the same underlying
1361+
// object as the argument.
1362+
if (CB.paramHasAttr(I, Attribute::ReadNone))
1363+
ValidParamAttrs.back().addAttribute(Attribute::ReadNone);
1364+
if (CB.paramHasAttr(I, Attribute::ReadOnly))
1365+
ValidParamAttrs.back().addAttribute(Attribute::ReadOnly);
1366+
HasAttrToPropagate |= ValidParamAttrs.back().hasAttributes();
1367+
}
1368+
1369+
// Won't be able to propagate anything.
1370+
if (!HasAttrToPropagate)
1371+
return;
1372+
1373+
for (BasicBlock &BB : *CalledFunction) {
1374+
for (Instruction &Ins : BB) {
1375+
const auto *InnerCB = dyn_cast<CallBase>(&Ins);
1376+
if (!InnerCB)
1377+
continue;
1378+
auto *NewInnerCB = dyn_cast_or_null<CallBase>(VMap.lookup(InnerCB));
1379+
if (!NewInnerCB)
1380+
continue;
1381+
AttributeList AL = NewInnerCB->getAttributes();
1382+
for (unsigned I = 0, E = InnerCB->arg_size(); I < E; ++I) {
1383+
// Check if the underlying value for the parameter is an argument.
1384+
const Value *UnderlyingV =
1385+
getUnderlyingObject(InnerCB->getArgOperand(I));
1386+
const Argument *Arg = dyn_cast<Argument>(UnderlyingV);
1387+
if (!Arg)
1388+
continue;
1389+
1390+
if (AL.hasParamAttr(I, Attribute::ByVal))
1391+
// It's unsound to propagate memory attributes to byval arguments.
1392+
// Even if CalledFunction doesn't e.g. write to the argument,
1393+
// the call to NewInnerCB may write to its by-value copy.
1394+
continue;
1395+
1396+
unsigned ArgNo = Arg->getArgNo();
1397+
// If so, propagate its access attributes.
1398+
AL = AL.addParamAttributes(Context, I, ValidParamAttrs[ArgNo]);
1399+
// We can have conflicting attributes from the inner callsite and
1400+
// to-be-inlined callsite. In that case, choose the most
1401+
// restrictive.
1402+
1403+
// readonly + writeonly means we can never deref so make readnone.
1404+
if (AL.hasParamAttr(I, Attribute::ReadOnly) &&
1405+
AL.hasParamAttr(I, Attribute::WriteOnly))
1406+
AL = AL.addParamAttribute(Context, I, Attribute::ReadNone);
1407+
1408+
// If have readnone, need to clear readonly/writeonly
1409+
if (AL.hasParamAttr(I, Attribute::ReadNone)) {
1410+
AL = AL.removeParamAttribute(Context, I, Attribute::ReadOnly);
1411+
AL = AL.removeParamAttribute(Context, I, Attribute::WriteOnly);
1412+
}
1413+
1414+
// Writable cannot exist in conjunction w/ readonly/readnone
1415+
if (AL.hasParamAttr(I, Attribute::ReadOnly) ||
1416+
AL.hasParamAttr(I, Attribute::ReadNone))
1417+
AL = AL.removeParamAttribute(Context, I, Attribute::Writable);
1418+
}
1419+
NewInnerCB->setAttributes(AL);
1420+
}
1421+
}
1422+
}
1423+
13471424
// Only allow these white listed attributes to be propagated back to the
13481425
// callee. This is because other attributes may only be valid on the call
13491426
// itself, i.e. attributes such as signext and zeroext.
@@ -2363,6 +2440,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
23632440
// function which feed into its return value.
23642441
AddReturnAttributes(CB, VMap);
23652442

2443+
// Clone attributes on the params of the callsite to calls within the
2444+
// inlined function which use the same param.
2445+
AddParamAndFnBasicAttributes(CB, VMap);
2446+
23662447
propagateMemProfMetadata(CalledFunc, CB,
23672448
InlinedFunctionInfo.ContainsMemProfMetadata, VMap);
23682449

llvm/test/Transforms/Inline/access-attributes-prop.ll

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
declare void @bar1(ptr %p)
77
declare void @bar2(ptr %p, ptr %p2)
88
declare void @bar3(ptr writable %p)
9+
declare void @bar4(ptr byval([4 x i32]) %p)
910
define dso_local void @foo1_rdonly(ptr readonly %p) {
1011
; CHECK-LABEL: define {{[^@]+}}@foo1_rdonly
1112
; CHECK-SAME: (ptr readonly [[P:%.*]]) {
@@ -186,10 +187,20 @@ define dso_local void @foo2_through_obj(ptr %p, ptr %p2) {
186187
ret void
187188
}
188189

190+
define dso_local void @foo_byval_readonly(ptr readonly %p) {
191+
; CHECK-LABEL: define {{[^@]+}}@foo_byval_readonly
192+
; CHECK-SAME: (ptr readonly [[P:%.*]]) {
193+
; CHECK-NEXT: call void @bar4(ptr byval([4 x i32]) [[P]])
194+
; CHECK-NEXT: ret void
195+
;
196+
call void @bar4(ptr byval([4 x i32]) %p)
197+
ret void
198+
}
199+
189200
define void @prop_param_func_decl(ptr %p) {
190201
; CHECK-LABEL: define {{[^@]+}}@prop_param_func_decl
191202
; CHECK-SAME: (ptr [[P:%.*]]) {
192-
; CHECK-NEXT: call void @bar1(ptr [[P]])
203+
; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
193204
; CHECK-NEXT: ret void
194205
;
195206
call void @foo1_rdonly(ptr %p)
@@ -199,7 +210,7 @@ define void @prop_param_func_decl(ptr %p) {
199210
define void @prop_param_callbase_def(ptr %p) {
200211
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def
201212
; CHECK-SAME: (ptr [[P:%.*]]) {
202-
; CHECK-NEXT: call void @bar1(ptr [[P]])
213+
; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
203214
; CHECK-NEXT: call void @bar1(ptr [[P]])
204215
; CHECK-NEXT: ret void
205216
;
@@ -211,7 +222,7 @@ define void @prop_param_callbase_def(ptr %p) {
211222
define void @prop_param_callbase_def_2x(ptr %p, ptr %p2) {
212223
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x
213224
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
214-
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
225+
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
215226
; CHECK-NEXT: ret void
216227
;
217228
call void @foo2(ptr readonly %p, ptr %p)
@@ -223,7 +234,7 @@ define void @prop_param_callbase_def_2x_2(ptr %p, ptr %p2) {
223234
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
224235
; CHECK-NEXT: [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
225236
; CHECK-NEXT: [[P2P_I:%.*]] = getelementptr i8, ptr [[P2]], i64 123
226-
; CHECK-NEXT: call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
237+
; CHECK-NEXT: call void @bar2(ptr [[P2P_I]], ptr readonly [[PP_I]])
227238
; CHECK-NEXT: ret void
228239
;
229240
call void @foo2_through_obj(ptr readonly %p, ptr writeonly %p2)
@@ -235,7 +246,7 @@ define void @prop_param_callbase_def_2x_incompat(ptr %p, ptr %p2) {
235246
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
236247
; CHECK-NEXT: [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
237248
; CHECK-NEXT: [[P2P_I:%.*]] = getelementptr i8, ptr [[P]], i64 123
238-
; CHECK-NEXT: call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
249+
; CHECK-NEXT: call void @bar2(ptr readonly [[P2P_I]], ptr readnone [[PP_I]])
239250
; CHECK-NEXT: ret void
240251
;
241252
call void @foo2_through_obj(ptr readnone %p, ptr readonly %p)
@@ -245,7 +256,7 @@ define void @prop_param_callbase_def_2x_incompat(ptr %p, ptr %p2) {
245256
define void @prop_param_callbase_def_2x_incompat_2(ptr %p, ptr %p2) {
246257
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_2
247258
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
248-
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
259+
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
249260
; CHECK-NEXT: ret void
250261
;
251262
call void @foo2(ptr readonly %p, ptr readnone %p)
@@ -255,7 +266,7 @@ define void @prop_param_callbase_def_2x_incompat_2(ptr %p, ptr %p2) {
255266
define void @prop_param_callbase_def_2x_incompat_3(ptr %p, ptr %p2) {
256267
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_3
257268
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
258-
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
269+
; CHECK-NEXT: call void @bar2(ptr readnone [[P]], ptr readnone [[P]])
259270
; CHECK-NEXT: ret void
260271
;
261272
call void @foo2_2(ptr readonly %p, ptr readnone %p)
@@ -265,7 +276,7 @@ define void @prop_param_callbase_def_2x_incompat_3(ptr %p, ptr %p2) {
265276
define void @prop_param_callbase_def_1x_partial(ptr %p, ptr %p2) {
266277
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial
267278
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
268-
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
279+
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
269280
; CHECK-NEXT: ret void
270281
;
271282
call void @foo2(ptr readonly %p, ptr %p)
@@ -285,7 +296,7 @@ define void @prop_param_callbase_def_1x_partial_2(ptr %p, ptr %p2) {
285296
define void @prop_param_callbase_def_1x_partial_3(ptr %p, ptr %p2) {
286297
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial_3
287298
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
288-
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
299+
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readnone [[P]])
289300
; CHECK-NEXT: ret void
290301
;
291302
call void @foo2_3(ptr readonly %p, ptr %p)
@@ -521,7 +532,7 @@ define void @prop_cb_def_mustprogress(ptr %p) {
521532
define void @prop_no_conflict_writable(ptr %p) {
522533
; CHECK-LABEL: define {{[^@]+}}@prop_no_conflict_writable
523534
; CHECK-SAME: (ptr [[P:%.*]]) {
524-
; CHECK-NEXT: call void @bar1(ptr writable [[P]])
535+
; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
525536
; CHECK-NEXT: ret void
526537
;
527538
call void @foo1_writable(ptr readonly %p)
@@ -532,10 +543,19 @@ define void @prop_no_conflict_writable(ptr %p) {
532543
define void @prop_no_conflict_writable2(ptr %p) {
533544
; CHECK-LABEL: define {{[^@]+}}@prop_no_conflict_writable2
534545
; CHECK-SAME: (ptr [[P:%.*]]) {
535-
; CHECK-NEXT: call void @bar3(ptr [[P]])
546+
; CHECK-NEXT: call void @bar3(ptr readnone [[P]])
536547
; CHECK-NEXT: ret void
537548
;
538549
call void @foo3_writable(ptr readnone %p)
539550
ret void
540551
}
541552

553+
define void @prop_byval_readonly(ptr %p) {
554+
; CHECK-LABEL: define {{[^@]+}}@prop_byval_readonly
555+
; CHECK-SAME: (ptr [[P:%.*]]) {
556+
; CHECK-NEXT: call void @bar4(ptr byval([4 x i32]) [[P]])
557+
; CHECK-NEXT: ret void
558+
;
559+
call void @foo_byval_readonly(ptr %p)
560+
ret void
561+
}

llvm/test/Transforms/Inline/noalias-calls-always.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
3434
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META0:![0-9]+]])
3535
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
3636
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
37-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias !3
38-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C:%.*]], i64 16, i1 false), !noalias !0
39-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !5
40-
; CHECK-NEXT: call void @hey(), !noalias !5
41-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !0
37+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias [[META3]]
38+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META0]]
39+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META5:![0-9]+]]
40+
; CHECK-NEXT: call void @hey(), !noalias [[META5]]
41+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
4242
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
4343
; CHECK-NEXT: ret void
4444
;
@@ -75,11 +75,11 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
7575
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
7676
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
7777
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
78-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias !9
79-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C:%.*]], i64 16, i1 false), !noalias !6
80-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !11
81-
; CHECK-NEXT: call void @hey(), !noalias !11
82-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !6
78+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias [[META9]]
79+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META6]]
80+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META11:![0-9]+]]
81+
; CHECK-NEXT: call void @hey(), !noalias [[META11]]
82+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
8383
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
8484
; CHECK-NEXT: ret void
8585
;

llvm/test/Transforms/Inline/noalias-calls.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
3737
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META0:![0-9]+]])
3838
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
3939
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
40-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias !3
41-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C]], i64 16, i1 false), !noalias !0
42-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !5
43-
; CHECK-NEXT: call void @hey(), !noalias !5
44-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !0
40+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias [[META3]]
41+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
42+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META5:![0-9]+]]
43+
; CHECK-NEXT: call void @hey(), !noalias [[META5]]
44+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
4545
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
4646
; CHECK-NEXT: ret void
4747
;
@@ -80,11 +80,11 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
8080
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
8181
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
8282
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
83-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias !9
84-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C]], i64 16, i1 false), !noalias !6
85-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !11
86-
; CHECK-NEXT: call void @hey(), !noalias !11
87-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !6
83+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias [[META9]]
84+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
85+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META11:![0-9]+]]
86+
; CHECK-NEXT: call void @hey(), !noalias [[META11]]
87+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
8888
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
8989
; CHECK-NEXT: ret void
9090
;

llvm/test/Transforms/PhaseOrdering/pr95152.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
; Make sure that interaction of "writable" with various passes does not
55
; result in the elimination of the store prior to @j().
6+
; FIXME: This is a miscompile.
67

78
declare void @use(i64)
89

0 commit comments

Comments
 (0)