Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions clang/test/CodeGen/PowerPC/inline-asm-constraints.c
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) {
return atomic_load((uint32_t*)argv[1], (uint32_t)*(argv[2]));
}
22 changes: 20 additions & 2 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
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);
Expand All @@ -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.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/PowerPC/inline-asm-constraints.ll
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 \
; 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
}
Loading