[llvm] [GlobalISel] Support GISelValueTracking for G_FREEZE. (PR #223696)
Vikash Gupta via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 03:56:14 PDT 2026
https://github.com/vg0204 updated https://github.com/llvm/llvm-project/pull/223696
>From a34603f0fae3e2f7b76031fc3c37744a3ce12dc0 Mon Sep 17 00:00:00 2001
From: vg0204 <Vikash.Gupta at amd.com>
Date: Tue, 15 Sep 2026 18:47:16 +0530
Subject: [PATCH 1/4] [GlobalISel] Support GISelValueTracking for G_FREEZE
Port the SDAG FREEZE handling to GlobalISel. Look through G_FREEZE in
computeKnownBits, computeNumSignBits, and computeKnownFPClass when the
source is guaranteed not undef or poison.
Part of #150515.
---
.../CodeGen/GlobalISel/GISelValueTracking.cpp | 25 +++++++++
.../AArch64/GlobalISel/knownbits-freeze.mir | 51 +++++++++++++++++++
.../CodeGen/GlobalISel/KnownBitsTest.cpp | 49 ++++++++++++++++++
3 files changed, 125 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 1a3bcd8e579ee4..45efef69719038 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -326,6 +326,16 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
Known = Known.trunc(BitWidth);
break;
}
+ case TargetOpcode::G_FREEZE: {
+ Register Src = MI.getOperand(1).getReg();
+ // freeze of undef/poison is an arbitrary noundef bit pattern, so known
+ // bits of the source are only valid when that source cannot be undef or
+ // poison.
+ if (Src.isVirtual() && MRI.getType(Src).isValid() &&
+ isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
+ computeKnownBitsImpl(Src, Known, DemandedElts, Depth + 1);
+ break;
+ }
case TargetOpcode::COPY:
case TargetOpcode::G_PHI:
case TargetOpcode::PHI: {
@@ -2253,6 +2263,14 @@ void GISelValueTracking::computeKnownFPClass(Register R,
}
break;
}
+ case TargetOpcode::G_FREEZE: {
+ Register Src = MI.getOperand(1).getReg();
+ if (Src.isVirtual() && MRI.getType(Src).isValid() &&
+ isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
+ computeKnownFPClass(Src, DemandedElts, InterestedClasses, Known,
+ Depth + 1);
+ break;
+ }
case TargetOpcode::COPY: {
Register Src = MI.getOperand(1).getReg();
@@ -2472,6 +2490,13 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
return 1;
}
+ case TargetOpcode::G_FREEZE: {
+ Register Src = MI.getOperand(1).getReg();
+ if (Src.isVirtual() && MRI.getType(Src).isValid() &&
+ isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
+ return computeNumSignBits(Src, DemandedElts, Depth + 1);
+ break;
+ }
case TargetOpcode::G_SEXT: {
Register Src = MI.getOperand(1).getReg();
LLT SrcTy = MRI.getType(Src);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir
new file mode 100644
index 00000000000000..4d381bad287920
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir
@@ -0,0 +1,51 @@
+# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=aarch64 -passes="print<gisel-value-tracking>" -filetype=null %s 2>&1 | FileCheck %s
+
+---
+name: FreezeAnd
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @FreezeAnd
+ ; CHECK-NEXT: %0:_ KnownBits:00000000000000001111111111111111 SignBits:16 IsKnownNeverZero:1
+ ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %3:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ %0:_(i32) = G_CONSTANT i32 65535
+ %1:_(i32) = G_CONSTANT i32 4080
+ %2:_(i32) = G_AND %0, %1
+ %3:_(i32) = G_FREEZE %2
+...
+---
+name: FreezeNeg1
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @FreezeNeg1
+ ; CHECK-NEXT: %0:_ KnownBits:11111111 SignBits:8 IsKnownNeverZero:1
+ ; CHECK-NEXT: %1:_ KnownBits:11111111 SignBits:8 IsKnownNeverZero:1
+ %0:_(i8) = G_CONSTANT i8 -1
+ %1:_(i8) = G_FREEZE %0
+...
+---
+name: FreezeUndef
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @FreezeUndef
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %1:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ %0:_(i8) = G_IMPLICIT_DEF
+ %1:_(i8) = G_FREEZE %0
+...
+---
+name: FreezeAndUndef
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @FreezeAndUndef
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000????????0000 SignBits:20 IsKnownNeverZero:0
+ ; CHECK-NEXT: %3:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ %0:_(i32) = G_IMPLICIT_DEF
+ %1:_(i32) = G_CONSTANT i32 4080
+ %2:_(i32) = G_AND %0, %1
+ %3:_(i32) = G_FREEZE %2
+...
diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
index 18aca17fe7e599..69a4d9637fcb80 100644
--- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
@@ -246,6 +246,55 @@ TEST_F(AArch64GISelMITest, TestKnownBitsAND) {
EXPECT_EQ(0xC7u, Res.Zero.getZExtValue());
}
+TEST_F(AArch64GISelMITest, TestKnownBitsFreeze) {
+ StringRef MIRString = R"(
+ %allones:_(s32) = G_CONSTANT i32 65535
+ %mask:_(s32) = G_CONSTANT i32 4080
+ %and:_(s32) = G_AND %allones, %mask
+ %fr_and:_(s32) = G_FREEZE %and
+ %copy_and:_(s32) = COPY %fr_and
+ %undef:_(s32) = G_IMPLICIT_DEF
+ %and_undef:_(s32) = G_AND %undef, %mask
+ %fr_undef:_(s32) = G_FREEZE %and_undef
+ %copy_undef:_(s32) = COPY %fr_undef
+)";
+ setUp(MIRString);
+ if (!TM)
+ GTEST_SKIP();
+
+ Register CopyAnd = Copies[Copies.size() - 2];
+ Register CopyUndef = Copies[Copies.size() - 1];
+ GISelValueTracking Info(*MF);
+
+ MachineInstr *FinalCopyAnd = MRI->getVRegDef(CopyAnd);
+ KnownBits AndBits = Info.getKnownBits(FinalCopyAnd->getOperand(1).getReg());
+ EXPECT_EQ(0xFF0u, AndBits.One.getZExtValue());
+ EXPECT_EQ(0xFFFFF00Fu, AndBits.Zero.getZExtValue());
+
+ MachineInstr *FinalCopyUndef = MRI->getVRegDef(CopyUndef);
+ KnownBits UndefBits =
+ Info.getKnownBits(FinalCopyUndef->getOperand(1).getReg());
+ EXPECT_TRUE(UndefBits.One.isZero());
+ EXPECT_TRUE(UndefBits.Zero.isZero());
+}
+
+TEST_F(AArch64GISelMITest, TestNumSignBitsFreeze) {
+ StringRef MIRString = " %3:_(s8) = G_CONSTANT i8 -1\n"
+ " %4:_(s8) = G_FREEZE %3\n"
+ " %5:_(s8) = COPY %4\n"
+ " %6:_(s8) = G_IMPLICIT_DEF\n"
+ " %7:_(s8) = G_FREEZE %6\n"
+ " %8:_(s8) = COPY %7\n";
+ setUp(MIRString);
+ if (!TM)
+ GTEST_SKIP();
+ Register CopyFr = Copies[Copies.size() - 2];
+ Register CopyUndef = Copies[Copies.size() - 1];
+ GISelValueTracking Info(*MF);
+ EXPECT_EQ(8u, Info.computeNumSignBits(CopyFr));
+ EXPECT_EQ(1u, Info.computeNumSignBits(CopyUndef));
+}
+
TEST_F(AArch64GISelMITest, TestKnownBitsOR) {
StringRef MIRString = R"(
%ptr:_(p0) = G_IMPLICIT_DEF
>From f86281d2572f61303d8994f09769d235a564cada Mon Sep 17 00:00:00 2001
From: vg0204 <Vikash.Gupta at amd.com>
Date: Wed, 16 Sep 2026 11:46:33 +0530
Subject: [PATCH 2/4] Addressed the reviewed comments.
---
.../CodeGen/GlobalISel/GISelValueTracking.cpp | 14 ++----
.../AArch64/GlobalISel/knownbits-freeze.mir | 26 ++++++++++
.../CodeGen/GlobalISel/KnownBitsTest.cpp | 49 -------------------
3 files changed, 31 insertions(+), 58 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 45efef69719038..e3cd6f95d7aafd 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -328,11 +328,9 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
}
case TargetOpcode::G_FREEZE: {
Register Src = MI.getOperand(1).getReg();
- // freeze of undef/poison is an arbitrary noundef bit pattern, so known
- // bits of the source are only valid when that source cannot be undef or
- // poison.
- if (Src.isVirtual() && MRI.getType(Src).isValid() &&
- isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
+ // freeze of undef/poison is an arbitrary noundef bit pattern, so the known
+ // bits of the source only carry over when it cannot be undef or poison.
+ if (isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
computeKnownBitsImpl(Src, Known, DemandedElts, Depth + 1);
break;
}
@@ -2265,8 +2263,7 @@ void GISelValueTracking::computeKnownFPClass(Register R,
}
case TargetOpcode::G_FREEZE: {
Register Src = MI.getOperand(1).getReg();
- if (Src.isVirtual() && MRI.getType(Src).isValid() &&
- isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
+ if (isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
computeKnownFPClass(Src, DemandedElts, InterestedClasses, Known,
Depth + 1);
break;
@@ -2492,8 +2489,7 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
}
case TargetOpcode::G_FREEZE: {
Register Src = MI.getOperand(1).getReg();
- if (Src.isVirtual() && MRI.getType(Src).isValid() &&
- isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
+ if (isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
return computeNumSignBits(Src, DemandedElts, Depth + 1);
break;
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir
index 4d381bad287920..3756c282387eeb 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-freeze.mir
@@ -16,6 +16,32 @@ body: |
%3:_(i32) = G_FREEZE %2
...
---
+name: FreezeCopy
+body: |
+ bb.1:
+ liveins: $w0
+ ; CHECK-LABEL: name: @FreezeCopy
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ %0:_(i32) = COPY $w0
+ %3:_(i32) = G_FREEZE %0
+...
+---
+name: FreezeCopyAnd
+body: |
+ bb.1:
+ liveins: $w0
+ ; CHECK-LABEL: name: @FreezeCopyAnd
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000????????0000 SignBits:20 IsKnownNeverZero:0
+ ; CHECK-NEXT: %3:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ %0:_(i32) = COPY $w0
+ %1:_(i32) = G_CONSTANT i32 4080
+ %2:_(i32) = G_AND %0, %1
+ %3:_(i32) = G_FREEZE %2
+...
+---
name: FreezeNeg1
body: |
bb.1:
diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
index 69a4d9637fcb80..18aca17fe7e599 100644
--- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
@@ -246,55 +246,6 @@ TEST_F(AArch64GISelMITest, TestKnownBitsAND) {
EXPECT_EQ(0xC7u, Res.Zero.getZExtValue());
}
-TEST_F(AArch64GISelMITest, TestKnownBitsFreeze) {
- StringRef MIRString = R"(
- %allones:_(s32) = G_CONSTANT i32 65535
- %mask:_(s32) = G_CONSTANT i32 4080
- %and:_(s32) = G_AND %allones, %mask
- %fr_and:_(s32) = G_FREEZE %and
- %copy_and:_(s32) = COPY %fr_and
- %undef:_(s32) = G_IMPLICIT_DEF
- %and_undef:_(s32) = G_AND %undef, %mask
- %fr_undef:_(s32) = G_FREEZE %and_undef
- %copy_undef:_(s32) = COPY %fr_undef
-)";
- setUp(MIRString);
- if (!TM)
- GTEST_SKIP();
-
- Register CopyAnd = Copies[Copies.size() - 2];
- Register CopyUndef = Copies[Copies.size() - 1];
- GISelValueTracking Info(*MF);
-
- MachineInstr *FinalCopyAnd = MRI->getVRegDef(CopyAnd);
- KnownBits AndBits = Info.getKnownBits(FinalCopyAnd->getOperand(1).getReg());
- EXPECT_EQ(0xFF0u, AndBits.One.getZExtValue());
- EXPECT_EQ(0xFFFFF00Fu, AndBits.Zero.getZExtValue());
-
- MachineInstr *FinalCopyUndef = MRI->getVRegDef(CopyUndef);
- KnownBits UndefBits =
- Info.getKnownBits(FinalCopyUndef->getOperand(1).getReg());
- EXPECT_TRUE(UndefBits.One.isZero());
- EXPECT_TRUE(UndefBits.Zero.isZero());
-}
-
-TEST_F(AArch64GISelMITest, TestNumSignBitsFreeze) {
- StringRef MIRString = " %3:_(s8) = G_CONSTANT i8 -1\n"
- " %4:_(s8) = G_FREEZE %3\n"
- " %5:_(s8) = COPY %4\n"
- " %6:_(s8) = G_IMPLICIT_DEF\n"
- " %7:_(s8) = G_FREEZE %6\n"
- " %8:_(s8) = COPY %7\n";
- setUp(MIRString);
- if (!TM)
- GTEST_SKIP();
- Register CopyFr = Copies[Copies.size() - 2];
- Register CopyUndef = Copies[Copies.size() - 1];
- GISelValueTracking Info(*MF);
- EXPECT_EQ(8u, Info.computeNumSignBits(CopyFr));
- EXPECT_EQ(1u, Info.computeNumSignBits(CopyUndef));
-}
-
TEST_F(AArch64GISelMITest, TestKnownBitsOR) {
StringRef MIRString = R"(
%ptr:_(p0) = G_IMPLICIT_DEF
>From 8b5800924ce8c8d7a0e258b3bee3c67c907cd252 Mon Sep 17 00:00:00 2001
From: vg0204 <Vikash.Gupta at amd.com>
Date: Wed, 23 Sep 2026 13:55:40 +0530
Subject: [PATCH 3/4] Add G_FREEZE ops test in knownfpclass-ops.mir for FP
tests.
---
.../AArch64/GlobalISel/knownfpclass-ops.mir | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownfpclass-ops.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownfpclass-ops.mir
index f0ab44d53a7633..0e301d0a4b9746 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownfpclass-ops.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownfpclass-ops.mir
@@ -12,6 +12,32 @@ body: |
%copy:_(s32) = COPY %def
...
---
+name: FreezeNegZero
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @FreezeNegZero
+ ; CHECK-NEXT: %neg0:_ FPClasses:(nzero) SignBitKnown:1
+ ; CHECK-NEXT: %fr:_ FPClasses:(nzero) SignBitKnown:1
+ ; CHECK-NEXT: %copy:_ FPClasses:(nzero) SignBitKnown:1
+ %neg0:_(s32) = G_FCONSTANT float -0.0
+ %fr:_(s32) = G_FREEZE %neg0
+ %copy:_(s32) = COPY %fr
+...
+---
+name: FreezeFabsUndef
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @FreezeFabsUndef
+ ; CHECK-NEXT: %def:_ FPClasses:(all) SignBitKnown:?
+ ; CHECK-NEXT: %fabs:_ FPClasses:(nan pinf pzero psub pnorm) SignBitKnown:0
+ ; CHECK-NEXT: %fr:_ FPClasses:(all) SignBitKnown:?
+ ; CHECK-NEXT: %copy:_ FPClasses:(all) SignBitKnown:?
+ %def:_(s32) = G_IMPLICIT_DEF
+ %fabs:_(s32) = G_FABS %def
+ %fr:_(s32) = G_FREEZE %fabs
+ %copy:_(s32) = COPY %fr
+...
+---
name: ScalableFAbs
body: |
bb.0:
>From 2419854530c0761fd4f5a7160d95e7544a96593a Mon Sep 17 00:00:00 2001
From: Vikash Gupta <Vikash.Gupta at amd.com>
Date: Thu, 24 Sep 2026 16:07:50 +0530
Subject: [PATCH 4/4] Update llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
Co-authored-by: Matt Arsenault <arsenm2 at gmail.com>
---
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index e3cd6f95d7aafd..71b68e223959e9 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2263,9 +2263,10 @@ void GISelValueTracking::computeKnownFPClass(Register R,
}
case TargetOpcode::G_FREEZE: {
Register Src = MI.getOperand(1).getReg();
- if (isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1))
+ if (isGuaranteedNotToBeUndefOrPoison(Src, MRI, Depth + 1)) {
computeKnownFPClass(Src, DemandedElts, InterestedClasses, Known,
Depth + 1);
+ }
break;
}
case TargetOpcode::COPY: {
More information about the llvm-commits
mailing list