[llvm] [GlobalOpt] Add range metadata to loads from constant global variables (PR #127695)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 20 01:02:44 PDT 2025
================
@@ -0,0 +1,433 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -p globalopt -S %s | FileCheck %s
+
+ at gvar0 = constant { <{ i64, i64, i64, [253 x i64] }> } { <{ i64, i64, i64, [253 x i64] }> <{ i64 -5, i64 1, i64 10, [253 x i64] zeroinitializer }> }, align 8
+ at gvar1 = constant { <{ i64, i64, i64, [253 x i64] }> } { <{ i64, i64, i64, [253 x i64] }> <{ i64 0, i64 1, i64 5, [253 x i64] zeroinitializer }> }, align 8
+ at gvar2 = global [8 x i32] [i32 0, i32 1, i32 2, i32 0, i32 0, i32 100, i32 -6789, i32 1], align 16
+ at gvar3 = constant [8 x i32] [i32 0, i32 1, i32 2, i32 0, i32 0, i32 100, i32 -6789, i32 8388608], align 16
+ at gvar5 = constant [2 x [6 x i8]] [[6 x i8] c"\01a_\02-0", [6 x i8] c" \0E\FF\07\08\09"], align 1
+
+%struct.A = type { i32, i8, ptr, i16, i8 }
+ at gvar6 = constant [2 x [2 x %struct.A]] [[2 x %struct.A] [%struct.A { i32 8, i8 97, ptr null, i16 9, i8 12 }, %struct.A { i32 -1, i8 107, ptr null, i16 7, i8 0 }], [2 x %struct.A] [%struct.A { i32 16, i8 46, ptr null, i16 59, i8 95 }, %struct.A { i32 0, i8 0, ptr null, i16 49, i8 100 }]], align 16
+%struct.B = type <{ i32, i8, ptr, i16, i8 }>
+ at gvar7 = constant [2 x [2 x %struct.B]] [[2 x %struct.B] [%struct.B <{ i32 8, i8 97, ptr null, i16 9, i8 12 }>, %struct.B <{ i32 -1, i8 107, ptr null, i16 7, i8 0 }>], [2 x %struct.B] [%struct.B <{ i32 16, i8 46, ptr null, i16 59, i8 95 }>, %struct.B <{ i32 0, i8 0, ptr null, i16 49, i8 100 }>]], align 32
+%struct.C = type { i32, i32, i32 }
+ at gvar8 = constant [34 x %struct.C] [%struct.C { i32 0, i32 1, i32 2 }, %struct.C { i32 3, i32 4, i32 5 }, %struct.C { i32 6, i32 7, i32 8 }, %struct.C { i32 9, i32 10, i32 11 }, %struct.C { i32 12, i32 13, i32 14 }, %struct.C { i32 15, i32 16, i32 17 }, %struct.C { i32 18, i32 19, i32 20 }, %struct.C { i32 21, i32 22, i32 23 }, %struct.C { i32 24, i32 25, i32 26 }, %struct.C { i32 27, i32 28, i32 29 }, %struct.C { i32 30, i32 31, i32 32 }, %struct.C { i32 33, i32 34, i32 35 }, %struct.C { i32 36, i32 37, i32 38 }, %struct.C { i32 39, i32 40, i32 41 }, %struct.C { i32 42, i32 43, i32 44 }, %struct.C { i32 45, i32 46, i32 47 }, %struct.C { i32 48, i32 49, i32 50 }, %struct.C { i32 51, i32 52, i32 53 }, %struct.C { i32 54, i32 55, i32 56 }, %struct.C { i32 57, i32 58, i32 59 }, %struct.C { i32 60, i32 61, i32 62 }, %struct.C { i32 63, i32 64, i32 65 }, %struct.C { i32 66, i32 67, i32 68 }, %struct.C { i32 69, i32 70, i32 71 }, %struct.C { i32 72, i32 73, i32 74 }, %struct.C { i32 75, i32 76, i32 77 }, %struct.C { i32 78, i32 79, i32 80 }, %struct.C { i32 81, i32 82, i32 83 }, %struct.C { i32 84, i32 85, i32 86 }, %struct.C { i32 87, i32 88, i32 89 }, %struct.C { i32 90, i32 91, i32 92 }, %struct.C { i32 93, i32 94, i32 95 }, %struct.C { i32 96, i32 97, i32 98 }, %struct.C { i32 99, i32 100, i32 101 }], align 16, align 256
+ at gvar9 = constant [6 x [18 x i8]] [[18 x i8] c"\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10\11", [18 x i8] c"\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F !\22#", [18 x i8] c"$%&'()*+,-./012345", [18 x i8] c"6789:;<=>?@ABCDEFG", [18 x i8] c"HIJKLMNOPQRSTUVWXY", [18 x i8] c"Z[\\]^_`abcdefghijk"], align 16
+
+define i64 @test_basic0(i64 %3) {
+; CHECK-LABEL: define i64 @test_basic0(
+; CHECK-SAME: i64 [[TMP0:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [256 x i64], ptr @gvar0, i64 0, i64 [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[PTR]], align 8, !range [[RNG0:![0-9]+]]
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %ptr = getelementptr inbounds [256 x i64], ptr @gvar0, i64 0, i64 %3
+ %5 = load i64, ptr %ptr, align 8
+ ret i64 %5
+}
+
+define i64 @test_basic1(i64 %3) {
+; CHECK-LABEL: define i64 @test_basic1(
+; CHECK-SAME: i64 [[TMP0:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [32 x i64], ptr @gvar0, i64 0, i64 [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[PTR]], align 8, !range [[RNG0]]
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %ptr = getelementptr inbounds [32 x i64], ptr @gvar0, i64 0, i64 %3
+ %5 = load i64, ptr %ptr, align 8
+ ret i64 %5
+}
+
+define i32 @test_different_type(i64 %3) {
+; CHECK-LABEL: define i32 @test_different_type(
+; CHECK-SAME: i64 [[TMP0:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [512 x i32], ptr @gvar1, i64 0, i64 [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[PTR]], align 8, !range [[RNG1:![0-9]+]]
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+ %ptr = getelementptr inbounds [512 x i32], ptr @gvar1, i64 0, i64 %3
+ %5 = load i32, ptr %ptr, align 8
+ ret i32 %5
+}
+
+define i32 @test_non_constant(i64 %3) {
+; CHECK-LABEL: define i32 @test_non_constant(
+; CHECK-SAME: i64 [[TMP0:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [8 x i32], ptr @gvar2, i64 0, i64 [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[PTR]], align 8
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+ %ptr = getelementptr inbounds [8 x i32], ptr @gvar2, i64 0, i64 %3
+ %5 = load i32, ptr %ptr, align 8
+ ret i32 %5
+}
+
+define i64 @test_other(i8 %first_idx) {
+; CHECK-LABEL: define i64 @test_other(
+; CHECK-SAME: i8 [[FIRST_IDX:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[FIRST_IDX]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr @gvar3, i64 [[IDXPROM]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[ARRAYIDX]], align 8, !range [[RNG2:![0-9]+]]
+; CHECK-NEXT: ret i64 [[TMP0]]
+;
+entry:
+ %idxprom = zext i8 %first_idx to i64
+ %arrayidx = getelementptr inbounds i64, ptr @gvar3, i64 %idxprom
+ %0 = load i64, ptr %arrayidx, align 8
+ ret i64 %0
+}
+
+; This could be supported but is rare and more complex for for now we dont process it.
+define i64 @test_multiple_types0(i8 %first_idx) {
+; CHECK-LABEL: define i64 @test_multiple_types0(
+; CHECK-SAME: i8 [[FIRST_IDX:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[FIRST_IDX]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr @gvar3, i64 [[IDXPROM]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[ARRAYIDX]], align 8, !range [[RNG2]]
+; CHECK-NEXT: ret i64 [[TMP0]]
+;
+entry:
+ %idxprom = zext i8 %first_idx to i64
+ %arrayidx = getelementptr inbounds i64, ptr @gvar3, i64 %idxprom
+ %0 = load i64, ptr %arrayidx, align 8
+ ret i64 %0
+}
+
+define i32 @test_multiple_types1(i8 %first_idx) {
+; CHECK-LABEL: define i32 @test_multiple_types1(
+; CHECK-SAME: i8 [[FIRST_IDX:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[FIRST_IDX]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr @gvar3, i64 [[IDXPROM]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 8, !range [[RNG3:![0-9]+]]
+; CHECK-NEXT: ret i32 [[TMP0]]
+;
+entry:
+ %idxprom = zext i8 %first_idx to i64
+ %arrayidx = getelementptr inbounds i32, ptr @gvar3, i64 %idxprom
+ %0 = load i32, ptr %arrayidx, align 8
+ ret i32 %0
+}
+
+define i32 @test_overaligned_load(i8 %first_idx) {
+; CHECK-LABEL: define i32 @test_overaligned_load(
+; CHECK-SAME: i8 [[FIRST_IDX:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[FIRST_IDX]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr @gvar3, i64 [[IDXPROM]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 32
+; CHECK-NEXT: ret i32 [[TMP0]]
+;
+entry:
+ %idxprom = zext i8 %first_idx to i64
+ %arrayidx = getelementptr inbounds i32, ptr @gvar3, i64 %idxprom
+ %0 = load i32, ptr %arrayidx, align 32
+ ret i32 %0
+}
+
+; This could be supported also be supported, but for now it not.
----------------
dtcxzyw wrote:
```suggestion
; This could also be supported, but for now it is not.
```
https://github.com/llvm/llvm-project/pull/127695
More information about the llvm-commits
mailing list