Skip to content

Conversation

@davemgreen
Copy link
Collaborator

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.

@llvmbot
Copy link
Member

llvmbot commented May 16, 2025

@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-aarch64

Author: David Green (davemgreen)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/140213.diff

4 Files Affected:

  • (modified) llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp (+11-16)
  • (added) llvm/test/CodeGen/AArch64/GlobalISel/knownbits-assertzext.mir (+67)
  • (added) llvm/test/CodeGen/AArch64/GlobalISel/knownbits-trunk.mir (+67)
  • (added) llvm/test/CodeGen/AArch64/GlobalISel/knownbits-zext.mir (+67)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 589936b6c260f..e7cd91cc93d3f 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -472,27 +472,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>)
+...

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.
@davemgreen davemgreen force-pushed the gh-gi-knownbits-zext branch from 77696aa to 823a8ff Compare May 20, 2025 14:33
@davemgreen davemgreen merged commit 77c8d21 into llvm:main May 21, 2025
11 checks passed
@davemgreen davemgreen deleted the gh-gi-knownbits-zext branch May 21, 2025 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants