Skip to content

[AArch64] Mark neon.stN intrinsics as writeonly #145289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 1, 2025

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Jun 23, 2025

I found this peculiar comment in EarlyCSE:

// from memory in the exception handler), forget LastStore. Load/store
// intrinsics will indicate both a read and a write to memory. The target
// may override this (e.g. so that a store intrinsic does not read from
// memory, and thus will be treated the same as a regular store for
// commoning purposes).

Looking back over history, this seems to be referring to the aarch64.neon.stN intrinsics, which are indeed not marked writeonly (though the ldN intrinsics are readonly).

Possibly I'm missing something special about these intrinsics, but I think it is safe to mark them as writeonly.

@llvmbot
Copy link
Member

llvmbot commented Jun 23, 2025

@llvm/pr-subscribers-backend-arm
@llvm/pr-subscribers-llvm-analysis
@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-backend-aarch64

Author: Nikita Popov (nikic)

Changes

I found this peculiar comment in EarlyCSE:

// from memory in the exception handler), forget LastStore. Load/store
// intrinsics will indicate both a read and a write to memory. The target
// may override this (e.g. so that a store intrinsic does not read from
// memory, and thus will be treated the same as a regular store for
// commoning purposes).

Looking back over history, this seems to be referring to the aarch64.neon.stN intrinsics, which are indeed not marked writeonly (though the ldN intrinsics are readonly).

Possibly I'm missing something special about these intrinsics, but I think it is safe to mark them as writeonly.


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

1 Files Affected:

  • (modified) llvm/include/llvm/IR/IntrinsicsAArch64.td (+7-7)
diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 0ec5f5163118e..3606bbe29eb93 100644
--- a/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -612,7 +612,7 @@ let TargetPrefix = "aarch64" in {  // All intrinsics start with "llvm.aarch64.".
                   [IntrReadMem, IntrArgMemOnly]>;
   class AdvSIMD_1Vec_Store_Lane_Intrinsic
     : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, llvm_i64_ty, llvm_anyptr_ty],
-                [IntrArgMemOnly, NoCapture<ArgIndex<2>>]>;
+                [IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<2>>]>;
 
   class AdvSIMD_2Vec_Load_Intrinsic
     : DefaultAttrsIntrinsic<[LLVMMatchType<0>, llvm_anyvector_ty],
@@ -626,11 +626,11 @@ let TargetPrefix = "aarch64" in {  // All intrinsics start with "llvm.aarch64.".
   class AdvSIMD_2Vec_Store_Intrinsic
     : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
                      llvm_anyptr_ty],
-                [IntrArgMemOnly, NoCapture<ArgIndex<2>>]>;
+                [IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<2>>]>;
   class AdvSIMD_2Vec_Store_Lane_Intrinsic
     : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
                  llvm_i64_ty, llvm_anyptr_ty],
-                [IntrArgMemOnly, NoCapture<ArgIndex<3>>]>;
+                [IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<3>>]>;
 
   class AdvSIMD_3Vec_Load_Intrinsic
     : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty],
@@ -644,12 +644,12 @@ let TargetPrefix = "aarch64" in {  // All intrinsics start with "llvm.aarch64.".
   class AdvSIMD_3Vec_Store_Intrinsic
     : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
                      LLVMMatchType<0>, llvm_anyptr_ty],
-                [IntrArgMemOnly, NoCapture<ArgIndex<3>>]>;
+                [IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<3>>]>;
   class AdvSIMD_3Vec_Store_Lane_Intrinsic
     : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty,
                  LLVMMatchType<0>, LLVMMatchType<0>,
                  llvm_i64_ty, llvm_anyptr_ty],
-                [IntrArgMemOnly, NoCapture<ArgIndex<4>>]>;
+                [IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<4>>]>;
 
   class AdvSIMD_4Vec_Load_Intrinsic
     : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>,
@@ -667,12 +667,12 @@ let TargetPrefix = "aarch64" in {  // All intrinsics start with "llvm.aarch64.".
     : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
                  LLVMMatchType<0>, LLVMMatchType<0>,
                  llvm_anyptr_ty],
-                [IntrArgMemOnly, NoCapture<ArgIndex<4>>]>;
+                [IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<4>>]>;
   class AdvSIMD_4Vec_Store_Lane_Intrinsic
     : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
                  LLVMMatchType<0>, LLVMMatchType<0>,
                  llvm_i64_ty, llvm_anyptr_ty],
-                [IntrArgMemOnly, NoCapture<ArgIndex<5>>]>;
+                [IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<5>>]>;
 }
 
 // Memory ops

@davemgreen davemgreen requested a review from efriedma-quic June 23, 2025 15:36
@davemgreen
Copy link
Collaborator

I don't know of a reason why this would be a problem. The MVE intrinsics already specify IntrWriteMem. Should we add it to the similar Arm neon intrinsics too, either here or in a followup?

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine; the intrinsics are supposed to have the same memory semantics as normal IR operations. (We currently don't provide "volatile" variants. You can use inline asm if you really need that for some strange reason.)

Please add a regression test of some sort to track that we've added this marking.

nikic added 3 commits June 30, 2025 12:10
I found this peculiar comment in EarlyCSE:
https://github.com/llvm/llvm-project/blob/1c78d8d9d7bcb4b20910047ad7db35f177a17c8c/llvm/lib/Transforms/Scalar/EarlyCSE.cpp#L1620-L1624

Looking back over history, this seems to be referring to the
aarch64.neon.stN intrinsics, which are indeed not marked writeonly
(though the ldN intrinsics are readonly).

Unless I'm missing something, these do not read memory.
@nikic nikic force-pushed the aarch64-store-intrinsics branch from 1bd17a7 to 25bc66c Compare June 30, 2025 10:50
@llvmbot llvmbot added backend:ARM llvm:analysis Includes value tracking, cost tables and constant folding labels Jun 30, 2025
@nikic
Copy link
Contributor Author

nikic commented Jun 30, 2025

I don't know of a reason why this would be a problem. The MVE intrinsics already specify IntrWriteMem. Should we add it to the similar Arm neon intrinsics too, either here or in a followup?

I've added the Arm variants now as well.

Copy link
Collaborator

@davemgreen davemgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nikic nikic merged commit a6592dd into llvm:main Jul 1, 2025
7 of 9 checks passed
@nikic nikic deleted the aarch64-store-intrinsics branch July 1, 2025 13:56
rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
I found this peculiar comment in EarlyCSE:

https://github.com/llvm/llvm-project/blob/1c78d8d9d7bcb4b20910047ad7db35f177a17c8c/llvm/lib/Transforms/Scalar/EarlyCSE.cpp#L1620-L1624

Looking back over history, this seems to be referring to the
aarch64.neon.stN intrinsics, which are indeed not marked writeonly
(though the ldN intrinsics are readonly).

Possibly I'm missing something special about these intrinsics, but I
think it is safe to mark them as writeonly.
rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
I found this peculiar comment in EarlyCSE:

https://github.com/llvm/llvm-project/blob/1c78d8d9d7bcb4b20910047ad7db35f177a17c8c/llvm/lib/Transforms/Scalar/EarlyCSE.cpp#L1620-L1624

Looking back over history, this seems to be referring to the
aarch64.neon.stN intrinsics, which are indeed not marked writeonly
(though the ldN intrinsics are readonly).

Possibly I'm missing something special about these intrinsics, but I
think it is safe to mark them as writeonly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 backend:ARM llvm:analysis Includes value tracking, cost tables and constant folding llvm:ir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants