[llvm] 48636d1 - [GlobalISel] Add G_UAVGFLOOR/G_UAVGCEIL/G_SAVGFLOOR/G_SAVGCEIL to computeKnownBits (#209171)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 04:12:27 PDT 2026
Author: Joel Walker
Date: 2026-07-14T12:12:23+01:00
New Revision: 48636d19ab5e3bf82cbff593a82573e8094abed1
URL: https://github.com/llvm/llvm-project/commit/48636d19ab5e3bf82cbff593a82573e8094abed1
DIFF: https://github.com/llvm/llvm-project/commit/48636d19ab5e3bf82cbff593a82573e8094abed1.diff
LOG: [GlobalISel] Add G_UAVGFLOOR/G_UAVGCEIL/G_SAVGFLOOR/G_SAVGCEIL to computeKnownBits (#209171)
Add known-bits handling for the averaging (halving add) opcodes G_UAVGFLOOR,
G_UAVGCEIL, G_SAVGFLOOR and G_SAVGCEIL in GISelValueTracking, using the
existing `KnownBits::avg{Floor,Ceil}{S,U}` helpers. This matches
SelectionDAG's handling of the corresponding ISD::AVGFLOOR*/AVGCEIL*
nodes.
This lets GlobalISel drop the redundant masking around hadd/rhadd of
zero-extended operands on AArch64 (see aarch64-known-bits-hadd.ll, where the
GlobalISel output now matches SelectionDAG). The sign-extended cases are
unaffected, since the masking is not redundant there.
Part of #150515.
---
Assisted by Claude (Anthropic).
Added:
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-avg.mir
Modified:
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
llvm/test/CodeGen/AArch64/aarch64-known-bits-hadd.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 5602038c828dd..9eea63420d551 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -398,6 +398,38 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
Known = KnownBits::mulhs(Known, Known2);
break;
}
+ case TargetOpcode::G_UAVGFLOOR: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::avgFloorU(Known, Known2);
+ break;
+ }
+ case TargetOpcode::G_UAVGCEIL: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::avgCeilU(Known, Known2);
+ break;
+ }
+ case TargetOpcode::G_SAVGFLOOR: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::avgFloorS(Known, Known2);
+ break;
+ }
+ case TargetOpcode::G_SAVGCEIL: {
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::avgCeilS(Known, Known2);
+ break;
+ }
case TargetOpcode::G_ABDU: {
computeKnownBitsImpl(MI.getOperand(2).getReg(), Known, DemandedElts,
Depth + 1);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-avg.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-avg.mir
new file mode 100644
index 0000000000000..9e1d485a035e0
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-avg.mir
@@ -0,0 +1,131 @@
+# 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_UAvgFloor
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Cst_UAvgFloor
+ ; CHECK-NEXT: %0:_ KnownBits:00001011 SignBits:4
+ ; CHECK-NEXT: %1:_ KnownBits:00000100 SignBits:5
+ ; CHECK-NEXT: %2:_ KnownBits:00000111 SignBits:5
+ %0:_(i8) = G_CONSTANT i8 11
+ %1:_(i8) = G_CONSTANT i8 4
+ %2:_(i8) = G_UAVGFLOOR %0, %1
+...
+---
+name: Cst_UAvgCeil
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Cst_UAvgCeil
+ ; CHECK-NEXT: %0:_ KnownBits:00001011 SignBits:4
+ ; CHECK-NEXT: %1:_ KnownBits:00000100 SignBits:5
+ ; CHECK-NEXT: %2:_ KnownBits:00001000 SignBits:4
+ %0:_(i8) = G_CONSTANT i8 11
+ %1:_(i8) = G_CONSTANT i8 4
+ %2:_(i8) = G_UAVGCEIL %0, %1
+...
+---
+name: CstNoOverflow_UAvgFloor
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstNoOverflow_UAvgFloor
+ ; CHECK-NEXT: %0:_ KnownBits:11001000 SignBits:2
+ ; CHECK-NEXT: %1:_ KnownBits:01100100 SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:10010110 SignBits:1
+ %0:_(i8) = G_CONSTANT i8 200
+ %1:_(i8) = G_CONSTANT i8 100
+ %2:_(i8) = G_UAVGFLOOR %0, %1
+...
+---
+name: CstNoOverflow_UAvgCeil
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstNoOverflow_UAvgCeil
+ ; CHECK-NEXT: %0:_ KnownBits:11111111 SignBits:8
+ ; CHECK-NEXT: %1:_ KnownBits:11111111 SignBits:8
+ ; CHECK-NEXT: %2:_ KnownBits:11111111 SignBits:8
+ %0:_(i8) = G_CONSTANT i8 255
+ %1:_(i8) = G_CONSTANT i8 255
+ %2:_(i8) = G_UAVGCEIL %0, %1
+...
+---
+name: Cst_SAvgFloor
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Cst_SAvgFloor
+ ; CHECK-NEXT: %0:_ KnownBits:11110110 SignBits:4
+ ; CHECK-NEXT: %1:_ KnownBits:00000100 SignBits:5
+ ; CHECK-NEXT: %2:_ KnownBits:11111101 SignBits:6
+ %0:_(i8) = G_CONSTANT i8 -10
+ %1:_(i8) = G_CONSTANT i8 4
+ %2:_(i8) = G_SAVGFLOOR %0, %1
+...
+---
+name: CstNoOverflow_SAvgFloor
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstNoOverflow_SAvgFloor
+ ; CHECK-NEXT: %0:_ KnownBits:10011100 SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:10011100 SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:10011100 SignBits:1
+ %0:_(i8) = G_CONSTANT i8 -100
+ %1:_(i8) = G_CONSTANT i8 -100
+ %2:_(i8) = G_SAVGFLOOR %0, %1
+...
+---
+name: CstNoOverflow_SAvgCeil
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CstNoOverflow_SAvgCeil
+ ; CHECK-NEXT: %0:_ KnownBits:01111111 SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:01111111 SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:01111111 SignBits:1
+ %0:_(i8) = G_CONSTANT i8 127
+ %1:_(i8) = G_CONSTANT i8 127
+ %2:_(i8) = G_SAVGCEIL %0, %1
+...
+---
+name: PartialKnown_UAvgFloor
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @PartialKnown_UAvgFloor
+ ; 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_UAVGFLOOR %2, %3
+...
+---
+name: Vector_UAvgFloor
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Vector_UAvgFloor
+ ; 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:10010110 SignBits:1
+ %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_UAVGFLOOR %2, %3
+...
+---
+name: Unknown_SAvgCeil
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @Unknown_SAvgCeil
+ ; 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_SAVGCEIL %0, %1
+...
diff --git a/llvm/test/CodeGen/AArch64/aarch64-known-bits-hadd.ll b/llvm/test/CodeGen/AArch64/aarch64-known-bits-hadd.ll
index a6fbaf01c5476..d0a7cb2604ed2 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-known-bits-hadd.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-known-bits-hadd.ll
@@ -18,9 +18,7 @@ define <8 x i16> @haddu_zext(<8 x i8> %a0, <8 x i8> %a1) {
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0
; CHECK-GI-NEXT: ushll v1.8h, v1.8b, #0
-; CHECK-GI-NEXT: mvni v2.8h, #254, lsl #8
; CHECK-GI-NEXT: uhadd v0.8h, v0.8h, v1.8h
-; CHECK-GI-NEXT: and v0.16b, v0.16b, v2.16b
; CHECK-GI-NEXT: ret
%x0 = zext <8 x i8> %a0 to <8 x i16>
%x1 = zext <8 x i8> %a1 to <8 x i16>
@@ -40,9 +38,7 @@ define <8 x i16> @rhaddu_zext(<8 x i8> %a0, <8 x i8> %a1) {
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0
; CHECK-GI-NEXT: ushll v1.8h, v1.8b, #0
-; CHECK-GI-NEXT: mvni v2.8h, #254, lsl #8
; CHECK-GI-NEXT: urhadd v0.8h, v0.8h, v1.8h
-; CHECK-GI-NEXT: and v0.16b, v0.16b, v2.16b
; CHECK-GI-NEXT: ret
%x0 = zext <8 x i8> %a0 to <8 x i16>
%x1 = zext <8 x i8> %a1 to <8 x i16>
@@ -62,9 +58,7 @@ define <8 x i16> @hadds_zext(<8 x i8> %a0, <8 x i8> %a1) {
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0
; CHECK-GI-NEXT: ushll v1.8h, v1.8b, #0
-; CHECK-GI-NEXT: mvni v2.8h, #254, lsl #8
; CHECK-GI-NEXT: shadd v0.8h, v0.8h, v1.8h
-; CHECK-GI-NEXT: and v0.16b, v0.16b, v2.16b
; CHECK-GI-NEXT: ret
%x0 = zext <8 x i8> %a0 to <8 x i16>
%x1 = zext <8 x i8> %a1 to <8 x i16>
@@ -74,21 +68,12 @@ define <8 x i16> @hadds_zext(<8 x i8> %a0, <8 x i8> %a1) {
}
define <8 x i16> @shaddu_zext(<8 x i8> %a0, <8 x i8> %a1) {
-; CHECK-SD-LABEL: shaddu_zext:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0
-; CHECK-SD-NEXT: ushll v1.8h, v1.8b, #0
-; CHECK-SD-NEXT: srhadd v0.8h, v0.8h, v1.8h
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: shaddu_zext:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0
-; CHECK-GI-NEXT: ushll v1.8h, v1.8b, #0
-; CHECK-GI-NEXT: mvni v2.8h, #254, lsl #8
-; CHECK-GI-NEXT: srhadd v0.8h, v0.8h, v1.8h
-; CHECK-GI-NEXT: and v0.16b, v0.16b, v2.16b
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: shaddu_zext:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ushll v0.8h, v0.8b, #0
+; CHECK-NEXT: ushll v1.8h, v1.8b, #0
+; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
+; CHECK-NEXT: ret
%x0 = zext <8 x i8> %a0 to <8 x i16>
%x1 = zext <8 x i8> %a1 to <8 x i16>
%hadd = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> %x0, <8 x i16> %x1)
@@ -191,5 +176,3 @@ define <8 x i16> @shaddu_sext(<8 x i8> %a0, <8 x i8> %a1) {
%res = and <8 x i16> %hadd, <i16 511, i16 511, i16 511, i16 511, i16 511, i16 511, i16 511, i16 511>
ret <8 x i16> %res
}
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
More information about the llvm-commits
mailing list