[llvm] [Verifier] Make verifier fail when global variable size exceeds address space size (PR #179625)

Steffen Larsen via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 8 23:13:13 PST 2026


https://github.com/steffenlarsen updated https://github.com/llvm/llvm-project/pull/179625

>From 36d580c1793422eca621dc6595ec82a84e747ebf Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <HolstLarsen.Steffen at amd.com>
Date: Wed, 4 Feb 2026 01:37:42 -0600
Subject: [PATCH 1/3] [Verifier] Make verifier fail when global variable size
 exceeds address space size

When a global variable has a size that exceeds the size of the address
space it resides in, the verifier should fail as the variable can
neither be materialized nor fully accessed. This patch adds a check to
the verifier to enforce it.

Signed-off-by: Steffen Holst Larsen <HolstLarsen.Steffen at amd.com>
---
 llvm/lib/IR/Verifier.cpp                      | 10 +++++++++
 .../LoongArch/merge-base-offset-tlsle.ll      |  2 +-
 .../CodeGen/LoongArch/merge-base-offset.ll    |  2 +-
 .../GlobalOpt/large-element-size.ll           |  2 +-
 llvm/test/Verifier/global-var-too-big.ll      | 21 +++++++++++++++++++
 5 files changed, 34 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/Verifier/global-var-too-big.ll

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 01d32d4a1825f..8d2d36c813207 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -955,6 +955,16 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
         "Global @" + GV.getName() + " has illegal target extension type",
         GVType);
 
+  // Check that the the address space can hold all bits of the type, recognized
+  // by an access in the address space being able to reach all bytes of the
+  // type.
+  Check(GVType->isScalableTy() || !GVType->isSized() ||
+            GV.getGlobalSize(DL) == 0 ||
+            isUIntN(DL.getAddressSizeInBits(GV.getAddressSpace()),
+                    GV.getGlobalSize(DL) - 1),
+        "Global variable is too large to fit into the address space", &GV,
+        GVType);
+
   if (!GV.hasInitializer()) {
     visitGlobalValue(GV);
     return;
diff --git a/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll b/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll
index 97d33379913e5..6605d5961aa6a 100644
--- a/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll
+++ b/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll
@@ -661,7 +661,7 @@ if.end:
   ret void
 }
 
- at g_a64 = dso_local thread_local(localexec) global [614750729487779976 x i64] zeroinitializer, align 8
+ at g_a64 = dso_local thread_local(localexec) global [536870912 x i64] zeroinitializer, align 8
 
 define dso_local ptr @tlsle_load_addr_offset_1() nounwind {
 ; LA32-LABEL: tlsle_load_addr_offset_1:
diff --git a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
index ea0fe3d0b0178..4cda6a708a80c 100644
--- a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
+++ b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
@@ -959,7 +959,7 @@ label:
   ret ptr %0
 }
 
- at g_a64 = dso_local global [614750729487779976 x i64] zeroinitializer, align 8
+ at g_a64 = dso_local global [536870912 x i64] zeroinitializer, align 8
 
 define dso_local ptr @load_addr_offset_1() nounwind {
 ; LA32-LABEL: load_addr_offset_1:
diff --git a/llvm/test/Transforms/GlobalOpt/large-element-size.ll b/llvm/test/Transforms/GlobalOpt/large-element-size.ll
index 914112af313a5..14a3cd035d26f 100644
--- a/llvm/test/Transforms/GlobalOpt/large-element-size.ll
+++ b/llvm/test/Transforms/GlobalOpt/large-element-size.ll
@@ -6,7 +6,7 @@ target datalayout = "p:32:32"
 %struct.t.1 = type { %struct.u.0, %struct.u.0, %struct.u.0, %struct.u.0, i32, i32, i32, i32 }
 %struct.u.0 = type { i32, i32, i32, i8 }
 
- at s = external global [700 x [24000 x %struct.s.2]], align 1
+ at s = external global [700 x [2400 x %struct.s.2]], align 1
 @p = global ptr getelementptr (i8, ptr @s, i64 2247483647), align 1
 
 ; CHECK: @p = local_unnamed_addr global ptr getelementptr (i8, ptr @s, i32 -2047483649), align 1
diff --git a/llvm/test/Verifier/global-var-too-big.ll b/llvm/test/Verifier/global-var-too-big.ll
new file mode 100644
index 0000000000000..478b093eb0bae
--- /dev/null
+++ b/llvm/test/Verifier/global-var-too-big.ll
@@ -0,0 +1,21 @@
+; RUN: not opt -S -passes=verify < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-p1:16:16-p2:32:32-p3:64:64-i8:8-i32:32-i64:64"
+
+; Too large for 16-bit address space.
+ at G1 = internal addrspace(1) global [65537 x i8] zeroinitializer, align 4
+
+; Too large for 32-bit address space.
+ at G2 = internal addrspace(2) global [2147483649 x i16] zeroinitializer, align 4
+
+; Fit within the address spaces
+ at G3 = internal addrspace(1) global [65536 x i8] zeroinitializer, align 4
+ at G4 = internal addrspace(2) global [2147483648 x i16] zeroinitializer, align 4
+
+; CHECK: Global variable is too large to fit into the address space
+; CHECK-NEXT: ptr addrspace(1) @G1
+; CHECK-NEXT: [65537 x i8]
+; CHECK: Global variable is too large to fit into the address space
+; CHECK-NEXT: ptr addrspace(2) @G2
+; CHECK-NEXT: [2147483649 x i16]
+; CHECK-NOT: Global variable is too large to fit into the address space

>From e5a604a5a9010b22b98fc1559b3993533ff9c4b8 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <HolstLarsen.Steffen at amd.com>
Date: Wed, 4 Feb 2026 05:55:34 -0600
Subject: [PATCH 2/3] Remove scalable check and -1

Signed-off-by: Steffen Holst Larsen <HolstLarsen.Steffen at amd.com>
---
 llvm/lib/IR/Verifier.cpp                 |  5 ++---
 llvm/test/Verifier/global-var-too-big.ll | 12 ++++++------
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 8d2d36c813207..79b531d42964a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -958,10 +958,9 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
   // Check that the the address space can hold all bits of the type, recognized
   // by an access in the address space being able to reach all bytes of the
   // type.
-  Check(GVType->isScalableTy() || !GVType->isSized() ||
-            GV.getGlobalSize(DL) == 0 ||
+  Check(!GVType->isSized() ||
             isUIntN(DL.getAddressSizeInBits(GV.getAddressSpace()),
-                    GV.getGlobalSize(DL) - 1),
+                    GV.getGlobalSize(DL)),
         "Global variable is too large to fit into the address space", &GV,
         GVType);
 
diff --git a/llvm/test/Verifier/global-var-too-big.ll b/llvm/test/Verifier/global-var-too-big.ll
index 478b093eb0bae..fecb021145ae1 100644
--- a/llvm/test/Verifier/global-var-too-big.ll
+++ b/llvm/test/Verifier/global-var-too-big.ll
@@ -3,19 +3,19 @@
 target datalayout = "e-m:e-p1:16:16-p2:32:32-p3:64:64-i8:8-i32:32-i64:64"
 
 ; Too large for 16-bit address space.
- at G1 = internal addrspace(1) global [65537 x i8] zeroinitializer, align 4
+ at G1 = internal addrspace(1) global [65536 x i8] zeroinitializer, align 4
 
 ; Too large for 32-bit address space.
- at G2 = internal addrspace(2) global [2147483649 x i16] zeroinitializer, align 4
+ at G2 = internal addrspace(2) global [2147483648 x i16] zeroinitializer, align 4
 
 ; Fit within the address spaces
- at G3 = internal addrspace(1) global [65536 x i8] zeroinitializer, align 4
- at G4 = internal addrspace(2) global [2147483648 x i16] zeroinitializer, align 4
+ at G3 = internal addrspace(1) global [65535 x i8] zeroinitializer, align 4
+ at G4 = internal addrspace(2) global [2147483647 x i16] zeroinitializer, align 4
 
 ; CHECK: Global variable is too large to fit into the address space
 ; CHECK-NEXT: ptr addrspace(1) @G1
-; CHECK-NEXT: [65537 x i8]
+; CHECK-NEXT: [65536 x i8]
 ; CHECK: Global variable is too large to fit into the address space
 ; CHECK-NEXT: ptr addrspace(2) @G2
-; CHECK-NEXT: [2147483649 x i16]
+; CHECK-NEXT: [2147483648 x i16]
 ; CHECK-NOT: Global variable is too large to fit into the address space

>From ae0335b075979450c7b77a0666def4baaf320a94 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <HolstLarsen.Steffen at amd.com>
Date: Wed, 4 Feb 2026 06:10:19 -0600
Subject: [PATCH 3/3] Fix merge-base-offset tests

Signed-off-by: Steffen Holst Larsen <HolstLarsen.Steffen at amd.com>
---
 llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll | 2 +-
 llvm/test/CodeGen/LoongArch/merge-base-offset.ll       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll b/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll
index 6605d5961aa6a..fd1468308ec62 100644
--- a/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll
+++ b/llvm/test/CodeGen/LoongArch/merge-base-offset-tlsle.ll
@@ -661,7 +661,7 @@ if.end:
   ret void
 }
 
- at g_a64 = dso_local thread_local(localexec) global [536870912 x i64] zeroinitializer, align 8
+ at g_a64 = dso_local thread_local(localexec) global [536870911 x i64] zeroinitializer, align 8
 
 define dso_local ptr @tlsle_load_addr_offset_1() nounwind {
 ; LA32-LABEL: tlsle_load_addr_offset_1:
diff --git a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
index 4cda6a708a80c..31916a4d36864 100644
--- a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
+++ b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
@@ -959,7 +959,7 @@ label:
   ret ptr %0
 }
 
- at g_a64 = dso_local global [536870912 x i64] zeroinitializer, align 8
+ at g_a64 = dso_local global [536870911 x i64] zeroinitializer, align 8
 
 define dso_local ptr @load_addr_offset_1() nounwind {
 ; LA32-LABEL: load_addr_offset_1:



More information about the llvm-commits mailing list