[llvm] [DAG] getNode - fold (sext (trunc x)) -> x iff the upper bits are already signbits (PR #151945)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 6 06:09:35 PDT 2025


https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/151945

>From 353d76c8e8e64a1c614f6cdc483a9138010a6173 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Mon, 4 Aug 2025 12:26:55 +0100
Subject: [PATCH] [DAG] getNode - fold (sext (trunc x)) -> x iff the upper bits
 are all signbits

Similar to what we already do for ZERO_EXTEND/ANY_EXTEND patterns.
---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 14 +++++++++++
 llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll   | 24 +++++++++----------
 llvm/test/CodeGen/X86/trunc-nsw-nuw.ll        |  7 +++---
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index f41b6eb26bbda..291f461f2cb50 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6415,6 +6415,20 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     if (N1.isUndef())
       // sext(undef) = 0, because the top bits will all be the same.
       return getConstant(0, DL, VT);
+
+    // Skip unnecessary sext_inreg pattern:
+    // (sext (trunc x)) -> x iff the upper bits are all signbits.
+    if (OpOpcode == ISD::TRUNCATE) {
+      SDValue OpOp = N1.getOperand(0);
+      if (OpOp.getValueType() == VT) {
+        unsigned NumSignExtBits =
+            VT.getScalarSizeInBits() - N1.getScalarValueSizeInBits();
+        if (ComputeNumSignBits(OpOp) > NumSignExtBits) {
+          transferDbgValues(N1, OpOp);
+          return OpOp;
+        }
+      }
+    }
     break;
   case ISD::ZERO_EXTEND:
     assert(VT.isInteger() && N1.getValueType().isInteger() &&
diff --git a/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll b/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll
index 9ffb4fd5eae45..258ddf60088c1 100644
--- a/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll
@@ -37,9 +37,9 @@ define signext i8 @test_chars(i8 signext %c1, i8 signext %c2, i8 signext %c3, i8
   ; 32BIT: bb.0.entry:
   ; 32BIT-NEXT:   liveins: $r3, $r4, $r5, $r6
   ; 32BIT-NEXT: {{  $}}
-  ; 32BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, killed renamable $r4
-  ; 32BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, killed renamable $r5
-  ; 32BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, killed renamable $r6
+  ; 32BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r4
+  ; 32BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r5
+  ; 32BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r6
   ; 32BIT-NEXT:   renamable $r3 = EXTSB killed renamable $r3
   ; 32BIT-NEXT:   BLR implicit $lr, implicit $rm, implicit $r3
   ;
@@ -47,9 +47,9 @@ define signext i8 @test_chars(i8 signext %c1, i8 signext %c2, i8 signext %c3, i8
   ; 64BIT: bb.0.entry:
   ; 64BIT-NEXT:   liveins: $x3, $x4, $x5, $x6
   ; 64BIT-NEXT: {{  $}}
-  ; 64BIT-NEXT:   renamable $r3 = ADD4 renamable $r3, renamable $r4, implicit killed $x4, implicit killed $x3
-  ; 64BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, renamable $r5, implicit killed $x5
-  ; 64BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, renamable $r6, implicit killed $x6, implicit-def $x3
+  ; 64BIT-NEXT:   renamable $r3 = nsw ADD4 renamable $r3, renamable $r4, implicit killed $x4, implicit killed $x3
+  ; 64BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, renamable $r5, implicit killed $x5
+  ; 64BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, renamable $r6, implicit killed $x6, implicit-def $x3
   ; 64BIT-NEXT:   renamable $x3 = EXTSB8 killed renamable $x3
   ; 64BIT-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $x3
 entry:
@@ -96,9 +96,9 @@ define signext i8 @test_chars_mix(i8 signext %c1, i8 zeroext %c2, i8 zeroext %c3
   ; 32BIT: bb.0.entry:
   ; 32BIT-NEXT:   liveins: $r3, $r4, $r5, $r6
   ; 32BIT-NEXT: {{  $}}
-  ; 32BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, killed renamable $r4
-  ; 32BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, killed renamable $r5
-  ; 32BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, killed renamable $r6
+  ; 32BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r4
+  ; 32BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r5
+  ; 32BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r6
   ; 32BIT-NEXT:   renamable $r3 = EXTSB killed renamable $r3
   ; 32BIT-NEXT:   BLR implicit $lr, implicit $rm, implicit $r3
   ;
@@ -106,9 +106,9 @@ define signext i8 @test_chars_mix(i8 signext %c1, i8 zeroext %c2, i8 zeroext %c3
   ; 64BIT: bb.0.entry:
   ; 64BIT-NEXT:   liveins: $x3, $x4, $x5, $x6
   ; 64BIT-NEXT: {{  $}}
-  ; 64BIT-NEXT:   renamable $r3 = ADD4 renamable $r3, renamable $r4, implicit killed $x4, implicit killed $x3
-  ; 64BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, renamable $r5, implicit killed $x5
-  ; 64BIT-NEXT:   renamable $r3 = ADD4 killed renamable $r3, renamable $r6, implicit killed $x6, implicit-def $x3
+  ; 64BIT-NEXT:   renamable $r3 = nsw ADD4 renamable $r3, renamable $r4, implicit killed $x4, implicit killed $x3
+  ; 64BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, renamable $r5, implicit killed $x5
+  ; 64BIT-NEXT:   renamable $r3 = nsw ADD4 killed renamable $r3, renamable $r6, implicit killed $x6, implicit-def $x3
   ; 64BIT-NEXT:   renamable $x3 = EXTSB8 killed renamable $x3
   ; 64BIT-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $x3
 entry:
diff --git a/llvm/test/CodeGen/X86/trunc-nsw-nuw.ll b/llvm/test/CodeGen/X86/trunc-nsw-nuw.ll
index 5c5f7045ea030..6b0789127f5f9 100644
--- a/llvm/test/CodeGen/X86/trunc-nsw-nuw.ll
+++ b/llvm/test/CodeGen/X86/trunc-nsw-nuw.ll
@@ -62,10 +62,11 @@ entry:
 define i32 @simplify_demanded_bits_drop_flag(i1 zeroext %x, i1 zeroext %y) nounwind {
 ; CHECK-LABEL: simplify_demanded_bits_drop_flag:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    negl %edi
+; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
 ; CHECK-NEXT:    shll $2, %esi
-; CHECK-NEXT:    xorl %edi, %esi
-; CHECK-NEXT:    movslq %esi, %rax
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    negq %rax
+; CHECK-NEXT:    xorq %rsi, %rax
 ; CHECK-NEXT:    imulq $-1634202141, %rax, %rax # imm = 0x9E980DE3
 ; CHECK-NEXT:    movq %rax, %rcx
 ; CHECK-NEXT:    shrq $63, %rcx



More information about the llvm-commits mailing list