blob: 60f7fc99c1d4dbca17de833fd453cc3736ec72c9 [file] [log] [blame]
Tyker8938a6c2020-06-19 15:45:27 +02001// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
Alex Richardson8c387cb2020-01-09 20:48:06 +00002/// 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 | \
Tyker8938a6c2020-06-19 15:45:27 +02006// RUN: FileCheck %s -check-prefixes CHECK,CHECK-VOID_PTR \
Alex Richardson8c387cb2020-01-09 20:48:06 +00007// 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 | \
Tyker8938a6c2020-06-19 15:45:27 +020010// RUN: FileCheck %s -check-prefixes CHECK,CHECK-FLOAT_PTR \
Alex Richardson8c387cb2020-01-09 20:48:06 +000011// 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 | \
Tyker8938a6c2020-06-19 15:45:27 +020014// RUN: FileCheck %s -check-prefixes CHECK,CHECK-LONG -enable-var-scope
Alex Richardson8c387cb2020-01-09 20:48:06 +000015/// 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 | \
Tyker8938a6c2020-06-19 15:45:27 +020019// RUN: FileCheck %s -check-prefixes CHECK,CHECK-USHORT -enable-var-scope
Alex Richardson8c387cb2020-01-09 20:48:06 +000020
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
Alex Richardson8c387cb2020-01-09 20:48:06 +000028#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);
Fangrui Songdbc96b52020-02-03 10:09:39 -080036// CHECK: @aligned_true = global i8 1, align 1
Alex Richardson8c387cb2020-01-09 20:48:06 +000037_Bool aligned_false = __builtin_is_aligned(123, 512);
Fangrui Songdbc96b52020-02-03 10:09:39 -080038// CHECK: @aligned_false = global i8 0, align 1
Alex Richardson8c387cb2020-01-09 20:48:06 +000039
40int down_1 = __builtin_align_down(1023, 32);
Fangrui Songdbc96b52020-02-03 10:09:39 -080041// CHECK: @down_1 = global i32 992, align 4
Alex Richardson8c387cb2020-01-09 20:48:06 +000042int down_2 = __builtin_align_down(256, 32);
Fangrui Songdbc96b52020-02-03 10:09:39 -080043// CHECK: @down_2 = global i32 256, align 4
Alex Richardson8c387cb2020-01-09 20:48:06 +000044
45int up_1 = __builtin_align_up(1023, 32);
Fangrui Songdbc96b52020-02-03 10:09:39 -080046// CHECK: @up_1 = global i32 1024, align 4
Alex Richardson8c387cb2020-01-09 20:48:06 +000047int up_2 = __builtin_align_up(256, 32);
Fangrui Songdbc96b52020-02-03 10:09:39 -080048// CHECK: @up_2 = global i32 256, align 4
Alex Richardson8c387cb2020-01-09 20:48:06 +000049
50/// Capture the IR type here to use in the remaining FileCheck captures:
Tyker8938a6c2020-06-19 15:45:27 +020051// 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
Alex Richardson8c387cb2020-01-09 20:48:06 +000066//
67TYPE get_type(void) {
68 return (TYPE)0;
69}
70
Tyker8938a6c2020-06-19 15:45:27 +020071// 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]]
Alex Richardson8c387cb2020-01-09 20:48:06 +0000108//
109_Bool is_aligned(TYPE ptr, unsigned align) {
110 return __builtin_is_aligned(ptr, align);
111}
112
Alex Richardson8c387cb2020-01-09 20:48:06 +0000113// NOTYET-POINTER-NEXT: [[ALIGNED_RESULT:%.*]] = call [[$TYPE]] @llvm.ptrmask.p0[[$PTRTYPE]].p0i8.i64(i8* [[OVER_BOUNDARY]], [[ALIGN_TYPE]] [[INVERTED_MASK]])
Tyker8938a6c2020-06-19 15:45:27 +0200114// 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]]
Tyker78de7292020-09-12 13:36:45 +0200125// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
Tyker8938a6c2020-06-19 15:45:27 +0200126// CHECK-VOID_PTR-NEXT: ret i8* [[ALIGNED_RESULT]]
127//
128// CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_up
129// CHECK-FLOAT_PTR-SAME: (float* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
130// CHECK-FLOAT_PTR-NEXT: entry:
131// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
132// CHECK-FLOAT_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
133// CHECK-FLOAT_PTR-NEXT: [[INTPTR:%.*]] = ptrtoint float* [[PTR]] to i64
134// CHECK-FLOAT_PTR-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[INTPTR]], [[MASK]]
135// CHECK-FLOAT_PTR-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
136// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
137// CHECK-FLOAT_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
138// CHECK-FLOAT_PTR-NEXT: [[TMP0:%.*]] = bitcast float* [[PTR]] to i8*
139// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 [[DIFF]]
140// CHECK-FLOAT_PTR-NEXT: [[TMP1:%.*]] = bitcast i8* [[ALIGNED_RESULT]] to float*
Tyker78de7292020-09-12 13:36:45 +0200141// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[TMP1]], i64 [[ALIGNMENT]]) ]
Tyker8938a6c2020-06-19 15:45:27 +0200142// CHECK-FLOAT_PTR-NEXT: ret float* [[TMP1]]
143//
144// CHECK-LONG-LABEL: define {{[^@]+}}@align_up
145// CHECK-LONG-SAME: (i64 [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
146// CHECK-LONG-NEXT: entry:
147// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
148// CHECK-LONG-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
149// CHECK-LONG-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[PTR]], [[MASK]]
150// CHECK-LONG-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
151// CHECK-LONG-NEXT: [[ALIGNED_RESULT:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
152// CHECK-LONG-NEXT: ret i64 [[ALIGNED_RESULT]]
153//
154// CHECK-USHORT-LABEL: define {{[^@]+}}@align_up
155// CHECK-USHORT-SAME: (i16 zeroext [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
156// CHECK-USHORT-NEXT: entry:
157// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
158// CHECK-USHORT-NEXT: [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
159// CHECK-USHORT-NEXT: [[OVER_BOUNDARY:%.*]] = add i16 [[PTR]], [[MASK]]
160// CHECK-USHORT-NEXT: [[INVERTED_MASK:%.*]] = xor i16 [[MASK]], -1
161// CHECK-USHORT-NEXT: [[ALIGNED_RESULT:%.*]] = and i16 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
162// CHECK-USHORT-NEXT: ret i16 [[ALIGNED_RESULT]]
Alex Richardson8c387cb2020-01-09 20:48:06 +0000163//
164TYPE align_up(TYPE ptr, unsigned align) {
165 return __builtin_align_up(ptr, align);
166}
167
Alex Richardson8c387cb2020-01-09 20:48:06 +0000168// NOTYET-POINTER-NEXT: [[ALIGNED_RESULT:%.*]] = call [[$TYPE]] @llvm.ptrmask.p0[[$PTRTYPE]].p0[[$PTRTYPE]].i64([[$TYPE]] [[PTR]], [[ALIGN_TYPE]] [[INVERTED_MASK]])
Tyker8938a6c2020-06-19 15:45:27 +0200169// CHECK-VOID_PTR-LABEL: define {{[^@]+}}@align_down
170// CHECK-VOID_PTR-SAME: (i8* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
171// CHECK-VOID_PTR-NEXT: entry:
172// CHECK-VOID_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
173// CHECK-VOID_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
174// CHECK-VOID_PTR-NEXT: [[INTPTR:%.*]] = ptrtoint i8* [[PTR]] to i64
175// CHECK-VOID_PTR-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
176// CHECK-VOID_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], [[INVERTED_MASK]]
177// CHECK-VOID_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
178// CHECK-VOID_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[DIFF]]
Tyker78de7292020-09-12 13:36:45 +0200179// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
Tyker8938a6c2020-06-19 15:45:27 +0200180// CHECK-VOID_PTR-NEXT: ret i8* [[ALIGNED_RESULT]]
181//
182// CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_down
183// CHECK-FLOAT_PTR-SAME: (float* [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
184// CHECK-FLOAT_PTR-NEXT: entry:
185// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
186// CHECK-FLOAT_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
187// CHECK-FLOAT_PTR-NEXT: [[INTPTR:%.*]] = ptrtoint float* [[PTR]] to i64
188// CHECK-FLOAT_PTR-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
189// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], [[INVERTED_MASK]]
190// CHECK-FLOAT_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
191// CHECK-FLOAT_PTR-NEXT: [[TMP0:%.*]] = bitcast float* [[PTR]] to i8*
192// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 [[DIFF]]
193// CHECK-FLOAT_PTR-NEXT: [[TMP1:%.*]] = bitcast i8* [[ALIGNED_RESULT]] to float*
Tyker78de7292020-09-12 13:36:45 +0200194// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[TMP1]], i64 [[ALIGNMENT]]) ]
Tyker8938a6c2020-06-19 15:45:27 +0200195// CHECK-FLOAT_PTR-NEXT: ret float* [[TMP1]]
196//
197// CHECK-LONG-LABEL: define {{[^@]+}}@align_down
198// CHECK-LONG-SAME: (i64 [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
199// CHECK-LONG-NEXT: entry:
200// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
201// CHECK-LONG-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
202// CHECK-LONG-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
203// CHECK-LONG-NEXT: [[ALIGNED_RESULT:%.*]] = and i64 [[PTR]], [[INVERTED_MASK]]
204// CHECK-LONG-NEXT: ret i64 [[ALIGNED_RESULT]]
205//
206// CHECK-USHORT-LABEL: define {{[^@]+}}@align_down
207// CHECK-USHORT-SAME: (i16 zeroext [[PTR:%.*]], i32 [[ALIGN:%.*]]) #0
208// CHECK-USHORT-NEXT: entry:
209// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
210// CHECK-USHORT-NEXT: [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
211// CHECK-USHORT-NEXT: [[INVERTED_MASK:%.*]] = xor i16 [[MASK]], -1
212// CHECK-USHORT-NEXT: [[ALIGNED_RESULT:%.*]] = and i16 [[PTR]], [[INVERTED_MASK]]
213// CHECK-USHORT-NEXT: ret i16 [[ALIGNED_RESULT]]
Alex Richardson8c387cb2020-01-09 20:48:06 +0000214//
215TYPE align_down(TYPE ptr, unsigned align) {
216 return __builtin_align_down(ptr, align);
217}