Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1036,8 +1036,9 @@ if (Action == TargetLowering::Expand) { // replace ISD::DEBUGTRAP with ISD::TRAP SDValue NewVal; + const SDValue TrapValue = DAG.getTargetConstant(2, SDLoc(Node), MVT::i16); NewVal = DAG.getNode(ISD::TRAP, SDLoc(Node), Node->getVTList(), - Node->getOperand(0)); + Node->getOperand(0), TrapValue); ReplaceNode(Node, NewVal.getNode()); LegalizeOp(NewVal.getNode()); return; Index: lib/Target/AMDGPU/AMDGPU.td =================================================================== --- lib/Target/AMDGPU/AMDGPU.td +++ lib/Target/AMDGPU/AMDGPU.td @@ -67,6 +67,12 @@ "Support unaligned global loads and stores" >; +def FeatureTrapHandler: SubtargetFeature<"trap-handler", + "TrapHandler", + "true", + "Trap handler support" +>; + def FeatureUnalignedScratchAccess : SubtargetFeature<"unaligned-scratch-access", "UnalignedScratchAccess", "true", Index: lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp +++ lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp @@ -191,7 +191,8 @@ { "llvm.amdgcn.dispatch.ptr", "amdgpu-dispatch-ptr" }, { "llvm.amdgcn.queue.ptr", "amdgpu-queue-ptr" }, { "llvm.amdgcn.dispatch.id", "amdgpu-dispatch-id" }, - { "llvm.trap", "amdgpu-queue-ptr" } + { "llvm.trap", "amdgpu-queue-ptr" }, + { "llvm.debugtrap", "amdgpu-queue-ptr" } }; // TODO: We should not add the attributes if the known compile time workgroup Index: lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -247,6 +247,9 @@ OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:USER_SGPR: " + Twine(G_00B84C_USER_SGPR(KernelInfo.ComputePGMRSrc2)), false); + OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TRAP_HANDLER: " + + Twine(G_00B84C_TRAP_HANDLER(KernelInfo.ComputePGMRSrc2)), + false); OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_X_EN: " + Twine(G_00B84C_TGID_X_EN(KernelInfo.ComputePGMRSrc2)), false); @@ -635,6 +638,7 @@ ProgInfo.ComputePGMRSrc2 = S_00B84C_SCRATCH_EN(ProgInfo.ScratchBlocks > 0) | S_00B84C_USER_SGPR(MFI->getNumUserSGPRs()) | + S_00B84C_TRAP_HANDLER(STM.isTrapHandlerEnabled()) | S_00B84C_TGID_X_EN(MFI->hasWorkGroupIDX()) | S_00B84C_TGID_Y_EN(MFI->hasWorkGroupIDY()) | S_00B84C_TGID_Z_EN(MFI->hasWorkGroupIDZ()) | Index: lib/Target/AMDGPU/AMDGPUSubtarget.h =================================================================== --- lib/Target/AMDGPU/AMDGPUSubtarget.h +++ lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -66,6 +66,16 @@ ISAVersion8_1_0, }; + enum TrapHandlerAbi { + TrapHandlerAbiNone = 0, + TrapHandlerAbiHsa = 1 + }; + + enum TrapCode { + TrapCodeLLVMTrap = 1, + TrapCodeLLVMDebugTrap = 2 + }; + protected: // Basic subtarget description. Triple TargetTriple; @@ -87,6 +97,7 @@ bool FlatForGlobal; bool NoAddr64; bool UnalignedScratchAccess; + bool TrapHandler; bool UnalignedBufferAccess; bool EnableXNACK; bool DebuggerInsertNops; @@ -257,6 +268,10 @@ return CaymanISA; } + TrapHandlerAbi getTrapHandlerAbi() const { + return isAmdHsaOS() ? TrapHandlerAbiHsa : TrapHandlerAbiNone; + } + bool isPromoteAllocaEnabled() const { return EnablePromoteAlloca; } @@ -309,6 +324,10 @@ return UnalignedScratchAccess; } + bool isTrapHandlerEnabled() const { + return TrapHandler; + } + bool isXNACKEnabled() const { return EnableXNACK; } @@ -488,7 +507,8 @@ enum { // The closed Vulkan driver sets 96, which limits the wave count to 8 but // doesn't spill SGPRs as much as when 80 is set. - FIXED_SGPR_COUNT_FOR_INIT_BUG = 96 + FIXED_SGPR_COUNT_FOR_INIT_BUG = 96, + TRAP_HANDLER_SGPR_COUNT = 16 }; private: Index: lib/Target/AMDGPU/AMDGPUSubtarget.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -43,7 +43,7 @@ SmallString<256> FullFS("+promote-alloca,+fp64-fp16-denormals,+load-store-opt,"); if (isAmdHsaOS()) // Turn on FlatForGlobal for HSA. - FullFS += "+flat-for-global,+unaligned-buffer-access,"; + FullFS += "+flat-for-global,+unaligned-buffer-access,+trap-handler,"; FullFS += FS; @@ -84,6 +84,7 @@ FlatForGlobal(false), NoAddr64(false), UnalignedScratchAccess(false), + TrapHandler(false), UnalignedBufferAccess(false), EnableXNACK(false), Index: lib/Target/AMDGPU/AMDKernelCodeT.h =================================================================== --- lib/Target/AMDGPU/AMDKernelCodeT.h +++ lib/Target/AMDGPU/AMDKernelCodeT.h @@ -195,7 +195,7 @@ AMD_CODE_PROPERTY_RESERVED2_SHIFT = 23, AMD_CODE_PROPERTY_RESERVED2_WIDTH = 9, - AMD_CODE_PROPERTY_RESERVED2 = ((1 << AMD_CODE_PROPERTY_RESERVED2_WIDTH) - 1) << AMD_CODE_PROPERTY_RESERVED2_SHIFT + AMD_CODE_PROPERTY_RESERVED2 = ((1 << AMD_CODE_PROPERTY_RESERVED2_WIDTH) - 1) << AMD_CODE_PROPERTY_RESERVED2_SHIFT, }; /// @brief The hsa_ext_control_directives_t specifies the values for the HSAIL Index: lib/Target/AMDGPU/SIDefines.h =================================================================== --- lib/Target/AMDGPU/SIDefines.h +++ lib/Target/AMDGPU/SIDefines.h @@ -300,6 +300,9 @@ #define S_00B84C_USER_SGPR(x) (((x) & 0x1F) << 1) #define G_00B84C_USER_SGPR(x) (((x) >> 1) & 0x1F) #define C_00B84C_USER_SGPR 0xFFFFFFC1 +#define S_00B84C_TRAP_HANDLER(x) (((x) & 0x1) << 6) +#define G_00B84C_TRAP_HANDLER(x) (((x) >> 6) & 0x1) +#define C_00B84C_TRAP_HANDLER 0xFFFFFFBF #define S_00B84C_TGID_X_EN(x) (((x) & 0x1) << 7) #define G_00B84C_TGID_X_EN(x) (((x) >> 7) & 0x1) #define C_00B84C_TGID_X_EN 0xFFFFFF7F Index: lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- lib/Target/AMDGPU/SIISelLowering.cpp +++ lib/Target/AMDGPU/SIISelLowering.cpp @@ -273,6 +273,7 @@ // On SI this is s_memtime and s_memrealtime on VI. setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Legal); setOperationAction(ISD::TRAP, MVT::Other, Legal); + setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal); setOperationAction(ISD::FMINNUM, MVT::f64, Legal); setOperationAction(ISD::FMAXNUM, MVT::f64, Legal); @@ -1786,25 +1787,65 @@ } switch (MI.getOpcode()) { - case AMDGPU::S_TRAP_PSEUDO: { - DebugLoc DL = MI.getDebugLoc(); - BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), AMDGPU::VGPR0) - .addImm(1); + case AMDGPU::S_TRAP_PSEUDO: { + const DebugLoc &DL = MI.getDebugLoc(); - MachineFunction *MF = BB->getParent(); - SIMachineFunctionInfo *Info = MF->getInfo(); - unsigned UserSGPR = Info->getQueuePtrUserSGPR(); - assert(UserSGPR != AMDGPU::NoRegister); + if (Subtarget->getTrapHandlerAbi() == SISubtarget::TrapHandlerAbiHsa) { + BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), AMDGPU::VGPR0) + .addImm(1); - if (!BB->isLiveIn(UserSGPR)) - BB->addLiveIn(UserSGPR); + MachineFunction *MF = BB->getParent(); + SIMachineFunctionInfo *Info = MF->getInfo(); + unsigned UserSGPR = Info->getQueuePtrUserSGPR(); + assert(UserSGPR != AMDGPU::NoRegister); - BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), AMDGPU::SGPR0_SGPR1) - .addReg(UserSGPR); - BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_TRAP)).addImm(0x1) - .addReg(AMDGPU::VGPR0, RegState::Implicit) - .addReg(AMDGPU::SGPR0_SGPR1, RegState::Implicit); + if (!BB->isLiveIn(UserSGPR)) + BB->addLiveIn(UserSGPR); + BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), AMDGPU::SGPR0_SGPR1) + .addReg(UserSGPR); + BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_TRAP)) + .addImm(SISubtarget::TrapCodeLLVMTrap) + .addReg(AMDGPU::VGPR0, RegState::Implicit) + .addReg(AMDGPU::SGPR0_SGPR1, RegState::Implicit); + } else { + BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_ENDPGM)); + } + + MI.eraseFromParent(); + return BB; + } + + case AMDGPU::S_DEBUGTRAP_PSEUDO: { + const DebugLoc &DL = MI.getDebugLoc(); + MachineFunction *MF = BB->getParent(); + if (Subtarget->getTrapHandlerAbi() == SISubtarget::TrapHandlerAbiHsa) { + BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), AMDGPU::VGPR0) + .addImm(1); + + SIMachineFunctionInfo *Info = MF->getInfo(); + unsigned UserSGPR = Info->getQueuePtrUserSGPR(); + assert(UserSGPR != AMDGPU::NoRegister); + + if (!BB->isLiveIn(UserSGPR)) + BB->addLiveIn(UserSGPR); + + BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), AMDGPU::SGPR0_SGPR1) + .addReg(UserSGPR); + BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_TRAP)) + .addImm(SISubtarget::TrapCodeLLVMDebugTrap) + .addReg(AMDGPU::VGPR0, RegState::Implicit) + .addReg(AMDGPU::SGPR0_SGPR1, RegState::Implicit); + } else { + DiagnosticInfoUnsupported NoTrap(*MF->getFunction(), + "debugtrap handler not supported", + DL, + DS_Warning); + + LLVMContext &C = MF->getFunction()->getContext(); + C.diagnose(NoTrap); + BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_ENDPGM)); + } MI.eraseFromParent(); return BB; } Index: lib/Target/AMDGPU/SIInstructions.td =================================================================== --- lib/Target/AMDGPU/SIInstructions.td +++ lib/Target/AMDGPU/SIInstructions.td @@ -118,6 +118,13 @@ let usesCustomInserter = 1; } +def S_DEBUGTRAP_PSEUDO : VPseudoInstSI <(outs), (ins), + [(debugtrap)]> { + let hasSideEffects = 1; + let SALU = 1; + let usesCustomInserter = 1; +} + let usesCustomInserter = 1, SALU = 1 in { def GET_GROUPSTATICSIZE : PseudoInstSI <(outs SReg_32:$sdst), (ins), [(set SReg_32:$sdst, (int_amdgcn_groupstaticsize))]>; Index: lib/Target/AMDGPU/SIRegisterInfo.cpp =================================================================== --- lib/Target/AMDGPU/SIRegisterInfo.cpp +++ lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -1163,9 +1163,11 @@ } unsigned SIRegisterInfo::getNumAddressableSGPRs(const SISubtarget &ST) const { + int trap_handler_reserved = + ST.isTrapHandlerEnabled() ? SISubtarget::TRAP_HANDLER_SGPR_COUNT : 0; if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) - return 102; - return 104; + return 102 - trap_handler_reserved; + return 104 - trap_handler_reserved; } unsigned SIRegisterInfo::getNumReservedSGPRs(const SISubtarget &ST, Index: lib/Target/AMDGPU/Utils/AMDKernelCodeTInfo.h =================================================================== --- lib/Target/AMDGPU/Utils/AMDKernelCodeTInfo.h +++ lib/Target/AMDGPU/Utils/AMDKernelCodeTInfo.h @@ -87,7 +87,7 @@ // TODO: cdbg_user COMPPGM2(enable_sgpr_private_segment_wave_byte_offset, compute_pgm_rsrc2_scratch_en, SCRATCH_EN), COMPPGM2(user_sgpr_count, compute_pgm_rsrc2_user_sgpr, USER_SGPR), -// TODO: enable_trap_handler +COMPPGM2(enable_trap_handler, compute_pgm_rsrc2_trap_handler, TRAP_HANDLER), COMPPGM2(enable_sgpr_workgroup_id_x, compute_pgm_rsrc2_tgid_x_en, TGID_X_EN), COMPPGM2(enable_sgpr_workgroup_id_y, compute_pgm_rsrc2_tgid_y_en, TGID_Y_EN), COMPPGM2(enable_sgpr_workgroup_id_z, compute_pgm_rsrc2_tgid_z_en, TGID_Z_EN), Index: test/CodeGen/AMDGPU/trap.ll =================================================================== --- test/CodeGen/AMDGPU/trap.ll +++ test/CodeGen/AMDGPU/trap.ll @@ -1,11 +1,36 @@ -; RUN: llc -mtriple=amdgcn--amdhsa -verify-machineinstrs < %s 2>&1 | FileCheck -check-prefix=GCN %s +; RUN: llc -mtriple=amdgcn--amdhsa -mattr=+trap-handler -verify-machineinstrs < %s | FileCheck -check-prefix=HSA -check-prefix=HSA-FUNC %s +; RUN: llc -mtriple=amdgcn--amdhsa -mattr=-trap-handler -verify-machineinstrs < %s | FileCheck -check-prefix=FUNC -check-prefix=HSA-FUNC %s +; RUN: llc -march=amdgcn -verify-machineinstrs < %s 2>&1 | FileCheck -check-prefix=NONHSA %s declare void @llvm.trap() #0 +declare void @llvm.debugtrap() #0 -; GCN-LABEL: {{^}}trap: -; GCN: v_mov_b32_e32 v0, 1 -; GCN: s_mov_b64 s[0:1], s[4:5] -; GCN: s_trap 1 +; HSA-LABEL: {{^}}hsa_trap: +; HSA: enable_trap_handler = 1 +; FUNC: enable_trap_handler = 0 +; HSA-FUNC: v_mov_b32_e32 v0, 1 +; HSA-FUNC: s_mov_b64 s[0:1], s[4:5] +; HSA-FUNC: s_trap 1 +define void @hsa_trap() { + call void @llvm.trap() + ret void +} + +; HSA-LABEL: {{^}}hsa_debugtrap: +; HSA: enable_trap_handler = 1 +; FUNC: enable_trap_handler = 0 +; HSA-FUNC: v_mov_b32_e32 v0, 1 +; HSA-FUNC: s_mov_b64 s[0:1], s[4:5] +; HSA-FUNC: s_trap 2 +; NONHSA: :0:0: in function hsa_debugtrap void (): debugtrap handler not supported +; NONHSA: s_endpgm +define void @hsa_debugtrap() { + call void @llvm.debugtrap() + ret void +} + +; For non-HSA path +; NONHSA: s_endpgm define void @trap() { call void @llvm.trap() ret void