[llvm] [GlobalISel] Fix ZExt known bits for scalable vectors. (PR #140213)

David Green via llvm-commits llvm-commits at lists.llvm.org
Tue May 20 07:33:35 PDT 2025


https://github.com/davemgreen updated https://github.com/llvm/llvm-project/pull/140213

>From c4914e80f54e4b84ce9966bd473973cafcf4841d Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Fri, 16 May 2025 08:42:24 +0100
Subject: [PATCH 1/2] [GlobalISel] Fix ZExt known bits for scalable vectors.

It was using the full size of the vector as the SrcBitWidth. This patch changes
the code to split G_ASSERT_ZEXT away from the others (G_INTTOPTR / G_PTRTOINT /
G_ZEXT / G_TRUNC) which are simpler, and make the code match the SDAG
equivalent.
---
 .../CodeGen/GlobalISel/GISelValueTracking.cpp | 27 +++-----
 .../GlobalISel/knownbits-assertzext.mir       | 67 +++++++++++++++++++
 .../AArch64/GlobalISel/knownbits-trunk.mir    | 67 +++++++++++++++++++
 .../AArch64/GlobalISel/knownbits-zext.mir     | 67 +++++++++++++++++++
 4 files changed, 212 insertions(+), 16 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 99794d690a91c..d16eef1178cbc 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -481,27 +481,22 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
       break;
     // Fall through and handle them the same as zext/trunc.
     [[fallthrough]];
-  case TargetOpcode::G_ASSERT_ZEXT:
   case TargetOpcode::G_ZEXT:
   case TargetOpcode::G_TRUNC: {
     Register SrcReg = MI.getOperand(1).getReg();
-    LLT SrcTy = MRI.getType(SrcReg);
-    unsigned SrcBitWidth;
-
-    // G_ASSERT_ZEXT stores the original bitwidth in the immediate operand.
-    if (Opcode == TargetOpcode::G_ASSERT_ZEXT)
-      SrcBitWidth = MI.getOperand(2).getImm();
-    else {
-      SrcBitWidth = SrcTy.isPointer()
-                        ? DL.getIndexSizeInBits(SrcTy.getAddressSpace())
-                        : SrcTy.getSizeInBits();
-    }
-    assert(SrcBitWidth && "SrcBitWidth can't be zero");
-    Known = Known.zextOrTrunc(SrcBitWidth);
     computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1);
     Known = Known.zextOrTrunc(BitWidth);
-    if (BitWidth > SrcBitWidth)
-      Known.Zero.setBitsFrom(SrcBitWidth);
+    break;
+  }
+  case TargetOpcode::G_ASSERT_ZEXT: {
+    Register SrcReg = MI.getOperand(1).getReg();
+    computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1);
+
+    unsigned SrcBitWidth = MI.getOperand(2).getImm();
+    assert(SrcBitWidth && "SrcBitWidth can't be zero");
+    APInt InMask = APInt::getLowBitsSet(BitWidth, SrcBitWidth);
+    Known.Zero |= (~InMask);
+    Known.One &= (~Known.Zero);
     break;
   }
   case TargetOpcode::G_ASSERT_ALIGN: {
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir
new file mode 100644
index 0000000000000..ab363618afc98
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir
@@ -0,0 +1,67 @@
+# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
+
+---
+name:            ScalarConst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalarConst
+  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:00000000000000000110010101000011 SignBits:17
+    %0:_(s32) = G_CONSTANT i32 2844222787
+    %1:_(s32) = G_ASSERT_ZEXT %0(s32), 16
+...
+---
+name:            ScalarVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalarVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(s32) = COPY $w0
+    %1:_(s32) = G_ASSERT_ZEXT %0(s32), 16
+...
+---
+name:            VectorCst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @VectorCst
+  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %2:_ KnownBits:00000000000000000110010101000011 SignBits:17
+    %0:_(s32) = G_CONSTANT i32 2844222787
+    %1:_(<4 x s32>) = G_BUILD_VECTOR %0, %0, %0, %0
+    %2:_(<4 x s32>) = G_ASSERT_ZEXT %1(<4 x s32>), 16
+...
+---
+name:            VectorVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @VectorVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(<4 x s32>) = COPY $q0
+    %1:_(<4 x s32>) = G_ASSERT_ZEXT %0(<4 x s32>), 16
+...
+---
+name:            ScalableCst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalableCst
+  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(s32) = G_CONSTANT i32 2844222787
+    %1:_(<vscale x 4 x s32>) = G_SPLAT_VECTOR %0
+    %2:_(<vscale x 4 x s32>) = G_ASSERT_ZEXT %1(<vscale x 4 x s32>), 16
+...
+---
+name:            ScalableVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalableVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(<vscale x 4 x s32>) = COPY $z0
+    %1:_(<vscale x 4 x s32>) = G_ASSERT_ZEXT %0(<vscale x 4 x s32>), 16
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir
new file mode 100644
index 0000000000000..23f1a98c91c0f
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir
@@ -0,0 +1,67 @@
+# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
+
+---
+name:            ScalarConst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalarConst
+  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:0110010101000011 SignBits:1
+    %0:_(s32) = G_CONSTANT i32 2844222787
+    %1:_(s16) = G_TRUNC %0(s32)
+...
+---
+name:            ScalarVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalarVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1
+    %0:_(s32) = COPY $w0
+    %1:_(s16) = G_TRUNC %0(s32)
+...
+---
+name:            VectorCst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @VectorCst
+  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %2:_ KnownBits:0110010101000011 SignBits:1
+    %0:_(s32) = G_CONSTANT i32 2844222787
+    %1:_(<4 x s32>) = G_BUILD_VECTOR %0, %0, %0, %0
+    %2:_(<4 x s16>) = G_TRUNC %1(<4 x s32>)
+...
+---
+name:            VectorVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @VectorVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1
+    %0:_(<4 x s32>) = COPY $q0
+    %1:_(<4 x s16>) = G_TRUNC %0(<4 x s32>)
+...
+---
+name:            ScalableCst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalableCst
+  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %2:_ KnownBits:???????????????? SignBits:1
+    %0:_(s32) = G_CONSTANT i32 2844222787
+    %1:_(<vscale x 4 x s32>) = G_SPLAT_VECTOR %0
+    %2:_(<vscale x 4 x s16>) = G_TRUNC %1(<vscale x 4 x s32>)
+...
+---
+name:            ScalableVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalableVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1
+    %0:_(<vscale x 4 x s32>) = COPY $z0
+    %1:_(<vscale x 4 x s16>) = G_TRUNC %0(<vscale x 4 x s32>)
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir
new file mode 100644
index 0000000000000..9275d2990bbe3
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir
@@ -0,0 +1,67 @@
+# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
+
+---
+name:            ScalarConst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalarConst
+  ; CHECK-NEXT: %0:_ KnownBits:0000000000001010 SignBits:12
+  ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000000000001010 SignBits:28
+    %0:_(s16) = G_CONSTANT i16 10
+    %1:_(s32) = G_ZEXT %0(s16)
+...
+---
+name:            ScalarVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalarVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(s16) = COPY $h0
+    %1:_(s32) = G_ZEXT %0(s16)
+...
+---
+name:            VectorCst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @VectorCst
+  ; CHECK-NEXT: %0:_ KnownBits:0000000000001010 SignBits:12
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000001010 SignBits:12
+  ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000000000001010 SignBits:28
+    %0:_(s16) = G_CONSTANT i16 10
+    %1:_(<4 x s16>) = G_BUILD_VECTOR %0, %0, %0, %0
+    %2:_(<4 x s32>) = G_ZEXT %1(<4 x s16>)
+...
+---
+name:            VectorVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @VectorVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(<4 x s16>) = COPY $d0
+    %1:_(<4 x s32>) = G_ZEXT %0(<4 x s16>)
+...
+---
+name:            ScalableCst
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalableCst
+  ; CHECK-NEXT: %0:_ KnownBits:0000000000001010 SignBits:12
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(s16) = G_CONSTANT i16 10
+    %1:_(<vscale x 4 x s16>) = G_SPLAT_VECTOR %0
+    %2:_(<vscale x 4 x s32>) = G_ZEXT %1(<vscale x 4 x s16>)
+...
+---
+name:            ScalableVar
+body:             |
+  bb.0:
+  ; CHECK-LABEL: name: @ScalableVar
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000000???????????????? SignBits:16
+    %0:_(<vscale x 4 x s16>) = COPY $z0
+    %1:_(<vscale x 4 x s32>) = G_ZEXT %0(<vscale x 4 x s16>)
+...

>From 823a8ff6425fddbc192375595c436ec5c693775b Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Tue, 20 May 2025 15:33:21 +0100
Subject: [PATCH 2/2] Update tests to use -filetype=null

---
 .../GlobalISel/knownbits-assertzext.mir       | 24 +++++++++----------
 .../AArch64/GlobalISel/knownbits-trunk.mir    |  6 ++---
 .../AArch64/GlobalISel/knownbits-zext.mir     |  6 ++---
 3 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir
index ab363618afc98..9b2089f17dea4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir
@@ -1,14 +1,14 @@
 # NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
-# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
+# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -filetype=null 2>&1 | FileCheck %s
 
 ---
 name:            ScalarConst
 body:             |
   bb.0:
   ; CHECK-LABEL: name: @ScalarConst
-  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
-  ; CHECK-NEXT: %1:_ KnownBits:00000000000000000110010101000011 SignBits:17
-    %0:_(s32) = G_CONSTANT i32 2844222787
+  ; CHECK-NEXT: %0:_ KnownBits:00000000000000000000000001111000 SignBits:25
+  ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000000001111000 SignBits:25
+    %0:_(s32) = G_CONSTANT i32 120
     %1:_(s32) = G_ASSERT_ZEXT %0(s32), 16
 ...
 ---
@@ -26,10 +26,10 @@ name:            VectorCst
 body:             |
   bb.0:
   ; CHECK-LABEL: name: @VectorCst
-  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
-  ; CHECK-NEXT: %1:_ KnownBits:10101001100001110110010101000011 SignBits:1
-  ; CHECK-NEXT: %2:_ KnownBits:00000000000000000110010101000011 SignBits:17
-    %0:_(s32) = G_CONSTANT i32 2844222787
+  ; CHECK-NEXT: %0:_ KnownBits:00000000000000000000000001111000 SignBits:25
+  ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000000001111000 SignBits:25
+  ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000000001111000 SignBits:25
+    %0:_(s32) = G_CONSTANT i32 120
     %1:_(<4 x s32>) = G_BUILD_VECTOR %0, %0, %0, %0
     %2:_(<4 x s32>) = G_ASSERT_ZEXT %1(<4 x s32>), 16
 ...
@@ -48,10 +48,10 @@ name:            ScalableCst
 body:             |
   bb.0:
   ; CHECK-LABEL: name: @ScalableCst
-  ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
-  ; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
-  ; CHECK-NEXT: %2:_ KnownBits:0000000000000000???????????????? SignBits:16
-    %0:_(s32) = G_CONSTANT i32 2844222787
+  ; CHECK-NEXT: %0:_ KnownBits:00000000000000000000000001111000 SignBits:25
+  ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000000001111000 SignBits:25
+  ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000000001111000 SignBits:25
+    %0:_(s32) = G_CONSTANT i32 120
     %1:_(<vscale x 4 x s32>) = G_SPLAT_VECTOR %0
     %2:_(<vscale x 4 x s32>) = G_ASSERT_ZEXT %1(<vscale x 4 x s32>), 16
 ...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir
index 23f1a98c91c0f..f680196a4225e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir
@@ -1,5 +1,5 @@
 # NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
-# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
+# RUN: llc -mtriple aarch64 -passes="print<gisel-value-tracking>" %s -filetype=null 2>&1 | FileCheck %s
 
 ---
 name:            ScalarConst
@@ -49,8 +49,8 @@ body:             |
   bb.0:
   ; CHECK-LABEL: name: @ScalableCst
   ; CHECK-NEXT: %0:_ KnownBits:10101001100001110110010101000011 SignBits:1
-  ; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
-  ; CHECK-NEXT: %2:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:10101001100001110110010101000011 SignBits:1
+  ; CHECK-NEXT: %2:_ KnownBits:0110010101000011 SignBits:1
     %0:_(s32) = G_CONSTANT i32 2844222787
     %1:_(<vscale x 4 x s32>) = G_SPLAT_VECTOR %0
     %2:_(<vscale x 4 x s16>) = G_TRUNC %1(<vscale x 4 x s32>)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir
index 9275d2990bbe3..a420ff669b3d3 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir
@@ -1,5 +1,5 @@
 # NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
-# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
+# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -filetype=null 2>&1 | FileCheck %s
 
 ---
 name:            ScalarConst
@@ -49,8 +49,8 @@ body:             |
   bb.0:
   ; CHECK-LABEL: name: @ScalableCst
   ; CHECK-NEXT: %0:_ KnownBits:0000000000001010 SignBits:12
-  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1
-  ; CHECK-NEXT: %2:_ KnownBits:0000000000000000???????????????? SignBits:16
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000001010 SignBits:1
+  ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000000000001010 SignBits:28
     %0:_(s16) = G_CONSTANT i16 10
     %1:_(<vscale x 4 x s16>) = G_SPLAT_VECTOR %0
     %2:_(<vscale x 4 x s32>) = G_ZEXT %1(<vscale x 4 x s16>)



More information about the llvm-commits mailing list