Skip to content

Commit 3fda1fd

Browse files
committed
AMDGPU/GlobalISel: Support llvm.trap and llvm.debugtrap intrinsics
Summary: Lower trap and debugtrap intrinsics to AMDGPU machine instruction(s). Reviewers: arsenm, nhaehnle, kerbowa, cdevadas, t-tye, kzhuravl Reviewed By: arsenm Subscribers: kzhuravl, jvesely, wdng, yaxunl, rovka, dstuttard, tpr, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D74688
1 parent b3722de commit 3fda1fd

File tree

3 files changed

+157
-44
lines changed

3 files changed

+157
-44
lines changed

llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp

Lines changed: 128 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,28 +2255,79 @@ static MachineInstr *verifyCFIntrinsic(MachineInstr &MI,
22552255
return &UseMI;
22562256
}
22572257

2258-
Register AMDGPULegalizerInfo::getLiveInRegister(MachineRegisterInfo &MRI,
2259-
Register Reg, LLT Ty) const {
2260-
Register LiveIn = MRI.getLiveInVirtReg(Reg);
2261-
if (LiveIn)
2258+
Register AMDGPULegalizerInfo::insertLiveInCopy(MachineIRBuilder &B,
2259+
MachineRegisterInfo &MRI,
2260+
Register LiveIn,
2261+
Register PhyReg) const {
2262+
assert(PhyReg.isPhysical() && "Physical register expected");
2263+
2264+
// Insert the live-in copy, if required, by defining destination virtual
2265+
// register.
2266+
// FIXME: It seems EmitLiveInCopies isn't called anywhere?
2267+
if (!MRI.getVRegDef(LiveIn)) {
2268+
// FIXME: Should have scoped insert pt
2269+
MachineBasicBlock &OrigInsBB = B.getMBB();
2270+
auto OrigInsPt = B.getInsertPt();
2271+
2272+
MachineBasicBlock &EntryMBB = B.getMF().front();
2273+
EntryMBB.addLiveIn(PhyReg);
2274+
B.setInsertPt(EntryMBB, EntryMBB.begin());
2275+
B.buildCopy(LiveIn, PhyReg);
2276+
2277+
B.setInsertPt(OrigInsBB, OrigInsPt);
2278+
}
2279+
2280+
return LiveIn;
2281+
}
2282+
2283+
Register AMDGPULegalizerInfo::getLiveInRegister(MachineIRBuilder &B,
2284+
MachineRegisterInfo &MRI,
2285+
Register PhyReg, LLT Ty,
2286+
bool InsertLiveInCopy) const {
2287+
assert(PhyReg.isPhysical() && "Physical register expected");
2288+
2289+
// Get or create virtual live-in regester
2290+
Register LiveIn = MRI.getLiveInVirtReg(PhyReg);
2291+
if (!LiveIn) {
2292+
LiveIn = MRI.createGenericVirtualRegister(Ty);
2293+
MRI.addLiveIn(PhyReg, LiveIn);
2294+
}
2295+
2296+
// When the actual true copy required is from virtual register to physical
2297+
// register (to be inserted later), live-in copy insertion from physical
2298+
// to register virtual register is not required
2299+
if (!InsertLiveInCopy)
22622300
return LiveIn;
22632301

2264-
Register NewReg = MRI.createGenericVirtualRegister(Ty);
2265-
MRI.addLiveIn(Reg, NewReg);
2266-
return NewReg;
2302+
return insertLiveInCopy(B, MRI, LiveIn, PhyReg);
2303+
}
2304+
2305+
const ArgDescriptor *AMDGPULegalizerInfo::getArgDescriptor(
2306+
MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const {
2307+
const SIMachineFunctionInfo *MFI = B.getMF().getInfo<SIMachineFunctionInfo>();
2308+
const ArgDescriptor *Arg;
2309+
const TargetRegisterClass *RC;
2310+
std::tie(Arg, RC) = MFI->getPreloadedValue(ArgType);
2311+
if (!Arg) {
2312+
LLVM_DEBUG(dbgs() << "Required arg register missing\n");
2313+
return nullptr;
2314+
}
2315+
return Arg;
22672316
}
22682317

22692318
bool AMDGPULegalizerInfo::loadInputValue(Register DstReg, MachineIRBuilder &B,
22702319
const ArgDescriptor *Arg) const {
22712320
if (!Arg->isRegister() || !Arg->getRegister().isValid())
22722321
return false; // TODO: Handle these
22732322

2274-
assert(Arg->getRegister().isPhysical());
2323+
Register SrcReg = Arg->getRegister();
2324+
assert(SrcReg.isPhysical() && "Physical register expected");
2325+
assert(DstReg.isVirtual() && "Virtual register expected");
22752326

22762327
MachineRegisterInfo &MRI = *B.getMRI();
22772328

22782329
LLT Ty = MRI.getType(DstReg);
2279-
Register LiveIn = getLiveInRegister(MRI, Arg->getRegister(), Ty);
2330+
Register LiveIn = getLiveInRegister(B, MRI, SrcReg, Ty);
22802331

22812332
if (Arg->isMasked()) {
22822333
// TODO: Should we try to emit this once in the entry block?
@@ -2292,50 +2343,27 @@ bool AMDGPULegalizerInfo::loadInputValue(Register DstReg, MachineIRBuilder &B,
22922343
}
22932344

22942345
B.buildAnd(DstReg, AndMaskSrc, B.buildConstant(S32, Mask >> Shift));
2295-
} else
2346+
} else {
22962347
B.buildCopy(DstReg, LiveIn);
2297-
2298-
// Insert the argument copy if it doens't already exist.
2299-
// FIXME: It seems EmitLiveInCopies isn't called anywhere?
2300-
if (!MRI.getVRegDef(LiveIn)) {
2301-
// FIXME: Should have scoped insert pt
2302-
MachineBasicBlock &OrigInsBB = B.getMBB();
2303-
auto OrigInsPt = B.getInsertPt();
2304-
2305-
MachineBasicBlock &EntryMBB = B.getMF().front();
2306-
EntryMBB.addLiveIn(Arg->getRegister());
2307-
B.setInsertPt(EntryMBB, EntryMBB.begin());
2308-
B.buildCopy(LiveIn, Arg->getRegister());
2309-
2310-
B.setInsertPt(OrigInsBB, OrigInsPt);
23112348
}
23122349

23132350
return true;
23142351
}
23152352

23162353
bool AMDGPULegalizerInfo::legalizePreloadedArgIntrin(
2317-
MachineInstr &MI,
2318-
MachineRegisterInfo &MRI,
2319-
MachineIRBuilder &B,
2320-
AMDGPUFunctionArgInfo::PreloadedValue ArgType) const {
2354+
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B,
2355+
AMDGPUFunctionArgInfo::PreloadedValue ArgType) const {
23212356
B.setInstr(MI);
23222357

2323-
const SIMachineFunctionInfo *MFI = B.getMF().getInfo<SIMachineFunctionInfo>();
2324-
2325-
const ArgDescriptor *Arg;
2326-
const TargetRegisterClass *RC;
2327-
std::tie(Arg, RC) = MFI->getPreloadedValue(ArgType);
2328-
if (!Arg) {
2329-
LLVM_DEBUG(dbgs() << "Required arg register missing\n");
2358+
const ArgDescriptor *Arg = getArgDescriptor(B, ArgType);
2359+
if (!Arg)
23302360
return false;
2331-
}
23322361

2333-
if (loadInputValue(MI.getOperand(0).getReg(), B, Arg)) {
2334-
MI.eraseFromParent();
2335-
return true;
2336-
}
2362+
if (!loadInputValue(MI.getOperand(0).getReg(), B, Arg))
2363+
return false;
23372364

2338-
return false;
2365+
MI.eraseFromParent();
2366+
return true;
23392367
}
23402368

23412369
bool AMDGPULegalizerInfo::legalizeFDIV(MachineInstr &MI,
@@ -3558,6 +3586,61 @@ bool AMDGPULegalizerInfo::legalizeSBufferLoad(
35583586
return true;
35593587
}
35603588

3589+
bool AMDGPULegalizerInfo::legalizeTrapIntrinsic(MachineInstr &MI,
3590+
MachineRegisterInfo &MRI,
3591+
MachineIRBuilder &B) const {
3592+
B.setInstr(MI);
3593+
3594+
// Is non-HSA path or trap-handler disabled? then, insert s_endpgm instruction
3595+
if (ST.getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbiHsa ||
3596+
!ST.isTrapHandlerEnabled()) {
3597+
B.buildInstr(AMDGPU::S_ENDPGM).addImm(0);
3598+
} else {
3599+
// Pass queue pointer to trap handler as input, and insert trap instruction
3600+
// Reference: https://llvm.org/docs/AMDGPUUsage.html#trap-handler-abi
3601+
const ArgDescriptor *Arg =
3602+
getArgDescriptor(B, AMDGPUFunctionArgInfo::QUEUE_PTR);
3603+
if (!Arg)
3604+
return false;
3605+
MachineRegisterInfo &MRI = *B.getMRI();
3606+
Register SGPR01(AMDGPU::SGPR0_SGPR1);
3607+
Register LiveIn = getLiveInRegister(
3608+
B, MRI, SGPR01, LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64),
3609+
/*InsertLiveInCopy=*/false);
3610+
if (!loadInputValue(LiveIn, B, Arg))
3611+
return false;
3612+
B.buildCopy(SGPR01, LiveIn);
3613+
B.buildInstr(AMDGPU::S_TRAP)
3614+
.addImm(GCNSubtarget::TrapIDLLVMTrap)
3615+
.addReg(SGPR01, RegState::Implicit);
3616+
}
3617+
3618+
MI.eraseFromParent();
3619+
return true;
3620+
}
3621+
3622+
bool AMDGPULegalizerInfo::legalizeDebugTrapIntrinsic(
3623+
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const {
3624+
B.setInstr(MI);
3625+
3626+
// Is non-HSA path or trap-handler disabled? then, report a warning
3627+
// accordingly
3628+
if (ST.getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbiHsa ||
3629+
!ST.isTrapHandlerEnabled()) {
3630+
DiagnosticInfoUnsupported NoTrap(B.getMF().getFunction(),
3631+
"debugtrap handler not supported",
3632+
MI.getDebugLoc(), DS_Warning);
3633+
LLVMContext &Ctx = B.getMF().getFunction().getContext();
3634+
Ctx.diagnose(NoTrap);
3635+
} else {
3636+
// Insert debug-trap instruction
3637+
B.buildInstr(AMDGPU::S_TRAP).addImm(GCNSubtarget::TrapIDLLVMDebugTrap);
3638+
}
3639+
3640+
MI.eraseFromParent();
3641+
return true;
3642+
}
3643+
35613644
bool AMDGPULegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
35623645
MachineIRBuilder &B,
35633646
GISelChangeObserver &Observer) const {
@@ -3732,6 +3815,10 @@ bool AMDGPULegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
37323815
return legalizeAtomicIncDec(MI, B, true);
37333816
case Intrinsic::amdgcn_atomic_dec:
37343817
return legalizeAtomicIncDec(MI, B, false);
3818+
case Intrinsic::trap:
3819+
return legalizeTrapIntrinsic(MI, MRI, B);
3820+
case Intrinsic::debugtrap:
3821+
return legalizeDebugTrapIntrinsic(MI, MRI, B);
37353822
default: {
37363823
if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
37373824
AMDGPU::getImageDimIntrinsicInfo(IntrID))

llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,14 @@ class AMDGPULegalizerInfo : public LegalizerInfo {
8989
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI,
9090
MachineIRBuilder &B) const;
9191

92-
Register getLiveInRegister(MachineRegisterInfo &MRI,
93-
Register Reg, LLT Ty) const;
94-
92+
Register getLiveInRegister(MachineIRBuilder &B, MachineRegisterInfo &MRI,
93+
Register PhyReg, LLT Ty,
94+
bool InsertLiveInCopy = true) const;
95+
Register insertLiveInCopy(MachineIRBuilder &B, MachineRegisterInfo &MRI,
96+
Register LiveIn, Register PhyReg) const;
97+
const ArgDescriptor *
98+
getArgDescriptor(MachineIRBuilder &B,
99+
AMDGPUFunctionArgInfo::PreloadedValue ArgType) const;
95100
bool loadInputValue(Register DstReg, MachineIRBuilder &B,
96101
const ArgDescriptor *Arg) const;
97102
bool legalizePreloadedArgIntrin(
@@ -163,6 +168,11 @@ class AMDGPULegalizerInfo : public LegalizerInfo {
163168
bool legalizeAtomicIncDec(MachineInstr &MI, MachineIRBuilder &B,
164169
bool IsInc) const;
165170

171+
bool legalizeTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
172+
MachineIRBuilder &B) const;
173+
bool legalizeDebugTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
174+
MachineIRBuilder &B) const;
175+
166176
bool legalizeIntrinsic(MachineInstr &MI, MachineIRBuilder &B,
167177
GISelChangeObserver &Observer) const override;
168178
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; Runs original SDAG test with -global-isel
2+
; RUN: llc -global-isel -mtriple=amdgcn--amdhsa -verify-machineinstrs < %S/../trap.ll | FileCheck -check-prefix=GCN -check-prefix=HSA-TRAP -enable-var-scope %S/../trap.ll
3+
4+
; RUN: llc -global-isel -mtriple=amdgcn--amdhsa -mattr=+trap-handler -verify-machineinstrs < %S/../trap.ll | FileCheck -check-prefix=GCN -check-prefix=HSA-TRAP -enable-var-scope %S/../trap.ll
5+
; RUN: llc -global-isel -mtriple=amdgcn--amdhsa -mattr=-trap-handler -verify-machineinstrs < %S/../trap.ll | FileCheck -check-prefix=GCN -check-prefix=NO-HSA-TRAP -enable-var-scope %S/../trap.ll
6+
; RUN: llc -global-isel -mtriple=amdgcn--amdhsa -mattr=-trap-handler -verify-machineinstrs < %S/../trap.ll 2>&1 | FileCheck -check-prefix=GCN -check-prefix=GCN-WARNING -enable-var-scope %S/../trap.ll
7+
8+
; enable trap handler feature
9+
; RUN: llc -global-isel -mtriple=amdgcn-unknown-mesa3d -mattr=+trap-handler -verify-machineinstrs < %S/../trap.ll | FileCheck -check-prefix=GCN -check-prefix=NO-MESA-TRAP -check-prefix=TRAP-BIT -check-prefix=MESA-TRAP -enable-var-scope %S/../trap.ll
10+
; RUN: llc -global-isel -mtriple=amdgcn-unknown-mesa3d -mattr=+trap-handler -verify-machineinstrs < %S/../trap.ll 2>&1 | FileCheck -check-prefix=GCN -check-prefix=GCN-WARNING -check-prefix=TRAP-BIT -enable-var-scope %S/../trap.ll
11+
12+
; disable trap handler feature
13+
; RUN: llc -global-isel -mtriple=amdgcn-unknown-mesa3d -mattr=-trap-handler -verify-machineinstrs < %S/../trap.ll | FileCheck -check-prefix=GCN -check-prefix=NO-MESA-TRAP -check-prefix=NO-TRAP-BIT -check-prefix=NOMESA-TRAP -enable-var-scope %S/../trap.ll
14+
; RUN: llc -global-isel -mtriple=amdgcn-unknown-mesa3d -mattr=-trap-handler -verify-machineinstrs < %S/../trap.ll 2>&1 | FileCheck -check-prefix=GCN -check-prefix=GCN-WARNING -check-prefix=NO-TRAP-BIT -enable-var-scope %S/../trap.ll
15+
16+
; RUN: llc -global-isel -march=amdgcn -verify-machineinstrs < %S/../trap.ll 2>&1 | FileCheck -check-prefix=GCN -check-prefix=GCN-WARNING -enable-var-scope %S/../trap.ll

0 commit comments

Comments
 (0)