[llvm-branch-commits] [llvm] release/23.x: [RISCV] Fix infinite DAGCombine loop with SETCC and SIGN_EXTEND_INREG (#221593) (PR #221855)

Douglas Yung via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Sep 9 20:47:52 PDT 2026


https://github.com/dyung updated https://github.com/llvm/llvm-project/pull/221855

>From 7fe36371c71bb6bef3361c4f7ef081fd2c913f16 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Mon, 7 Sep 2026 15:03:42 -0400
Subject: [PATCH] [RISCV] Fix infinite DAGCombine loop with SETCC and
 SIGN_EXTEND_INREG (#221593)

We generalized (X & -(1 << C1) & 0xffffffff) == C2 << C1 using `sraiw`.
The combine generates a `SIGN_EXTEND_INREG` when simplifying.

However, when C1 is 0 and the sign bit (bit 31) of X is already known to
be zero, `DAGCombiner` sees that `SIGN_EXTEND_INREG` is semantically
equivalent to `AND X, 0xFFFFFFFF` (zext). Because `DAGCombiner`
considers `AND` to be more canonical than `SIGN_EXTEND_INREG` in this
context, it immediately reverts the node back to `AND`.

This caused an infinite DAGCombine loop. This patch disables the folding
when the C1 is zero. That case is covered by a later combine that already
checks if bit 31 is known to be zero.

Fixes: https://github.com/llvm/llvm-project/issues/221521
(cherry picked from commit f9a8dec9496fea7c55f591a66a64dbcdc085fc2d)
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp |  2 +-
 llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll  | 34 +++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 00a13c95d1607..a14637055c36e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -18547,7 +18547,7 @@ static SDValue performSETCCCombine(SDNode *N,
         isPowerOf2_32(-uint32_t(AndRHSInt)) && (N1Int & AndRHSInt) == N1Int) {
       unsigned ShiftBits = llvm::countr_zero(AndRHSInt);
       int64_t NewC = SignExtend64<32>(N1Int) >> ShiftBits;
-      if (NewC >= -2048 && NewC <= 2048) {
+      if (ShiftBits != 0 && NewC >= -2048 && NewC <= 2048) {
         SDValue SExt =
             DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, OpVT, N0.getOperand(0),
                         DAG.getValueType(MVT::i32));
diff --git a/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll b/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll
index 5bd1edb783fce..50324a100c4c1 100644
--- a/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll
+++ b/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll
@@ -261,3 +261,37 @@ entry:
   %4 = zext i1 %3 to i64
   ret i64 %4
 }
+
+define i64 @PR221593(i1 %0) {
+; RV32-LABEL: PR221593:
+; RV32:       # %bb.0:
+; RV32-NEXT:    lui a1, 245379
+; RV32-NEXT:    slli a0, a0, 31
+; RV32-NEXT:    srai a0, a0, 31
+; RV32-NEXT:    addi a1, a1, 78
+; RV32-NEXT:    lui a2, 3
+; RV32-NEXT:    and a3, a0, a1
+; RV32-NEXT:    addi a1, a2, -1907
+; RV32-NEXT:    seqz a2, a3
+; RV32-NEXT:    and a1, a0, a1
+; RV32-NEXT:    or a0, a3, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: PR221593:
+; RV64:       # %bb.0:
+; RV64-NEXT:    lui a1, %hi(.LCPI13_0)
+; RV64-NEXT:    ld a1, %lo(.LCPI13_0)(a1)
+; RV64-NEXT:    slli a0, a0, 63
+; RV64-NEXT:    srai a0, a0, 63
+; RV64-NEXT:    and a0, a0, a1
+; RV64-NEXT:    slli a1, a0, 32
+; RV64-NEXT:    seqz a1, a1
+; RV64-NEXT:    or a0, a0, a1
+; RV64-NEXT:    ret
+  %2 = select i1 %0, i64 44587060572238, i64 0
+  %3 = and i64 %2, 1005072462
+  %4 = icmp eq i64 %3, 0
+  %5 = zext i1 %4 to i64
+  %6 = or i64 %2, %5
+  ret i64 %6
+}



More information about the llvm-branch-commits mailing list