diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -57,6 +57,8 @@ setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom); setOperationAction(ISD::ROTL, GRLenVT, Expand); setOperationAction(ISD::CTPOP, GRLenVT, Expand); + setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal); + setOperationAction(ISD::TRAP, MVT::Other, Legal); setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool, ISD::JumpTable}, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -742,6 +742,21 @@ def : Pat<(or GPR:$rj, (not GPR:$rk)), (ORN GPR:$rj, GPR:$rk)>; def : Pat<(and GPR:$rj, (not GPR:$rk)), (ANDN GPR:$rj, GPR:$rk)>; +/// Traps + +// We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed +// to trap with an INE (non-existent on LA32, explicitly documented to INE on +// LA64). And the resulting signal is different from `debugtrap` like on some +// other existing ports so programs/porters might have an easier time. +def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>, + PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>; + +// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work, +// even for LA32 Primary. Also, because so far the ISA does not provide a +// specific trap instruction/kind exclusively for alerting the debugger, +// every other project uses the generic immediate of 0 for this. +def : Pat<(debugtrap), (BREAK 0)>; + /// Bit counting operations let Predicates = [IsLA64] in { diff --git a/llvm/test/CodeGen/LoongArch/trap.ll b/llvm/test/CodeGen/LoongArch/trap.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/trap.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s + +;; Verify that we lower @llvm.trap() and @llvm.debugtrap() correctly. + +declare void @llvm.trap() +declare void @llvm.debugtrap() + +define void @test_trap() nounwind { +; CHECK-LABEL: test_trap: +; CHECK: # %bb.0: +; CHECK-NEXT: amswap.w $zero, $ra, $zero +; CHECK-NEXT: ret + tail call void @llvm.trap() + ret void +} + +define void @test_debugtrap() nounwind { +; CHECK-LABEL: test_debugtrap: +; CHECK: # %bb.0: +; CHECK-NEXT: break 0 +; CHECK-NEXT: ret + tail call void @llvm.debugtrap() + ret void +}