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* noundef [[PTR:%.*]], i32 noundef [[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* noundef [[PTR:%.*]], i32 noundef [[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 noundef [[PTR:%.*]], i32 noundef [[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 noundef zeroext [[PTR:%.*]], i32 noundef [[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* noundef [[PTR:%.*]], i32 noundef [[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: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ] 126 // CHECK-VOID_PTR-NEXT: ret i8* [[ALIGNED_RESULT]] 127 // 128 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_up 129 // CHECK-FLOAT_PTR-SAME: (float* noundef [[PTR:%.*]], i32 noundef [[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* 141 // CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[TMP1]], i64 [[ALIGNMENT]]) ] 142 // CHECK-FLOAT_PTR-NEXT: ret float* [[TMP1]] 143 // 144 // CHECK-LONG-LABEL: define {{[^@]+}}@align_up 145 // CHECK-LONG-SAME: (i64 noundef [[PTR:%.*]], i32 noundef [[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 noundef zeroext [[PTR:%.*]], i32 noundef [[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]] 163 // 164 TYPE align_up(TYPE ptr, unsigned align) { 165 return __builtin_align_up(ptr, align); 166 } 167 168 // NOTYET-POINTER-NEXT: [[ALIGNED_RESULT:%.*]] = call [[$TYPE]] @llvm.ptrmask.p0[[$PTRTYPE]].p0[[$PTRTYPE]].i64([[$TYPE]] [[PTR]], [[ALIGN_TYPE]] [[INVERTED_MASK]]) 169 // CHECK-VOID_PTR-LABEL: define {{[^@]+}}@align_down 170 // CHECK-VOID_PTR-SAME: (i8* noundef [[PTR:%.*]], i32 noundef [[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]] 179 // CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ] 180 // CHECK-VOID_PTR-NEXT: ret i8* [[ALIGNED_RESULT]] 181 // 182 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_down 183 // CHECK-FLOAT_PTR-SAME: (float* noundef [[PTR:%.*]], i32 noundef [[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* 194 // CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[TMP1]], i64 [[ALIGNMENT]]) ] 195 // CHECK-FLOAT_PTR-NEXT: ret float* [[TMP1]] 196 // 197 // CHECK-LONG-LABEL: define {{[^@]+}}@align_down 198 // CHECK-LONG-SAME: (i64 noundef [[PTR:%.*]], i32 noundef [[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 noundef zeroext [[PTR:%.*]], i32 noundef [[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]] 214 // 215 TYPE align_down(TYPE ptr, unsigned align) { 216 return __builtin_align_down(ptr, align); 217 } 218