1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 2 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s | \ 3 // RUN: FileCheck %s --check-prefix=CHECK-X86 4 // RUN: %clang_cc1 -triple ppc64le-linux-gnu -emit-llvm -o - %s | FileCheck %s \ 5 // RUN: --check-prefix=CHECK-PPC 6 // RUN: %clang_cc1 -triple riscv32-linux-gnu -emit-llvm -o - %s | FileCheck %s \ 7 // RUN: --check-prefix=CHECK-RV32 8 // RUN: %clang_cc1 -triple riscv64-linux-gnu -emit-llvm -o - %s | FileCheck %s \ 9 // RUN: --check-prefix=CHECK-RV64 10 #ifdef __x86_64__ 11 12 // Test that we have the structure definition, the gep offsets, the name of the 13 // global, the bit grab, and the icmp correct. 14 extern void a(const char *); 15 16 17 // CHECK-X86-LABEL: define dso_local i32 @main( 18 // CHECK-X86-SAME: ) #[[ATTR0:[0-9]+]] { 19 // CHECK-X86-NEXT: entry: 20 // CHECK-X86-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 21 // CHECK-X86-NEXT: store i32 0, ptr [[RETVAL]], align 4 22 // CHECK-X86-NEXT: call void @__cpu_indicator_init() 23 // CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 4 24 // CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 256 25 // CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 256 26 // CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] 27 // CHECK-X86-NEXT: br i1 [[TMP3]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 28 // CHECK-X86: if.then: 29 // CHECK-X86-NEXT: call void @a(ptr noundef @.str) 30 // CHECK-X86-NEXT: br label [[IF_END]] 31 // CHECK-X86: if.end: 32 // CHECK-X86-NEXT: [[TMP4:%.*]] = load i32, ptr @__cpu_features2, align 4 33 // CHECK-X86-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 1 34 // CHECK-X86-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 1 35 // CHECK-X86-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] 36 // CHECK-X86-NEXT: br i1 [[TMP7]], label [[IF_THEN1:%.*]], label [[IF_END2:%.*]] 37 // CHECK-X86: if.then1: 38 // CHECK-X86-NEXT: call void @a(ptr noundef @.str.1) 39 // CHECK-X86-NEXT: br label [[IF_END2]] 40 // CHECK-X86: if.end2: 41 // CHECK-X86-NEXT: ret i32 0 42 // 43 int main(void) { 44 __builtin_cpu_init(); 45 46 // CHECK: call void @__cpu_indicator_init 47 48 if (__builtin_cpu_supports("sse4.2")) 49 a("sse4.2"); 50 51 52 if (__builtin_cpu_supports("gfni")) 53 a("gfni"); 54 55 56 return 0; 57 } 58 59 60 // CHECK-X86-LABEL: define dso_local i32 @baseline( 61 // CHECK-X86-SAME: ) #[[ATTR0]] { 62 // CHECK-X86-NEXT: entry: 63 // CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 1), align 4 64 // CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], -2147483648 65 // CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], -2147483648 66 // CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] 67 // CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 68 // CHECK-X86-NEXT: ret i32 [[CONV]] 69 // 70 int baseline() { return __builtin_cpu_supports("x86-64"); } 71 72 // CHECK-X86-LABEL: define dso_local i32 @v2( 73 // CHECK-X86-SAME: ) #[[ATTR0]] { 74 // CHECK-X86-NEXT: entry: 75 // CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2), align 4 76 // CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 77 // CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 78 // CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] 79 // CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 80 // CHECK-X86-NEXT: ret i32 [[CONV]] 81 // 82 int v2() { return __builtin_cpu_supports("x86-64-v2"); } 83 84 // CHECK-X86-LABEL: define dso_local i32 @v3( 85 // CHECK-X86-SAME: ) #[[ATTR0]] { 86 // CHECK-X86-NEXT: entry: 87 // CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2), align 4 88 // CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 2 89 // CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 2 90 // CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] 91 // CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 92 // CHECK-X86-NEXT: ret i32 [[CONV]] 93 // 94 int v3() { return __builtin_cpu_supports("x86-64-v3"); } 95 96 // CHECK-X86-LABEL: define dso_local i32 @v4( 97 // CHECK-X86-SAME: ) #[[ATTR0]] { 98 // CHECK-X86-NEXT: entry: 99 // CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2), align 4 100 // CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 4 101 // CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 4 102 // CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] 103 // CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 104 // CHECK-X86-NEXT: ret i32 [[CONV]] 105 // 106 int v4() { return __builtin_cpu_supports("x86-64-v4"); } 107 #endif 108 109 #ifdef __PPC__ 110 // CHECK-PPC-LABEL: define dso_local signext i32 @test_ppc( 111 // CHECK-PPC-SAME: i32 noundef signext [[A:%.*]]) #[[ATTR0:[0-9]+]] { 112 // CHECK-PPC-NEXT: entry: 113 // CHECK-PPC-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 114 // CHECK-PPC-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 115 // CHECK-PPC-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 116 // CHECK-PPC-NEXT: [[CPU_SUPPORTS:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 2) 117 // CHECK-PPC-NEXT: [[TMP0:%.*]] = and i32 [[CPU_SUPPORTS]], 8388608 118 // CHECK-PPC-NEXT: [[TMP1:%.*]] = icmp ne i32 [[TMP0]], 0 119 // CHECK-PPC-NEXT: br i1 [[TMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 120 // CHECK-PPC: if.then: 121 // CHECK-PPC-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR]], align 4 122 // CHECK-PPC-NEXT: store i32 [[TMP2]], ptr [[RETVAL]], align 4 123 // CHECK-PPC-NEXT: br label [[RETURN:%.*]] 124 // CHECK-PPC: if.else: 125 // CHECK-PPC-NEXT: [[CPU_SUPPORTS1:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 1) 126 // CHECK-PPC-NEXT: [[TMP3:%.*]] = and i32 [[CPU_SUPPORTS1]], 67108864 127 // CHECK-PPC-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0 128 // CHECK-PPC-NEXT: br i1 [[TMP4]], label [[IF_THEN2:%.*]], label [[IF_ELSE3:%.*]] 129 // CHECK-PPC: if.then2: 130 // CHECK-PPC-NEXT: [[TMP5:%.*]] = load i32, ptr [[A_ADDR]], align 4 131 // CHECK-PPC-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP5]], 5 132 // CHECK-PPC-NEXT: store i32 [[SUB]], ptr [[RETVAL]], align 4 133 // CHECK-PPC-NEXT: br label [[RETURN]] 134 // CHECK-PPC: if.else3: 135 // CHECK-PPC-NEXT: [[CPU_IS:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) 136 // CHECK-PPC-NEXT: [[TMP6:%.*]] = icmp eq i32 [[CPU_IS]], 39 137 // CHECK-PPC-NEXT: br i1 [[TMP6]], label [[IF_THEN4:%.*]], label [[IF_ELSE5:%.*]] 138 // CHECK-PPC: if.then4: 139 // CHECK-PPC-NEXT: [[TMP7:%.*]] = load i32, ptr [[A_ADDR]], align 4 140 // CHECK-PPC-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 141 // CHECK-PPC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] 142 // CHECK-PPC-NEXT: store i32 [[ADD]], ptr [[RETVAL]], align 4 143 // CHECK-PPC-NEXT: br label [[RETURN]] 144 // CHECK-PPC: if.else5: 145 // CHECK-PPC-NEXT: [[CPU_IS6:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) 146 // CHECK-PPC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[CPU_IS6]], 39 147 // CHECK-PPC-NEXT: br i1 [[TMP9]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]] 148 // CHECK-PPC: if.then7: 149 // CHECK-PPC-NEXT: [[TMP10:%.*]] = load i32, ptr [[A_ADDR]], align 4 150 // CHECK-PPC-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP10]], 3 151 // CHECK-PPC-NEXT: store i32 [[MUL]], ptr [[RETVAL]], align 4 152 // CHECK-PPC-NEXT: br label [[RETURN]] 153 // CHECK-PPC: if.else8: 154 // CHECK-PPC-NEXT: [[CPU_IS9:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) 155 // CHECK-PPC-NEXT: [[TMP11:%.*]] = icmp eq i32 [[CPU_IS9]], 33 156 // CHECK-PPC-NEXT: br i1 [[TMP11]], label [[IF_THEN10:%.*]], label [[IF_ELSE12:%.*]] 157 // CHECK-PPC: if.then10: 158 // CHECK-PPC-NEXT: [[TMP12:%.*]] = load i32, ptr [[A_ADDR]], align 4 159 // CHECK-PPC-NEXT: [[MUL11:%.*]] = mul nsw i32 [[TMP12]], 4 160 // CHECK-PPC-NEXT: store i32 [[MUL11]], ptr [[RETVAL]], align 4 161 // CHECK-PPC-NEXT: br label [[RETURN]] 162 // CHECK-PPC: if.else12: 163 // CHECK-PPC-NEXT: [[CPU_IS13:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) 164 // CHECK-PPC-NEXT: [[TMP13:%.*]] = icmp eq i32 [[CPU_IS13]], 45 165 // CHECK-PPC-NEXT: br i1 [[TMP13]], label [[IF_THEN14:%.*]], label [[IF_ELSE16:%.*]] 166 // CHECK-PPC: if.then14: 167 // CHECK-PPC-NEXT: [[TMP14:%.*]] = load i32, ptr [[A_ADDR]], align 4 168 // CHECK-PPC-NEXT: [[ADD15:%.*]] = add nsw i32 [[TMP14]], 3 169 // CHECK-PPC-NEXT: store i32 [[ADD15]], ptr [[RETVAL]], align 4 170 // CHECK-PPC-NEXT: br label [[RETURN]] 171 // CHECK-PPC: if.else16: 172 // CHECK-PPC-NEXT: [[CPU_IS17:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) 173 // CHECK-PPC-NEXT: [[TMP15:%.*]] = icmp eq i32 [[CPU_IS17]], 46 174 // CHECK-PPC-NEXT: br i1 [[TMP15]], label [[IF_THEN18:%.*]], label [[IF_ELSE20:%.*]] 175 // CHECK-PPC: if.then18: 176 // CHECK-PPC-NEXT: [[TMP16:%.*]] = load i32, ptr [[A_ADDR]], align 4 177 // CHECK-PPC-NEXT: [[SUB19:%.*]] = sub nsw i32 [[TMP16]], 3 178 // CHECK-PPC-NEXT: store i32 [[SUB19]], ptr [[RETVAL]], align 4 179 // CHECK-PPC-NEXT: br label [[RETURN]] 180 // CHECK-PPC: if.else20: 181 // CHECK-PPC-NEXT: [[CPU_IS21:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) 182 // CHECK-PPC-NEXT: [[TMP17:%.*]] = icmp eq i32 [[CPU_IS21]], 47 183 // CHECK-PPC-NEXT: br i1 [[TMP17]], label [[IF_THEN22:%.*]], label [[IF_ELSE24:%.*]] 184 // CHECK-PPC: if.then22: 185 // CHECK-PPC-NEXT: [[TMP18:%.*]] = load i32, ptr [[A_ADDR]], align 4 186 // CHECK-PPC-NEXT: [[ADD23:%.*]] = add nsw i32 [[TMP18]], 7 187 // CHECK-PPC-NEXT: store i32 [[ADD23]], ptr [[RETVAL]], align 4 188 // CHECK-PPC-NEXT: br label [[RETURN]] 189 // CHECK-PPC: if.else24: 190 // CHECK-PPC-NEXT: [[CPU_IS25:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) 191 // CHECK-PPC-NEXT: [[TMP19:%.*]] = icmp eq i32 [[CPU_IS25]], 48 192 // CHECK-PPC-NEXT: br i1 [[TMP19]], label [[IF_THEN26:%.*]], label [[IF_END:%.*]] 193 // CHECK-PPC: if.then26: 194 // CHECK-PPC-NEXT: [[TMP20:%.*]] = load i32, ptr [[A_ADDR]], align 4 195 // CHECK-PPC-NEXT: [[SUB27:%.*]] = sub nsw i32 [[TMP20]], 7 196 // CHECK-PPC-NEXT: store i32 [[SUB27]], ptr [[RETVAL]], align 4 197 // CHECK-PPC-NEXT: br label [[RETURN]] 198 // CHECK-PPC: if.end: 199 // CHECK-PPC-NEXT: br label [[IF_END28:%.*]] 200 // CHECK-PPC: if.end28: 201 // CHECK-PPC-NEXT: br label [[IF_END29:%.*]] 202 // CHECK-PPC: if.end29: 203 // CHECK-PPC-NEXT: br label [[IF_END30:%.*]] 204 // CHECK-PPC: if.end30: 205 // CHECK-PPC-NEXT: br label [[IF_END31:%.*]] 206 // CHECK-PPC: if.end31: 207 // CHECK-PPC-NEXT: br label [[IF_END32:%.*]] 208 // CHECK-PPC: if.end32: 209 // CHECK-PPC-NEXT: br label [[IF_END33:%.*]] 210 // CHECK-PPC: if.end33: 211 // CHECK-PPC-NEXT: br label [[IF_END34:%.*]] 212 // CHECK-PPC: if.end34: 213 // CHECK-PPC-NEXT: br label [[IF_END35:%.*]] 214 // CHECK-PPC: if.end35: 215 // CHECK-PPC-NEXT: [[TMP21:%.*]] = load i32, ptr [[A_ADDR]], align 4 216 // CHECK-PPC-NEXT: [[ADD36:%.*]] = add nsw i32 [[TMP21]], 5 217 // CHECK-PPC-NEXT: store i32 [[ADD36]], ptr [[RETVAL]], align 4 218 // CHECK-PPC-NEXT: br label [[RETURN]] 219 // CHECK-PPC: return: 220 // CHECK-PPC-NEXT: [[TMP22:%.*]] = load i32, ptr [[RETVAL]], align 4 221 // CHECK-PPC-NEXT: ret i32 [[TMP22]] 222 // 223 int test_ppc(int a) { 224 if (__builtin_cpu_supports("arch_3_00")) // HWCAP2 225 return a; 226 else if (__builtin_cpu_supports("mmu")) // HWCAP 227 return a - 5; 228 else if (__builtin_cpu_is("power7")) // CPUID 229 return a + a; 230 else if (__builtin_cpu_is("pwr7")) // CPUID 231 return a * 3; 232 else if (__builtin_cpu_is("ppc970")) // CPUID 233 return a * 4; 234 else if (__builtin_cpu_is("power8")) 235 return a + 3; 236 else if (__builtin_cpu_is("power9")) 237 return a - 3; 238 else if (__builtin_cpu_is("power10")) 239 return a + 7; 240 else if (__builtin_cpu_is("power11")) 241 return a - 7; 242 return a + 5; 243 } 244 #endif 245 246 #ifdef __riscv 247 // CHECK-RV32-LABEL: define dso_local i32 @test_riscv( 248 // CHECK-RV32-SAME: i32 noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] { 249 // CHECK-RV32-NEXT: entry: 250 // CHECK-RV32-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 251 // CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 252 // CHECK-RV32-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 253 // CHECK-RV32-NEXT: call void @__init_riscv_feature_bits(ptr null) 254 // CHECK-RV32-NEXT: [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 255 // CHECK-RV32-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1 256 // CHECK-RV32-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1 257 // CHECK-RV32-NEXT: br i1 [[TMP2]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 258 // CHECK-RV32: if.then: 259 // CHECK-RV32-NEXT: store i32 3, ptr [[RETVAL]], align 4 260 // CHECK-RV32-NEXT: br label [[RETURN:%.*]] 261 // CHECK-RV32: if.else: 262 // CHECK-RV32-NEXT: [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 263 // CHECK-RV32-NEXT: [[TMP4:%.*]] = and i64 [[TMP3]], 4 264 // CHECK-RV32-NEXT: [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 4 265 // CHECK-RV32-NEXT: br i1 [[TMP5]], label [[IF_THEN1:%.*]], label [[IF_ELSE2:%.*]] 266 // CHECK-RV32: if.then1: 267 // CHECK-RV32-NEXT: store i32 7, ptr [[RETVAL]], align 4 268 // CHECK-RV32-NEXT: br label [[RETURN]] 269 // CHECK-RV32: if.else2: 270 // CHECK-RV32-NEXT: [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 271 // CHECK-RV32-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 2097152 272 // CHECK-RV32-NEXT: [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 2097152 273 // CHECK-RV32-NEXT: br i1 [[TMP8]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]] 274 // CHECK-RV32: if.then3: 275 // CHECK-RV32-NEXT: store i32 11, ptr [[RETVAL]], align 4 276 // CHECK-RV32-NEXT: br label [[RETURN]] 277 // CHECK-RV32: if.else4: 278 // CHECK-RV32-NEXT: [[TMP9:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 1), align 8 279 // CHECK-RV32-NEXT: [[TMP10:%.*]] = and i64 [[TMP9]], 8 280 // CHECK-RV32-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 8 281 // CHECK-RV32-NEXT: br i1 [[TMP11]], label [[IF_THEN5:%.*]], label [[IF_END:%.*]] 282 // CHECK-RV32: if.then5: 283 // CHECK-RV32-NEXT: store i32 13, ptr [[RETVAL]], align 4 284 // CHECK-RV32-NEXT: br label [[RETURN]] 285 // CHECK-RV32: if.end: 286 // CHECK-RV32-NEXT: br label [[IF_END6:%.*]] 287 // CHECK-RV32: if.end6: 288 // CHECK-RV32-NEXT: br label [[IF_END7:%.*]] 289 // CHECK-RV32: if.end7: 290 // CHECK-RV32-NEXT: br label [[IF_END8:%.*]] 291 // CHECK-RV32: if.end8: 292 // CHECK-RV32-NEXT: store i32 0, ptr [[RETVAL]], align 4 293 // CHECK-RV32-NEXT: br label [[RETURN]] 294 // CHECK-RV32: return: 295 // CHECK-RV32-NEXT: [[TMP12:%.*]] = load i32, ptr [[RETVAL]], align 4 296 // CHECK-RV32-NEXT: ret i32 [[TMP12]] 297 // 298 // CHECK-RV64-LABEL: define dso_local signext i32 @test_riscv( 299 // CHECK-RV64-SAME: i32 noundef signext [[A:%.*]]) #[[ATTR0:[0-9]+]] { 300 // CHECK-RV64-NEXT: entry: 301 // CHECK-RV64-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 302 // CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 303 // CHECK-RV64-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 304 // CHECK-RV64-NEXT: call void @__init_riscv_feature_bits(ptr null) 305 // CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 306 // CHECK-RV64-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1 307 // CHECK-RV64-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1 308 // CHECK-RV64-NEXT: br i1 [[TMP2]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 309 // CHECK-RV64: if.then: 310 // CHECK-RV64-NEXT: store i32 3, ptr [[RETVAL]], align 4 311 // CHECK-RV64-NEXT: br label [[RETURN:%.*]] 312 // CHECK-RV64: if.else: 313 // CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 314 // CHECK-RV64-NEXT: [[TMP4:%.*]] = and i64 [[TMP3]], 4 315 // CHECK-RV64-NEXT: [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 4 316 // CHECK-RV64-NEXT: br i1 [[TMP5]], label [[IF_THEN1:%.*]], label [[IF_ELSE2:%.*]] 317 // CHECK-RV64: if.then1: 318 // CHECK-RV64-NEXT: store i32 7, ptr [[RETVAL]], align 4 319 // CHECK-RV64-NEXT: br label [[RETURN]] 320 // CHECK-RV64: if.else2: 321 // CHECK-RV64-NEXT: [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 322 // CHECK-RV64-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 2097152 323 // CHECK-RV64-NEXT: [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 2097152 324 // CHECK-RV64-NEXT: br i1 [[TMP8]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]] 325 // CHECK-RV64: if.then3: 326 // CHECK-RV64-NEXT: store i32 11, ptr [[RETVAL]], align 4 327 // CHECK-RV64-NEXT: br label [[RETURN]] 328 // CHECK-RV64: if.else4: 329 // CHECK-RV64-NEXT: [[TMP9:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 1), align 8 330 // CHECK-RV64-NEXT: [[TMP10:%.*]] = and i64 [[TMP9]], 8 331 // CHECK-RV64-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 8 332 // CHECK-RV64-NEXT: br i1 [[TMP11]], label [[IF_THEN5:%.*]], label [[IF_END:%.*]] 333 // CHECK-RV64: if.then5: 334 // CHECK-RV64-NEXT: store i32 13, ptr [[RETVAL]], align 4 335 // CHECK-RV64-NEXT: br label [[RETURN]] 336 // CHECK-RV64: if.end: 337 // CHECK-RV64-NEXT: br label [[IF_END6:%.*]] 338 // CHECK-RV64: if.end6: 339 // CHECK-RV64-NEXT: br label [[IF_END7:%.*]] 340 // CHECK-RV64: if.end7: 341 // CHECK-RV64-NEXT: br label [[IF_END8:%.*]] 342 // CHECK-RV64: if.end8: 343 // CHECK-RV64-NEXT: store i32 0, ptr [[RETVAL]], align 4 344 // CHECK-RV64-NEXT: br label [[RETURN]] 345 // CHECK-RV64: return: 346 // CHECK-RV64-NEXT: [[TMP12:%.*]] = load i32, ptr [[RETVAL]], align 4 347 // CHECK-RV64-NEXT: ret i32 [[TMP12]] 348 // 349 int test_riscv(int a) { 350 __builtin_cpu_init(); 351 if (__builtin_cpu_supports("a")) 352 return 3; 353 else if (__builtin_cpu_supports("c")) 354 return 7; 355 else if (__builtin_cpu_supports("v")) 356 return 11; 357 else if (__builtin_cpu_supports("zcb")) 358 return 13; 359 return 0; 360 } 361 #endif 362