diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index d004ced9dff14..e002195cb7ed5 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1725,6 +1725,10 @@ Currently, only the following parameter attributes are defined: and negative values are allowed in case the argument points partway into an allocation. An empty list is not allowed. + On a ``byval`` argument, ``initializes`` refers to the given parts of the + callee copy being overwritten. A ``byval`` callee can never initialize the + original caller memory passed to the ``byval`` argument. + ``dead_on_unwind`` At a high level, this attribute indicates that the pointer argument is dead if the call unwinds, in the sense that the caller will not depend on the diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index 13f3de07c3c44..0fdc3354753b1 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -2281,7 +2281,9 @@ DSEState::getInitializesArgMemLoc(const Instruction *I) { for (unsigned Idx = 0, Count = CB->arg_size(); Idx < Count; ++Idx) { ConstantRangeList Inits; Attribute InitializesAttr = CB->getParamAttr(Idx, Attribute::Initializes); - if (InitializesAttr.isValid()) + // initializes on byval arguments refers to the callee copy, not the + // original memory the caller passed in. + if (InitializesAttr.isValid() && !CB->isByValArgument(Idx)) Inits = InitializesAttr.getValueAsConstantRangeList(); Value *CurArg = CB->getArgOperand(Idx); diff --git a/llvm/test/Transforms/DeadStoreElimination/inter-procedural.ll b/llvm/test/Transforms/DeadStoreElimination/inter-procedural.ll index e590c5bf4004a..5f8ab56c22754 100644 --- a/llvm/test/Transforms/DeadStoreElimination/inter-procedural.ll +++ b/llvm/test/Transforms/DeadStoreElimination/inter-procedural.ll @@ -338,3 +338,17 @@ define i16 @global_var_alias() { ret i16 %l } +declare void @byval_fn(ptr byval(i32) initializes((0, 4)) %am) + +define void @test_byval() { +; CHECK-LABEL: @test_byval( +; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i32 0, ptr [[A]], align 4 +; CHECK-NEXT: call void @byval_fn(ptr [[A]]) +; CHECK-NEXT: ret void +; + %a = alloca i32 + store i32 0, ptr %a + call void @byval_fn(ptr %a) + ret void +}