[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / PhaseOrdering / AArch64 / peel-multiple-unreachable-exits-for-vectorization.ll
blobc24affbeaad127d8574ab6286c89a74038a472ea
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -O2 -mtriple=arm64-apple-ios -S %s | FileCheck %s
4 %vec = type { i64*, i64* }
6 ; Test to ensure a loop with multiple loads guarded by runtime-checks (like
7 ; from multiple calls to C++'s std::vector::at) can be vectorized after
8 ; hoisting the runtime checks out of the loop.
10 define i64 @sum_2_at_with_int_conversion(%vec* %A, %vec* %B, i64 %N) {
11 ; CHECK-LABEL: @sum_2_at_with_int_conversion(
12 ; CHECK-NEXT:  entry:
13 ; CHECK-NEXT:    [[GEP_START_I:%.*]] = getelementptr [[VEC:%.*]], %vec* [[A:%.*]], i64 0, i32 0
14 ; CHECK-NEXT:    [[START_I:%.*]] = load i64*, i64** [[GEP_START_I]], align 8
15 ; CHECK-NEXT:    [[GEP_END_I:%.*]] = getelementptr [[VEC]], %vec* [[A]], i64 0, i32 1
16 ; CHECK-NEXT:    [[END_I:%.*]] = load i64*, i64** [[GEP_END_I]], align 8
17 ; CHECK-NEXT:    [[START_INT_I:%.*]] = ptrtoint i64* [[START_I]] to i64
18 ; CHECK-NEXT:    [[END_INT_I:%.*]] = ptrtoint i64* [[END_I]] to i64
19 ; CHECK-NEXT:    [[SUB_I:%.*]] = sub i64 [[END_INT_I]], [[START_INT_I]]
20 ; CHECK-NEXT:    [[GEP_START_I1:%.*]] = getelementptr [[VEC]], %vec* [[B:%.*]], i64 0, i32 0
21 ; CHECK-NEXT:    [[GEP_END_I3:%.*]] = getelementptr [[VEC]], %vec* [[B]], i64 0, i32 1
22 ; CHECK-NEXT:    br label [[LOOP:%.*]]
23 ; CHECK:       loop:
24 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12:%.*]] ]
25 ; CHECK-NEXT:    [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12]] ]
26 ; CHECK-NEXT:    [[INRANGE_I:%.*]] = icmp ult i64 [[SUB_I]], [[IV]]
27 ; CHECK-NEXT:    br i1 [[INRANGE_I]], label [[ERROR_I:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT:%.*]]
28 ; CHECK:       error.i:
29 ; CHECK-NEXT:    tail call void @error()
30 ; CHECK-NEXT:    unreachable
31 ; CHECK:       at_with_int_conversion.exit:
32 ; CHECK-NEXT:    [[START_I2:%.*]] = load i64*, i64** [[GEP_START_I1]], align 8
33 ; CHECK-NEXT:    [[END_I4:%.*]] = load i64*, i64** [[GEP_END_I3]], align 8
34 ; CHECK-NEXT:    [[START_INT_I5:%.*]] = ptrtoint i64* [[START_I2]] to i64
35 ; CHECK-NEXT:    [[END_INT_I6:%.*]] = ptrtoint i64* [[END_I4]] to i64
36 ; CHECK-NEXT:    [[SUB_I7:%.*]] = sub i64 [[END_INT_I6]], [[START_INT_I5]]
37 ; CHECK-NEXT:    [[INRANGE_I8:%.*]] = icmp ult i64 [[SUB_I7]], [[IV]]
38 ; CHECK-NEXT:    br i1 [[INRANGE_I8]], label [[ERROR_I11:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT12]]
39 ; CHECK:       error.i11:
40 ; CHECK-NEXT:    tail call void @error()
41 ; CHECK-NEXT:    unreachable
42 ; CHECK:       at_with_int_conversion.exit12:
43 ; CHECK-NEXT:    [[GEP_IDX_I:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[IV]]
44 ; CHECK-NEXT:    [[LV_I:%.*]] = load i64, i64* [[GEP_IDX_I]], align 4
45 ; CHECK-NEXT:    [[GEP_IDX_I9:%.*]] = getelementptr i64, i64* [[START_I2]], i64 [[IV]]
46 ; CHECK-NEXT:    [[LV_I10:%.*]] = load i64, i64* [[GEP_IDX_I9]], align 4
47 ; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[LV_I]], [[SUM]]
48 ; CHECK-NEXT:    [[SUM_NEXT]] = add i64 [[ADD]], [[LV_I10]]
49 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
50 ; CHECK-NEXT:    [[C:%.*]] = icmp slt i64 [[IV]], [[N:%.*]]
51 ; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]]
52 ; CHECK:       exit:
53 ; CHECK-NEXT:    ret i64 [[SUM_NEXT]]
55 entry:
56   br label %loop
58 loop:
59   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
60   %sum = phi i64 [ 0, %entry ], [ %sum.next, %loop ]
61   %a = call i64 @at_with_int_conversion(%vec* %A, i64 %iv)
62   %b = call i64 @at_with_int_conversion(%vec* %B, i64 %iv)
63   %add = add i64 %a, %b
64   %sum.next = add i64 %sum, %add
65   %iv.next = add nuw nsw i64 %iv, 1
66   %c = icmp slt i64 %iv, %N
67   br i1 %c, label %loop, label %exit
69 exit:
70   ret i64 %sum.next
73 define i64 @sum_3_at_with_int_conversion(%vec* %A, %vec* %B, %vec* %C, i64 %N) {
74 ; CHECK-LABEL: @sum_3_at_with_int_conversion(
75 ; CHECK-NEXT:  entry:
76 ; CHECK-NEXT:    [[GEP_START_I:%.*]] = getelementptr [[VEC:%.*]], %vec* [[A:%.*]], i64 0, i32 0
77 ; CHECK-NEXT:    [[START_I:%.*]] = load i64*, i64** [[GEP_START_I]], align 8
78 ; CHECK-NEXT:    [[GEP_END_I:%.*]] = getelementptr [[VEC]], %vec* [[A]], i64 0, i32 1
79 ; CHECK-NEXT:    [[END_I:%.*]] = load i64*, i64** [[GEP_END_I]], align 8
80 ; CHECK-NEXT:    [[START_INT_I:%.*]] = ptrtoint i64* [[START_I]] to i64
81 ; CHECK-NEXT:    [[END_INT_I:%.*]] = ptrtoint i64* [[END_I]] to i64
82 ; CHECK-NEXT:    [[SUB_I:%.*]] = sub i64 [[END_INT_I]], [[START_INT_I]]
83 ; CHECK-NEXT:    [[GEP_START_I1:%.*]] = getelementptr [[VEC]], %vec* [[B:%.*]], i64 0, i32 0
84 ; CHECK-NEXT:    [[GEP_END_I3:%.*]] = getelementptr [[VEC]], %vec* [[B]], i64 0, i32 1
85 ; CHECK-NEXT:    [[GEP_START_I13:%.*]] = getelementptr [[VEC]], %vec* [[C:%.*]], i64 0, i32 0
86 ; CHECK-NEXT:    [[GEP_END_I15:%.*]] = getelementptr [[VEC]], %vec* [[C]], i64 0, i32 1
87 ; CHECK-NEXT:    br label [[LOOP:%.*]]
88 ; CHECK:       loop:
89 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24:%.*]] ]
90 ; CHECK-NEXT:    [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24]] ]
91 ; CHECK-NEXT:    [[INRANGE_I:%.*]] = icmp ult i64 [[SUB_I]], [[IV]]
92 ; CHECK-NEXT:    br i1 [[INRANGE_I]], label [[ERROR_I:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT:%.*]]
93 ; CHECK:       error.i:
94 ; CHECK-NEXT:    tail call void @error()
95 ; CHECK-NEXT:    unreachable
96 ; CHECK:       at_with_int_conversion.exit:
97 ; CHECK-NEXT:    [[GEP_IDX_I:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[IV]]
98 ; CHECK-NEXT:    [[LV_I:%.*]] = load i64, i64* [[GEP_IDX_I]], align 4
99 ; CHECK-NEXT:    [[START_I2:%.*]] = load i64*, i64** [[GEP_START_I1]], align 8
100 ; CHECK-NEXT:    [[END_I4:%.*]] = load i64*, i64** [[GEP_END_I3]], align 8
101 ; CHECK-NEXT:    [[START_INT_I5:%.*]] = ptrtoint i64* [[START_I2]] to i64
102 ; CHECK-NEXT:    [[END_INT_I6:%.*]] = ptrtoint i64* [[END_I4]] to i64
103 ; CHECK-NEXT:    [[SUB_I7:%.*]] = sub i64 [[END_INT_I6]], [[START_INT_I5]]
104 ; CHECK-NEXT:    [[INRANGE_I8:%.*]] = icmp ult i64 [[SUB_I7]], [[IV]]
105 ; CHECK-NEXT:    br i1 [[INRANGE_I8]], label [[ERROR_I11:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT12:%.*]]
106 ; CHECK:       error.i11:
107 ; CHECK-NEXT:    tail call void @error()
108 ; CHECK-NEXT:    unreachable
109 ; CHECK:       at_with_int_conversion.exit12:
110 ; CHECK-NEXT:    [[START_I14:%.*]] = load i64*, i64** [[GEP_START_I13]], align 8
111 ; CHECK-NEXT:    [[END_I16:%.*]] = load i64*, i64** [[GEP_END_I15]], align 8
112 ; CHECK-NEXT:    [[START_INT_I17:%.*]] = ptrtoint i64* [[START_I14]] to i64
113 ; CHECK-NEXT:    [[END_INT_I18:%.*]] = ptrtoint i64* [[END_I16]] to i64
114 ; CHECK-NEXT:    [[SUB_I19:%.*]] = sub i64 [[END_INT_I18]], [[START_INT_I17]]
115 ; CHECK-NEXT:    [[INRANGE_I20:%.*]] = icmp ult i64 [[SUB_I19]], [[IV]]
116 ; CHECK-NEXT:    br i1 [[INRANGE_I20]], label [[ERROR_I23:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT24]]
117 ; CHECK:       error.i23:
118 ; CHECK-NEXT:    tail call void @error()
119 ; CHECK-NEXT:    unreachable
120 ; CHECK:       at_with_int_conversion.exit24:
121 ; CHECK-NEXT:    [[GEP_IDX_I9:%.*]] = getelementptr i64, i64* [[START_I2]], i64 [[IV]]
122 ; CHECK-NEXT:    [[LV_I10:%.*]] = load i64, i64* [[GEP_IDX_I9]], align 4
123 ; CHECK-NEXT:    [[GEP_IDX_I21:%.*]] = getelementptr i64, i64* [[START_I14]], i64 [[IV]]
124 ; CHECK-NEXT:    [[LV_I22:%.*]] = load i64, i64* [[GEP_IDX_I21]], align 4
125 ; CHECK-NEXT:    [[ADD_1:%.*]] = add i64 [[LV_I]], [[SUM]]
126 ; CHECK-NEXT:    [[ADD_2:%.*]] = add i64 [[ADD_1]], [[LV_I10]]
127 ; CHECK-NEXT:    [[SUM_NEXT]] = add i64 [[ADD_2]], [[LV_I22]]
128 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
129 ; CHECK-NEXT:    [[COND:%.*]] = icmp slt i64 [[IV]], [[N:%.*]]
130 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
131 ; CHECK:       exit:
132 ; CHECK-NEXT:    ret i64 [[SUM_NEXT]]
134 entry:
135   br label %loop
137 loop:
138   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
139   %sum = phi i64 [ 0, %entry ], [ %sum.next, %loop ]
140   %a = call i64 @at_with_int_conversion(%vec* %A, i64 %iv)
141   %b = call i64 @at_with_int_conversion(%vec* %B, i64 %iv)
142   %c = call i64 @at_with_int_conversion(%vec* %C, i64 %iv)
143   %add.1 = add i64 %a, %b
144   %add.2 = add i64 %add.1, %c
145   %sum.next = add i64 %sum, %add.2
146   %iv.next = add nuw nsw i64 %iv, 1
147   %cond = icmp slt i64 %iv, %N
148   br i1 %cond, label %loop, label %exit
150 exit:
151   ret i64 %sum.next
155 define i64 @at_with_int_conversion(%vec* %ptr, i64 %idx) {
156 ; CHECK-LABEL: @at_with_int_conversion(
157 ; CHECK-NEXT:    [[GEP_START:%.*]] = getelementptr [[VEC:%.*]], %vec* [[PTR:%.*]], i64 0, i32 0
158 ; CHECK-NEXT:    [[START:%.*]] = load i64*, i64** [[GEP_START]], align 8
159 ; CHECK-NEXT:    [[GEP_END:%.*]] = getelementptr [[VEC]], %vec* [[PTR]], i64 0, i32 1
160 ; CHECK-NEXT:    [[END:%.*]] = load i64*, i64** [[GEP_END]], align 8
161 ; CHECK-NEXT:    [[START_INT:%.*]] = ptrtoint i64* [[START]] to i64
162 ; CHECK-NEXT:    [[END_INT:%.*]] = ptrtoint i64* [[END]] to i64
163 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[END_INT]], [[START_INT]]
164 ; CHECK-NEXT:    [[INRANGE:%.*]] = icmp ult i64 [[SUB]], [[IDX:%.*]]
165 ; CHECK-NEXT:    br i1 [[INRANGE]], label [[ERROR:%.*]], label [[EXIT:%.*]]
166 ; CHECK:       exit:
167 ; CHECK-NEXT:    [[GEP_IDX:%.*]] = getelementptr i64, i64* [[START]], i64 [[IDX]]
168 ; CHECK-NEXT:    [[LV:%.*]] = load i64, i64* [[GEP_IDX]], align 4
169 ; CHECK-NEXT:    ret i64 [[LV]]
170 ; CHECK:       error:
171 ; CHECK-NEXT:    tail call void @error()
172 ; CHECK-NEXT:    unreachable
174   %gep.start = getelementptr %vec, %vec* %ptr, i64 0, i32 0
175   %start = load i64*, i64** %gep.start
176   %gep.end = getelementptr %vec, %vec* %ptr, i64 0, i32 1
177   %end = load i64*, i64** %gep.end
178   %start.int = ptrtoint i64* %start to i64
179   %end.int = ptrtoint i64* %end to i64
180   %sub = sub i64 %end.int, %start.int
181   %inrange = icmp ugt i64 %idx, %sub
182   br i1 %inrange, label %error, label %exit
184 exit:
185   %gep.idx = getelementptr i64, i64* %start, i64 %idx
186   %lv = load i64, i64* %gep.idx
187   ret i64 %lv
189 error:
190   call void @error()
191   unreachable
194 declare void @error()