[llvm] [GlobalISel] Add G_INSERT_SUBVECTOR to computeNumSignBits (PR #220976)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 28 00:03:16 PDT 2026
https://github.com/pkuyo updated https://github.com/llvm/llvm-project/pull/220976
>From e40dfd30b2bb5a1d9428ccf081873ff28e0d8fb1 Mon Sep 17 00:00:00 2001
From: Pkuyo <miku_mi at foxmail.com>
Date: Sun, 27 Sep 2026 23:17:00 -0700
Subject: [PATCH 1/2] [SelectionDAG] Move INSERT_SUBVECTOR sign bits logic into
SignBitsOps (NFC)
---
llvm/include/llvm/Support/KnownBits.h | 12 ++++++
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 29 +++-----------
llvm/lib/Support/KnownBits.cpp | 39 +++++++++++++++++++
3 files changed, 57 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index 1353955c8e325..b62ed58844215 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -15,11 +15,14 @@
#define LLVM_SUPPORT_KNOWNBITS_H
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Support/Compiler.h"
#include <optional>
namespace llvm {
+class ElementCount;
+
// Struct for tracking the known zeros and ones of a value.
struct KnownBits {
APInt Zero;
@@ -596,6 +599,15 @@ namespace SignBitsOps {
LLVM_ABI unsigned rot(unsigned SrcSignBits, unsigned BitWidth,
std::optional<APInt> RotAmt, bool IsRotateRight);
+/// Compute a lower bound on the number of sign bits in the demanded
+/// elements of an INSERT_SUBVECTOR. ComputeNumSignBits(OpIdx, Demanded)
+/// returns the number of sign bits of operand OpIdx (0 for the source, 1 for
+/// the subvector) in the demanded elements.
+LLVM_ABI unsigned insertSubvector(
+ ElementCount SrcEC, ElementCount SubEC, uint64_t Idx,
+ const APInt &DemandedElts,
+ function_ref<unsigned(unsigned, const APInt &)> ComputeNumSignBits);
+
} // end namespace SignBitsOps
inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 541c378a2eda1..c01abb8adb082 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5460,29 +5460,12 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
case ISD::INSERT_SUBVECTOR: {
SDValue Src = Op.getOperand(0);
SDValue Sub = Op.getOperand(1);
- if (VT.isScalableVector()) {
- Tmp = ComputeNumSignBits(Sub, Depth + 1);
- Tmp = std::min(Tmp, ComputeNumSignBits(Src, Depth + 1));
- return Tmp;
- }
- // Demand any elements from the subvector and the remainder from the src its
- // inserted into.
- uint64_t Idx = Op.getConstantOperandVal(2);
- unsigned NumSubElts = Sub.getValueType().getVectorNumElements();
- APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
- APInt DemandedSrcElts = DemandedElts;
- DemandedSrcElts.clearBits(Idx, Idx + NumSubElts);
-
- Tmp = std::numeric_limits<unsigned>::max();
- if (!!DemandedSubElts) {
- Tmp = ComputeNumSignBits(Sub, DemandedSubElts, Depth + 1);
- if (Tmp == 1)
- return 1; // early-out
- }
- if (!!DemandedSrcElts) {
- Tmp2 = ComputeNumSignBits(Src, DemandedSrcElts, Depth + 1);
- Tmp = std::min(Tmp, Tmp2);
- }
+ Tmp = SignBitsOps::insertSubvector(
+ Src.getValueType().getVectorElementCount(),
+ Sub.getValueType().getVectorElementCount(), Op.getConstantOperandVal(2),
+ DemandedElts, [&](unsigned OpIdx, const APInt &Demanded) {
+ return ComputeNumSignBits(Op.getOperand(OpIdx), Demanded, Depth + 1);
+ });
assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
return Tmp;
}
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 70f7a2f4fc887..f4d88d3082333 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -14,8 +14,10 @@
#include "llvm/Support/KnownBits.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/TypeSize.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
+#include <limits>
using namespace llvm;
@@ -1469,3 +1471,40 @@ unsigned llvm::SignBitsOps::rot(unsigned SrcSignBits, unsigned BitWidth,
return SrcSignBits - Amt;
return 1;
}
+
+unsigned llvm::SignBitsOps::insertSubvector(
+ ElementCount SrcEC, ElementCount SubEC, uint64_t Idx,
+ const APInt &DemandedElts,
+ function_ref<unsigned(unsigned, const APInt &)> ComputeNumSignBits) {
+
+ unsigned Result = std::numeric_limits<unsigned>::max();
+ if (SrcEC.isScalable()) {
+ APInt DemandedSubElts = SubEC.isScalable()
+ ? APInt(1, 1)
+ : APInt::getAllOnes(SubEC.getFixedValue());
+ Result = ComputeNumSignBits(1, DemandedSubElts);
+ if (Result == 1)
+ return 1;
+ return std::min(Result, ComputeNumSignBits(0, APInt(1, 1)));
+ }
+
+ unsigned NumSubElts = SubEC.getFixedValue();
+ unsigned Offset = static_cast<unsigned>(Idx);
+ APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Offset);
+ APInt DemandedSrcElts = DemandedElts;
+ DemandedSrcElts.clearBits(Offset, Offset + NumSubElts);
+
+ // Only query the operands that contribute demanded elements, and take the
+ // minimum over them.
+ if (!!DemandedSubElts) {
+ Result = ComputeNumSignBits(1, DemandedSubElts);
+ // If we don't know any bits, early out.
+ if (Result == 1)
+ return 1;
+ }
+ if (!!DemandedSrcElts) {
+ unsigned SrcAnswer = ComputeNumSignBits(0, DemandedSrcElts);
+ Result = std::min(Result, SrcAnswer);
+ }
+ return Result;
+}
>From bd70e5e87df0d87800072c9037fa27df137d960f Mon Sep 17 00:00:00 2001
From: Pkuyo <miku_mi at foxmail.com>
Date: Sun, 27 Sep 2026 23:17:03 -0700
Subject: [PATCH 2/2] [GlobalISel] Add G_INSERT_SUBVECTOR to computeNumSignBits
---
.../CodeGen/GlobalISel/GISelValueTracking.cpp | 12 +++
.../GlobalISel/knownbits-insert-subvector.mir | 88 +++++++++++++++++++
2 files changed, 100 insertions(+)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 1a3bcd8e579ee..e7a44a9b966eb 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2857,6 +2857,18 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
}
return computeNumSignBits(SrcReg, DemandedSrcElts, Depth + 1);
}
+ case TargetOpcode::G_INSERT_SUBVECTOR: {
+ Register Src = MI.getOperand(1).getReg();
+ Register Sub = MI.getOperand(2).getReg();
+ FirstAnswer = SignBitsOps::insertSubvector(
+ MRI.getType(Src).getElementCount(), MRI.getType(Sub).getElementCount(),
+ MI.getOperand(3).getImm(), DemandedElts,
+ [&](unsigned OpIdx, const APInt &Demanded) {
+ return computeNumSignBits(OpIdx == 0 ? Src : Sub, Demanded,
+ Depth + 1);
+ });
+ break;
+ }
case TargetOpcode::G_SHUFFLE_VECTOR: {
// Collect the minimum number of sign bits that are shared by every vector
// element referenced by the shuffle.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir
index 7275f008368c5..4de62e59b82c7 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir
@@ -103,3 +103,91 @@ body: |
%sub:_(<2 x i16>) = G_BUILD_VECTOR %subval, %subval
%res:_(<vscale x 4 x i16>) = G_INSERT_SUBVECTOR %src, %sub, 2
...
+---
+name: insert_min_of_operands
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @insert_min_of_operands
+ ; CHECK-NEXT: %v0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %v1:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %base:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ ; CHECK-NEXT: %sub:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ ; CHECK-NEXT: %res:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ %v0:_(<4 x i8>) = COPY $s0
+ %v1:_(<2 x i16>) = COPY $s1
+ %base:_(<4 x i32>) = G_SEXT %v0
+ %sub:_(<2 x i32>) = G_SEXT %v1
+ %res:_(<4 x i32>) = G_INSERT_SUBVECTOR %base, %sub, 2
+...
+
+---
+name: extract_untouched_lanes_of_insert
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @extract_untouched_lanes_of_insert
+ ; CHECK-NEXT: %v0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %v1:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %base:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ ; CHECK-NEXT: %sub:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ ; CHECK-NEXT: %res:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ ; CHECK-NEXT: %ext:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ %v0:_(<4 x i8>) = COPY $s0
+ %v1:_(<2 x i16>) = COPY $s1
+ %base:_(<4 x i32>) = G_SEXT %v0
+ %sub:_(<2 x i32>) = G_SEXT %v1
+ %res:_(<4 x i32>) = G_INSERT_SUBVECTOR %base, %sub, 2
+ %ext:_(<2 x i32>) = G_EXTRACT_SUBVECTOR %res, 0
+...
+
+---
+name: extract_inserted_lanes_of_insert
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @extract_inserted_lanes_of_insert
+ ; CHECK-NEXT: %v0:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %v1:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %base:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ ; CHECK-NEXT: %sub:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ ; CHECK-NEXT: %res:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ ; CHECK-NEXT: %ext:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ %v0:_(<4 x i16>) = COPY $d0
+ %v1:_(<2 x i8>) = COPY $h1
+ %base:_(<4 x i32>) = G_SEXT %v0
+ %sub:_(<2 x i32>) = G_SEXT %v1
+ %res:_(<4 x i32>) = G_INSERT_SUBVECTOR %base, %sub, 2
+ %ext:_(<2 x i32>) = G_EXTRACT_SUBVECTOR %res, 2
+...
+
+---
+name: insert_scalable
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @insert_scalable
+ ; CHECK-NEXT: %v0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %v1:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %base:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ ; CHECK-NEXT: %sub:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ ; CHECK-NEXT: %res:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ %v0:_(<vscale x 4 x i8>) = COPY $z0
+ %v1:_(<vscale x 2 x i16>) = COPY $z1
+ %base:_(<vscale x 4 x i32>) = G_SEXT %v0
+ %sub:_(<vscale x 2 x i32>) = G_SEXT %v1
+ %res:_(<vscale x 4 x i32>) = G_INSERT_SUBVECTOR %base, %sub, 0
+...
+
+---
+name: insert_fixed_into_scalable
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @insert_fixed_into_scalable
+ ; CHECK-NEXT: %v0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %v1:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %base:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ ; CHECK-NEXT: %sub:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ ; CHECK-NEXT: %res:_ KnownBits:???????????????????????????????? SignBits:17 IsKnownNeverZero:0
+ %v0:_(<vscale x 4 x i8>) = COPY $z0
+ %v1:_(<2 x i16>) = COPY $s1
+ %base:_(<vscale x 4 x i32>) = G_SEXT %v0
+ %sub:_(<2 x i32>) = G_SEXT %v1
+ %res:_(<vscale x 4 x i32>) = G_INSERT_SUBVECTOR %base, %sub, 0
+...
More information about the llvm-commits
mailing list