[llvm] [LoongArch] Fix out-of-range assert in DAG constant getting (PR #141586)

via llvm-commits llvm-commits at lists.llvm.org
Tue May 27 06:39:28 PDT 2025


https://github.com/heiher updated https://github.com/llvm/llvm-project/pull/141586

>From 00944f9d2b8503028b3cc663e38bbccec12823ab Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Tue, 27 May 2025 20:07:24 +0800
Subject: [PATCH 1/2] [LoongArch] Fix assertion failure in performORCombine

Fixes #141583
---
 llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp |  2 +-
 llvm/test/CodeGen/LoongArch/bstrins_w.ll            | 12 ++++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 9f5c94ddea44f..7a9ec9f5e96b3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -4410,7 +4410,7 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
     LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 5\n");
     return DAG.getNode(
         LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),
-        DAG.getConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy),
+        DAG.getSignedConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy),
         DAG.getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
                                       : (MaskIdx0 + MaskLen0 - 1),
                         DL, GRLenVT),
diff --git a/llvm/test/CodeGen/LoongArch/bstrins_w.ll b/llvm/test/CodeGen/LoongArch/bstrins_w.ll
index c59f15bd64112..0fea0470394d2 100644
--- a/llvm/test/CodeGen/LoongArch/bstrins_w.ll
+++ b/llvm/test/CodeGen/LoongArch/bstrins_w.ll
@@ -207,6 +207,18 @@ define i32 @pat8(i32 %c) nounwind {
   ret i32 %or
 }
 
+define i32 @pat9(i32 %a) {
+; CHECK-LABEL: pat9:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lu12i.w $a1, -8
+; CHECK-NEXT:    ori $a1, $a1, 564
+; CHECK-NEXT:    bstrins.w $a0, $a1, 31, 16
+; CHECK-NEXT:    ret
+  %and = and i32 %a, 65535       ; 0x0000ffff
+  %or = or i32 %and, -2110521344 ; 0x82340000
+  ret i32 %or
+}
+
 ;; Test that bstrins.w is not generated because constant OR operand
 ;; doesn't fit into bits cleared by constant AND operand.
 define i32 @no_bstrins_w(i32 %a) nounwind {

>From 71617cae3b8af926f5cc4f198ac365c55d2a39e3 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Tue, 27 May 2025 21:40:49 +0800
Subject: [PATCH 2/2] Add defensive fixes

---
 .../lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp | 14 +++++++-------
 llvm/lib/Target/LoongArch/LoongArchInstrInfo.td    | 12 ++++++------
 llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td |  3 ++-
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
index cb0fb9bc9c7f9..7c1f55a26c919 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
@@ -76,7 +76,7 @@ void LoongArchDAGToDAGISel::Select(SDNode *Node) {
         Result = CurDAG->getMachineNode(
             Inst.Opc, DL, GRLenVT,
             {SrcReg, SrcReg,
-             CurDAG->getTargetConstant(Inst.Imm >> 32, DL, GRLenVT),
+             CurDAG->getSignedTargetConstant(Inst.Imm >> 32, DL, GRLenVT),
              CurDAG->getTargetConstant(Inst.Imm & 0xFF, DL, GRLenVT)});
         break;
       default:
@@ -233,7 +233,7 @@ bool LoongArchDAGToDAGISel::SelectAddrConstant(SDValue Addr, SDValue &Base,
   if (!isInt<12>(CVal))
     return false;
   Base = CurDAG->getRegister(LoongArch::R0, VT);
-  Offset = CurDAG->getTargetConstant(SignExtend64<12>(CVal), DL, VT);
+  Offset = CurDAG->getSignedTargetConstant(SignExtend64<12>(CVal), DL, VT);
   return true;
 }
 
@@ -255,7 +255,7 @@ bool LoongArchDAGToDAGISel::SelectAddrRegImm12(SDValue Addr, SDValue &Base,
     int64_t Imm = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
     if (isInt<12>(Imm)) {
       Base = Addr.getOperand(0);
-      Offset = CurDAG->getTargetConstant(SignExtend64<12>(Imm), DL, VT);
+      Offset = CurDAG->getSignedTargetConstant(SignExtend64<12>(Imm), DL, VT);
       return true;
     }
   }
@@ -398,8 +398,8 @@ bool LoongArchDAGToDAGISel::selectVSplatImm(SDValue N, SDValue &SplatVal) {
   if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
       ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
     if (IsSigned && ImmValue.isSignedIntN(ImmBitSize)) {
-      SplatVal = CurDAG->getTargetConstant(ImmValue.getSExtValue(), SDLoc(N),
-                                           Subtarget->getGRLenVT());
+      SplatVal = CurDAG->getSignedTargetConstant(
+          ImmValue.getSExtValue(), SDLoc(N), Subtarget->getGRLenVT());
       return true;
     }
     if (!IsSigned && ImmValue.isIntN(ImmBitSize)) {
@@ -425,7 +425,7 @@ bool LoongArchDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N,
     int32_t Log2 = (~ImmValue).exactLogBase2();
 
     if (Log2 != -1) {
-      SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
+      SplatImm = CurDAG->getSignedTargetConstant(Log2, SDLoc(N), EltTy);
       return true;
     }
   }
@@ -446,7 +446,7 @@ bool LoongArchDAGToDAGISel::selectVSplatUimmPow2(SDValue N,
     int32_t Log2 = ImmValue.exactLogBase2();
 
     if (Log2 != -1) {
-      SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
+      SplatImm = CurDAG->getSignedTargetConstant(Log2, SDLoc(N), EltTy);
       return true;
     }
   }
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index fcdd9a130d8b6..449b3363d8a58 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -524,22 +524,22 @@ def ImmSubFrom32 : SDNodeXForm<imm, [{
 
 // Return the lowest 12 bits of the signed immediate.
 def LO12: SDNodeXForm<imm, [{
-  return CurDAG->getTargetConstant(SignExtend64<12>(N->getSExtValue()),
-                                   SDLoc(N), N->getValueType(0));
+  return CurDAG->getSignedTargetConstant(SignExtend64<12>(N->getSExtValue()),
+                                         SDLoc(N), N->getValueType(0));
 }]>;
 
 // Return the higher 16 bits of the signed immediate.
 def HI16 : SDNodeXForm<imm, [{
-  return CurDAG->getTargetConstant(N->getSExtValue() >> 16, SDLoc(N),
-                                   N->getValueType(0));
+  return CurDAG->getSignedTargetConstant(N->getSExtValue() >> 16, SDLoc(N),
+                                         N->getValueType(0));
 }]>;
 
 // Return the higher 16 bits of the signed immediate, adjusted for use within an
 // `addu16i.d + addi` pair.
 def HI16ForAddu16idAddiPair: SDNodeXForm<imm, [{
   auto Imm = N->getSExtValue();
-  return CurDAG->getTargetConstant((Imm - SignExtend64<12>(Imm)) >> 16,
-                                   SDLoc(N), N->getValueType(0));
+  return CurDAG->getSignedTargetConstant((Imm - SignExtend64<12>(Imm)) >> 16,
+                                          SDLoc(N), N->getValueType(0));
 }]>;
 
 def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index 7bb7c02a54349..b2b3b65155265 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -221,7 +221,8 @@ def lsxsplatf64 : PatFrag<(ops node:$e0),
 
 def to_valid_timm : SDNodeXForm<timm, [{
   auto CN = cast<ConstantSDNode>(N);
-  return CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(N), Subtarget->getGRLenVT());
+  return CurDAG->getSignedTargetConstant(CN->getSExtValue(), SDLoc(N),
+                                         Subtarget->getGRLenVT());
 }]>;
 
 // FP immediate of VLDI patterns.



More information about the llvm-commits mailing list