[llvm] 477bb26 - [GlobalISel] Add G_SADDSAT/G_UADDSAT/G_SSUBSAT/G_USUBSAT to computeKnownBits (#209075)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 13 05:30:12 PDT 2026
Author: Joel Walker
Date: 2026-07-13T14:30:07+02:00
New Revision: 477bb26c7c0c5eee0491ce058968ce3c4b89623b
URL: https://github.com/llvm/llvm-project/commit/477bb26c7c0c5eee0491ce058968ce3c4b89623b
DIFF: https://github.com/llvm/llvm-project/commit/477bb26c7c0c5eee0491ce058968ce3c4b89623b.diff
LOG: [GlobalISel] Add G_SADDSAT/G_UADDSAT/G_SSUBSAT/G_USUBSAT to computeKnownBits (#209075)
Add known-bits handling for the saturating arithmetic opcodes G_SADDSAT,
G_UADDSAT, G_SSUBSAT and G_USUBSAT in GISelValueTracking, using the
existing
`KnownBits::{sadd,uadd,ssub,usub}_sat` helpers - the same ones
ValueTracking
uses for the corresponding IR intrinsics. (On the SelectionDAG side only
`ISD::USUBSAT` is currently handled.)
The new test covers exact constant folding, all four saturation clamps
(255, 127, 0, -128), partially known operands, a vector case, and fully
unknown operands. Without the change, all of these results are unknown.
Part of #150515.
---
Assisted by Claude (Anthropic).
Added:
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sat.mir
Modified:
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 517eb66d66620..5602038c828dd 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -424,6 +424,38 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
Known.Zero.setHighBits(std::min(SignBits0, SignBits1) - 1);
break;
}
+ case TargetOpcode::G_SADDSAT: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::sadd_sat(Known, Known2);
+ break;
+ }
+ case TargetOpcode::G_UADDSAT: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::uadd_sat(Known, Known2);
+ break;
+ }
+ case TargetOpcode::G_SSUBSAT: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::ssub_sat(Known, Known2);
+ break;
+ }
+ case TargetOpcode::G_USUBSAT: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::usub_sat(Known, Known2);
+ break;
+ }
case TargetOpcode::G_UDIV: {
computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
Depth + 1);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sat.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sat.mir
new file mode 100644
index 0000000000000..23f90c134c941
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sat.mir
@@ -0,0 +1,159 @@
+# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=aarch64 -passes="print<gisel-value-tracking>" -filetype=null %s 2>&1 | FileCheck %s
+
+---
+name: Cst_UAddSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Cst_UAddSat
+ ; CHECK-NEXT: %0:_ KnownBits:00001010 SignBits:4
+ ; CHECK-NEXT: %1:_ KnownBits:00000011 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:00001101 SignBits:4
+ %0:_(i8) = G_CONSTANT i8 10
+ %1:_(i8) = G_CONSTANT i8 3
+ %2:_(i8) = G_UADDSAT %0, %1
+...
+---
+name: CstSat_UAddSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstSat_UAddSat
+ ; CHECK-NEXT: %0:_ KnownBits:11001000 SignBits:2
+ ; CHECK-NEXT: %1:_ KnownBits:01100100 SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:11111111 SignBits:8
+ %0:_(i8) = G_CONSTANT i8 200
+ %1:_(i8) = G_CONSTANT i8 100
+ %2:_(i8) = G_UADDSAT %0, %1
+...
+---
+name: Cst_SAddSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Cst_SAddSat
+ ; CHECK-NEXT: %0:_ KnownBits:00001010 SignBits:4
+ ; CHECK-NEXT: %1:_ KnownBits:00000011 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:00001101 SignBits:4
+ %0:_(i8) = G_CONSTANT i8 10
+ %1:_(i8) = G_CONSTANT i8 3
+ %2:_(i8) = G_SADDSAT %0, %1
+...
+---
+name: CstSat_SAddSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstSat_SAddSat
+ ; CHECK-NEXT: %0:_ KnownBits:01100100 SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:01100100 SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:01111111 SignBits:1
+ %0:_(i8) = G_CONSTANT i8 100
+ %1:_(i8) = G_CONSTANT i8 100
+ %2:_(i8) = G_SADDSAT %0, %1
+...
+---
+name: Cst_USubSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Cst_USubSat
+ ; CHECK-NEXT: %0:_ KnownBits:00001010 SignBits:4
+ ; CHECK-NEXT: %1:_ KnownBits:00000011 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:00000111 SignBits:5
+ %0:_(i8) = G_CONSTANT i8 10
+ %1:_(i8) = G_CONSTANT i8 3
+ %2:_(i8) = G_USUBSAT %0, %1
+...
+---
+name: CstSat_USubSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstSat_USubSat
+ ; CHECK-NEXT: %0:_ KnownBits:00000011 SignBits:6
+ ; CHECK-NEXT: %1:_ KnownBits:00001010 SignBits:4
+ ; CHECK-NEXT: %2:_ KnownBits:00000000 SignBits:8
+ %0:_(i8) = G_CONSTANT i8 3
+ %1:_(i8) = G_CONSTANT i8 10
+ %2:_(i8) = G_USUBSAT %0, %1
+...
+---
+name: Cst_SSubSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Cst_SSubSat
+ ; CHECK-NEXT: %0:_ KnownBits:00001010 SignBits:4
+ ; CHECK-NEXT: %1:_ KnownBits:00000011 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:00000111 SignBits:5
+ %0:_(i8) = G_CONSTANT i8 10
+ %1:_(i8) = G_CONSTANT i8 3
+ %2:_(i8) = G_SSUBSAT %0, %1
+...
+---
+name: CstSat_SSubSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstSat_SSubSat
+ ; CHECK-NEXT: %0:_ KnownBits:10011100 SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:01100100 SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:10000000 SignBits:1
+ %0:_(i8) = G_CONSTANT i8 -100
+ %1:_(i8) = G_CONSTANT i8 100
+ %2:_(i8) = G_SSUBSAT %0, %1
+...
+---
+name: PartialKnown_UAddSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @PartialKnown_UAddSat
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:00001111 SignBits:4
+ ; CHECK-NEXT: %2:_ KnownBits:0000???? SignBits:4
+ ; CHECK-NEXT: %3:_ KnownBits:00000100 SignBits:5
+ ; CHECK-NEXT: %4:_ KnownBits:000????? SignBits:3
+ %0:_(i8) = G_IMPLICIT_DEF
+ %1:_(i8) = G_CONSTANT i8 15
+ %2:_(i8) = G_AND %0, %1
+ %3:_(i8) = G_CONSTANT i8 4
+ %4:_(i8) = G_UADDSAT %2, %3
+...
+---
+name: PartialKnown_USubSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @PartialKnown_USubSat
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:00001111 SignBits:4
+ ; CHECK-NEXT: %2:_ KnownBits:0000???? SignBits:4
+ ; CHECK-NEXT: %3:_ KnownBits:00000100 SignBits:5
+ ; CHECK-NEXT: %4:_ KnownBits:0000???? SignBits:4
+ %0:_(i8) = G_IMPLICIT_DEF
+ %1:_(i8) = G_CONSTANT i8 15
+ %2:_(i8) = G_AND %0, %1
+ %3:_(i8) = G_CONSTANT i8 4
+ %4:_(i8) = G_USUBSAT %2, %3
+...
+---
+name: Vector_UAddSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Vector_UAddSat
+ ; CHECK-NEXT: %0:_ KnownBits:11001000 SignBits:2
+ ; CHECK-NEXT: %1:_ KnownBits:01100100 SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:11001000 SignBits:2
+ ; CHECK-NEXT: %3:_ KnownBits:01100100 SignBits:1
+ ; CHECK-NEXT: %4:_ KnownBits:11111111 SignBits:8
+ %0:_(i8) = G_CONSTANT i8 200
+ %1:_(i8) = G_CONSTANT i8 100
+ %2:_(<2 x i8>) = G_BUILD_VECTOR %0, %0
+ %3:_(<2 x i8>) = G_BUILD_VECTOR %1, %1
+ %4:_(<2 x i8>) = G_UADDSAT %2, %3
+...
+---
+name: Unknown_SAddSat
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Unknown_SAddSat
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1
+ %0:_(i8) = COPY $b0
+ %1:_(i8) = COPY $b1
+ %2:_(i8) = G_SADDSAT %0, %1
+...
More information about the llvm-commits
mailing list