1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 /// Check the code generation for the alignment builtins
3 /// To make the test case easier to read, run SROA after generating IR to remove the alloca instructions.
4 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -DTEST_VOID_PTR \
5 // RUN:   -o - -emit-llvm %s -disable-O0-optnone | opt -S -sroa | \
6 // RUN:   FileCheck %s -check-prefixes CHECK,CHECK-VOID_PTR \
7 // RUN:   -enable-var-scope '-D$PTRTYPE=i8'
8 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -DTEST_FLOAT_PTR \
9 // RUN:   -o - -emit-llvm %s -disable-O0-optnone | opt -S -sroa | \
10 // RUN:   FileCheck %s -check-prefixes CHECK,CHECK-FLOAT_PTR \
11 // RUN:   -enable-var-scope '-D$PTRTYPE=f32'
12 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -DTEST_LONG \
13 // RUN:   -o - -emit-llvm %s -disable-O0-optnone | opt -S -sroa | \
14 // RUN:   FileCheck %s -check-prefixes CHECK,CHECK-LONG -enable-var-scope
15 /// Check that we can handle the case where the alignment parameter is wider
16 /// than the source type (generate a trunc on alignment instead of zext)
17 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -DTEST_USHORT \
18 // RUN:   -o - -emit-llvm %s -disable-O0-optnone | opt -S -sroa | \
19 // RUN:   FileCheck %s -check-prefixes CHECK,CHECK-USHORT -enable-var-scope
20 
21 
22 #ifdef TEST_VOID_PTR
23 #define TYPE void *
24 #elif defined(TEST_FLOAT_PTR)
25 #define TYPE float *
26 #elif defined(TEST_LONG)
27 #define TYPE long
28 #elif defined(TEST_USHORT)
29 #define TYPE unsigned short
30 #else
31 #error MISSING TYPE
32 #endif
33 
34 /// Check that constant initializers work and are correct
35 _Bool aligned_true = __builtin_is_aligned(1024, 512);
36 // CHECK: @aligned_true = global i8 1, align 1
37 _Bool aligned_false = __builtin_is_aligned(123, 512);
38 // CHECK: @aligned_false = global i8 0, align 1
39 
40 int down_1 = __builtin_align_down(1023, 32);
41 // CHECK: @down_1 = global i32 992, align 4
42 int down_2 = __builtin_align_down(256, 32);
43 // CHECK: @down_2 = global i32 256, align 4
44 
45 int up_1 = __builtin_align_up(1023, 32);
46 // CHECK: @up_1 = global i32 1024, align 4
47 int up_2 = __builtin_align_up(256, 32);
48 // CHECK: @up_2 = global i32 256, align 4
49 
50 /// Capture the IR type here to use in the remaining FileCheck captures:
51 // CHECK-VOID_PTR-LABEL: define {{[^@]+}}@get_type() #0
52 // CHECK-VOID_PTR-NEXT:  entry:
53 // CHECK-VOID_PTR-NEXT:    ret i8* null
54 //
55 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@get_type() #0
56 // CHECK-FLOAT_PTR-NEXT:  entry:
57 // CHECK-FLOAT_PTR-NEXT:    ret float* null
58 //
59 // CHECK-LONG-LABEL: define {{[^@]+}}@get_type() #0
60 // CHECK-LONG-NEXT:  entry:
61 // CHECK-LONG-NEXT:    ret i64 0
62 //
63 // CHECK-USHORT-LABEL: define {{[^@]+}}@get_type() #0
64 // CHECK-USHORT-NEXT:  entry:
65 // CHECK-USHORT-NEXT:    ret i16 0
66 //
67 TYPE get_type(void) {
68   return (TYPE)0;
69 }
70 
71 // CHECK-VOID_PTR-LABEL: define {{[^@]+}}@is_aligned
72 // CHECK-VOID_PTR-SAME: (i8* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
73 // CHECK-VOID_PTR-NEXT:  entry:
74 // CHECK-VOID_PTR-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
75 // CHECK-VOID_PTR-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
76 // CHECK-VOID_PTR-NEXT:    [[SRC_ADDR:%.*]] = ptrtoint i8* [[PTR]] to i64
77 // CHECK-VOID_PTR-NEXT:    [[SET_BITS:%.*]] = and i64 [[SRC_ADDR]], [[MASK]]
78 // CHECK-VOID_PTR-NEXT:    [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0
79 // CHECK-VOID_PTR-NEXT:    ret i1 [[IS_ALIGNED]]
80 //
81 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@is_aligned
82 // CHECK-FLOAT_PTR-SAME: (float* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
83 // CHECK-FLOAT_PTR-NEXT:  entry:
84 // CHECK-FLOAT_PTR-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
85 // CHECK-FLOAT_PTR-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
86 // CHECK-FLOAT_PTR-NEXT:    [[SRC_ADDR:%.*]] = ptrtoint float* [[PTR]] to i64
87 // CHECK-FLOAT_PTR-NEXT:    [[SET_BITS:%.*]] = and i64 [[SRC_ADDR]], [[MASK]]
88 // CHECK-FLOAT_PTR-NEXT:    [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0
89 // CHECK-FLOAT_PTR-NEXT:    ret i1 [[IS_ALIGNED]]
90 //
91 // CHECK-LONG-LABEL: define {{[^@]+}}@is_aligned
92 // CHECK-LONG-SAME: (i64 [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
93 // CHECK-LONG-NEXT:  entry:
94 // CHECK-LONG-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
95 // CHECK-LONG-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
96 // CHECK-LONG-NEXT:    [[SET_BITS:%.*]] = and i64 [[PTR]], [[MASK]]
97 // CHECK-LONG-NEXT:    [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0
98 // CHECK-LONG-NEXT:    ret i1 [[IS_ALIGNED]]
99 //
100 // CHECK-USHORT-LABEL: define {{[^@]+}}@is_aligned
101 // CHECK-USHORT-SAME: (i16 zeroext [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
102 // CHECK-USHORT-NEXT:  entry:
103 // CHECK-USHORT-NEXT:    [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
104 // CHECK-USHORT-NEXT:    [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
105 // CHECK-USHORT-NEXT:    [[SET_BITS:%.*]] = and i16 [[PTR]], [[MASK]]
106 // CHECK-USHORT-NEXT:    [[IS_ALIGNED:%.*]] = icmp eq i16 [[SET_BITS]], 0
107 // CHECK-USHORT-NEXT:    ret i1 [[IS_ALIGNED]]
108 //
109 _Bool is_aligned(TYPE ptr, unsigned align) {
110   return __builtin_is_aligned(ptr, align);
111 }
112 
113 // NOTYET-POINTER-NEXT:  [[ALIGNED_RESULT:%.*]] = call [[$TYPE]] @llvm.ptrmask.p0[[$PTRTYPE]].p0i8.i64(i8* [[OVER_BOUNDARY]], [[ALIGN_TYPE]] [[INVERTED_MASK]])
114 // CHECK-VOID_PTR-LABEL: define {{[^@]+}}@align_up
115 // CHECK-VOID_PTR-SAME: (i8* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
116 // CHECK-VOID_PTR-NEXT:  entry:
117 // CHECK-VOID_PTR-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
118 // CHECK-VOID_PTR-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
119 // CHECK-VOID_PTR-NEXT:    [[INTPTR:%.*]] = ptrtoint i8* [[PTR]] to i64
120 // CHECK-VOID_PTR-NEXT:    [[OVER_BOUNDARY:%.*]] = add i64 [[INTPTR]], [[MASK]]
121 // CHECK-VOID_PTR-NEXT:    [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
122 // CHECK-VOID_PTR-NEXT:    [[ALIGNED_INTPTR:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
123 // CHECK-VOID_PTR-NEXT:    [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
124 // CHECK-VOID_PTR-NEXT:    [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[DIFF]]
125 // CHECK-VOID_PTR-NEXT:    [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1
126 // CHECK-VOID_PTR-NEXT:    [[PTRINT:%.*]] = ptrtoint i8* [[ALIGNED_RESULT]] to i64
127 // CHECK-VOID_PTR-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]]
128 // CHECK-VOID_PTR-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
129 // CHECK-VOID_PTR-NEXT:    call void @llvm.assume(i1 [[MASKCOND]])
130 // CHECK-VOID_PTR-NEXT:    ret i8* [[ALIGNED_RESULT]]
131 //
132 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_up
133 // CHECK-FLOAT_PTR-SAME: (float* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
134 // CHECK-FLOAT_PTR-NEXT:  entry:
135 // CHECK-FLOAT_PTR-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
136 // CHECK-FLOAT_PTR-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
137 // CHECK-FLOAT_PTR-NEXT:    [[INTPTR:%.*]] = ptrtoint float* [[PTR]] to i64
138 // CHECK-FLOAT_PTR-NEXT:    [[OVER_BOUNDARY:%.*]] = add i64 [[INTPTR]], [[MASK]]
139 // CHECK-FLOAT_PTR-NEXT:    [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
140 // CHECK-FLOAT_PTR-NEXT:    [[ALIGNED_INTPTR:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
141 // CHECK-FLOAT_PTR-NEXT:    [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
142 // CHECK-FLOAT_PTR-NEXT:    [[TMP0:%.*]] = bitcast float* [[PTR]] to i8*
143 // CHECK-FLOAT_PTR-NEXT:    [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 [[DIFF]]
144 // CHECK-FLOAT_PTR-NEXT:    [[TMP1:%.*]] = bitcast i8* [[ALIGNED_RESULT]] to float*
145 // CHECK-FLOAT_PTR-NEXT:    [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1
146 // CHECK-FLOAT_PTR-NEXT:    [[PTRINT:%.*]] = ptrtoint float* [[TMP1]] to i64
147 // CHECK-FLOAT_PTR-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]]
148 // CHECK-FLOAT_PTR-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
149 // CHECK-FLOAT_PTR-NEXT:    call void @llvm.assume(i1 [[MASKCOND]])
150 // CHECK-FLOAT_PTR-NEXT:    ret float* [[TMP1]]
151 //
152 // CHECK-LONG-LABEL: define {{[^@]+}}@align_up
153 // CHECK-LONG-SAME: (i64 [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
154 // CHECK-LONG-NEXT:  entry:
155 // CHECK-LONG-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
156 // CHECK-LONG-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
157 // CHECK-LONG-NEXT:    [[OVER_BOUNDARY:%.*]] = add i64 [[PTR]], [[MASK]]
158 // CHECK-LONG-NEXT:    [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
159 // CHECK-LONG-NEXT:    [[ALIGNED_RESULT:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
160 // CHECK-LONG-NEXT:    ret i64 [[ALIGNED_RESULT]]
161 //
162 // CHECK-USHORT-LABEL: define {{[^@]+}}@align_up
163 // CHECK-USHORT-SAME: (i16 zeroext [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
164 // CHECK-USHORT-NEXT:  entry:
165 // CHECK-USHORT-NEXT:    [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
166 // CHECK-USHORT-NEXT:    [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
167 // CHECK-USHORT-NEXT:    [[OVER_BOUNDARY:%.*]] = add i16 [[PTR]], [[MASK]]
168 // CHECK-USHORT-NEXT:    [[INVERTED_MASK:%.*]] = xor i16 [[MASK]], -1
169 // CHECK-USHORT-NEXT:    [[ALIGNED_RESULT:%.*]] = and i16 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
170 // CHECK-USHORT-NEXT:    ret i16 [[ALIGNED_RESULT]]
171 //
172 TYPE align_up(TYPE ptr, unsigned align) {
173   return __builtin_align_up(ptr, align);
174 }
175 
176 // NOTYET-POINTER-NEXT:  [[ALIGNED_RESULT:%.*]] = call [[$TYPE]] @llvm.ptrmask.p0[[$PTRTYPE]].p0[[$PTRTYPE]].i64([[$TYPE]] [[PTR]], [[ALIGN_TYPE]] [[INVERTED_MASK]])
177 // CHECK-VOID_PTR-LABEL: define {{[^@]+}}@align_down
178 // CHECK-VOID_PTR-SAME: (i8* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
179 // CHECK-VOID_PTR-NEXT:  entry:
180 // CHECK-VOID_PTR-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
181 // CHECK-VOID_PTR-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
182 // CHECK-VOID_PTR-NEXT:    [[INTPTR:%.*]] = ptrtoint i8* [[PTR]] to i64
183 // CHECK-VOID_PTR-NEXT:    [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
184 // CHECK-VOID_PTR-NEXT:    [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], [[INVERTED_MASK]]
185 // CHECK-VOID_PTR-NEXT:    [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
186 // CHECK-VOID_PTR-NEXT:    [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[DIFF]]
187 // CHECK-VOID_PTR-NEXT:    [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1
188 // CHECK-VOID_PTR-NEXT:    [[PTRINT:%.*]] = ptrtoint i8* [[ALIGNED_RESULT]] to i64
189 // CHECK-VOID_PTR-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]]
190 // CHECK-VOID_PTR-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
191 // CHECK-VOID_PTR-NEXT:    call void @llvm.assume(i1 [[MASKCOND]])
192 // CHECK-VOID_PTR-NEXT:    ret i8* [[ALIGNED_RESULT]]
193 //
194 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_down
195 // CHECK-FLOAT_PTR-SAME: (float* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
196 // CHECK-FLOAT_PTR-NEXT:  entry:
197 // CHECK-FLOAT_PTR-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
198 // CHECK-FLOAT_PTR-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
199 // CHECK-FLOAT_PTR-NEXT:    [[INTPTR:%.*]] = ptrtoint float* [[PTR]] to i64
200 // CHECK-FLOAT_PTR-NEXT:    [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
201 // CHECK-FLOAT_PTR-NEXT:    [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], [[INVERTED_MASK]]
202 // CHECK-FLOAT_PTR-NEXT:    [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
203 // CHECK-FLOAT_PTR-NEXT:    [[TMP0:%.*]] = bitcast float* [[PTR]] to i8*
204 // CHECK-FLOAT_PTR-NEXT:    [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 [[DIFF]]
205 // CHECK-FLOAT_PTR-NEXT:    [[TMP1:%.*]] = bitcast i8* [[ALIGNED_RESULT]] to float*
206 // CHECK-FLOAT_PTR-NEXT:    [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1
207 // CHECK-FLOAT_PTR-NEXT:    [[PTRINT:%.*]] = ptrtoint float* [[TMP1]] to i64
208 // CHECK-FLOAT_PTR-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]]
209 // CHECK-FLOAT_PTR-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
210 // CHECK-FLOAT_PTR-NEXT:    call void @llvm.assume(i1 [[MASKCOND]])
211 // CHECK-FLOAT_PTR-NEXT:    ret float* [[TMP1]]
212 //
213 // CHECK-LONG-LABEL: define {{[^@]+}}@align_down
214 // CHECK-LONG-SAME: (i64 [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
215 // CHECK-LONG-NEXT:  entry:
216 // CHECK-LONG-NEXT:    [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
217 // CHECK-LONG-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
218 // CHECK-LONG-NEXT:    [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
219 // CHECK-LONG-NEXT:    [[ALIGNED_RESULT:%.*]] = and i64 [[PTR]], [[INVERTED_MASK]]
220 // CHECK-LONG-NEXT:    ret i64 [[ALIGNED_RESULT]]
221 //
222 // CHECK-USHORT-LABEL: define {{[^@]+}}@align_down
223 // CHECK-USHORT-SAME: (i16 zeroext [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
224 // CHECK-USHORT-NEXT:  entry:
225 // CHECK-USHORT-NEXT:    [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
226 // CHECK-USHORT-NEXT:    [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
227 // CHECK-USHORT-NEXT:    [[INVERTED_MASK:%.*]] = xor i16 [[MASK]], -1
228 // CHECK-USHORT-NEXT:    [[ALIGNED_RESULT:%.*]] = and i16 [[PTR]], [[INVERTED_MASK]]
229 // CHECK-USHORT-NEXT:    ret i16 [[ALIGNED_RESULT]]
230 //
231 TYPE align_down(TYPE ptr, unsigned align) {
232   return __builtin_align_down(ptr, align);
233 }
234