-
Notifications
You must be signed in to change notification settings - Fork 14.9k
PowerPC: Support Q
constraint and P
modifier in Inline Asm
#163616
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
base: main
Are you sure you want to change the base?
Conversation
Constraint Q was not defined as a C_Memory constraint type in the PowerPC backend. This is a step towards supporting atomic memory operations using inline assembly.
A reduced test case revealed that input operand constraint modifiers, commonly known in llvm as Extra Codes, can be "weakly" diagnosed as "invalid operand in inline asm". This change adds further diagnostics to state "Unknown modifier in inline asm" when the extra code switch statement defaults.
The `P` constraint argument modifier is an GCC extended inline asm feature that has been observed to translate to an X-Form [Reg] register allocation and address mode encoding. i.e `ldx R<In>, %P<Op1>, R<Op2> == ldx r3, r1, r2`. This allows users to modify the default addressing mode, D-Form, to X-Form for `Q`, `m`, and `Z`, inline asm constraint types. These constraints produce `<Offset>([reg])` otherwise.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-backend-powerpc Author: Kamau Bridgeman (kamaub) ChangesSupport atomic memory operations by enabling
Full diff: https://github.com/llvm/llvm-project/pull/163616.diff 4 Files Affected:
diff --git a/clang/test/CodeGen/PowerPC/inline-asm-constraints.c b/clang/test/CodeGen/PowerPC/inline-asm-constraints.c
new file mode 100644
index 0000000000000..1464500359046
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/inline-asm-constraints.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -emit-llvm -triple powerpc64-ibm-aix-xcoff \
+// RUN: %s -o - | FileCheck %s
+
+#include <stdint.h>
+
+// Test Atomic Memory Operation Support:
+// This test case takes an address and performs an atomic load at that address.
+// The purpose is to test the Q machine constraint and P machine constraint
+// argument modifier together.
+// These constraints on the pointer `ptr` read as: constrain (uint32_t*)ptr to
+// read and writeable X-Form Addressed Memory operands.
+static __attribute__((noinline))
+uint32_t atomic_load(uint32_t *ptr, uint32_t val)
+{
+// CHECK-LABEL: define{{.*}} i32 @atomic_load(ptr noundef %ptr, i32 noundef zeroext %val)
+// CHECK: %3 = call { i128, i32 } asm sideeffect "mr ${1:L},$3\0A\09 lwat $1,${0:P},$4\0A\09 mr $2,$1\0A", "=*Q,=&r,=r,r,n,0"(ptr elementtype(i32) %arrayidx, i32 %2, i32 0, i32 %1)
+ unsigned __int128 tmp;
+ uint32_t ret;
+ __asm__ volatile ("mr %L1,%3\n"
+ "\t lwat %1,%P0,%4\n"
+ "\t mr %2,%1\n"
+ : "+Q" (ptr[0]), "=&r" (tmp), "=r" (ret)
+ : "r" (val), "n" (0x00));
+ return ret;
+}
+
+int main(int argc, char **argv) {
+ return atomic_load((uint32_t*)argv[1], (uint32_t)*(argv[2]));
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index bcb3f507e98d6..2e31ea7392aeb 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -411,11 +411,24 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode,
raw_ostream &O) {
+ auto reportAsmMemError = [&] (StringRef errMsg) {
+ const char *AsmStr = MI->getOperand(0).getSymbolName();
+ const MDNode *LocMD = MI->getLocCookieMD();
+ uint64_t LocCookie = LocMD ?
+ mdconst::extract<ConstantInt>(LocMD->getOperand(0))->getZExtValue() : 0;
+ const Function &Fn = MI->getMF()->getFunction();
+ Fn.getContext().diagnose(DiagnosticInfoInlineAsm(
+ LocCookie, errMsg + Twine(AsmStr) + "'"));
+ return true;
+ };
if (ExtraCode && ExtraCode[0]) {
- if (ExtraCode[1] != 0) return true; // Unknown modifier.
+ if (ExtraCode[1] != 0)
+ return reportAsmMemError("Unknown modifier in inline asm:");
switch (ExtraCode[0]) {
- default: return true; // Unknown modifier.
+ default: {
+ return reportAsmMemError("Unknown modifier in inline asm:");
+ }
case 'L': // A memory reference to the upper word of a double word op.
O << getDataLayout().getPointerSize() << "(";
printOperand(MI, OpNo, O);
@@ -425,6 +438,9 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
O << "0, ";
printOperand(MI, OpNo, O);
return false;
+ case 'P': // A memory reference for an single inout to an X-form instr.
+ printOperand(MI, OpNo, O);
+ return false;
case 'I':
// Write 'i' if an integer constant, otherwise nothing. Used to print
// addi vs add, etc.
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 8bf0d118da575..de26677c161d1 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -17882,6 +17882,7 @@ PPCTargetLowering::getConstraintType(StringRef Constraint) const {
case 'y':
return C_RegisterClass;
case 'Z':
+ case 'Q':
// FIXME: While Z does indicate a memory constraint, it specifically
// indicates an r+r address (used in conjunction with the 'y' modifier
// in the replacement string). Currently, we're forcing the base
diff --git a/llvm/test/CodeGen/PowerPC/inline-asm-constraints.ll b/llvm/test/CodeGen/PowerPC/inline-asm-constraints.ll
new file mode 100644
index 0000000000000..72d370ce8567f
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/inline-asm-constraints.ll
@@ -0,0 +1,21 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -verify-machineinstrs < %s -mcpu=pwr8 \
+; RUN: -mtriple=powerpc64-ibm-aix-xcoff | FileCheck %s
+
+define zeroext i32 @atomic_load(ptr %ptr, i32 zeroext range(i32 0, 256) %val) {
+; CHECK-LABEL: atomic_load:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: mr 6, 4
+; CHECK-NEXT: lwat 5, 3, 0
+; CHECK-NEXT: mr 3, 5
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: clrldi 3, 3, 32
+; CHECK-NEXT: blr
+entry:
+ %0 = load i32, ptr %ptr, align 4
+ %1 = tail call { i128, i32 } asm sideeffect "mr ${1:L},$3\0A\09 lwat $1,${0:P},$4\0A\09 mr $2,$1\0A", "=*Q,=&r,=r,r,n,0"(ptr nonnull elementtype(i32) %ptr, i32 %val, i32 0, i32 %0)
+ %asmresult1 = extractvalue { i128, i32 } %1, 1
+ ret i32 %asmresult1
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Q
constraint and P
modifier in Inline Asm
Increase GCC extended ASM Support by enabling
P
argument modifiedQ
constrained inputs to inline assembly memory operations.
Constraint Q was not defined as a C_Memory constraint type in the
PowerPC backend.
The
P
constraint argument modifier is an GCC extended inline asm feature thathas been observed to translate to an X-Form [Reg] register allocation and
address mode encoding. i.e
ldx R<In>, %P<Op1>, R<Op2> == ldx r3, r1, r2
.This allows users to modify the default addressing mode, D-Form,
to X-Form for
Q
,m
, andZ
, inline asm constraint types.These constraints produce
<Offset>([reg])
otherwise.References: