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