[clang] [llvm] [X86] Accept 'a' modifier for 'p' constraint in inline asm (PR #185590)
Fangrui Song via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 10 10:28:19 PDT 2026
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/185590
>From 6d59200f6edcf635a5b61b4896d8e40df9ddc523 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 9 Mar 2026 23:46:36 -0700
Subject: [PATCH 1/2] [X86] Accept 'a' modifier for 'p' constraint in inline
asm
GCC requires the %a modifier with the p constraint (e.g., %a0), while
Clang rejected it. The 'a' modifier means "print as address", which on
a 'p' constraint memory operand is what the default path already does.
Like GCC, reject 'a' with other memory constraints (e.g. 'm').
Close https://github.com/llvm/llvm-project/issues/185343
---
.../test/CodeGen/X86/inline-asm-constraints.c | 12 ++++++--
llvm/lib/Target/X86/X86AsmPrinter.cpp | 7 +++++
llvm/test/CodeGen/X86/asm-modifier-error.ll | 6 ++++
llvm/test/CodeGen/X86/asm-modifier.ll | 30 +++++++++++++++++++
4 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/clang/test/CodeGen/X86/inline-asm-constraints.c b/clang/test/CodeGen/X86/inline-asm-constraints.c
index c89d94cab946b..ab61e99103df5 100644
--- a/clang/test/CodeGen/X86/inline-asm-constraints.c
+++ b/clang/test/CodeGen/X86/inline-asm-constraints.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu x86-64 -o - |FileCheck %s --check-prefix SSE
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu x86-64 -o - | FileCheck %s --check-prefixes=CHECK,SSE
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu skylake -D AVX -o - | FileCheck %s --check-prefixes AVX,SSE
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu skylake-avx512 -D AVX512 -D AVX -o - | FileCheck %s --check-prefixes AVX512,AVX,SSE
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu knl -D AVX -D AVX512 -o - | FileCheck %s --check-prefixes AVX512,AVX,SSE
@@ -54,12 +54,18 @@ __m512 testZMM0(void) {
return zmm0;
}
+// CHECK-LABEL: test_a_p(
+// CHECK: call void asm sideeffect "lea ${0:a}, %eax", "p,~{eax},~{dirflag},~{fpsr},~{flags}"(ptr %0)
+void test_a_p(int *ptr) {
+ asm("lea %a0, %%eax" :: "p"(ptr) : "eax");
+}
+
extern int var, arr[4];
struct Pair { int a, b; } pair;
// CHECK-LABEL: test_Ws(
-// CHECK: call void asm sideeffect "// ${0:p} ${1:p} ${2:p}", "^Ws,^Ws,^Ws,~{dirflag},~{fpsr},~{flags}"(ptr @var, ptr getelementptr inbounds ([4 x i32], ptr @arr, i64 0, i64 3), ptr @test_Ws)
-// CHECK: call void asm sideeffect "// $0", "^Ws,~{dirflag},~{fpsr},~{flags}"(ptr getelementptr inbounds (%struct.Pair, ptr @pair, i32 0, i32 1))
+// CHECK: call void asm sideeffect "// ${0:p} ${1:p} ${2:p}", "^Ws,^Ws,^Ws,~{dirflag},~{fpsr},~{flags}"(ptr @var, ptr getelementptr inbounds nuw (i8, ptr @arr, i64 12), ptr @test_Ws)
+// CHECK: call void asm sideeffect "// $0", "^Ws,~{dirflag},~{fpsr},~{flags}"(ptr getelementptr inbounds nuw (i8, ptr @pair, i64 4))
void test_Ws(void) {
asm("// %p0 %p1 %p2" :: "Ws"(&var), "Ws"(&arr[3]), "Ws"(test_Ws));
asm("// %0" :: "Ws"(&pair.b));
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index 84203c4b3da63..992040c46ceda 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -867,6 +867,13 @@ bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
+ case 'a': {
+ // Print as address — only valid with 'p' constraint.
+ const InlineAsm::Flag Flags(MI->getOperand(OpNo - 1).getImm());
+ if (Flags.getMemoryConstraintID() != InlineAsm::ConstraintCode::p)
+ return true;
+ break;
+ }
case 'b': // Print QImode register
case 'h': // Print QImode high register
case 'w': // Print HImode register
diff --git a/llvm/test/CodeGen/X86/asm-modifier-error.ll b/llvm/test/CodeGen/X86/asm-modifier-error.ll
index 2d942c01fe0de..bea96a8253ddc 100644
--- a/llvm/test/CodeGen/X86/asm-modifier-error.ll
+++ b/llvm/test/CodeGen/X86/asm-modifier-error.ll
@@ -7,6 +7,12 @@ entry:
ret void
}
+; CHECK: error: invalid operand in inline asm: '#TEST ${0:a}'
+define void @test_a_m(ptr %p) {
+ call void asm sideeffect "#TEST ${0:a}", "*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) %p)
+ ret void
+}
+
;CHECK: error: invalid operand in inline asm: 'vmovd ${1:k}, $0'
define i32 @foo() {
entry:
diff --git a/llvm/test/CodeGen/X86/asm-modifier.ll b/llvm/test/CodeGen/X86/asm-modifier.ll
index 7fa1e34a288da..e1aac95a1ff6a 100644
--- a/llvm/test/CodeGen/X86/asm-modifier.ll
+++ b/llvm/test/CodeGen/X86/asm-modifier.ll
@@ -23,6 +23,36 @@ define dso_local void @test_a() nounwind {
ret void
}
+define dso_local void @test_a_p(ptr %p) nounwind {
+; X86-LABEL: test_a_p:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: #APP
+; X86-NEXT: #TEST (%eax)
+; X86-NEXT: #NO_APP
+; X86-NEXT: #APP
+; X86-EMPTY:
+; X86-NEXT: #TEST [eax]
+; X86-EMPTY:
+; X86-NEXT: #NO_APP
+; X86-NEXT: retl
+;
+; X64-LABEL: test_a_p:
+; X64: # %bb.0:
+; X64-NEXT: #APP
+; X64-NEXT: #TEST (%rdi)
+; X64-NEXT: #NO_APP
+; X64-NEXT: #APP
+; X64-EMPTY:
+; X64-NEXT: #TEST [rdi]
+; X64-EMPTY:
+; X64-NEXT: #NO_APP
+; X64-NEXT: retq
+ tail call void asm sideeffect "#TEST ${0:a}", "p,~{dirflag},~{fpsr},~{flags}"(ptr %p)
+ tail call void asm sideeffect inteldialect "#TEST ${0:a}", "p,~{dirflag},~{fpsr},~{flags}"(ptr %p)
+ ret void
+}
+
define dso_local void @test_c() nounwind {
; CHECK-LABEL: test_c:
; CHECK: # %bb.0:
>From c09f1ce8d31f8b882d144a27596d381e75136b39 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Tue, 10 Mar 2026 00:47:42 -0700
Subject: [PATCH 2/2] improve clang test
---
clang/test/CodeGen/X86/inline-asm-constraints.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/clang/test/CodeGen/X86/inline-asm-constraints.c b/clang/test/CodeGen/X86/inline-asm-constraints.c
index ab61e99103df5..20c4e26ddffe5 100644
--- a/clang/test/CodeGen/X86/inline-asm-constraints.c
+++ b/clang/test/CodeGen/X86/inline-asm-constraints.c
@@ -56,8 +56,10 @@ __m512 testZMM0(void) {
// CHECK-LABEL: test_a_p(
// CHECK: call void asm sideeffect "lea ${0:a}, %eax", "p,~{eax},~{dirflag},~{fpsr},~{flags}"(ptr %0)
-void test_a_p(int *ptr) {
+// CHECK: call void asm sideeffect "lea ${0:a}, %eax", "p,~{eax},~{dirflag},~{fpsr},~{flags}"(i32 %add)
+void test_a_p(int *ptr, int i) {
asm("lea %a0, %%eax" :: "p"(ptr) : "eax");
+ asm("lea %a0, %%eax" :: "p"(0x1480 + i * 8) : "eax");
}
extern int var, arr[4];
More information about the cfe-commits
mailing list