[llvm] [DAGCombiner] Fold sext_in_reg when adding sign bit to an already extended value. (PR #214848)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 13:51:23 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: Usman Nadeem (UsmanNadeem)

<details>
<summary>Changes</summary>

Proof: https://alive2.llvm.org/ce/z/HEaaA5

---
Full diff: https://github.com/llvm/llvm-project/pull/214848.diff


4 Files Affected:

- (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+19) 
- (modified) llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll (-1) 
- (modified) llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll (-4) 
- (modified) llvm/test/CodeGen/RISCV/sdiv-pow2-cmov.ll (+2-2) 


``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index f5620743d6ed1..6973bcdc9d259 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -17223,6 +17223,25 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
   if (DAG.MaskedValueIsZero(N0, APInt::getOneBitSet(VTBits, ExtVTBits - 1)))
     return DAG.getZeroExtendInReg(N0, DL, ExtVT);
 
+  // fold (sext_in_reg add(x, sign_bit_of(x))) -> add(x, sign_bit_of(x))
+  // if we are not extending beyond the original extension type of x.
+  {
+    SDValue AddOp;
+    uint64_t BitNo;
+    APInt BitMask;
+    if (sd_match(N0,
+                 m_c_BinOp(ISD::ADD, m_Value(AddOp),
+                           m_Srl(m_And(m_Deferred(AddOp), m_ConstInt(BitMask)),
+                                 m_ConstInt(BitNo)))) &&
+        BitMask == APInt::getOneBitSet(VTBits, BitNo)) {
+      unsigned SignBits = DAG.ComputeNumSignBits(AddOp);
+      unsigned NonSignBits = VTBits - DAG.ComputeNumSignBits(AddOp);
+      unsigned ExtendedBits = VTBits - ExtVTBits;
+      if (BitNo >= NonSignBits && ExtendedBits < SignBits)
+        return N0;
+    }
+  }
+
   // fold operands of sext_in_reg based on knowledge that the top bits are not
   // demanded.
   if (SimplifyDemandedBits(SDValue(N, 0)))
diff --git a/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll b/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll
index 53bc7f603bde1..e7490803924d3 100644
--- a/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll
+++ b/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll
@@ -30,7 +30,6 @@ define dso_local signext i16 @f0(i16 signext %F) local_unnamed_addr #0 {
 ; NODIV:       @ %bb.0: @ %entry
 ; NODIV-NEXT:    uxth r1, r0
 ; NODIV-NEXT:    add r0, r0, r1, lsr #15
-; NODIV-NEXT:    sxth r0, r0
 ; NODIV-NEXT:    asr r0, r0, #1
 ; NODIV-NEXT:    bx lr
 
diff --git a/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll b/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll
index cfd37bd3b86c0..819c14823a8b6 100644
--- a/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll
+++ b/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll
@@ -26,7 +26,6 @@ define dso_local signext i16 @f0(i16 signext %F) local_unnamed_addr #0 {
 ; V6M-NEXT:    uxth r1, r0
 ; V6M-NEXT:    lsrs r1, r1, #15
 ; V6M-NEXT:    adds r0, r0, r1
-; V6M-NEXT:    sxth r0, r0
 ; V6M-NEXT:    asrs r0, r0, #1
 ; V6M-NEXT:    bx lr
 
@@ -117,7 +116,6 @@ define dso_local signext i16 @f4(i16 signext %F) {
 ; T2:       @ %bb.0: @ %entry
 ; T2-NEXT:    uxth r1, r0
 ; T2-NEXT:    add.w r0, r0, r1, lsr #15
-; T2-NEXT:    sxth r0, r0
 ; T2-NEXT:    asrs r0, r0, #1
 ; T2-NEXT:    bx lr
 ;
@@ -126,7 +124,6 @@ define dso_local signext i16 @f4(i16 signext %F) {
 ; T1-NEXT:    uxth r1, r0
 ; T1-NEXT:    lsrs r1, r1, #15
 ; T1-NEXT:    adds r0, r0, r1
-; T1-NEXT:    sxth r0, r0
 ; T1-NEXT:    asrs r0, r0, #1
 ; T1-NEXT:    bx lr
 ;
@@ -135,7 +132,6 @@ define dso_local signext i16 @f4(i16 signext %F) {
 ; V6M-NEXT:    uxth r1, r0
 ; V6M-NEXT:    lsrs r1, r1, #15
 ; V6M-NEXT:    adds r0, r0, r1
-; V6M-NEXT:    sxth r0, r0
 ; V6M-NEXT:    asrs r0, r0, #1
 ; V6M-NEXT:    bx lr
 
diff --git a/llvm/test/CodeGen/RISCV/sdiv-pow2-cmov.ll b/llvm/test/CodeGen/RISCV/sdiv-pow2-cmov.ll
index f7dda82885678..7bbc9a55834f2 100644
--- a/llvm/test/CodeGen/RISCV/sdiv-pow2-cmov.ll
+++ b/llvm/test/CodeGen/RISCV/sdiv-pow2-cmov.ll
@@ -9,7 +9,7 @@ define signext i32 @sdiv2_32(i32 signext %0) {
 ; NOSFB:       # %bb.0:
 ; NOSFB-NEXT:    srliw a1, a0, 31
 ; NOSFB-NEXT:    add a0, a0, a1
-; NOSFB-NEXT:    sraiw a0, a0, 1
+; NOSFB-NEXT:    srai a0, a0, 1
 ; NOSFB-NEXT:    ret
 ;
 ; SFB-LABEL: sdiv2_32:
@@ -29,7 +29,7 @@ define signext i32 @sdivneg2_32(i32 signext %0) {
 ; NOSFB:       # %bb.0:
 ; NOSFB-NEXT:    srliw a1, a0, 31
 ; NOSFB-NEXT:    add a0, a0, a1
-; NOSFB-NEXT:    sraiw a0, a0, 1
+; NOSFB-NEXT:    srai a0, a0, 1
 ; NOSFB-NEXT:    neg a0, a0
 ; NOSFB-NEXT:    ret
 ;

``````````

</details>


https://github.com/llvm/llvm-project/pull/214848


More information about the llvm-commits mailing list