xref: /llvm-project/llvm/test/Transforms/GlobalOpt/global-demotion.ll (revision d3ac92f1e12c0420a2fe73f554851f9f866ebf88)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=globalopt -S < %s | FileCheck %s
3
4@G1 = internal global i32 5
5@G2 = internal global i32 5
6@G3 = internal global i32 5
7@G4 = internal global i32 5
8@G5 = internal global i32 5
9
10define i32 @test1() norecurse {
11; CHECK-LABEL: @test1(
12; CHECK-NEXT:    [[G1:%.*]] = alloca i32, align 4
13; CHECK-NEXT:    store i32 5, ptr [[G1]], align 4
14; CHECK-NEXT:    store i32 4, ptr [[G1]], align 4
15; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[G1]], align 4
16; CHECK-NEXT:    ret i32 [[A]]
17;
18  store i32 4, ptr @G1
19  %a = load i32, ptr @G1
20  ret i32 %a
21}
22
23; The load comes before the store which makes @G2 live before the call.
24define i32 @test2() norecurse {
25; CHECK-LABEL: @test2(
26; CHECK-NEXT:    [[A_B:%.*]] = load i1, ptr @G2, align 1
27; CHECK-NEXT:    [[A:%.*]] = select i1 [[A_B]], i32 4, i32 5
28; CHECK-NEXT:    store i1 true, ptr @G2, align 1
29; CHECK-NEXT:    ret i32 [[A]]
30;
31  %a = load i32, ptr @G2
32  store i32 4, ptr @G2
33  ret i32 %a
34}
35
36; This global is indexed by a GEP - this makes it partial alias and we bail out.
37; FIXME: We don't actually have to bail out in this case.
38define i32 @test3() norecurse {
39; CHECK-LABEL: @test3(
40; CHECK-NEXT:    [[A_B:%.*]] = load i1, ptr @G3, align 1
41; CHECK-NEXT:    [[A:%.*]] = select i1 [[A_B]], i32 4, i32 5
42; CHECK-NEXT:    store i1 true, ptr @G3, align 1
43; CHECK-NEXT:    ret i32 [[A]]
44;
45  %a = load i32, ptr @G3
46  store i32 4, ptr @G3
47  ret i32 %a
48}
49
50; The global is casted away to a larger type then loaded. The store only partially
51; covers the load, so we must not demote.
52define i32 @test4() norecurse {
53; CHECK-LABEL: @test4(
54; CHECK-NEXT:    store i32 4, ptr @G4, align 4
55; CHECK-NEXT:    [[A:%.*]] = load i64, ptr @G4, align 4
56; CHECK-NEXT:    [[B:%.*]] = trunc i64 [[A]] to i32
57; CHECK-NEXT:    ret i32 [[B]]
58;
59  store i32 4, ptr @G4
60  %a = load i64, ptr @G4
61  %b = trunc i64 %a to i32
62  ret i32 %b
63}
64
65; The global is casted away to a smaller type then loaded. This one is fine.
66define i32 @test5() norecurse {
67; CHECK-LABEL: @test5(
68; CHECK-NEXT:    [[G5:%.*]] = alloca i32, align 4
69; CHECK-NEXT:    store i32 5, ptr [[G5]], align 4
70; CHECK-NEXT:    store i32 4, ptr [[G5]], align 4
71; CHECK-NEXT:    [[A:%.*]] = load i16, ptr [[G5]], align 2
72; CHECK-NEXT:    [[B:%.*]] = zext i16 [[A]] to i32
73; CHECK-NEXT:    ret i32 [[B]]
74;
75  store i32 4, ptr @G5
76  %a = load i16, ptr @G5
77  %b = zext i16 %a to i32
78  ret i32 %b
79}
80