[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