[llvm] 5f99a7a - Revert "[Inliner] Propagate callee argument memory access attributes before inlining"
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 12 03:36:12 PDT 2024
Author: Nikita Popov
Date: 2024-06-12T12:32:50+02:00
New Revision: 5f99a7a51a1e2aa66bbe98a905711f4eb0bb7a74
URL: https://github.com/llvm/llvm-project/commit/5f99a7a51a1e2aa66bbe98a905711f4eb0bb7a74
DIFF: https://github.com/llvm/llvm-project/commit/5f99a7a51a1e2aa66bbe98a905711f4eb0bb7a74.diff
LOG: Revert "[Inliner] Propagate callee argument memory access attributes before inlining"
This exposes a miscompile reported in
https://github.com/llvm/llvm-project/issues/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 285dbed147e243f416b003e150d67ffb0922ff16.
This reverts commit cda5790e38af5da3ad455eddab36ef16bf3e8104.
Added:
Modified:
llvm/lib/Transforms/Utils/InlineFunction.cpp
llvm/test/Transforms/Inline/access-attributes-prop.ll
llvm/test/Transforms/Inline/noalias-calls-always.ll
llvm/test/Transforms/Inline/noalias-calls.ll
llvm/test/Transforms/PhaseOrdering/pr95152.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index cfe63496a1007..c4baafd1fc5bb 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1344,85 +1344,6 @@ static bool MayContainThrowingOrExitingCallAfterCB(CallBase *Begin,
++BeginIt, End->getIterator(), InlinerAttributeWindow + 1);
}
-// Add attributes from CB params and Fn attributes that can always be propagated
-// to the corresponding argument / inner callbases.
-static void AddParamAndFnBasicAttributes(const CallBase &CB,
- ValueToValueMapTy &VMap) {
- auto *CalledFunction = CB.getCalledFunction();
- auto &Context = CalledFunction->getContext();
-
- // Collect valid attributes for all params.
- SmallVector<AttrBuilder> ValidParamAttrs;
- bool HasAttrToPropagate = false;
-
- for (unsigned I = 0, E = CB.arg_size(); I < E; ++I) {
- ValidParamAttrs.emplace_back(AttrBuilder{CB.getContext()});
- // Access attributes can be propagated to any param with the same underlying
- // object as the argument.
- if (CB.paramHasAttr(I, Attribute::ReadNone))
- ValidParamAttrs.back().addAttribute(Attribute::ReadNone);
- if (CB.paramHasAttr(I, Attribute::ReadOnly))
- ValidParamAttrs.back().addAttribute(Attribute::ReadOnly);
- if (CB.paramHasAttr(I, Attribute::WriteOnly))
- ValidParamAttrs.back().addAttribute(Attribute::WriteOnly);
- HasAttrToPropagate |= ValidParamAttrs.back().hasAttributes();
- }
-
- // Won't be able to propagate anything.
- if (!HasAttrToPropagate)
- return;
-
- for (BasicBlock &BB : *CalledFunction) {
- for (Instruction &Ins : BB) {
- const auto *InnerCB = dyn_cast<CallBase>(&Ins);
- if (!InnerCB)
- continue;
- auto *NewInnerCB = dyn_cast_or_null<CallBase>(VMap.lookup(InnerCB));
- if (!NewInnerCB)
- continue;
- AttributeList AL = NewInnerCB->getAttributes();
- for (unsigned I = 0, E = InnerCB->arg_size(); I < E; ++I) {
- // Check if the underlying value for the parameter is an argument.
- const Value *UnderlyingV =
- getUnderlyingObject(InnerCB->getArgOperand(I));
- const Argument *Arg = dyn_cast<Argument>(UnderlyingV);
- if (!Arg)
- continue;
-
- if (AL.hasParamAttr(I, Attribute::ByVal))
- // It's unsound to propagate memory attributes to byval arguments.
- // Even if CalledFunction doesn't e.g. write to the argument,
- // the call to NewInnerCB may write to its by-value copy.
- continue;
-
- unsigned ArgNo = Arg->getArgNo();
- // If so, propagate its access attributes.
- AL = AL.addParamAttributes(Context, I, ValidParamAttrs[ArgNo]);
- // We can have conflicting attributes from the inner callsite and
- // to-be-inlined callsite. In that case, choose the most
- // restrictive.
-
- // readonly + writeonly means we can never deref so make readnone.
- if (AL.hasParamAttr(I, Attribute::ReadOnly) &&
- AL.hasParamAttr(I, Attribute::WriteOnly))
- AL = AL.addParamAttribute(Context, I, Attribute::ReadNone);
-
- // If have readnone, need to clear readonly/writeonly
- if (AL.hasParamAttr(I, Attribute::ReadNone)) {
- AL = AL.removeParamAttribute(Context, I, Attribute::ReadOnly);
- AL = AL.removeParamAttribute(Context, I, Attribute::WriteOnly);
- }
-
- // Writable cannot exist in conjunction w/ readonly/readnone
- if (AL.hasParamAttr(I, Attribute::ReadOnly) ||
- AL.hasParamAttr(I, Attribute::ReadNone))
- AL = AL.removeParamAttribute(Context, I, Attribute::Writable);
- }
- NewInnerCB->setAttributes(AL);
- }
- }
-}
-
// Only allow these white listed attributes to be propagated back to the
// callee. This is because other attributes may only be valid on the call
// itself, i.e. attributes such as signext and zeroext.
@@ -2442,10 +2363,6 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
// function which feed into its return value.
AddReturnAttributes(CB, VMap);
- // Clone attributes on the params of the callsite to calls within the
- // inlined function which use the same param.
- AddParamAndFnBasicAttributes(CB, VMap);
-
propagateMemProfMetadata(CalledFunc, CB,
InlinedFunctionInfo.ContainsMemProfMetadata, VMap);
diff --git a/llvm/test/Transforms/Inline/access-attributes-prop.ll b/llvm/test/Transforms/Inline/access-attributes-prop.ll
index 48665e9bbafd1..c242472f083df 100644
--- a/llvm/test/Transforms/Inline/access-attributes-prop.ll
+++ b/llvm/test/Transforms/Inline/access-attributes-prop.ll
@@ -6,7 +6,6 @@
declare void @bar1(ptr %p)
declare void @bar2(ptr %p, ptr %p2)
declare void @bar3(ptr writable %p)
-declare void @bar4(ptr byval([4 x i32]) %p)
define dso_local void @foo1_rdonly(ptr readonly %p) {
; CHECK-LABEL: define {{[^@]+}}@foo1_rdonly
; CHECK-SAME: (ptr readonly [[P:%.*]]) {
@@ -187,19 +186,10 @@ define dso_local void @foo2_through_obj(ptr %p, ptr %p2) {
ret void
}
-define dso_local void @foo_byval_readonly(ptr readonly %p) {
-; CHECK-LABEL: define {{[^@]+}}@foo_byval_readonly
-; CHECK-SAME: (ptr readonly [[P:%.*]])
-; CHECK-NEXT: call void @bar4(ptr byval([4 x i32]) [[P]])
-; CHECK-NEXT: ret void
- call void @bar4(ptr byval([4 x i32]) %p)
- ret void
-}
-
define void @prop_param_func_decl(ptr %p) {
; CHECK-LABEL: define {{[^@]+}}@prop_param_func_decl
; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
+; CHECK-NEXT: call void @bar1(ptr [[P]])
; CHECK-NEXT: ret void
;
call void @foo1_rdonly(ptr %p)
@@ -209,7 +199,7 @@ define void @prop_param_func_decl(ptr %p) {
define void @prop_param_callbase_def(ptr %p) {
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def
; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
+; CHECK-NEXT: call void @bar1(ptr [[P]])
; CHECK-NEXT: call void @bar1(ptr [[P]])
; CHECK-NEXT: ret void
;
@@ -221,7 +211,7 @@ define void @prop_param_callbase_def(ptr %p) {
define void @prop_param_callbase_def_2x(ptr %p, ptr %p2) {
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
-; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
+; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
; CHECK-NEXT: ret void
;
call void @foo2(ptr readonly %p, ptr %p)
@@ -233,7 +223,7 @@ define void @prop_param_callbase_def_2x_2(ptr %p, ptr %p2) {
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
; CHECK-NEXT: [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
; CHECK-NEXT: [[P2P_I:%.*]] = getelementptr i8, ptr [[P2]], i64 123
-; CHECK-NEXT: call void @bar2(ptr writeonly [[P2P_I]], ptr readonly [[PP_I]])
+; CHECK-NEXT: call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
; CHECK-NEXT: ret void
;
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) {
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
; CHECK-NEXT: [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
; CHECK-NEXT: [[P2P_I:%.*]] = getelementptr i8, ptr [[P]], i64 123
-; CHECK-NEXT: call void @bar2(ptr readonly [[P2P_I]], ptr readnone [[PP_I]])
+; CHECK-NEXT: call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
; CHECK-NEXT: ret void
;
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) {
define void @prop_param_callbase_def_2x_incompat_2(ptr %p, ptr %p2) {
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_2
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
-; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
+; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
; CHECK-NEXT: ret void
;
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) {
define void @prop_param_callbase_def_2x_incompat_3(ptr %p, ptr %p2) {
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_3
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
-; CHECK-NEXT: call void @bar2(ptr readnone [[P]], ptr readnone [[P]])
+; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
; CHECK-NEXT: ret void
;
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) {
define void @prop_param_callbase_def_1x_partial(ptr %p, ptr %p2) {
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
-; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readonly [[P]])
+; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
; CHECK-NEXT: ret void
;
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) {
define void @prop_param_callbase_def_1x_partial_3(ptr %p, ptr %p2) {
; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial_3
; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
-; CHECK-NEXT: call void @bar2(ptr readonly [[P]], ptr readnone [[P]])
+; CHECK-NEXT: call void @bar2(ptr [[P]], ptr [[P]])
; CHECK-NEXT: ret void
;
call void @foo2_3(ptr readonly %p, ptr %p)
@@ -531,7 +521,7 @@ define void @prop_cb_def_mustprogress(ptr %p) {
define void @prop_no_conflict_writable(ptr %p) {
; CHECK-LABEL: define {{[^@]+}}@prop_no_conflict_writable
; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT: call void @bar1(ptr readonly [[P]])
+; CHECK-NEXT: call void @bar1(ptr writable [[P]])
; CHECK-NEXT: ret void
;
call void @foo1_writable(ptr readonly %p)
@@ -542,18 +532,10 @@ define void @prop_no_conflict_writable(ptr %p) {
define void @prop_no_conflict_writable2(ptr %p) {
; CHECK-LABEL: define {{[^@]+}}@prop_no_conflict_writable2
; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT: call void @bar3(ptr readnone [[P]])
+; CHECK-NEXT: call void @bar3(ptr [[P]])
; CHECK-NEXT: ret void
;
call void @foo3_writable(ptr readnone %p)
ret void
}
-define void @prop_byval_readonly(ptr %p) {
-; CHECK-LABEL: define {{[^@]+}}@prop_byval_readonly
-; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT: call void @bar4(ptr byval([4 x i32]) [[P]])
-; CHECK-NEXT: ret void
- call void @foo_byval_readonly(ptr %p)
- ret void
-}
diff --git a/llvm/test/Transforms/Inline/noalias-calls-always.ll b/llvm/test/Transforms/Inline/noalias-calls-always.ll
index a80cd12b26b65..9c851b9327839 100644
--- a/llvm/test/Transforms/Inline/noalias-calls-always.ll
+++ b/llvm/test/Transforms/Inline/noalias-calls-always.ll
@@ -34,11 +34,11 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META0:![0-9]+]])
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias [[META3]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META0]]
-; 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]+]]
-; CHECK-NEXT: call void @hey(), !noalias [[META5]]
-; 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]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias !3
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C:%.*]], i64 16, i1 false), !noalias !0
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !5
+; CHECK-NEXT: call void @hey(), !noalias !5
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !0
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
@@ -75,11 +75,11 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias [[META9]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META6]]
-; 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]+]]
-; CHECK-NEXT: call void @hey(), !noalias [[META11]]
-; 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]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A:%.*]], ptr align 16 [[B:%.*]], i64 16, i1 false), !noalias !9
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C:%.*]], i64 16, i1 false), !noalias !6
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !11
+; CHECK-NEXT: call void @hey(), !noalias !11
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !6
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/Inline/noalias-calls.ll b/llvm/test/Transforms/Inline/noalias-calls.ll
index 0dd9ec3498a93..e3791da54b232 100644
--- a/llvm/test/Transforms/Inline/noalias-calls.ll
+++ b/llvm/test/Transforms/Inline/noalias-calls.ll
@@ -37,11 +37,11 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META0:![0-9]+]])
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias [[META3]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
-; 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]+]]
-; CHECK-NEXT: call void @hey(), !noalias [[META5]]
-; 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]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias !3
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C]], i64 16, i1 false), !noalias !0
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !5
+; CHECK-NEXT: call void @hey(), !noalias !5
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !0
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
@@ -80,11 +80,11 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 512, ptr [[L_I]])
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias [[META9]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
-; 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]+]]
-; CHECK-NEXT: call void @hey(), !noalias [[META11]]
-; 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]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[B]], i64 16, i1 false), !noalias !9
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr align 16 [[C]], i64 16, i1 false), !noalias !6
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr align 16 [[C]], i64 16, i1 false), !alias.scope !11
+; CHECK-NEXT: call void @hey(), !noalias !11
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr align 16 [[C]], i64 16, i1 false), !noalias !6
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/PhaseOrdering/pr95152.ll b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
index 7d77a4029ed0e..a6f290a3e3ed7 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr95152.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
@@ -3,7 +3,6 @@
; Make sure that interaction of "writable" with various passes does not
; result in the elimination of the store prior to @j().
-; FIXME: This is a miscompile.
declare void @use(i64)
@@ -46,7 +45,8 @@ define void @g(ptr dead_on_unwind noalias writable dereferenceable(8) align 8 %p
define void @f(ptr dead_on_unwind noalias %p) {
; CHECK-LABEL: define void @f(
; CHECK-SAME: ptr dead_on_unwind noalias [[P:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: tail call void @j(ptr nonnull writeonly [[P]])
+; CHECK-NEXT: store i64 3, ptr [[P]], align 4
+; CHECK-NEXT: tail call void @j(ptr nonnull [[P]])
; CHECK-NEXT: store i64 43, ptr [[P]], align 4
; CHECK-NEXT: ret void
;
More information about the llvm-commits
mailing list