376 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE %s2// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare -o %t.cir %s 2>&1 | FileCheck --check-prefixes=CIR-AFTER %s3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll6// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG7 8double _Complex cd;9float _Complex cf;10int _Complex ci;11short _Complex cs;12double sd;13int si;14bool b;15 16void scalar_to_complex() {17 cd = sd;18 ci = si;19 cd = si;20 ci = sd;21}22 23// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast float_to_complex %{{.*}} : !cir.double -> !cir.complex<!cir.double>24 25// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double26// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double27// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>28 29// LLVM: %[[REAL:.*]] = load double, ptr {{.*}}, align 830// LLVM-NEXT: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[REAL]], 031// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP]], double 0.000000e+00, 132// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 833 34// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 835// OGCG: store double %[[REAL]], ptr {{.*}}, align 836// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr @cd, i32 0, i32 1), align 837 38// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast int_to_complex %{{.*}} : !s32i -> !cir.complex<!s32i>39 40// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i41// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i42// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>43 44// LLVM: %[[REAL:.*]] = load i32, ptr {{.*}}, align 445// LLVM-NEXT: %[[TMP:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 046// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP]], i32 0, 147// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 448 49// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 450// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 451// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci, i32 0, i32 1), align 452 53// CIR-BEFORE: %[[INT_TO_FP:.*]] = cir.cast int_to_float %{{.*}} : !s32i -> !cir.double54// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast float_to_complex %[[INT_TO_FP]] : !cir.double -> !cir.complex<!cir.double>55 56// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i57// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast int_to_float %[[TMP]] : !s32i -> !cir.double58// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double59// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>60 61// LLVM: %[[TMP:.*]] = load i32, ptr {{.*}}, align 462// LLVM-NEXT: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double63// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { double, double } undef, double %[[REAL]], 064// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP_2]], double 0.000000e+00, 165// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 866 67// OGCG: %[[TMP:.*]] = load i32, ptr {{.*}}, align 468// OGCG: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double69// OGCG: store double %[[REAL]], ptr {{.*}}, align 870// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 871 72// CIR-BEFORE: %[[FP_TO_INT:.*]] = cir.cast float_to_int %{{.*}} : !cir.double -> !s32i73// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast int_to_complex %[[FP_TO_INT]] : !s32i -> !cir.complex<!s32i>74 75// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double76// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast float_to_int %[[TMP]] : !cir.double -> !s32i77// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i78// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>79 80// LLVM: %[[TMP:.*]] = load double, ptr {{.*}}, align 881// LLVM-NEXT: %[[REAL:.*]] = fptosi double %[[TMP]] to i3282// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 083// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP_2]], i32 0, 184// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 485 86// OGCG: %[[TMP:.*]] = load double, ptr {{.*}}, align 887// OGCG: %[[REAL:.*]] = fptosi double %[[TMP]] to i3288// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 489// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 490 91void scalar_to_complex_explicit() {92 cd = (double _Complex)sd;93 ci = (int _Complex)si;94 cd = (double _Complex)si;95 ci = (int _Complex)sd;96}97 98// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast float_to_complex %{{.*}} : !cir.double -> !cir.complex<!cir.double>99 100// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double101// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double102// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>103 104// LLVM: %[[REAL:.*]] = load double, ptr {{.*}}, align 8105// LLVM-NEXT: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[REAL]], 0106// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP]], double 0.000000e+00, 1107// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8108 109// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8110// OGCG: store double %[[REAL]], ptr {{.*}}, align 8111// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr @cd, i32 0, i32 1), align 8112 113// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast int_to_complex %{{.*}} : !s32i -> !cir.complex<!s32i>114 115// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i116// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i117// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>118 119// LLVM: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4120// LLVM-NEXT: %[[TMP:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 0121// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP]], i32 0, 1122// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4123 124// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4125// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4126// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci, i32 0, i32 1), align 4127 128// CIR-BEFORE: %[[INT_TO_FP:.*]] = cir.cast int_to_float %{{.*}} : !s32i -> !cir.double129// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast float_to_complex %[[INT_TO_FP]] : !cir.double -> !cir.complex<!cir.double>130 131// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i132// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast int_to_float %[[TMP]] : !s32i -> !cir.double133// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double134// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>135 136// LLVM: %[[TMP:.*]] = load i32, ptr {{.*}}, align 4137// LLVM-NEXT: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double138// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { double, double } undef, double %[[REAL]], 0139// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP_2]], double 0.000000e+00, 1140// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8141 142// OGCG: %[[TMP:.*]] = load i32, ptr {{.*}}, align 4143// OGCG: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double144// OGCG: store double %[[REAL]], ptr {{.*}}, align 8145// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 8146 147// CIR-BEFORE: %[[FP_TO_INT:.*]] = cir.cast float_to_int %{{.*}} : !cir.double -> !s32i148// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast int_to_complex %[[FP_TO_INT]] : !s32i -> !cir.complex<!s32i>149 150// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double151// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast float_to_int %[[TMP]] : !cir.double -> !s32i152// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i153// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>154 155// LLVM: %[[TMP:.*]] = load double, ptr {{.*}}, align 8156// LLVM-NEXT: %[[REAL:.*]] = fptosi double %[[TMP]] to i32157// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 0158// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP_2]], i32 0, 1159// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4160 161// OGCG: %[[TMP:.*]] = load double, ptr {{.*}}, align 8162// OGCG: %[[REAL:.*]] = fptosi double %[[TMP]] to i32163// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4164// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4165 166void complex_to_scalar() {167 sd = (double)cd;168 si = (int)ci;169 sd = (double)ci;170 si = (int)cd;171}172 173// CIR-BEFORE: %[[FP_TO_COMPLEX_REAL:.*]] = cir.cast float_complex_to_real %{{.*}} : !cir.complex<!cir.double> -> !cir.double174 175// CIR-AFTER: %{{.*}} = cir.complex.real %{{.*}} : !cir.complex<!cir.double> -> !cir.double176 177// LLVM: %[[REAL:.*]] = extractvalue { double, double } %{{.*}}, 0178// LLVM: store double %[[REAL]], ptr {{.*}}, align 8179 180// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8181// OGCG: store double %[[REAL]], ptr {{.*}}, align 8182 183// CIR-BEFORE: %[[INT_COMPLEX_TO_REAL:.*]] = cir.cast int_complex_to_real %{{.*}} : !cir.complex<!s32i> -> !s32i184 185// CIR-AFTER: %{{.*}} = cir.complex.real %{{.*}} : !cir.complex<!s32i> -> !s32i186 187// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %{{.*}}, 0188// LLVM: store i32 %[[REAL]], ptr {{.*}}, align 4189 190// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4191// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4192 193// CIR-BEFORE: %[[INT_COMPLEX_TO_REAL:.*]] = cir.cast int_complex_to_real %{{.*}} : !cir.complex<!s32i> -> !s32i194// CIR-BEFORE: %[[INT_TO_FP:.*]] = cir.cast int_to_float %[[INT_COMPLEX_TO_REAL]] : !s32i -> !cir.double195 196// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!s32i> -> !s32i197// CIR-AFTER-NEXT: %{{.*}} = cir.cast int_to_float %[[REAL]] : !s32i -> !cir.double198 199// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %{{.+}}, 0200// LLVM-NEXT: %[[REAL_TO_DOUBLE:.*]] = sitofp i32 %[[REAL]] to double201// LLVM-NEXT: store double %[[REAL_TO_DOUBLE]], ptr {{.*}}, align 8202 203// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4204// OGCG: %[[INT_TO_FP:.*]] = sitofp i32 %[[REAL]] to double205// OGCG: store double %[[INT_TO_FP]], ptr {{.*}}, align 8206 207// CIR-BEFORE: %[[FP_TO_COMPLEX_REAL:.*]] = cir.cast float_complex_to_real %{{.*}} : !cir.complex<!cir.double> -> !cir.double208// CIR-BEFORE: %[[FP_TO_INT:.*]] = cir.cast float_to_int %[[FP_TO_COMPLEX_REAL]] : !cir.double -> !s32i209 210// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!cir.double> -> !cir.double211// CIR-AFTER-NEXT: %{{.*}} = cir.cast float_to_int %[[REAL]] : !cir.double -> !s32i212 213// LLVM: %[[REAL:.*]] = extractvalue { double, double } %{{.+}}, 0214// LLVM-NEXT: %[[REAL_TO_INT:.*]] = fptosi double %[[REAL]] to i32215// LLVM-NEXT: store i32 %[[REAL_TO_INT]], ptr {{.*}}, align 4216 217// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8218// OGCG: %[[FP_TO_INT:.*]] = fptosi double %[[REAL]] to i32219// OGCG: store i32 %[[FP_TO_INT]], ptr {{.*}}, align 4220 221void complex_to_bool() {222 b = (bool)cd;223 b = (bool)ci;224}225 226// CIR-BEFORE: %[[FP_COMPLEX_TO_BOOL:.*]] = cir.cast float_complex_to_bool %{{.*}} : !cir.complex<!cir.double> -> !cir.bool227 228// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!cir.double> -> !cir.double229// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!cir.double> -> !cir.double230// CIR-AFTER-NEXT: %[[REAL_TO_BOOL:.*]] = cir.cast float_to_bool %[[REAL]] : !cir.double -> !cir.bool231// CIR-AFTER-NEXT: %[[IMAG_TO_BOOL:.*]] = cir.cast float_to_bool %[[IMAG]] : !cir.double -> !cir.bool232// CIR-AFTER-NEXT: %[[CONST_TRUE:.*]] = cir.const #true233// CIR-AFTER-NEXT: %{{.*}} = cir.select if %[[REAL_TO_BOOL]] then %[[CONST_TRUE]] else %[[IMAG_TO_BOOL]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool234 235// LLVM: %[[REAL:.*]] = extractvalue { double, double } %{{.*}}, 0236// LLVM-NEXT: %[[IMAG:.*]] = extractvalue { double, double } %{{.*}}, 1237// LLVM-NEXT: %[[REAL_TO_BOOL:.*]] = fcmp une double %[[REAL]], 0.000000e+00238// LLVM-NEXT: %[[IMAG_TO_BOOL:.*]] = fcmp une double %[[IMAG]], 0.000000e+00239// LLVM-NEXT: %[[OR:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]240// LLVM-NEXT: %[[RESULT:.*]] = zext i1 %[[OR]] to i8241// LLVM-NEXT: store i8 %[[RESULT]], ptr {{.*}}, align 1242 243// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8244// OGCG: %[[IMAG:.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 8245// OGCG: %[[REAL_TO_BOOL:.*]] = fcmp une double %[[REAL]], 0.000000e+00246// OGCG: %[[IMAG_TO_BOOL:.*]] = fcmp une double %[[IMAG]], 0.000000e+00247// OGCG: %[[COMPLEX_TO_BOOL:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]248// OGCG: %[[BOOL_TO_INT:.*]] = zext i1 %[[COMPLEX_TO_BOOL]] to i8249// OGCG: store i8 %[[BOOL_TO_INT]], ptr {{.*}}, align 1250 251// CIR-BEFORE: %[[INT_COMPLEX_TO_BOOL:.*]] = cir.cast int_complex_to_bool %{{.*}} : !cir.complex<!s32i> -> !cir.bool252 253// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!s32i> -> !s32i254// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!s32i> -> !s32i255// CIR-AFTER-NEXT: %[[REAL_TO_BOOL:.*]] = cir.cast int_to_bool %[[REAL]] : !s32i -> !cir.bool256// CIR-AFTER-NEXT: %[[IMAG_TO_BOOL:.*]] = cir.cast int_to_bool %[[IMAG]] : !s32i -> !cir.bool257// CIR-AFTER-NEXT: %[[CONST_TRUE:.*]] = cir.const #true258// CIR-AFTER-NEXT: %{{.+}} = cir.select if %[[REAL_TO_BOOL]] then %[[CONST_TRUE]] else %[[IMAG_TO_BOOL]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool259 260// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %{{.*}}, 0261// LLVM-NEXT: %[[IMAG:.*]] = extractvalue { i32, i32 } %{{.*}}, 1262// LLVM-NEXT: %[[REAL_TO_BOOL:.*]] = icmp ne i32 %[[REAL]], 0263// LLVM-NEXT: %[[IMAG_TO_BOOL:.*]] = icmp ne i32 %[[IMAG]], 0264// LLVM-NEXT: %[[OR:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]265// LLVM-NEXT: %[[RESULT:.*]] = zext i1 %[[OR]] to i8266// LLVM-NEXT: store i8 %[[RESULT]], ptr {{.*}}, align 1267 268// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4269// OGCG: %[[IMAG:.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4270// OGCG: %[[REAL_TO_BOOL:.*]] = icmp ne i32 %[[REAL]], 0271// OGCG: %[[IMAG_TO_BOOL:.*]] = icmp ne i32 %[[IMAG]], 0272// OGCG: %[[COMPLEX_TO_BOOL:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]273// OGCG: %[[BOOL_TO_INT:.*]] = zext i1 %[[COMPLEX_TO_BOOL]] to i8274// OGCG: store i8 %[[BOOL_TO_INT]], ptr {{.*}}, align 1275 276void complex_to_complex_cast() {277 cd = cf;278 ci = cs;279}280 281// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>282// CIR-BEFORE: %[[FP_COMPLEX:.*]] = cir.cast float_complex %[[TMP]] : !cir.complex<!cir.float> -> !cir.complex<!cir.double>283 284// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!cir.float> -> !cir.float285// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!cir.float> -> !cir.float286// CIR-AFTER: %[[REAL_FP_CAST:.*]] = cir.cast floating %[[REAL]] : !cir.float -> !cir.double287// CIR-AFTER: %[[IMAG_FP_CAST:.*]] = cir.cast floating %[[IMAG]] : !cir.float -> !cir.double288// CIR-AFTER: %{{.*}} = cir.complex.create %[[REAL_FP_CAST]], %[[IMAG_FP_CAST]] : !cir.double -> !cir.complex<!cir.double>289 290// LLVM: %[[REAL:.*]] = extractvalue { float, float } %{{.*}}, 0291// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %{{.*}}, 1292// LLVM: %[[REAL_FP_CAST:.*]] = fpext float %[[REAL]] to double293// LLVM: %[[IMAG_FP_CAST:.*]] = fpext float %[[IMAG]] to double294// LLVM: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[REAL_FP_CAST]], 0295// LLVM: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP]], double %[[IMAG_FP_CAST]], 1296// LLVM: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8297 298// OGCG: %[[REAL:.*]] = load float, ptr {{.*}}, align 4299// OGCG: %[[IMAG:.*]] = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr {{.*}}, i32 0, i32 1), align 4300// OGCG: %[[REAL_FP_CAST:.*]] = fpext float %[[REAL]] to double301// OGCG: %[[IMAG_FP_CAST:.*]] = fpext float %[[IMAG]] to double302// OGCG: store double %[[REAL_FP_CAST]], ptr {{.*}}, align 8303// OGCG: store double %[[IMAG_FP_CAST]], ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 8304 305// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.complex<!s16i>>, !cir.complex<!s16i>306// CIR-BEFORE: %[[INT_COMPLEX:.*]] = cir.cast int_complex %[[TMP]] : !cir.complex<!s16i> -> !cir.complex<!s32i>307 308// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!s16i> -> !s16i309// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!s16i> -> !s16i310// CIR-AFTER: %[[REAL_INT_CAST:.*]] = cir.cast integral %[[REAL]] : !s16i -> !s32i311// CIR-AFTER: %[[IMAG_INT_CAST:.*]] = cir.cast integral %[[IMAG]] : !s16i -> !s32i312// CIR-AFTER: %{{.*}} = cir.complex.create %[[REAL_INT_CAST]], %[[IMAG_INT_CAST]] : !s32i -> !cir.complex<!s32i>313 314// LLVM: %[[REAL:.*]] = extractvalue { i16, i16 } %{{.*}}, 0315// LLVM: %[[IMAG:.*]] = extractvalue { i16, i16 } %{{.*}}, 1316// LLVM: %[[REAL_INT_CAST:.*]] = sext i16 %[[REAL]] to i32317// LLVM: %[[IMAG_INT_CAST:.*]] = sext i16 %[[IMAG]] to i32318// LLVM: %[[TMP:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL_INT_CAST]], 0319// LLVM: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP]], i32 %[[IMAG_INT_CAST]], 1320// LLVM: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4321 322// OGCG: %[[REAL:.*]] = load i16, ptr {{.*}}, align 2323// OGCG: %[[IMAG:.*]] = load i16, ptr getelementptr inbounds nuw ({ i16, i16 }, ptr {{.*}}, i32 0, i32 1), align 2324// OGCG: %[[REAL_INT_CAST:.*]] = sext i16 %[[REAL]] to i32325// OGCG: %[[IMAG_INT_CAST:.*]] = sext i16 %[[IMAG]] to i32326// OGCG: store i32 %[[REAL_INT_CAST]], ptr {{.*}}, align 4327// OGCG: store i32 %[[IMAG_INT_CAST]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4328 329struct CX {330 double real;331 double imag;332};333 334void lvalue_to_rvalue_bitcast() {335 CX a;336 double _Complex b = __builtin_bit_cast(double _Complex, a);337}338 339// CIR-BEFORE: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_CX> -> !cir.ptr<!cir.complex<!cir.double>>340 341// CIR-AFTER: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_CX> -> !cir.ptr<!cir.complex<!cir.double>>342 343// LLVM: %[[PTR_ADDR:.*]] = alloca %struct.CX, i64 1, align 8344// LLVM: %[[COMPLEX_ADDR:.*]] = alloca { double, double }, i64 1, align 8345// LLVM: %[[PTR_TO_COMPLEX:.*]] = load { double, double }, ptr %[[PTR_ADDR]], align 8346// LLVM: store { double, double } %[[PTR_TO_COMPLEX]], ptr %[[COMPLEX_ADDR]], align 8347 348// OGCG: %[[A_ADDR:.*]] = alloca %struct.CX, align 8349// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8350// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0351// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8352// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1353// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8354// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0355// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1356// OGCG: store double %[[A_REAL]], ptr %[[B_REAL_PTR]], align 8357// OGCG: store double %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 8358 359void lvalue_bitcast() {360 CX a;361 (double _Complex &)a = {};362}363 364// CIR-BEFORE: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_CX> -> !cir.ptr<!cir.complex<!cir.double>>365 366// CIR-AFTER: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_CX> -> !cir.ptr<!cir.complex<!cir.double>>367 368// LLVM: %[[A_ADDR:.*]] = alloca %struct.CX, i64 1, align 8369// LLVM: store { double, double } zeroinitializer, ptr %[[A_ADDR]], align 8370 371// OGCG: %[[A_ADDR]] = alloca %struct.CX, align 8372// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0373// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1374// OGCG: store double 0.000000e+00, ptr %[[A_REAL_PTR]], align 8375// OGCG: store double 0.000000e+00, ptr %[[A_IMAG_PTR]], align 8376