-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[LoongArch] Make the code generation of the trap pattern configurable #166913
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?
Conversation
|
@llvm/pr-subscribers-backend-loongarch Author: hev (heiher) ChangesRelevant GCC patch: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=15c8169ec55b52630ab884dd7a30c3237ada98b2 Full diff: https://github.com/llvm/llvm-project/pull/166913.diff 4 Files Affected:
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index cf4ffc82f6009..f3b725c731a95 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -74,6 +74,13 @@ static cl::opt<bool> ZeroDivCheck("loongarch-check-zero-division", cl::Hidden,
cl::desc("Trap on integer division by zero."),
cl::init(false));
+static cl::opt<int> TrapBreakCode("loongarch-trap-break-code", cl::init(-1),
+ cl::desc("Use 'break CODE' for traps "
+ "supposed to be unrecoverable, "
+ "or an 'amswap.w' instruction "
+ "leading to INE if CODE is out "
+ "of range."));
+
LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
const LoongArchSubtarget &STI)
: TargetLowering(TM), Subtarget(STI) {
@@ -125,7 +132,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction({ISD::VAARG, ISD::VACOPY, ISD::VAEND}, MVT::Other, Expand);
setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal);
- setOperationAction(ISD::TRAP, MVT::Other, Legal);
+ setOperationAction(ISD::TRAP, MVT::Other, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
@@ -610,10 +617,25 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
return lowerVECREDUCE(Op, DAG);
case ISD::ConstantFP:
return lowerConstantFP(Op, DAG);
+ case ISD::TRAP:
+ return lowerTrap(Op, DAG);
}
return SDValue();
}
+SDValue LoongArchTargetLowering::lowerTrap(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ SDValue Chain = Op.getOperand(0);
+
+ if (isUInt<15>(TrapBreakCode))
+ return DAG.getNode(
+ LoongArchISD::BREAK, DL, MVT::Other, Chain,
+ DAG.getConstant(TrapBreakCode, DL, Subtarget.getGRLenVT()));
+
+ return DAG.getNode(LoongArchISD::UNIMP, DL, MVT::Other, Chain);
+}
+
SDValue LoongArchTargetLowering::lowerConstantFP(SDValue Op,
SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
@@ -7500,6 +7522,7 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(TAIL)
NODE_NAME_CASE(TAIL_MEDIUM)
NODE_NAME_CASE(TAIL_LARGE)
+ NODE_NAME_CASE(UNIMP)
NODE_NAME_CASE(SELECT_CC)
NODE_NAME_CASE(BR_CC)
NODE_NAME_CASE(BRCOND)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 8a4d7748467c7..86682d4b9e9e6 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -33,6 +33,7 @@ enum NodeType : unsigned {
TAIL,
TAIL_MEDIUM,
TAIL_LARGE,
+ UNIMP,
// Select
SELECT_CC,
@@ -415,6 +416,7 @@ class LoongArchTargetLowering : public TargetLowering {
SDValue lowerVECREDUCE_ADD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerTrap(SDValue Op, SelectionDAG &DAG) const;
bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 9565a55e4c6c5..72cda642d0546 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -97,6 +97,8 @@ def loongarch_call_large : SDNode<"LoongArchISD::CALL_LARGE", SDT_LoongArchCall,
def loongarch_tail_large : SDNode<"LoongArchISD::TAIL_LARGE", SDT_LoongArchCall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
SDNPVariadic]>;
+def loongarch_unimp : SDNode<"LoongArchISD::UNIMP", SDTypeProfile<0, 0, []>,
+ [SDNPHasChain, SDNPSideEffect]>;
def loongarch_selectcc : SDNode<"LoongArchISD::SELECT_CC", SDT_LoongArchSelectCC>;
def loongarch_brcc : SDNode<"LoongArchISD::BR_CC", SDT_LoongArchBrCC,
[SDNPHasChain]>;
@@ -1373,11 +1375,18 @@ def : Pat<(and GPR:$rj, BstrinsImm:$imm),
/// 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)]>,
+// ISD::TRAP is lowered to either LoongArchISD::UNIMP or LoongArchISD::BREAK
+// depending on the --loongarch-trap-break-code=<N> option (default: -1).
+// - If N is a valid 15-bit unsigned integer (0 <= N <= 32767), it expands to
+// LoongArchISD::BREAK N, producing a BREAK instruction with the specified
+// code.
+// - Otherwise, it expands to LoongArchISD::UNIMP.
+
+// We lower `loongarch_unimp` 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), [(loongarch_unimp)]>,
PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>;
// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work,
diff --git a/llvm/test/CodeGen/LoongArch/trap.ll b/llvm/test/CodeGen/LoongArch/trap.ll
index 15a7ad82bd7a8..434807207f63d 100644
--- a/llvm/test/CodeGen/LoongArch/trap.ll
+++ b/llvm/test/CodeGen/LoongArch/trap.ll
@@ -1,6 +1,14 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s
-; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | \
+; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-AMSWAP
+; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs \
+; RUN: --loongarch-trap-break-code=1 < %s | \
+; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-BREAK
+; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | \
+; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-AMSWAP
+; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs \
+; RUN: --loongarch-trap-break-code=1 < %s | \
+; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-BREAK
;; Verify that we lower @llvm.trap() and @llvm.debugtrap() correctly.
@@ -8,10 +16,15 @@ 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
+; CHECK-AMSWAP-LABEL: test_trap:
+; CHECK-AMSWAP: # %bb.0:
+; CHECK-AMSWAP-NEXT: amswap.w $zero, $ra, $zero
+; CHECK-AMSWAP-NEXT: ret
+;
+; CHECK-BREAK-LABEL: test_trap:
+; CHECK-BREAK: # %bb.0:
+; CHECK-BREAK-NEXT: break 1
+; CHECK-BREAK-NEXT: ret
tail call void @llvm.trap()
ret void
}
|
|
Should we make Clang support a GCC-style |
Relevant GCC patch: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=15c8169ec55b52630ab884dd7a30c3237ada98b2