Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / SROA / invariant-group.ll
blob1be6f6e2fc32bb72c85e3a709d98c5b23e8df186
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes='sroa<preserve-cfg>' -S -o - < %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG
3 ; RUN: opt -passes='sroa<modify-cfg>' -S -o - < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG
5 %t = type { i32, i32 }
7 declare ptr @llvm.launder.invariant.group.p0(ptr %a)
8 declare ptr @llvm.strip.invariant.group.p0(ptr %a)
9 declare void @h(i32 %a)
10 declare i32 @somevalue()
12 define void @f() {
13 ; CHECK-LABEL: @f(
14 ; CHECK-NEXT:    [[SV1:%.*]] = call i32 @somevalue()
15 ; CHECK-NEXT:    [[SV2:%.*]] = call i32 @somevalue()
16 ; CHECK-NEXT:    call void @h(i32 [[SV1]])
17 ; CHECK-NEXT:    call void @h(i32 [[SV2]])
18 ; CHECK-NEXT:    ret void
20   %a = alloca %t
22   %a1_i8_inv = call ptr @llvm.launder.invariant.group.p0(ptr %a)
23   %a2 = getelementptr inbounds %t, ptr %a, i32 0, i32 1
25   %sv1 = call i32 @somevalue()
26   %sv2 = call i32 @somevalue()
28   store i32 %sv1, ptr %a1_i8_inv, !invariant.group !0
29   store i32 %sv2, ptr %a2
31   %v1 = load i32, ptr %a1_i8_inv, !invariant.group !0
32   %v2 = load i32, ptr %a2
34   call void @h(i32 %v1)
35   call void @h(i32 %v2)
37   ret void
40 define void @g() {
41 ; CHECK-LABEL: @g(
42 ; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 8
43 ; CHECK-NEXT:    [[A1_I8_INV:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[A]])
44 ; CHECK-NEXT:    [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1
45 ; CHECK-NEXT:    [[SV1:%.*]] = call i32 @somevalue()
46 ; CHECK-NEXT:    [[SV2:%.*]] = call i32 @somevalue()
47 ; CHECK-NEXT:    store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+]]
48 ; CHECK-NEXT:    store i32 [[SV2]], ptr [[A2]], align 4
49 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
50 ; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[A2]], align 4
51 ; CHECK-NEXT:    call void @h(i32 [[V1]])
52 ; CHECK-NEXT:    call void @h(i32 [[V2]])
53 ; CHECK-NEXT:    [[A1_STRIPPED:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[A]])
54 ; CHECK-NEXT:    [[A1_INT:%.*]] = ptrtoint ptr [[A1_STRIPPED]] to i32
55 ; CHECK-NEXT:    call void @h(i32 [[A1_INT]])
56 ; CHECK-NEXT:    ret void
58   %a = alloca %t
60   %a1_i8_inv = call ptr @llvm.launder.invariant.group.p0(ptr %a)
61   %a2 = getelementptr inbounds %t, ptr %a, i32 0, i32 1
63   %sv1 = call i32 @somevalue()
64   %sv2 = call i32 @somevalue()
66   store i32 %sv1, ptr %a1_i8_inv, !invariant.group !0
67   store i32 %sv2, ptr %a2
69   %v1 = load i32, ptr %a1_i8_inv, !invariant.group !0
70   %v2 = load i32, ptr %a2
72   call void @h(i32 %v1)
73   call void @h(i32 %v2)
75   %a1_stripped = call ptr @llvm.strip.invariant.group.p0(ptr %a)
76   %a1_int = ptrtoint ptr %a1_stripped to i32
77   call void @h(i32 %a1_int)
79   ret void
82 define void @store_and_launder() {
83 ; CHECK-LABEL: @store_and_launder(
84 ; CHECK-NEXT:    ret void
86   %valptr = alloca i32, align 4
87   store i32 0, ptr %valptr, align 4
88   %barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
89   ret void
92 define i32 @launder_and_load() {
93 ; CHECK-LABEL: @launder_and_load(
94 ; CHECK-NEXT:    ret i32 undef
96   %valptr = alloca i32, align 4
97   %barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
98   %v2 = load i32, ptr %valptr
99   ret i32 %v2
102 define void @launder_and_ptr_arith() {
103 ; CHECK-LABEL: @launder_and_ptr_arith(
104 ; CHECK-NEXT:    ret void
106   %valptr = alloca i32, align 4
107   %barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
108   %a2 = getelementptr inbounds i32, ptr %valptr, i32 0
109   ret void
112 define void @partial_use_of_alloca() {
113 ; CHECK-LABEL: @partial_use_of_alloca(
114 ; CHECK-NEXT:    [[VALPTR:%.*]] = alloca i32, align 4
115 ; CHECK-NEXT:    store i32 0, ptr [[VALPTR]], align 4
116 ; CHECK-NEXT:    [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
117 ; CHECK-NEXT:    [[LOAD_VAL:%.*]] = load i32, ptr [[VALPTR]], align 4
118 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[LOAD_VAL]], 0
119 ; CHECK-NEXT:    br i1 [[COND]], label [[USE_ALLOCA:%.*]], label [[END:%.*]]
120 ; CHECK:       use_alloca:
121 ; CHECK-NEXT:    call void @use(ptr nonnull [[VALPTR]])
122 ; CHECK-NEXT:    br label [[END]]
123 ; CHECK:       end:
124 ; CHECK-NEXT:    ret void
126   %valptr = alloca i32, align 4
127   store i32 0, ptr %valptr, align 4
128   %barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
129   %load_val = load i32, ptr %valptr, align 4
130   %cond = icmp eq i32 %load_val, 0
131   br i1 %cond, label %use_alloca, label %end
133 use_alloca:
134   call void @use(ptr nonnull %valptr)
135   br label %end
137 end:
138   ret void
141 define void @partial_promotion_of_alloca() {
142 ; CHECK-LABEL: @partial_promotion_of_alloca(
143 ; CHECK-NEXT:    [[STRUCT_PTR_SROA_2:%.*]] = alloca i32, align 4
144 ; CHECK-NEXT:    store volatile i32 0, ptr [[STRUCT_PTR_SROA_2]], align 4
145 ; CHECK-NEXT:    [[STRUCT_PTR_SROA_2_0_STRUCT_PTR_SROA_2_4_LOAD_VAL:%.*]] = load volatile i32, ptr [[STRUCT_PTR_SROA_2]], align 4
146 ; CHECK-NEXT:    ret void
148   %struct_ptr = alloca %t, align 4
149   %field_ptr = getelementptr inbounds %t, ptr %struct_ptr, i32 0, i32 0
150   store i32 0, ptr %field_ptr, align 4
151   %volatile_field_ptr = getelementptr inbounds %t, ptr %struct_ptr, i32 0, i32 1
152   store volatile i32 0, ptr %volatile_field_ptr, align 4, !invariant.group !0
153   %barr = call ptr @llvm.launder.invariant.group.p0(ptr %struct_ptr)
154   %load_val = load volatile i32, ptr %volatile_field_ptr, align 4, !invariant.group !0
155   ret void
158 declare void @use(ptr)
160 !0 = !{}
161 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
162 ; CHECK-MODIFY-CFG: {{.*}}
163 ; CHECK-PRESERVE-CFG: {{.*}}