[llvm] [SafeStack] Don't move a scalable byval argument to the unsafe stack (PR #225067)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 04:43:02 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Timur Baidusenov (bai-tim)

<details>
<summary>Changes</summary>

The unsafe stack frame is laid out at compile time, but the size of a byval argument of a scalable type is not known then, so getTypeStoreSize() aborts with "Cannot implicitly convert a scalable size to a fixed-width size" before the argument is even classified. Skip it, the way MemCpyOpt bails out of the call-slot optimization for a byval argument of the same shape; the earlier 537f3d3a7588 fixed the other half of #<!-- -->182759, where the size of an access rather than of an argument was scalable.

Fixes #<!-- -->182759.

---
Full diff: https://github.com/llvm/llvm-project/pull/225067.diff


2 Files Affected:

- (modified) llvm/lib/CodeGen/SafeStack.cpp (+7-2) 
- (modified) llvm/test/CodeGen/AArch64/safestack_scalar.ll (+26) 


``````````diff
diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp
index 75a8762cc7090..07d8854a1629e 100644
--- a/llvm/lib/CodeGen/SafeStack.cpp
+++ b/llvm/lib/CodeGen/SafeStack.cpp
@@ -418,8 +418,13 @@ void SafeStack::findInsts(Function &F,
   for (Argument &Arg : F.args()) {
     if (!Arg.hasByValAttr())
       continue;
-    uint64_t Size = DL.getTypeStoreSize(Arg.getParamByValType());
-    if (IsSafeStackAlloca(&Arg, Size))
+    TypeSize Size = DL.getTypeStoreSize(Arg.getParamByValType());
+    // The unsafe stack frame is laid out at compile time, so an argument of a
+    // scalable type has no place on it. Leave it on the regular stack rather
+    // than reject a function that is otherwise valid.
+    if (Size.isScalable())
+      continue;
+    if (IsSafeStackAlloca(&Arg, Size.getFixedValue()))
       continue;
 
     ++NumUnsafeByValArguments;
diff --git a/llvm/test/CodeGen/AArch64/safestack_scalar.ll b/llvm/test/CodeGen/AArch64/safestack_scalar.ll
index f8675e7a709d3..0488218b6c848 100644
--- a/llvm/test/CodeGen/AArch64/safestack_scalar.ll
+++ b/llvm/test/CodeGen/AArch64/safestack_scalar.ll
@@ -15,3 +15,29 @@ entry:
 ; CHECK: load <vscale x 16 x i8>, ptr [[PTR]]
 ; CHECK: store ptr [[USP]], ptr @__safestack_unsafe_stack_ptr
 ; CHECK: ret void
+
+declare void @escape(ptr)
+
+; A byval argument of a scalable type has no size known at compile time, so it
+; cannot be placed on the unsafe stack frame and is left alone.
+
+define void @test_sve_byval(ptr byval(<vscale x 4 x i32>) %p) safestack {
+  call void @escape(ptr %p)
+  ret void
+}
+
+; CHECK-LABEL: define void @test_sve_byval(
+; CHECK-NEXT: call void @escape(ptr %p)
+; CHECK-NEXT: ret void
+
+; A byval argument of a fixed size is still copied onto the unsafe stack.
+
+define void @test_byval(ptr byval([16 x i8]) %p) safestack {
+  call void @escape(ptr %p)
+  ret void
+}
+
+; CHECK-LABEL: define void @test_byval(
+; CHECK: load ptr, ptr @__safestack_unsafe_stack_ptr
+; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[SLOT:%.*]], ptr %p, i64 16, i1 false)
+; CHECK: call void @escape(ptr [[SLOT]])

``````````

</details>


https://github.com/llvm/llvm-project/pull/225067


More information about the llvm-commits mailing list