[llvm] [MemCpyOpt] Clear writeonly from dest argument after call slot optimization (PR #95179)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 11 16:00:04 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Arthur Eubanks (aeubanks)
<details>
<summary>Changes</summary>
After call slot optimization, the function may read from the parameter even if it was previously writeonly (due to the only use of it being a memcpy to it). This can cause miscompiles, as seen in #<!-- -->95152.
This is essentially intersecting the implicit alloca attributes with the argument attributes.
No need to worry about readnone/readonly since the dest already has a memcpy to it, so it shouldn't be marked readnone/readonly.
Fixes #<!-- -->95152
---
Full diff: https://github.com/llvm/llvm-project/pull/95179.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp (+6)
- (added) llvm/test/Transforms/MemCpyOpt/callslot-writeonly.ll (+19)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 8fe3780bcf1b3..1cb37e5c7bc02 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1115,6 +1115,12 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
if (cpyLoad != cpyStore)
combineAAMetadata(C, cpyStore);
+ // Clear writeonly from the dest if it's an argument because we may now read
+ // from it in the call.
+ if (auto *A = dyn_cast<Argument>(cpyDest))
+ if (A->hasAttribute(Attribute::WriteOnly))
+ A->removeAttr(Attribute::WriteOnly);
+
++NumCallSlot;
return true;
}
diff --git a/llvm/test/Transforms/MemCpyOpt/callslot-writeonly.ll b/llvm/test/Transforms/MemCpyOpt/callslot-writeonly.ll
new file mode 100644
index 0000000000000..c336ccf8984f0
--- /dev/null
+++ b/llvm/test/Transforms/MemCpyOpt/callslot-writeonly.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=memcpyopt < %s | FileCheck %s
+
+; Check that we clear writeonly from the parameter when performing call slot optimization.
+
+define void @writeonly_param(ptr noalias writable writeonly dereferenceable(8) %dst) {
+; CHECK-LABEL: define void @writeonly_param(
+; CHECK-SAME: ptr noalias writable dereferenceable(8) [[DST:%.*]]) {
+; CHECK-NEXT: [[SRC:%.*]] = alloca i64, align 8
+; CHECK-NEXT: call void @accept_ptr(ptr nocapture [[DST]]) #[[ATTR1:[0-9]+]]
+; CHECK-NEXT: ret void
+;
+ %src = alloca i64, align 8
+ call void @accept_ptr(ptr nocapture %src) nounwind
+ call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dst, ptr %src, i64 8, i1 false)
+ ret void
+}
+
+declare void @accept_ptr(ptr)
``````````
</details>
https://github.com/llvm/llvm-project/pull/95179
More information about the llvm-commits
mailing list