[llvm] eca62f9 - [LoongArch] Diagnose the behavior of reading and writing registers that do not conform to the hardware register size

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 23 18:42:41 PST 2022


Author: gonglingqin
Date: 2022-11-24T10:38:44+08:00
New Revision: eca62f92045ca8d2896a1e2ee2113056a13596ef

URL: https://github.com/llvm/llvm-project/commit/eca62f92045ca8d2896a1e2ee2113056a13596ef
DIFF: https://github.com/llvm/llvm-project/commit/eca62f92045ca8d2896a1e2ee2113056a13596ef.diff

LOG: [LoongArch] Diagnose the behavior of reading and writing registers that do not conform to the hardware register size

When reading or writing a register that does not conform to the size of a
hardware register, an error message is generated instead of a compiler crash.

Differential Revision: https://reviews.llvm.org/D138008

Added: 
    llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll
    llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll

Modified: 
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/lib/Target/LoongArch/LoongArchISelLowering.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index d80d292f0691e..4f341c8cbb613 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -93,6 +93,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::CTLZ, MVT::i32, Custom);
     setOperationAction(ISD::INTRINSIC_VOID, MVT::i32, Custom);
     setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i32, Custom);
+    setOperationAction(ISD::READ_REGISTER, MVT::i32, Custom);
+    setOperationAction(ISD::WRITE_REGISTER, MVT::i32, Custom);
     if (Subtarget.hasBasicF() && !Subtarget.hasBasicD())
       setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
     if (Subtarget.hasBasicF())
@@ -118,6 +120,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
   } else {
     setOperationAction(ISD::BITREVERSE, MVT::i32, Legal);
     setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);
+    setOperationAction(ISD::READ_REGISTER, MVT::i64, Custom);
+    setOperationAction(ISD::WRITE_REGISTER, MVT::i64, Custom);
   }
 
   static const ISD::CondCode FPCCToExpand[] = {
@@ -244,10 +248,30 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
     return lowerFRAMEADDR(Op, DAG);
   case ISD::RETURNADDR:
     return lowerRETURNADDR(Op, DAG);
+  case ISD::WRITE_REGISTER:
+    return lowerWRITE_REGISTER(Op, DAG);
   }
   return SDValue();
 }
 
+SDValue LoongArchTargetLowering::lowerWRITE_REGISTER(SDValue Op,
+                                                     SelectionDAG &DAG) const {
+
+  if (Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i32) {
+    DAG.getContext()->emitError(
+        "On LA64, only 64-bit registers can be written.");
+    return Op.getOperand(0);
+  }
+
+  if (!Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i64) {
+    DAG.getContext()->emitError(
+        "On LA32, only 32-bit registers can be written.");
+    return Op.getOperand(0);
+  }
+
+  return Op;
+}
+
 SDValue LoongArchTargetLowering::lowerFRAMEADDR(SDValue Op,
                                                 SelectionDAG &DAG) const {
   if (!isa<ConstantSDNode>(Op.getOperand(0))) {
@@ -927,6 +951,17 @@ void LoongArchTargetLowering::ReplaceNodeResults(
     }
     break;
   }
+  case ISD::READ_REGISTER: {
+    if (Subtarget.is64Bit())
+      DAG.getContext()->emitError(
+          "On LA64, only 64-bit registers can be read.");
+    else
+      DAG.getContext()->emitError(
+          "On LA32, only 32-bit registers can be read.");
+    Results.push_back(DAG.getUNDEF(N->getValueType(0)));
+    Results.push_back(N->getOperand(0));
+    break;
+  }
   }
 }
 

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 6f98e40c41d39..4f650feee47a0 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -192,6 +192,7 @@ class LoongArchTargetLowering : public TargetLowering {
   SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
 
   bool isFPImmLegal(const APFloat &Imm, EVT VT,
                     bool ForCodeSize) const override;

diff  --git a/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll b/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll
new file mode 100644
index 0000000000000..7440bfe5c85a5
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll
@@ -0,0 +1,21 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: not llc < %s --mtriple=loongarch32 2>&1 | FileCheck %s
+
+define i64 @read_sp() nounwind {
+entry:
+; CHECK: On LA32, only 32-bit registers can be read.
+  %a1 = call i64 @llvm.read_register.i64(metadata !0)
+  ret i64 %a1
+}
+
+define void @write_sp(i64 %val) nounwind {
+entry:
+; CHECK: On LA32, only 32-bit registers can be written.
+  call void @llvm.write_register.i64(metadata !0, i64 %val)
+  ret void
+}
+
+declare i64 @llvm.read_register.i64(metadata) nounwind
+declare void @llvm.write_register.i64(metadata, i64) nounwind
+
+!0 = !{!"$sp\00"}

diff  --git a/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll b/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll
new file mode 100644
index 0000000000000..9312aa9020ba9
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll
@@ -0,0 +1,21 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: not llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s
+
+define i32 @read_sp() nounwind {
+entry:
+; CHECK: On LA64, only 64-bit registers can be read.
+  %a1 = call i32 @llvm.read_register.i32(metadata !0)
+  ret i32 %a1
+}
+
+define void @write_sp(i32 %val) nounwind {
+entry:
+; CHECK: On LA64, only 64-bit registers can be written.
+  call void @llvm.write_register.i32(metadata !0, i32 %val)
+  ret void
+}
+
+declare i32 @llvm.read_register.i32(metadata) nounwind
+declare void @llvm.write_register.i32(metadata, i32) nounwind
+
+!0 = !{!"$sp\00"}


        


More information about the llvm-commits mailing list