-
Notifications
You must be signed in to change notification settings - Fork 15.3k
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?
Changes from all commits
ab45984
37c382a
d05348b
d6e99ad
f5095e9
04e5e72
67a0f19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given what the checks are, main seems not needed. |
||
| return atomic_load((uint32_t*)argv[1], (uint32_t)*(argv[2])); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -411,11 +411,26 @@ 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) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 +440,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. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17882,6 +17882,7 @@ PPCTargetLowering::getConstraintType(StringRef Constraint) const { | |
| case 'y': | ||
| return C_RegisterClass; | ||
| case 'Z': | ||
| case 'Q': | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe put the 'Q' above the 'Z' so the comment is adjacent. |
||
| // 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 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 \ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lwat is a pwr9 instruction. I guess the cpu isn't checked for inline asm? But if we're going to specify a cpu it should probably be pwr9. |
||
| ; 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 | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think these 2 lines are needed.