Skip to content

Commit 5f99a7a

Browse files
committed
Revert "[Inliner] Propagate callee argument memory access attributes before inlining"
This exposes a miscompile reported in #95152. Whether the new inference or MemCpyOpt is at fault depends on the precise semantics of writeonly attributes. Revert the patch while this is being pinned down. This reverts commit 285dbed. This reverts commit cda5790.
1 parent 1a5f906 commit 5f99a7a

File tree

5 files changed

+33
-134
lines changed

5 files changed

+33
-134
lines changed

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,85 +1344,6 @@ 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-
if (CB.paramHasAttr(I, Attribute::WriteOnly))
1367-
ValidParamAttrs.back().addAttribute(Attribute::WriteOnly);
1368-
HasAttrToPropagate |= ValidParamAttrs.back().hasAttributes();
1369-
}
1370-
1371-
// Won't be able to propagate anything.
1372-
if (!HasAttrToPropagate)
1373-
return;
1374-
1375-
for (BasicBlock &BB : *CalledFunction) {
1376-
for (Instruction &Ins : BB) {
1377-
const auto *InnerCB = dyn_cast<CallBase>(&Ins);
1378-
if (!InnerCB)
1379-
continue;
1380-
auto *NewInnerCB = dyn_cast_or_null<CallBase>(VMap.lookup(InnerCB));
1381-
if (!NewInnerCB)
1382-
continue;
1383-
AttributeList AL = NewInnerCB->getAttributes();
1384-
for (unsigned I = 0, E = InnerCB->arg_size(); I < E; ++I) {
1385-
// Check if the underlying value for the parameter is an argument.
1386-
const Value *UnderlyingV =
1387-
getUnderlyingObject(InnerCB->getArgOperand(I));
1388-
const Argument *Arg = dyn_cast<Argument>(UnderlyingV);
1389-
if (!Arg)
1390-
continue;
1391-
1392-
if (AL.hasParamAttr(I, Attribute::ByVal))
1393-
// It's unsound to propagate memory attributes to byval arguments.
1394-
// Even if CalledFunction doesn't e.g. write to the argument,
1395-
// the call to NewInnerCB may write to its by-value copy.
1396-
continue;
1397-
1398-
unsigned ArgNo = Arg->getArgNo();
1399-
// If so, propagate its access attributes.
1400-
AL = AL.addParamAttributes(Context, I, ValidParamAttrs[ArgNo]);
1401-
// We can have conflicting attributes from the inner callsite and
1402-
// to-be-inlined callsite. In that case, choose the most
1403-
// restrictive.
1404-
1405-
// readonly + writeonly means we can never deref so make readnone.
1406-
if (AL.hasParamAttr(I, Attribute::ReadOnly) &&
1407-
AL.hasParamAttr(I, Attribute::WriteOnly))
1408-
AL = AL.addParamAttribute(Context, I, Attribute::ReadNone);
1409-
1410-
// If have readnone, need to clear readonly/writeonly
1411-
if (AL.hasParamAttr(I, Attribute::ReadNone)) {
1412-
AL = AL.removeParamAttribute(Context, I, Attribute::ReadOnly);
1413-
AL = AL.removeParamAttribute(Context, I, Attribute::WriteOnly);
1414-
}
1415-
1416-
// Writable cannot exist in conjunction w/ readonly/readnone
1417-
if (AL.hasParamAttr(I, Attribute::ReadOnly) ||
1418-
AL.hasParamAttr(I, Attribute::ReadNone))
1419-
AL = AL.removeParamAttribute(Context, I, Attribute::Writable);
1420-
}
1421-
NewInnerCB->setAttributes(AL);
1422-
}
1423-
}
1424-
}
1425-
14261347
// Only allow these white listed attributes to be propagated back to the
14271348
// callee. This is because other attributes may only be valid on the call
14281349
// itself, i.e. attributes such as signext and zeroext.
@@ -2442,10 +2363,6 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24422363
// function which feed into its return value.
24432364
AddReturnAttributes(CB, VMap);
24442365

2445-
// Clone attributes on the params of the callsite to calls within the
2446-
// inlined function which use the same param.
2447-
AddParamAndFnBasicAttributes(CB, VMap);
2448-
24492366
propagateMemProfMetadata(CalledFunc, CB,
24502367
InlinedFunctionInfo.ContainsMemProfMetadata, VMap);
24512368

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

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
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)
109
define dso_local void @foo1_rdonly(ptr readonly %p) {
1110
; CHECK-LABEL: define {{[^@]+}}@foo1_rdonly
1211
; CHECK-SAME: (ptr readonly [[P:%.*]]) {
@@ -187,19 +186,10 @@ define dso_local void @foo2_through_obj(ptr %p, ptr %p2) {
187186
ret void
188187
}
189188

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-
call void @bar4(ptr byval([4 x i32]) %p)
196-
ret void
197-
}
198-
199189
define void @prop_param_func_decl(ptr %p) {
200190
; CHECK-LABEL: define {{[^@]+}}@prop_param_func_decl
201191
; CHECK-SAME: (ptr [[P:%.*]]) {
202-
; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
192+
; CHECK-NEXT: call void @bar1(ptr [[P]])
203193
; CHECK-NEXT: ret void
204194
;
205195
call void @foo1_rdonly(ptr %p)
@@ -209,7 +199,7 @@ define void @prop_param_func_decl(ptr %p) {
209199
define void @prop_param_callbase_def(ptr %p) {
210200
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def
211201
; CHECK-SAME: (ptr [[P:%.*]]) {
212-
; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
202+
; CHECK-NEXT: call void @bar1(ptr [[P]])
213203
; CHECK-NEXT: call void @bar1(ptr [[P]])
214204
; CHECK-NEXT: ret void
215205
;
@@ -221,7 +211,7 @@ define void @prop_param_callbase_def(ptr %p) {
221211
define void @prop_param_callbase_def_2x(ptr %p, ptr %p2) {
222212
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x
223213
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
224-
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
214+
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
225215
; CHECK-NEXT: ret void
226216
;
227217
call void @foo2(ptr readonly %p, ptr %p)
@@ -233,7 +223,7 @@ define void @prop_param_callbase_def_2x_2(ptr %p, ptr %p2) {
233223
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
234224
; CHECK-NEXT: [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
235225
; CHECK-NEXT: [[P2P_I:%.*]] = getelementptr i8, ptr [[P2]], i64 123
236-
; CHECK-NEXT: call void @bar2(ptr writeonly [[P2P_I]], ptr readonly [[PP_I]])
226+
; CHECK-NEXT: call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
237227
; CHECK-NEXT: ret void
238228
;
239229
call void @foo2_through_obj(ptr readonly %p, ptr writeonly %p2)
@@ -245,7 +235,7 @@ define void @prop_param_callbase_def_2x_incompat(ptr %p, ptr %p2) {
245235
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
246236
; CHECK-NEXT: [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
247237
; CHECK-NEXT: [[P2P_I:%.*]] = getelementptr i8, ptr [[P]], i64 123
248-
; CHECK-NEXT: call void @bar2(ptr readonly [[P2P_I]], ptr readnone [[PP_I]])
238+
; CHECK-NEXT: call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
249239
; CHECK-NEXT: ret void
250240
;
251241
call void @foo2_through_obj(ptr readnone %p, ptr readonly %p)
@@ -255,7 +245,7 @@ define void @prop_param_callbase_def_2x_incompat(ptr %p, ptr %p2) {
255245
define void @prop_param_callbase_def_2x_incompat_2(ptr %p, ptr %p2) {
256246
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_2
257247
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
258-
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
248+
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
259249
; CHECK-NEXT: ret void
260250
;
261251
call void @foo2(ptr readonly %p, ptr readnone %p)
@@ -265,7 +255,7 @@ define void @prop_param_callbase_def_2x_incompat_2(ptr %p, ptr %p2) {
265255
define void @prop_param_callbase_def_2x_incompat_3(ptr %p, ptr %p2) {
266256
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_3
267257
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
268-
; CHECK-NEXT: call void @bar2(ptr readnone [[P]], ptr readnone [[P]])
258+
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
269259
; CHECK-NEXT: ret void
270260
;
271261
call void @foo2_2(ptr readonly %p, ptr readnone %p)
@@ -275,7 +265,7 @@ define void @prop_param_callbase_def_2x_incompat_3(ptr %p, ptr %p2) {
275265
define void @prop_param_callbase_def_1x_partial(ptr %p, ptr %p2) {
276266
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial
277267
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
278-
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
268+
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
279269
; CHECK-NEXT: ret void
280270
;
281271
call void @foo2(ptr readonly %p, ptr %p)
@@ -295,7 +285,7 @@ define void @prop_param_callbase_def_1x_partial_2(ptr %p, ptr %p2) {
295285
define void @prop_param_callbase_def_1x_partial_3(ptr %p, ptr %p2) {
296286
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial_3
297287
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
298-
; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readnone [[P]])
288+
; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
299289
; CHECK-NEXT: ret void
300290
;
301291
call void @foo2_3(ptr readonly %p, ptr %p)
@@ -531,7 +521,7 @@ define void @prop_cb_def_mustprogress(ptr %p) {
531521
define void @prop_no_conflict_writable(ptr %p) {
532522
; CHECK-LABEL: define {{[^@]+}}@prop_no_conflict_writable
533523
; CHECK-SAME: (ptr [[P:%.*]]) {
534-
; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
524+
; CHECK-NEXT: call void @bar1(ptr writable [[P]])
535525
; CHECK-NEXT: ret void
536526
;
537527
call void @foo1_writable(ptr readonly %p)
@@ -542,18 +532,10 @@ define void @prop_no_conflict_writable(ptr %p) {
542532
define void @prop_no_conflict_writable2(ptr %p) {
543533
; CHECK-LABEL: define {{[^@]+}}@prop_no_conflict_writable2
544534
; CHECK-SAME: (ptr [[P:%.*]]) {
545-
; CHECK-NEXT: call void @bar3(ptr readnone [[P]])
535+
; CHECK-NEXT: call void @bar3(ptr [[P]])
546536
; CHECK-NEXT: ret void
547537
;
548538
call void @foo3_writable(ptr readnone %p)
549539
ret void
550540
}
551541

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

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 [[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]]
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
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 [[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]]
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
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 [[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]]
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
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 [[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]]
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
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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
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.
76

87
declare void @use(i64)
98

@@ -46,7 +45,8 @@ define void @g(ptr dead_on_unwind noalias writable dereferenceable(8) align 8 %p
4645
define void @f(ptr dead_on_unwind noalias %p) {
4746
; CHECK-LABEL: define void @f(
4847
; CHECK-SAME: ptr dead_on_unwind noalias [[P:%.*]]) local_unnamed_addr {
49-
; CHECK-NEXT: tail call void @j(ptr nonnull writeonly [[P]])
48+
; CHECK-NEXT: store i64 3, ptr [[P]], align 4
49+
; CHECK-NEXT: tail call void @j(ptr nonnull [[P]])
5050
; CHECK-NEXT: store i64 43, ptr [[P]], align 4
5151
; CHECK-NEXT: ret void
5252
;

0 commit comments

Comments
 (0)