[llvm-branch-commits] [llvm] [LoongArch] Compute known bits and sign bits for BSTRINS/BSTRPICK (PR #233738)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Oct 20 01:18:01 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-loongarch

Author: hev (heiher)

<details>
<summary>Changes</summary>

BSTRINS and BSTRPICK are formed early by DAG combines, so the generic known-bits and sign-bits analyses see them as opaque target nodes. When such a value is live out of a block, its LiveOutInfo is lost and PHIs merging it can no longer prove that the value is already sign- or zero-extended, leaving redundant addi.w/bstrpick.d behind.

This is common in Rust code decoding UTF-8, e.g. `str::chars().rev()`, where the multi-byte path assembles the code point with bstrins.d and is merged with the ASCII byte loaded by ld.b before an i32 compare.

rustc-perf svg-parse-1 on LA664: instructions -2.4%, cycles -1.7%.

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


3 Files Affected:

- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+41) 
- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.h (+4) 
- (modified) llvm/test/CodeGen/LoongArch/bstrins-bstrpick-known-bits.ll (+1-5) 


``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 1d01e76a5ebd2..687212daa08fc 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -11940,7 +11940,48 @@ void LoongArchTargetLowering::computeKnownBitsForTargetNode(
     Known.Zero.setBitsFrom(VTBits);
     break;
   }
+  case LoongArchISD::BSTRINS: {
+    // BSTRINS X, Y, msb, lsb: replace X[msb:lsb] with Y[msb-lsb:0].
+    unsigned Msb = Op.getConstantOperandVal(2);
+    unsigned Lsb = Op.getConstantOperandVal(3);
+    Known = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
+    KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
+    Known.insertBits(Known2.trunc(Msb - Lsb + 1), Lsb);
+    break;
+  }
+  case LoongArchISD::BSTRPICK: {
+    // BSTRPICK X, msb, lsb: zero-extend X[msb:lsb].
+    unsigned BitWidth = Known.getBitWidth();
+    unsigned Msb = Op.getConstantOperandVal(1);
+    unsigned Lsb = Op.getConstantOperandVal(2);
+    Known = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
+    Known = Known.extractBits(Msb - Lsb + 1, Lsb).zext(BitWidth);
+    break;
+  }
+  }
+}
+
+unsigned LoongArchTargetLowering::ComputeNumSignBitsForTargetNode(
+    SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
+    unsigned Depth) const {
+  switch (Op.getOpcode()) {
+  default:
+    break;
+  case LoongArchISD::BSTRINS: {
+    unsigned BitWidth = Op.getScalarValueSizeInBits();
+    unsigned Msb = Op.getConstantOperandVal(2);
+    unsigned Lsb = Op.getConstantOperandVal(3);
+    // The bits above msb come from X.
+    if (Msb != BitWidth - 1) {
+      unsigned Tmp = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);
+      return std::min(Tmp, BitWidth - 1 - Msb);
+    }
+    // The high bits come from Y shifted left by lsb.
+    unsigned Tmp = DAG.ComputeNumSignBits(Op.getOperand(1), Depth + 1);
+    return Tmp > Lsb ? Tmp - Lsb : 1;
+  }
   }
+  return 1;
 }
 
 bool LoongArchTargetLowering::SimplifyDemandedBitsForTargetNode(
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 7c3ae7d6aac14..926fb8296507e 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -164,6 +164,10 @@ class LoongArchTargetLowering : public TargetLowering {
                                      const APInt &DemandedElts,
                                      const SelectionDAG &DAG,
                                      unsigned Depth) const override;
+  unsigned ComputeNumSignBitsForTargetNode(SDValue Op,
+                                           const APInt &DemandedElts,
+                                           const SelectionDAG &DAG,
+                                           unsigned Depth) const override;
   bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits,
                                          const APInt &DemandedElts,
                                          KnownBits &Known,
diff --git a/llvm/test/CodeGen/LoongArch/bstrins-bstrpick-known-bits.ll b/llvm/test/CodeGen/LoongArch/bstrins-bstrpick-known-bits.ll
index 6800b48e272f0..bdca1f01eeb21 100644
--- a/llvm/test/CodeGen/LoongArch/bstrins-bstrpick-known-bits.ll
+++ b/llvm/test/CodeGen/LoongArch/bstrins-bstrpick-known-bits.ll
@@ -19,7 +19,6 @@ define i32 @utf8_rev_col(ptr %begin, ptr %end) nounwind {
 ; CHECK-NEXT:  # %bb.2: # %one
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
 ; CHECK-NEXT:    addi.d $a1, $a1, -1
-; CHECK-NEXT:    addi.w $a4, $a4, 0
 ; CHECK-NEXT:    bne $a4, $a3, .LBB0_4
 ; CHECK-NEXT:    b .LBB0_5
 ; CHECK-NEXT:    .p2align 4, , 16
@@ -29,7 +28,6 @@ define i32 @utf8_rev_col(ptr %begin, ptr %end) nounwind {
 ; CHECK-NEXT:    addi.d $a1, $a1, -2
 ; CHECK-NEXT:    andi $a5, $a5, 31
 ; CHECK-NEXT:    bstrins.d $a4, $a5, 63, 6
-; CHECK-NEXT:    addi.w $a4, $a4, 0
 ; CHECK-NEXT:    beq $a4, $a3, .LBB0_5
 ; CHECK-NEXT:  .LBB0_4: # %latch
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
@@ -90,8 +88,7 @@ define i32 @bstrins_low_sext(i1 %c, i32 signext %x, i64 %y, i32 signext %z) noun
 ; CHECK-NEXT:    bstrins.d $a1, $a0, 7, 0
 ; CHECK-NEXT:    move $a3, $a1
 ; CHECK-NEXT:  .LBB1_2: # %b
-; CHECK-NEXT:    addi.w $a0, $a3, 0
-; CHECK-NEXT:    addi.d $a0, $a0, -10
+; CHECK-NEXT:    addi.d $a0, $a3, -10
 ; CHECK-NEXT:    sltui $a0, $a0, 1
 ; CHECK-NEXT:    ret
 entry:
@@ -122,7 +119,6 @@ define i64 @bstrpick_zext(i1 %c, i64 %x, i64 %y) nounwind {
 ; CHECK-NEXT:  # %bb.1: # %a
 ; CHECK-NEXT:    bstrpick.d $a0, $a1, 23, 8
 ; CHECK-NEXT:  .LBB2_2: # %b
-; CHECK-NEXT:    bstrpick.d $a0, $a0, 31, 0
 ; CHECK-NEXT:    ret
 entry:
   br i1 %c, label %a, label %b

``````````

</details>


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


More information about the llvm-branch-commits mailing list