brintos

brintos / llvm-project-archived public Read only

0
0
Text · 97.7 KiB · 82c9f2d Raw
1680 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR3// RUN: %clang_cc1 -std=c++20 -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 -std=c++20 -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 8int _Complex ci;9 10float _Complex cf;11 12int _Complex ci2 = { 1, 2 };13 14float _Complex cf2 = { 1.0f, 2.0f };15 16// CIR: cir.global external @ci = #cir.zero : !cir.complex<!s32i>17// CIR: cir.global external @cf = #cir.zero : !cir.complex<!cir.float>18// CIR: cir.global external @ci2 = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i> : !cir.complex<!s32i>19// CIR: cir.global external @cf2 = #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float, #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>20 21// LLVM: {{.*}} = global { i32, i32 } zeroinitializer, align 422// LLVM: {{.*}} = global { float, float } zeroinitializer, align 423// LLVM: {{.*}} = global { i32, i32 } { i32 1, i32 2 }, align 424// LLVM: {{.*}} = global { float, float } { float 1.000000e+00, float 2.000000e+00 }, align 425 26// OGCG: {{.*}} = global { i32, i32 } zeroinitializer, align 427// OGCG: {{.*}} = global { float, float } zeroinitializer, align 428// OGCG: {{.*}} = global { i32, i32 } { i32 1, i32 2 }, align 429// OGCG: {{.*}} = global { float, float } { float 1.000000e+00, float 2.000000e+00 }, align 430 31void foo() { int _Complex c = {}; }32 33// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]34// CIR: %[[COMPLEX:.*]] = cir.const #cir.zero : !cir.complex<!s32i>35// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>36 37// LLVM: %[[INIT:.*]] = alloca { i32, i32 }, i64 1, align 438// LLVM: store { i32, i32 } zeroinitializer, ptr %[[INIT]], align 439 40// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 441// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 042// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 143// OGCG: store i32 0, ptr %[[C_REAL_PTR]], align 444// OGCG: store i32 0, ptr %[[C_IMAG_PTR]], align 445 46void foo2() { int _Complex c = {1, 2}; }47 48// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]49// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i> : !cir.complex<!s32i>50// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>51 52// LLVM: %[[INIT:.*]] = alloca { i32, i32 }, i64 1, align 453// LLVM: store { i32, i32 } { i32 1, i32 2 }, ptr %[[INIT]], align 454 55// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 456// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 057// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 158// OGCG: store i32 1, ptr %[[C_REAL_PTR]], align 459// OGCG: store i32 2, ptr %[[C_IMAG_PTR]], align 460 61void foo3() {62  int a;63  int b;64  int _Complex c = {a, b};65}66 67// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]68// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>69// CIR: %[[TMP_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>70// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[TMP_B]] : !s32i -> !cir.complex<!s32i>71// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>72 73// LLVM: %[[INIT:.*]] = alloca { i32, i32 }, i64 1, align 474// LLVM: %[[TMP_A:.*]] = load i32, ptr {{.*}}, align 475// LLVM: %[[TMP_B:.*]] = load i32, ptr {{.*}}, align 476// LLVM: %[[TMP:.*]] = insertvalue { i32, i32 } undef, i32 %[[TMP_A]], 077// LLVM: %[[TMP_2:.*]] = insertvalue { i32, i32 } %[[TMP]], i32 %[[TMP_B]], 178// LLVM: store { i32, i32 } %[[TMP_2]], ptr %[[INIT]], align 479 80// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 481// OGCG: %[[REAL_VAL:.*]] = load i32, ptr {{.*}}, align 482// OGCG: %[[IMAG_VAL:.*]] = load i32, ptr {{.*}}, align 483// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 084// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 185// OGCG: store i32 %[[REAL_VAL]], ptr %[[C_REAL_PTR]], align 486// OGCG: store i32 %[[IMAG_VAL]], ptr %[[C_IMAG_PTR]], align 487 88void foo4() {89  int a;90  int _Complex c = {1, a};91}92 93// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]94// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i95// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i96// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[CONST_1]], %[[TMP_A]] : !s32i -> !cir.complex<!s32i>97// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>98 99// LLVM: %[[INIT:.*]] = alloca { i32, i32 }, i64 1, align 4100// LLVM: %[[TMP_A:.*]] = load i32, ptr {{.*}}, align 4101// LLVM: %[[COMPLEX:.*]] = insertvalue { i32, i32 } { i32 1, i32 undef }, i32 %[[TMP_A]], 1102// LLVM: store { i32, i32 } %[[COMPLEX]], ptr %[[INIT]], align 4103 104// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 4105// OGCG: %[[TMP_A:.*]] = load i32, ptr {{.*}}, align 4106// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 0107// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 1108// OGCG: store i32 1, ptr %[[C_REAL_PTR]], align 4109// OGCG: store i32 %[[TMP_A]], ptr %[[C_IMAG_PTR]], align 4110 111void foo5() {112  float _Complex c = {1.0f, 2.0f};113}114 115// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["c", init]116// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float, #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>117// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>118 119// LLVM: %[[INIT:.*]] = alloca { float, float }, i64 1, align 4120// LLVM: store { float, float } { float 1.000000e+00, float 2.000000e+00 }, ptr %[[INIT]], align 4121 122// OGCG: %[[COMPLEX]] = alloca { float, float }, align 4123// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0124// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1125// OGCG: store float 1.000000e+00, ptr %[[C_REAL_PTR]], align 4126// OGCG: store float 2.000000e+00, ptr %[[C_IMAG_PTR]], align 4127 128void foo6() {129  float a;130  float b;131  float _Complex c = {a, b};132}133 134// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["c", init]135// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.float>, !cir.float136// CIR: %[[TMP_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.float>, !cir.float137// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[TMP_B]] : !cir.float -> !cir.complex<!cir.float>138// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>139 140// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4141// LLVM: %[[TMP_A:.*]] = load float, ptr {{.*}}, align 4142// LLVM: %[[TMP_B:.*]] = load float, ptr {{.*}}, align 4143// LLVM: %[[TMP:.*]] = insertvalue { float, float } undef, float %[[TMP_A]], 0144// LLVM: %[[TMP_2:.*]] = insertvalue { float, float } %[[TMP]], float %[[TMP_B]], 1145// LLVM: store { float, float } %[[TMP_2]], ptr %[[COMPLEX]], align 4146 147// OGCG: %[[COMPLEX]] = alloca { float, float }, align 4148// OGCG: %[[TMP_A:.*]] = load float, ptr {{.*}}, align 4149// OGCG: %[[TMP_B:.*]] = load float, ptr {{.*}}, align 4150// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0151// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1152// OGCG: store float %[[TMP_A]], ptr %[[C_REAL_PTR]], align 4153// OGCG: store float %[[TMP_B]], ptr %[[C_IMAG_PTR]], align 4154 155void foo7() {156  float a;157  float _Complex c = {a, 2.0f};158}159 160// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["c", init]161// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.float>, !cir.float162// CIR: %[[CONST_2F:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.float163// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[CONST_2F]] : !cir.float -> !cir.complex<!cir.float>164// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>165 166// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4167// LLVM: %[[TMP_A:.*]] = load float, ptr {{.*}}, align 4168// LLVM: %[[TMP:.*]] = insertvalue { float, float } undef, float %[[TMP_A]], 0169// LLVM: %[[TMP_2:.*]] = insertvalue { float, float } %[[TMP]], float 2.000000e+00, 1170// LLVM: store { float, float } %[[TMP_2]], ptr %[[COMPLEX]], align 4171 172// OGCG: %[[COMPLEX:.*]] = alloca { float, float }, align 4173// OGCG: %[[TMP_A:.*]] = load float, ptr {{.*}}, align 4174// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0175// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1176// OGCG: store float %[[TMP_A]], ptr %[[C_REAL_PTR]], align 4177// OGCG: store float 2.000000e+00, ptr %[[C_IMAG_PTR]], align 4178 179void foo8() {180  double _Complex c = 2.00i;181}182 183// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.fp<0.000000e+00> : !cir.double, #cir.fp<2.000000e+00> : !cir.double> : !cir.complex<!cir.double>184 185// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8186// LLVM: store { double, double } { double 0.000000e+00, double 2.000000e+00 }, ptr %[[COMPLEX]], align 8187 188// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8189// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0190// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1191// OGCG: store double 0.000000e+00, ptr %[[C_REAL_PTR]], align 8192// OGCG: store double 2.000000e+00, ptr %[[C_IMAG_PTR]], align 8193 194void foo9(double a, double b) {195  double _Complex c = __builtin_complex(a, b);196}197 198// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c", init]199// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double200// CIR: %[[TMP_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double201// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[TMP_B]] : !cir.double -> !cir.complex<!cir.double>202// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>203 204// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8205// LLVM: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8206// LLVM: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8207// LLVM: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[TMP_A]], 0208// LLVM: %[[TMP_2:.*]] = insertvalue { double, double } %[[TMP]], double %[[TMP_B]], 1209// LLVM: store { double, double } %[[TMP_2]], ptr %[[COMPLEX]], align 8210 211// OGCG: %[[COMPLEX]] = alloca { double, double }, align 8212// OGCG: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8213// OGCG: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8214// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0215// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1216// OGCG: store double %[[TMP_A]], ptr %[[C_REAL_PTR]], align 8217// OGCG: store double %[[TMP_B]], ptr %[[C_IMAG_PTR]], align 8218 219void foo10() {220  double _Complex c;221  double *realPtr = &__real__ c;222}223 224// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c"]225// CIR: %[[REAL_PTR:.*]] = cir.complex.real_ptr %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.double>> -> !cir.ptr<!cir.double>226 227// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8228// LLVM: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0229 230// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8231// OGCG: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0232 233void foo11() {234  double _Complex c;235  double *imagPtr = &__imag__ c;236}237 238// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c"]239// CIR: %[[IMAG_PTR:.*]] = cir.complex.imag_ptr %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.double>> -> !cir.ptr<!cir.double>240 241// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8242// LLVM: %[[IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1243 244// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8245// OGCG: %[[IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1246 247void foo12() {248  double _Complex c;249  double imag = __imag__ c;250}251 252// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c"]253// CIR: %[[INIT:.*]] = cir.alloca !cir.double, !cir.ptr<!cir.double>, ["imag", init]254// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>255// CIR: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.double> -> !cir.double256// CIR: cir.store{{.*}} %[[IMAG]], %[[INIT]] : !cir.double, !cir.ptr<!cir.double>257 258// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8259// LLVM: %[[INIT:.*]] = alloca double, i64 1, align 8260// LLVM: %[[TMP:.*]] = load { double, double }, ptr %[[COMPLEX]], align 8261// LLVM: %[[IMAG:.*]] = extractvalue { double, double } %[[TMP]], 1262// LLVM: store double %[[IMAG]], ptr %[[INIT]], align 8263 264// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8265// OGCG: %[[INIT:.*]] = alloca double, align 8266// OGCG: %[[IMAG:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1267// OGCG: %[[TMP:.*]] = load double, ptr %[[IMAG]], align 8268// OGCG: store double %[[TMP]], ptr %[[INIT]], align 8269 270void foo13() {271  double _Complex c;272  double real = __real__ c;273}274 275// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c"]276// CIR: %[[INIT:.*]] = cir.alloca !cir.double, !cir.ptr<!cir.double>, ["real", init]277// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>278// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.double> -> !cir.double279// CIR: cir.store{{.*}} %[[REAL]], %[[INIT]] : !cir.double, !cir.ptr<!cir.double>280 281// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8282// LLVM: %[[INIT:.*]] = alloca double, i64 1, align 8283// LLVM: %[[TMP:.*]] = load { double, double }, ptr %[[COMPLEX]], align 8284// LLVM: %[[REAL:.*]] = extractvalue { double, double } %[[TMP]], 0285// LLVM: store double %[[REAL]], ptr %[[INIT]], align 8286 287// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8288// OGCG: %[[INIT:.*]] = alloca double, align 8289// OGCG: %[[REAL:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0290// OGCG: %[[TMP:.*]] = load double, ptr %[[REAL]], align 8291// OGCG: store double %[[TMP]], ptr %[[INIT]], align 8292 293 294void foo14() {295  int _Complex c = 2i;296}297 298// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.int<0> : !s32i, #cir.int<2> : !s32i> : !cir.complex<!s32i>299 300// LLVM: %[[COMPLEX:.*]] = alloca { i32, i32 }, i64 1, align 4301// LLVM: store { i32, i32 } { i32 0, i32 2 }, ptr %[[COMPLEX]], align 4302 303// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 4304// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 0305// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 1306// OGCG: store i32 0, ptr %[[C_REAL_PTR]], align 4307// OGCG: store i32 2, ptr %[[C_IMAG_PTR]], align 4308 309void foo15() {310  int _Complex a;311  int _Complex b = a;312}313 314// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]315// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]316// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>317// CIR: cir.store{{.*}} %[[TMP_A]], %[[COMPLEX_B]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>318 319// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4320// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4321// LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4322// LLVM: store { i32, i32 } %[[TMP_A]], ptr %[[COMPLEX_B]], align 4323 324// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4325// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4326// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0327// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4328// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1329// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4330// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0331// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1332// OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4333// OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4334 335int foo16(int _Complex a, int _Complex b) {336  return __imag__ a + __imag__ b;337}338 339// CIR: %[[RET:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]340// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>341// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[COMPLEX_A]] : !cir.complex<!s32i> -> !s32i342// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>343// CIR: %[[B_IMAG:.*]] = cir.complex.imag %[[COMPLEX_B]] : !cir.complex<!s32i> -> !s32i344// CIR: %[[ADD:.*]] = cir.binop(add, %[[A_IMAG]], %[[B_IMAG]]) nsw : !s32i345// CIR: cir.store %[[ADD]], %[[RET]] : !s32i, !cir.ptr<!s32i>346// CIR: %[[TMP:.*]] = cir.load %[[RET]] : !cir.ptr<!s32i>, !s32i347// CIR: cir.return %[[TMP]] : !s32i348 349// LLVM: %[[RET:.*]] = alloca i32, i64 1, align 4350// LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4351// LLVM: %[[A_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 1352// LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4353// LLVM: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 1354// LLVM: %[[ADD:.*]] = add nsw i32 %[[A_IMAG]], %[[B_IMAG]]355// LLVM: store i32 %[[ADD]], ptr %[[RET]], align 4356// LLVM: %[[TMP:.*]] = load i32, ptr %[[RET]], align 4357// LLVM: ret i32 %[[TMP]]358 359// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4360// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4361// OGCG: %[[A_IMAG:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1362// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_IMAG]], align 4363// OGCG: %[[B_IMAG:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1364// OGCG: %[[TMP_B:.*]] = load i32, ptr %[[B_IMAG]], align 4365// OGCG: %[[ADD:.*]] = add nsw i32 %[[TMP_A]], %[[TMP_B]]366// OGCG: ret i32 %[[ADD]]367 368int foo17(int _Complex a, int _Complex b) {369  return __real__ a + __real__ b;370}371 372// CIR: %[[RET:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]373// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>374// CIR: %[[A_REAL:.*]] = cir.complex.real %[[COMPLEX_A]] : !cir.complex<!s32i> -> !s32i375// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>376// CIR: %[[B_REAL:.*]] = cir.complex.real %[[COMPLEX_B]] : !cir.complex<!s32i> -> !s32i377// CIR: %[[ADD:.*]] = cir.binop(add, %[[A_REAL]], %[[B_REAL]]) nsw : !s32i378// CIR: cir.store %[[ADD]], %[[RET]] : !s32i, !cir.ptr<!s32i>379// CIR: %[[TMP:.*]] = cir.load %[[RET]] : !cir.ptr<!s32i>, !s32i380// CIR: cir.return %[[TMP]] : !s32i381 382// LLVM: %[[RET:.*]] = alloca i32, i64 1, align 4383// LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4384// LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 0385// LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4386// LLVM: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 0387// LLVM: %[[ADD:.*]] = add nsw i32 %[[A_REAL]], %[[B_REAL]]388// LLVM: store i32 %[[ADD]], ptr %[[RET]], align 4389// LLVM: %[[TMP:.*]] = load i32, ptr %[[RET]], align 4390// LLVM: ret i32 %[[TMP]]391 392// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4393// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4394// OGCG: %[[A_REAL:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0395// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_REAL]], align 4396// OGCG: %[[B_REAL:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0397// OGCG: %[[TMP_B:.*]] = load i32, ptr %[[B_REAL]], align 4398// OGCG: %[[ADD:.*]] = add nsw i32 %[[TMP_A]], %[[TMP_B]]399// OGCG: ret i32 %[[ADD]]400 401bool foo18(int _Complex a, int _Complex b) {402  return a == b;403}404 405// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>406// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>407// CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!s32i>, !cir.bool408 409// LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4410// LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4411// LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 0412// LLVM: %[[A_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 1413// LLVM: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 0414// LLVM: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 1415// LLVM: %[[CMP_REAL:.*]] = icmp eq i32 %[[A_REAL]], %[[B_REAL]]416// LLVM: %[[CMP_IMAG:.*]] = icmp eq i32 %[[A_IMAG]], %[[B_IMAG]]417// LLVM: %[[RESULT:.*]] = and i1 %[[CMP_REAL]], %[[CMP_IMAG]]418 419// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4420// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4421// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0422// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4423// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1424// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4425// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0426// OGCG: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4427// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1428// OGCG: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4429// OGCG: %[[CMP_REAL:.*]] = icmp eq i32 %[[A_REAL]], %[[B_REAL]]430// OGCG: %[[CMP_IMAG:.*]] = icmp eq i32 %[[A_IMAG]], %[[B_IMAG]]431// OGCG: %[[RESULT:.*]] = and i1 %[[CMP_REAL]], %[[CMP_IMAG]]432 433bool foo19(double _Complex a, double _Complex b) {434  return a == b;435}436 437// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>438// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>439// CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!cir.double>, !cir.bool440 441 442// LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8443// LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8444// LLVM: %[[A_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 0445// LLVM: %[[A_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 1446// LLVM: %[[B_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 0447// LLVM: %[[B_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 1448// LLVM: %[[CMP_REAL:.*]] = fcmp oeq double %[[A_REAL]], %[[B_REAL]]449// LLVM: %[[CMP_IMAG:.*]] = fcmp oeq double %[[A_IMAG]], %[[B_IMAG]]450// LLVM: %[[RESULT:.*]] = and i1 %[[CMP_REAL]], %[[CMP_IMAG]]451 452// OGCG: %[[COMPLEX_A:.*]] = alloca { double, double }, align 8453// OGCG: %[[COMPLEX_B:.*]] = alloca { double, double }, align 8454// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 0455// OGCG: store double {{.*}}, ptr %[[A_REAL_PTR]], align 8456// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 1457// OGCG: store double {{.*}}, ptr %[[A_IMAG_PTR]], align 8458// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 0459// OGCG: store double {{.*}}, ptr %[[B_REAL_PTR]], align 8460// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 1461// OGCG: store double {{.*}}, ptr %[[B_IMAG_PTR]], align 8462// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 0463// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8464// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 1465// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8466// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 0467// OGCG: %[[B_REAL:.*]] = load double, ptr %[[B_REAL_PTR]], align 8468// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 1469// OGCG: %[[B_IMAG:.*]] = load double, ptr %[[B_IMAG_PTR]], align 8470// OGCG: %[[CMP_REAL:.*]] = fcmp oeq double %[[A_REAL]], %[[B_REAL]]471// OGCG: %[[CMP_IMAG:.*]] = fcmp oeq double %[[A_IMAG]], %[[B_IMAG]]472// OGCG: %[[RESULT:.*]] = and i1 %[[CMP_REAL]], %[[CMP_IMAG]]473 474 475bool foo20(int _Complex a, int _Complex b) {476  return a != b;477}478 479// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>480// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>481// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!s32i>, !cir.bool482 483// LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4484// LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4485// LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 0486// LLVM: %[[A_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 1487// LLVM: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 0488// LLVM: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 1489// LLVM: %[[CMP_REAL:.*]] = icmp ne i32 %[[A_REAL]], %[[B_REAL]]490// LLVM: %[[CMP_IMAG:.*]] = icmp ne i32 %[[A_IMAG]], %[[B_IMAG]]491// LLVM: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]492 493// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4494// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4495// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0496// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4497// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1498// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4499// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0500// OGCG: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4501// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1502// OGCG: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4503// OGCG: %[[CMP_REAL:.*]] = icmp ne i32 %[[A_REAL]], %[[B_REAL]]504// OGCG: %[[CMP_IMAG:.*]] = icmp ne i32 %[[A_IMAG]], %[[B_IMAG]]505// OGCG: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]506 507bool foo21(double _Complex a, double _Complex b) {508  return a != b;509}510 511// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>512// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>513// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!cir.double>, !cir.bool514 515// LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8516// LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8517// LLVM: %[[A_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 0518// LLVM: %[[A_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 1519// LLVM: %[[B_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 0520// LLVM: %[[B_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 1521// LLVM: %[[CMP_REAL:.*]] = fcmp une double %[[A_REAL]], %[[B_REAL]]522// LLVM: %[[CMP_IMAG:.*]] = fcmp une double %[[A_IMAG]], %[[B_IMAG]]523// LLVM: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]524 525// OGCG: %[[COMPLEX_A:.*]] = alloca { double, double }, align 8526// OGCG: %[[COMPLEX_B:.*]] = alloca { double, double }, align 8527// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 0528// OGCG: store double {{.*}}, ptr %[[A_REAL_PTR]], align 8529// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 1530// OGCG: store double {{.*}}, ptr %[[A_IMAG_PTR]], align 8531// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 0532// OGCG: store double {{.*}}, ptr %[[B_REAL_PTR]], align 8533// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 1534// OGCG: store double {{.*}}, ptr %[[B_IMAG_PTR]], align 8535// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 0536// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8537// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 1538// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8539// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 0540// OGCG: %[[B_REAL:.*]] = load double, ptr %[[B_REAL_PTR]], align 8541// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 1542// OGCG: %[[B_IMAG:.*]] = load double, ptr %[[B_IMAG_PTR]], align 8543// OGCG: %[[CMP_REAL:.*]] = fcmp une double %[[A_REAL]], %[[B_REAL]]544// OGCG: %[[CMP_IMAG:.*]] = fcmp une double %[[A_IMAG]], %[[B_IMAG]]545// OGCG: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]546 547void foo22(int _Complex a, int _Complex b) {548  int _Complex c = (a, b);549}550 551// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a", init]552// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]553// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]554// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[COMPLEX_B]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>555// CIR: cir.store{{.*}} %[[TMP_B]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>556 557// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4558// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4559// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4560// LLVM: %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[COMPLEX_B]], align 4561// LLVM: store { i32, i32 } %[[TMP_B]], ptr %[[RESULT]], align 4562 563// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4564// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4565// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4566// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0567// OGCG: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4568// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1569// OGCG: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4570// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0571// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1572// OGCG: store i32 %[[B_REAL]], ptr %[[RESULT_REAL_PTR]], align 4573// OGCG: store i32 %[[B_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4574 575void foo23(int _Complex a, int _Complex b) {576  float _Complex f;577  int _Complex c = _Generic(a, int _Complex: b, default: f);578}579 580// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a", init]581// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]582// CIR: %[[COMPLEX_F:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["f"]583// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]584// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX_B]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>585// CIR: cir.store{{.*}} %[[TMP]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>586 587// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4588// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4589// LLVM: %[[COMPLEX_F:.*]] = alloca { float, float }, i64 1, align 4590// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4591// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[COMPLEX_B]], align 4592// LLVM: store { i32, i32 } %[[TMP]], ptr %[[RESULT]], align 4593 594// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4595// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4596// OGCG: %[[COMPLEX_F:.*]] = alloca { float, float }, align 4597// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4598// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0599// OGCG: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4600// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1601// OGCG: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4602// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0603// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1604// OGCG: store i32 %[[B_REAL]], ptr %[[RESULT_REAL_PTR]], align 4605// OGCG: store i32 %[[B_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4606 607void foo24() {608  int _Complex arr[2];609  int _Complex r = arr[1];610}611 612// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!cir.complex<!s32i> x 2>, !cir.ptr<!cir.array<!cir.complex<!s32i> x 2>>, ["arr"]613// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["r", init]614// CIR: %[[IDX:.*]] = cir.const #cir.int<1> : !s32i615// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!cir.complex<!s32i> x 2>> -> !cir.ptr<!cir.complex<!s32i>>616// CIR: %[[RESULT_VAL:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[IDX]] : (!cir.ptr<!cir.complex<!s32i>>, !s32i) -> !cir.ptr<!cir.complex<!s32i>>617// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[RESULT_VAL]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>618// CIR: cir.store{{.*}} %[[TMP]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>619 620// LLVM: %[[ARR:.*]] = alloca [2 x { i32, i32 }], i64 1, align 16621// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4622// LLVM: %[[ARR_PTR:.*]] = getelementptr { i32, i32 }, ptr %[[ARR]], i32 0623// LLVM: %[[RESULT_VAL:.*]] = getelementptr { i32, i32 }, ptr %[[ARR_PTR]], i64 1624// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[RESULT_VAL]], align 8625// LLVM: store { i32, i32 } %[[TMP]], ptr %[[RESULT]], align 4626 627// OGCG: %[[ARR:.*]] = alloca [2 x { i32, i32 }], align 16628// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4629// OGCG: %[[ELEM_PTR:.*]] = getelementptr inbounds [2 x { i32, i32 }], ptr %[[ARR]], i64 0, i64 1630// OGCG: %[[ELEM_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ELEM_PTR]], i32 0, i32 0631// OGCG: %[[ELEM_REAL:.*]] = load i32, ptr %[[ELEM_REAL_PTR]]632// OGCG: %[[ELEM_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ELEM_PTR]], i32 0, i32 1633// OGCG: %[[ELEM_IMAG:.*]] = load i32, ptr %[[ELEM_IMAG_PTR]]634// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0635// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1636// OGCG: store i32 %[[ELEM_REAL]], ptr %[[RESULT_REAL_PTR]], align 4637// OGCG: store i32 %[[ELEM_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4638 639template <double _Complex N> void template_foo() { double _Complex C = N; }640 641void foo25() {642  template_foo<__builtin_complex(1.0, 2.0)>();643}644 645// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["C", init]646// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.fp<1.000000e+00> : !cir.double, #cir.fp<2.000000e+00> : !cir.double> : !cir.complex<!cir.double>647// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>648 649// LLVM: %[[INIT:.*]] = alloca { double, double }, i64 1, align 8650// LLVM: store { double, double } { double 1.000000e+00, double 2.000000e+00 }, ptr %[[INIT]], align 8651 652// OGCG: %[[INIT:.*]] = alloca { double, double }, align 8653// OGCG: %[[INIT_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[INIT]], i32 0, i32 0654// OGCG: %[[INIT_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[INIT]], i32 0, i32 1655// OGCG: store double 1.000000e+00, ptr %[[INIT_REAL_PTR]], align 8656// OGCG: store double 2.000000e+00, ptr %[[INIT_IMAG_PTR]], align 8657 658void foo26(int _Complex* a) {659  int _Complex b = *a;660}661 662// CIR: %[[COMPLEX_A_PTR:.*]] = cir.alloca !cir.ptr<!cir.complex<!s32i>>, !cir.ptr<!cir.ptr<!cir.complex<!s32i>>>, ["a", init]663// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]664// CIR: %[[COMPLEX_A:.*]] = cir.load deref {{.*}} %[[COMPLEX_A_PTR]] : !cir.ptr<!cir.ptr<!cir.complex<!s32i>>>, !cir.ptr<!cir.complex<!s32i>>665// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>666// CIR: cir.store{{.*}} %[[TMP]], %[[COMPLEX_B]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>667 668// LLVM: %[[COMPLEX_A_PTR:.*]] = alloca ptr, i64 1, align 8669// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4670// LLVM: %[[COMPLEX_A:.*]] = load ptr, ptr %[[COMPLEX_A_PTR]], align 8671// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4672// LLVM: store { i32, i32 } %[[TMP]], ptr %[[COMPLEX_B]], align 4673 674// OGCG: %[[COMPLEX_A_PTR:.*]] = alloca ptr, align 8675// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4676// OGCG: %[[COMPLEX_A:.*]] = load ptr, ptr %[[COMPLEX_A_PTR]], align 8677// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0678// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4679// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1680// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4681// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0682// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1683// OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4684// OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4685 686void foo27(bool cond, int _Complex a, int _Complex b) {687  int _Complex c = cond ? a : b;688}689 690// CIR: %[[COND:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["cond", init]691// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a", init]692// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]693// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]694// CIR: %[[TMP_COND:.*]] = cir.load{{.*}} %[[COND]] : !cir.ptr<!cir.bool>, !cir.bool695// CIR: %[[RESULT_VAL:.*]] = cir.ternary(%[[TMP_COND]], true {696// CIR:   %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>697// CIR:   cir.yield %[[TMP_A]] : !cir.complex<!s32i>698// CIR: }, false {699// CIR:   %[[TMP_B:.*]] = cir.load{{.*}} %[[COMPLEX_B]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>700// CIR:   cir.yield %[[TMP_B]] : !cir.complex<!s32i>701// CIR: }) : (!cir.bool) -> !cir.complex<!s32i>702// CIR: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>703 704// LLVM: %[[COND:.*]] = alloca i8, i64 1, align 1705// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4706// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4707// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4708// LLVM: %[[TMP_COND:.*]] = load i8, ptr %[[COND]], align 1709// LLVM: %[[COND_VAL:.*]] = trunc i8 %[[TMP_COND]] to i1710// LLVM: br i1 %[[COND_VAL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]711// LLVM: [[TRUE_BB]]:712// LLVM:  %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4713// LLVM:  br label %[[END_BB:.*]]714// LLVM: [[FALSE_BB]]:715// LLVM:  %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[COMPLEX_B]], align 4716// LLVM:  br label %[[END_BB]]717// LLVM: [[END_BB]]:718// LLVM: %[[RESULT_VAL:.*]] = phi { i32, i32 } [ %[[TMP_B]], %[[FALSE_BB]] ], [ %[[TMP_A]], %[[TRUE_BB]] ]719// LLVM: store { i32, i32 } %[[RESULT_VAL]], ptr %[[RESULT]], align 4720 721// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4722// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4723// OGCG: %[[COND:.*]] = alloca i8, align 1724// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4725// OGCG: %[[TMP_COND:.*]] = load i8, ptr %[[COND]], align 1726// OGCG: %[[COND_VAL:.*]] = trunc i8 %[[TMP_COND]] to i1727// OGCG: br i1 %[[COND_VAL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]728// OGCG: [[TRUE_BB]]:729// OGCG:  %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0730// OGCG:  %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4731// OGCG:  %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1732// OGCG:  %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4733// OGCG:  br label %[[END_BB:.*]]734// OGCG: [[FALSE_BB]]:735// OGCG:  %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0736// OGCG:  %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4737// OGCG:  %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1738// OGCG:  %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4739// OGCG:  br label %[[END_BB]]740// OGCG: [[END_BB]]:741// OGCG:  %[[REAL:.*]] = phi i32 [ %[[A_REAL]], %[[TRUE_BB]] ], [ %[[B_REAL]], %[[FALSE_BB]] ]742// OGCG:  %[[IMAG:.*]] = phi i32 [ %[[A_IMAG]], %[[TRUE_BB]] ], [ %[[B_IMAG]], %[[FALSE_BB]] ]743// OGCG:  %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0744// OGCG:  %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1745// OGCG:  store i32 %[[REAL]], ptr %[[RESULT_REAL_PTR]], align 4746// OGCG:  store i32 %[[IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4747 748void foo28() {749  using IntComplex = int _Complex;750  int _Complex a = IntComplex();751}752 753// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a", init]754// CIR: %[[COMPLEX:.*]] = cir.const #cir.zero : !cir.complex<!s32i>755// CIR: cir.store align(4) %[[COMPLEX]], %[[INIT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>756 757// LLVM: %[[INIT:.*]] = alloca { i32, i32 }, i64 1, align 4758// LLVM: store { i32, i32 } zeroinitializer, ptr %[[INIT]], align 4759 760// OGCG: %[[INIT:.*]] = alloca { i32, i32 }, align 4761// OGCG: %[[INIT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[INIT]], i32 0, i32 0762// OGCG: %[[INIT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[INIT]], i32 0, i32 1763// OGCG: store i32 0, ptr %[[INIT_REAL_PTR]], align 4764// OGCG: store i32 0, ptr %[[INIT_IMAG_PTR]], align 4765 766void foo29() {767  using IntComplex = int _Complex;768  int _Complex a = IntComplex{};769}770 771// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a", init]772// CIR: %[[COMPLEX:.*]] = cir.const #cir.zero : !cir.complex<!s32i>773// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>774 775// LLVM: %[[INIT:.*]] = alloca { i32, i32 }, i64 1, align 4776// LLVM: store { i32, i32 } zeroinitializer, ptr %[[INIT]], align 4777 778// OGCG: %[[INIT:.*]] = alloca { i32, i32 }, align 4779// OGCG: %[[INIT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[INIT]], i32 0, i32 0780// OGCG: %[[INIT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[INIT]], i32 0, i32 1781// OGCG: store i32 0, ptr %[[INIT_REAL_PTR]], align 4782// OGCG: store i32 0, ptr %[[INIT_IMAG_PTR]], align 4783 784void foo30() {785  float _Complex a = { 1.0f };786}787 788// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]789// CIR: %[[CONST_1F:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float790// CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float791// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[CONST_1F]], %[[CONST_0F]] : !cir.float -> !cir.complex<!cir.float>792// CIR: cir.store{{.*}} %[[COMPLEX]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>793 794// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4795// LLVM: store { float, float } { float 1.000000e+00, float 0.000000e+00 }, ptr %[[A_ADDR]], align 4796 797// OGCG:  %[[A_ADDR:.*]] = alloca { float, float }, align 4798// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0799// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1800// OGCG: store float 1.000000e+00, ptr %[[A_REAL_PTR]], align 4801// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4802 803void foo31() {804  struct Wrapper {805    int _Complex c;806  };807 808  Wrapper w;809  int r = __real__ w.c;810}811 812// CIR: %[[W_ADDR:.*]] = cir.alloca !rec_Wrapper, !cir.ptr<!rec_Wrapper>, ["w"]813// CIR: %[[REAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init]814// CIR: %[[ELEM_PTR:.*]] = cir.get_member %[[W_ADDR]][0] {name = "c"} : !cir.ptr<!rec_Wrapper> -> !cir.ptr<!cir.complex<!s32i>>815// CIR: %[[TMP_ELEM_PTR:.*]] = cir.load{{.*}} %[[ELEM_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>816// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP_ELEM_PTR]] : !cir.complex<!s32i> -> !s32i817// CIR: cir.store{{.*}} %[[REAL]], %[[REAL_ADDR]] : !s32i, !cir.ptr<!s32i>818 819// LLVM: %[[W_ADDR:.*]] = alloca %struct.Wrapper, i64 1, align 4820// LLVM: %[[REAL_ADDR:.*]] = alloca i32, i64 1, align 4821// LLVM: %[[ELEM_PTR:.*]] = getelementptr %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0822// LLVM: %[[TMP_ELEM_PTR:.*]] = load { i32, i32 }, ptr %[[ELEM_PTR]], align 4823// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP_ELEM_PTR]], 0824// LLVM: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4825 826// OGCG: %[[W_ADDR:.*]] = alloca %struct.Wrapper, align 4827// OGCG: %[[REAL_ADDR:.*]] = alloca i32, align 4828// OGCG: %[[ELEM_PTR:.*]] = getelementptr inbounds nuw %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0829// OGCG: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ELEM_PTR]], i32 0, i32 0830// OGCG: %[[REAL:.*]] = load i32, ptr %[[REAL_PTR]], align 4831// OGCG: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4832 833struct Container {834  static int _Complex c;835};836 837void foo32() {838  Container con;839  int r = __real__ con.c;840}841 842// CIR: %[[REAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init]843// CIR: %[[ELEM_PTR:.*]] = cir.get_global @_ZN9Container1cE : !cir.ptr<!cir.complex<!s32i>>844// CIR: %[[ELEM:.*]] = cir.load{{.*}} %[[ELEM_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>845// CIR: %[[REAL:.*]] = cir.complex.real %[[ELEM]] : !cir.complex<!s32i> -> !s32i846// CIR: cir.store{{.*}} %[[REAL]], %[[REAL_ADDR]] : !s32i, !cir.ptr<!s32i>847 848// LLVM: %[[REAL_ADDR:.*]] = alloca i32, i64 1, align 4849// LLVM: %[[ELEM:.*]] = load { i32, i32 }, ptr @_ZN9Container1cE, align 4850// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[ELEM]], 0851// LLVM: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4852 853// OGCG: %[[REAL_ADDR:.*]] = alloca i32, align 4854// OGCG: %[[REAL:.*]] = load i32, ptr @_ZN9Container1cE, align 4855// OGCG: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4856 857void foo33(__builtin_va_list a) {858  float _Complex b = __builtin_va_arg(a, float _Complex);859}860 861// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr<!rec___va_list_tag>, !cir.ptr<!cir.ptr<!rec___va_list_tag>>, ["a", init]862// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]863// CIR: cir.store %[[ARG_0:.*]], %[[A_ADDR]] : !cir.ptr<!rec___va_list_tag>, !cir.ptr<!cir.ptr<!rec___va_list_tag>>864// CIR: %[[VA_TAG:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.ptr<!rec___va_list_tag>>, !cir.ptr<!rec___va_list_tag>865// CIR: %[[COMPLEX:.*]] = cir.va_arg %[[VA_TAG]] : (!cir.ptr<!rec___va_list_tag>) -> !cir.complex<!cir.float>866// CIR: cir.store{{.*}} %[[COMPLEX]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>867 868// LLVM: %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8869// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4870// LLVM: store ptr %[[ARG_0:.*]], ptr %[[A_ADDR]], align 8871// LLVM: %[[TMP_A:.*]] = load ptr, ptr %[[A_ADDR]], align 8872// LLVM: %[[COMPLEX:.*]] = va_arg ptr %[[TMP_A]], { float, float }873// LLVM: store { float, float } %[[COMPLEX]], ptr %[[B_ADDR]], align 4874 875// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,876// Test will be updated when that is implemented877 878// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8879// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4880// OGCG: store ptr %[[ARG_0:.*]], ptr %[[A_ADDR]], align 8881// OGCG: %[[TMP_A:.*]] = load ptr, ptr %[[A_ADDR]], align 8882// OGCG: %[[GP_OFFSET_PTR:.*]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[TMP_A]], i32 0, i32 1883// OGCG: %[[GP_OFFSET:.*]] = load i32, ptr %[[GP_OFFSET_PTR]], align 4884// OGCG: %[[COND:.*]] = icmp ule i32 %[[GP_OFFSET]], 160885// OGCG: br i1 %[[COND]], label %[[VA_ARG_IN_REG:.*]], label %[[VA_ARG_IN_MEM:.*]]886//887// OGCG: [[VA_ARG_IN_REG]]:888// OGCG:  %[[REG_SAVE_PTR:.*]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[TMP_A]], i32 0, i32 3889// OGCG:  %[[REG_SAVE:.*]] = load ptr, ptr %[[REG_SAVE_PTR]], align 8890// OGCG:  %[[VA_ADDR:..*]] = getelementptr i8, ptr %[[REG_SAVE]], i32 %[[GP_OFFSET]]891// OGCG:  %[[GP_OFFSET_NEXT:.*]] = add i32 %[[GP_OFFSET]], 16892// OGCG:  store i32 %[[GP_OFFSET_NEXT]], ptr %[[GP_OFFSET_PTR]], align 4893// OGCG:  br label %[[VA_ARG_END:.*]]894//895// OGCG: [[VA_ARG_IN_MEM]]:896// OGCG:  %[[OVERFLOW_PTR:.*]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[TMP_A]], i32 0, i32 2897// OGCG:  %[[OVERFLOW:.*]] = load ptr, ptr %[[OVERFLOW_PTR]], align 8898// OGCG:  %[[OVERFLOW_NEXT:.*]] = getelementptr i8, ptr %[[OVERFLOW]], i32 8899// OGCG:  store ptr %[[OVERFLOW_NEXT]], ptr %[[OVERFLOW_PTR]], align 8900// OGCG:  br label %[[VA_ARG_END]]901//902// OGCG: [[VA_ARG_END]]:903// OGCG:  %[[RESULT:.*]] = phi ptr [ %[[VA_ADDR]], %[[VA_ARG_IN_REG]] ], [ %[[OVERFLOW]], %[[VA_ARG_IN_MEM]] ]904// OGCG:  %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0905// OGCG:  %[[RESULT_REAL:.*]] = load float, ptr %[[RESULT_REAL_PTR]], align 4906// OGCG:  %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1907// OGCG:  %[[RESULT_IMAG:.*]] = load float, ptr %[[RESULT_IMAG_PTR]], align 4908// OGCG:  %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0909// OGCG:  %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1910// OGCG:  store float %[[RESULT_REAL]], ptr %[[B_REAL_PTR]], align 4911// OGCG:  store float %[[RESULT_IMAG]], ptr %[[B_IMAG_PTR]], align 4912 913void foo34() {914  _Atomic(float _Complex) a;915  __c11_atomic_init(&a, {1.0f, 2.0f});916}917 918// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]919// CIR: %[[CONST_COMPLEX:.*]] = cir.const #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float, #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>920// CIR: cir.store{{.*}} %[[CONST_COMPLEX]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>921 922// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 8923// LLVM: store { float, float } { float 1.000000e+00, float 2.000000e+00 }, ptr %[[A_ADDR]], align 8924 925// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 8926// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0927// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1928// OGCG: store float 1.000000e+00, ptr %[[A_REAL_PTR]], align 8929// OGCG: store float 2.000000e+00, ptr %[[A_IMAG_PTR]], align 4930 931void foo35() {932  _Float16 _Complex a;933  _Float16 real = __real__ a;934}935 936// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.f16>, !cir.ptr<!cir.complex<!cir.f16>>, ["a"]937// CIR: %[[REAL_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["real", init]938// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.f16>>, !cir.complex<!cir.f16>939// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f16940// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f16941// CIR: %[[A_REAL_F32:.*]] = cir.cast floating %[[A_REAL]] : !cir.f16 -> !cir.float942// CIR: %[[A_IMAG_F32:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.float943// CIR: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], %[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>944// CIR: %[[A_REAL_F32:.*]] = cir.complex.real %[[A_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float945// CIR: %[[A_REAL_F16:.*]] = cir.cast floating %[[A_REAL_F32]] : !cir.float -> !cir.f16946// CIR: cir.store{{.*}} %[[A_REAL_F16]], %[[REAL_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>947 948// LLVM: %[[A_ADDR:.*]] = alloca { half, half }, i64 1, align 2949// LLVM: %[[REAL_ADDR:.*]] = alloca half, i64 1, align 2950// LLVM: %[[TMP_A:.*]] = load { half, half }, ptr %[[A_ADDR]], align 2951// LLVM: %[[A_REAL:.*]] = extractvalue { half, half } %[[TMP_A]], 0952// LLVM: %[[A_IMAG:.*]] = extractvalue { half, half } %[[TMP_A]], 1953// LLVM: %[[A_REAL_F32:.*]] = fpext half %[[A_REAL]] to float954// LLVM: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float955// LLVM: %[[TMP_A_COMPLEX_F32:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL_F32]], 0956// LLVM: %[[A_COMPLEX_F32:.*]] = insertvalue { float, float } %[[TMP_A_COMPLEX_F32]], float %[[A_IMAG_F32]], 1957// LLVM: %[[A_REAL_F16:.*]] = fptrunc float %[[A_REAL_F32]] to half958// LLVM: store half %[[A_REAL_F16]], ptr %[[REAL_ADDR]], align 2959 960// OGCG: %[[A_ADDR:.*]] = alloca { half, half }, align 2961// OGCG: %[[REAL_ADDR:.*]] = alloca half, align 2962// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { half, half }, ptr %[[A_ADDR]], i32 0, i32 0963// OGCG: %[[A_REAL:.*]] = load half, ptr %[[A_REAL_PTR]], align 2964// OGCG: %[[A_REAL_F32:.*]] = fpext half %[[A_REAL]] to float965// OGCG: %[[A_REAL_F16:.*]] = fptrunc float %[[A_REAL_F32]] to half966// OGCG: store half %[[A_REAL_F16]], ptr %[[REAL_ADDR]], align 2967 968void foo36() {969  _Float16 _Complex a;970  _Float16 imag = __imag__ a;971}972 973// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.f16>, !cir.ptr<!cir.complex<!cir.f16>>, ["a"]974// CIR: %[[IMAG_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["imag", init]975// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.f16>>, !cir.complex<!cir.f16>976// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f16977// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f16978// CIR: %[[A_REAL_F32:.*]] = cir.cast floating %[[A_REAL]] : !cir.f16 -> !cir.float979// CIR: %[[A_IMAG_F32:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.float980// CIR: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], %[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>981// CIR: %[[A_IMAG_F32:.*]] = cir.complex.imag %[[A_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float982// CIR: %[[A_IMAG_F16:.*]] = cir.cast floating %[[A_IMAG_F32]] : !cir.float -> !cir.f16983// CIR: cir.store{{.*}} %[[A_IMAG_F16]], %[[IMAG_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>984 985// LLVM: %[[A_ADDR:.*]] = alloca { half, half }, i64 1, align 2986// LLVM: %[[IMAG_ADDR:.*]] = alloca half, i64 1, align 2987// LLVM: %[[TMP_A:.*]] = load { half, half }, ptr %[[A_ADDR]], align 2988// LLVM: %[[A_REAL:.*]] = extractvalue { half, half } %[[TMP_A]], 0989// LLVM: %[[A_IMAG:.*]] = extractvalue { half, half } %[[TMP_A]], 1990// LLVM: %[[A_REAL_F32:.*]] = fpext half %[[A_REAL]] to float991// LLVM: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float992// LLVM: %[[TMP_A_COMPLEX_F32:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL_F32]], 0993// LLVM: %[[A_COMPLEX_F32:.*]] = insertvalue { float, float } %[[TMP_A_COMPLEX_F32]], float %[[A_IMAG_F32]], 1994// LLVM: %[[A_IMAG_F16:.*]] = fptrunc float %[[A_IMAG_F32]] to half995// LLVM: store half %[[A_IMAG_F16]], ptr %[[IMAG_ADDR]], align 2996 997// OGCG: %[[A_ADDR:.*]] = alloca { half, half }, align 2998// OGCG: %[[IMAG_ADDR:.*]] = alloca half, align 2999// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { half, half }, ptr %[[A_ADDR]], i32 0, i32 11000// OGCG: %[[A_IMAG:.*]] = load half, ptr %[[A_IMAG_PTR]], align 21001// OGCG: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float1002// OGCG: %[[A_IMAG_F16:.*]] = fptrunc float %[[A_IMAG_F32]] to half1003// OGCG: store half %[[A_IMAG_F16]], ptr %[[IMAG_ADDR]], align 21004 1005void foo37() {1006  _Complex float a;1007  _Complex float b = __extension__ a;1008}1009 1010// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]1011// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]1012// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1013// CIR: cir.store{{.*}} %[[TMP_A]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1014 1015// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 41016// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 41017// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 41018// LLVM: store { float, float } %[[TMP_A]], ptr %[[B_ADDR]], align 41019 1020// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 41021// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 41022// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 01023// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 41024// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 11025// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 41026// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 01027// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 11028// OGCG: store float %[[A_REAL]], ptr %[[B_REAL_PTR]], align 41029// OGCG: store float %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 41030 1031void real_on_non_glvalue() {1032  float _Complex a;1033  float b = __real__(+a);1034}1035 1036// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]1037// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]1038// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1039// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float1040// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float1041// CIR: %[[A_REAL_PLUS:.*]] = cir.unary(plus, %[[A_REAL]]) : !cir.float, !cir.float1042// CIR: %[[A_IMAG_PLUS:.*]] = cir.unary(plus, %[[A_IMAG]]) : !cir.float, !cir.float1043// CIR: %[[RESULT:.*]] = cir.complex.create %[[A_REAL_PLUS]], %[[A_IMAG_PLUS]] : !cir.float -> !cir.complex<!cir.float>1044// CIR: %[[RESULT_REAL:.*]] = cir.complex.real %[[RESULT]] : !cir.complex<!cir.float> -> !cir.float1045// CIR: cir.store{{.*}} %[[RESULT_REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>1046 1047// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 41048// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 41049// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 41050// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 01051// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 11052// LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL]], 01053// LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float %[[A_IMAG]], 11054// LLVM: store float %[[A_REAL]], ptr %[[B_ADDR]], align 41055 1056// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 41057// OGCG: %[[B_ADDR:.*]] = alloca float, align 41058// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 01059// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 41060// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 11061// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 41062// OGCG: store float %[[A_REAL]], ptr %[[B_ADDR]], align 41063 1064void imag_on_non_glvalue() {1065  float _Complex a;1066  float b = __imag__(+a);1067}1068 1069// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]1070// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]1071// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1072// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float1073// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float1074// CIR: %[[A_REAL_PLUS:.*]] = cir.unary(plus, %[[A_REAL]]) : !cir.float, !cir.float1075// CIR: %[[A_IMAG_PLUS:.*]] = cir.unary(plus, %[[A_IMAG]]) : !cir.float, !cir.float1076// CIR: %[[RESULT:.*]] = cir.complex.create %[[A_REAL_PLUS]], %[[A_IMAG_PLUS]] : !cir.float -> !cir.complex<!cir.float>1077// CIR: %[[RESULT_IMAG:.*]] = cir.complex.imag %[[RESULT]] : !cir.complex<!cir.float> -> !cir.float1078// CIR: cir.store{{.*}} %[[RESULT_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>1079 1080// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 41081// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 41082// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 41083// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 01084// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 11085// LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL]], 01086// LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float %[[A_IMAG]], 11087// LLVM: store float %[[A_IMAG]], ptr %[[B_ADDR]], align 41088 1089// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 41090// OGCG: %[[B_ADDR:.*]] = alloca float, align 41091// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 01092// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 41093// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 11094// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 41095// OGCG: store float %[[A_IMAG]], ptr %[[B_ADDR]], align 41096 1097void atomic_complex_type() {1098  _Atomic(float _Complex) a;1099  float _Complex b = __c11_atomic_load(&a, __ATOMIC_RELAXED);1100}1101 1102// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]1103// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]1104// CIR: %[[ATOMIC_TMP_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["atomic-temp"]1105// CIR: %[[A_PTR:.*]] = cir.cast bitcast %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i>1106// CIR: %[[ATOMIC_TMP_PTR:.*]] = cir.cast bitcast %[[ATOMIC_TMP_ADDR]] : !cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i>1107// CIR: %[[TMP_A_ATOMIC:.*]] = cir.load{{.*}} atomic(relaxed) %[[A_PTR]] : !cir.ptr<!u64i>, !u64i1108// CIR: cir.store{{.*}} %[[TMP_A_ATOMIC]], %[[ATOMIC_TMP_PTR]] : !u64i, !cir.ptr<!u64i>1109// CIR: %[[TMP_ATOMIC_PTR:.*]] = cir.cast bitcast %[[ATOMIC_TMP_PTR]] : !cir.ptr<!u64i> -> !cir.ptr<!cir.complex<!cir.float>>1110// CIR: %[[TMP_ATOMIC:.*]] = cir.load{{.*}} %[[TMP_ATOMIC_PTR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1111// CIR: cir.store{{.*}} %[[TMP_ATOMIC]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1112 1113// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 81114// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 41115// LLVM: %[[ATOMIC_TMP_ADDR:.*]] = alloca { float, float }, i64 1, align 81116// LLVM: %[[TMP_A_ATOMIC:.*]] = load atomic i64, ptr %[[A_ADDR]] monotonic, align 81117// LLVM: store i64 %[[TMP_A_ATOMIC]], ptr %[[ATOMIC_TMP_ADDR]], align 81118// LLVM: %[[TMP_ATOMIC:.*]] = load { float, float }, ptr %[[ATOMIC_TMP_ADDR]], align 81119// LLVM: store { float, float } %[[TMP_ATOMIC]], ptr %[[B_ADDR]], align 41120 1121// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 81122// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 41123// OGCG: %[[ATOMIC_TMP_ADDR:.*]] = alloca { float, float }, align 81124// OGCG: %[[TMP_A_ATOMIC:.*]] = load atomic i64, ptr %[[A_ADDR]] monotonic, align 81125// OGCG: store i64 %[[TMP_A_ATOMIC]], ptr %[[ATOMIC_TMP_ADDR]], align 81126// OGCG: %[[ATOMIC_TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 01127// OGCG: %[[ATOMIC_TMP_REAL:.*]] = load float, ptr %[[ATOMIC_TMP_REAL_PTR]], align 81128// OGCG: %[[ATOMIC_TMP_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 11129// OGCG: %[[ATOMIC_TMP_IMAG:.*]] = load float, ptr %[[ATOMIC_TMP_IMAG_PTR]], align 41130// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 01131// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 11132// OGCG: store float %[[ATOMIC_TMP_REAL]], ptr %[[B_REAL_PTR]], align 41133// OGCG: store float %[[ATOMIC_TMP_IMAG]], ptr %[[B_IMAG_PTR]], align 41134 1135void real_on_scalar_glvalue() {1136  float a;1137  float b = __real__ a;1138}1139 1140// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"]1141// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]1142// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float1143// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.float -> !cir.float1144// CIR: cir.store{{.*}} %[[A_REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>1145 1146// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 41147// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 41148// LLVM: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 41149// LLVM: store float %[[TMP_A]], ptr %[[B_ADDR]], align 41150 1151// OGCG: %[[A_ADDR:.*]] = alloca float, align 41152// OGCG: %[[B_ADDR:.*]] = alloca float, align 41153// OGCG: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 41154// OGCG: store float %[[TMP_A]], ptr %[[B_ADDR]], align 41155 1156void imag_on_scalar_glvalue() {1157  float a;1158  float b = __imag__ a;1159}1160 1161// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"]1162// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]1163// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float1164// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.float -> !cir.float1165// CIR: cir.store{{.*}} %[[A_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>1166 1167// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 41168// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 41169// LLVM: store float 0.000000e+00, ptr %[[B_ADDR]], align 41170 1171// OGCG: %[[A_ADDR:.*]] = alloca float, align 41172// OGCG: %[[B_ADDR:.*]] = alloca float, align 41173// OGCG: store float 0.000000e+00, ptr %[[B_ADDR]], align 41174 1175void real_on_scalar_with_type_promotion() {1176  _Float16 a;1177  _Float16 b = __real__ a;1178}1179 1180// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"]1181// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]1182// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f161183// CIR: %[[TMP_A_F32:.*]] = cir.cast floating %[[TMP_A]] : !cir.f16 -> !cir.float1184// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A_F32]] : !cir.float -> !cir.float1185// CIR: %[[TMP_A_F16:.*]] = cir.cast floating %[[A_REAL]] : !cir.float -> !cir.f161186// CIR: cir.store{{.*}} %[[TMP_A_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>1187 1188// LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 21189// LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 21190// LLVM: %[[TMP_A:.*]] = load half, ptr %[[A_ADDR]], align 21191// LLVM: %[[TMP_A_F32:.*]] = fpext half %[[TMP_A]] to float1192// LLVM: %[[TMP_A_F16:.*]] = fptrunc float %[[TMP_A_F32]] to half1193// LLVM: store half %[[TMP_A_F16]], ptr %[[B_ADDR]], align 21194 1195// OGCG: %[[A_ADDR:.*]] = alloca half, align 21196// OGCG: %[[B_ADDR:.*]] = alloca half, align 21197// OGCG: %[[TMP_A:.*]] = load half, ptr %[[A_ADDR]], align 21198// OGCG: %[[TMP_A_F32:.*]] = fpext half %[[TMP_A]] to float1199// OGCG: %[[TMP_A_F16:.*]] = fptrunc float %[[TMP_A_F32]] to half1200// OGCG: store half %[[TMP_A_F16]], ptr %[[B_ADDR]], align 21201 1202void imag_on_scalar_with_type_promotion() {1203  _Float16 a;1204  _Float16 b = __imag__ a;1205}1206 1207// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"]1208// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]1209// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f161210// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.f16 -> !cir.f161211// CIR: %[[A_IMAG_F16:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.f161212// CIR: cir.store{{.*}} %[[A_IMAG_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>1213 1214// LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 21215// LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 21216// LLVM: store half 0xH0000, ptr %[[B_ADDR]], align 21217 1218// OGCG: %[[A_ADDR:.*]] = alloca half, align 21219// OGCG: %[[B_ADDR:.*]] = alloca half, align 21220// OGCG: store half 0xH0000, ptr %[[B_ADDR]], align 21221 1222void imag_on_const_scalar() {1223  float a;1224  float b = __imag__ 1.0f;1225}1226 1227// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"]1228// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]1229// CIR: %[[CONST_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float1230// CIR: %[[CONST_IMAG:.*]] = cir.complex.imag %[[CONST_ONE]] : !cir.float -> !cir.float1231// CIR: cir.store{{.*}} %[[CONST_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>1232 1233// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 41234// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 41235// LLVM: store float 0.000000e+00, ptr %[[B_ADDR]], align 41236 1237// OGCG: %[[A_ADDR:.*]] = alloca float, align 41238// OGCG: %[[B_ADDR:.*]] = alloca float, align 41239// OGCG: store float 0.000000e+00, ptr %[[B_ADDR]], align 41240 1241void real_on_scalar_from_real_with_type_promotion() {1242  _Float16 _Complex a;1243  _Float16 b = __real__(__real__ a);1244}1245 1246// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.f16>, !cir.ptr<!cir.complex<!cir.f16>>, ["a"]1247// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]1248// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.f16>>, !cir.complex<!cir.f16>1249// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f161250// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f161251// CIR: %[[A_REAL_F32:.*]] = cir.cast floating %[[A_REAL]] : !cir.f16 -> !cir.float1252// CIR: %[[A_IMAG_F32:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.float1253// CIR: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], %[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>1254// CIR: %[[A_REAL_F32:.*]] = cir.complex.real %[[A_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float1255// CIR: %[[A_REAL:.*]] = cir.complex.real %[[A_REAL_F32]] : !cir.float -> !cir.float1256// CIR: %[[A_REAL_F16:.*]] = cir.cast floating %[[A_REAL]] : !cir.float -> !cir.f161257// CIR: cir.store{{.*}} %[[A_REAL_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>1258 1259// LLVM: %[[A_ADDR:.*]] = alloca { half, half }, i64 1, align 21260// LLVM: %[[B_ADDR]] = alloca half, i64 1, align 21261// LLVM: %[[TMP_A:.*]] = load { half, half }, ptr %[[A_ADDR]], align 21262// LLVM: %[[A_REAL:.*]] = extractvalue { half, half } %[[TMP_A]], 01263// LLVM: %[[A_IMAG:.*]] = extractvalue { half, half } %[[TMP_A]], 11264// LLVM: %[[A_REAL_F32:.*]] = fpext half %[[A_REAL]] to float1265// LLVM: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float1266// LLVM: %[[TMP_A_COMPLEX_F32:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL_F32]], 01267// LLVM: %[[A_COMPLEX_F32:.*]] = insertvalue { float, float } %[[TMP_A_COMPLEX_F32]], float %[[A_IMAG_F32]], 11268// LLVM: %[[A_REAL_F16:.*]] = fptrunc float %[[A_REAL_F32]] to half1269// LLVM: store half %[[A_REAL_F16]], ptr %[[B_ADDR]], align 21270 1271// OGCG: %[[A_ADDR:.*]] = alloca { half, half }, align 21272// OGCG: %[[B_ADDR:.*]] = alloca half, align 21273// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { half, half }, ptr %[[A_ADDR]], i32 0, i32 01274// OGCG: %[[A_REAL:.*]] = load half, ptr %[[A_REAL_PTR]], align 21275// OGCG: %[[A_REAL_F32:.*]] = fpext half %[[A_REAL]] to float1276// OGCG: %[[A_REAL_F16:.*]] = fptrunc float %[[A_REAL_F32]] to half1277// OGCG: store half %[[A_REAL_F16]], ptr %[[B_ADDR]], align 21278 1279void real_on_scalar_from_imag_with_type_promotion() {1280  _Float16 _Complex a;1281  _Float16 b = __real__(__imag__ a);1282}1283 1284// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.f16>, !cir.ptr<!cir.complex<!cir.f16>>, ["a"]1285// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]1286// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.f16>>, !cir.complex<!cir.f16>1287// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f161288// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.f16> -> !cir.f161289// CIR: %[[A_REAL_F32:.*]] = cir.cast floating %[[A_REAL]] : !cir.f16 -> !cir.float1290// CIR: %[[A_IMAG_F32:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.float1291// CIR: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], %[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>1292// CIR: %[[A_IMAG_F32:.*]] = cir.complex.imag %[[A_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float1293// CIR: %[[A_REAL_F32:.*]] = cir.complex.real %[[A_IMAG_F32]] : !cir.float -> !cir.float1294// CIR: %[[A_REAL_F16:.*]] = cir.cast floating %[[A_REAL_F32]] : !cir.float -> !cir.f161295// CIR: cir.store{{.*}} %[[A_REAL_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>1296 1297// LLVM: %[[A_ADDR:.*]] = alloca { half, half }, i64 1, align 21298// LLVM: %[[B_ADDR]] = alloca half, i64 1, align 21299// LLVM: %[[TMP_A:.*]] = load { half, half }, ptr %[[A_ADDR]], align 21300// LLVM: %[[A_REAL:.*]] = extractvalue { half, half } %[[TMP_A]], 01301// LLVM: %[[A_IMAG:.*]] = extractvalue { half, half } %[[TMP_A]], 11302// LLVM: %[[A_REAL_F32:.*]] = fpext half %[[A_REAL]] to float1303// LLVM: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float1304// LLVM: %[[TMP_A_COMPLEX_F32:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL_F32]], 01305// LLVM: %[[A_COMPLEX_F32:.*]] = insertvalue { float, float } %[[TMP_A_COMPLEX_F32]], float %[[A_IMAG_F32]], 11306// LLVM: %[[A_IMAG_F16:.*]] = fptrunc float %[[A_IMAG_F32]] to half1307// LLVM: store half %[[A_IMAG_F16]], ptr %[[B_ADDR]], align 21308 1309// OGCG: %[[A_ADDR:.*]] = alloca { half, half }, align 21310// OGCG: %[[B_ADDR:.*]] = alloca half, align 21311// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { half, half }, ptr %[[A_ADDR]], i32 0, i32 11312// OGCG: %[[A_IMAG:.*]] = load half, ptr %[[A_IMAG_PTR]], align 21313// OGCG: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float1314// OGCG: %[[A_IMAG_F16:.*]] = fptrunc float %[[A_IMAG_F32]] to half1315// OGCG: store half %[[A_IMAG_F16]], ptr %[[B_ADDR]], align 21316 1317void complex_type_parameter(float _Complex a) {}1318 1319// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]1320// CIR: cir.store %{{.*}}, %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1321 1322// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,1323// Test will be updated when that is implemented1324 1325// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 41326// LLVM: store { float, float } %{{.*}}, ptr %[[A_ADDR]], align 41327 1328// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 41329// OGCG: store <2 x float> %a.coerce, ptr %[[A_ADDR]], align 41330 1331void complex_type_argument() {1332  float _Complex a;1333  complex_type_parameter(a);1334}1335 1336// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]1337// CIR: %[[ARG_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["coerce"]1338// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1339// CIR: cir.store{{.*}} %[[TMP_A]], %[[ARG_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1340// CIR: %[[TMP_ARG:.*]] = cir.load{{.*}} %[[ARG_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1341// CIR: cir.call @_Z22complex_type_parameterCf(%[[TMP_ARG]]) : (!cir.complex<!cir.float>) -> ()1342 1343// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 41344// LLVM: %[[ARG_ADDR:.*]] = alloca { float, float }, i64 1, align 41345// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 41346// LLVM: store { float, float } %[[TMP_A]], ptr %[[ARG_ADDR]], align 41347// LLVM: %[[TMP_ARG:.*]] = load { float, float }, ptr %[[ARG_ADDR]], align 41348// LLVM: call void @_Z22complex_type_parameterCf({ float, float } %[[TMP_ARG]])1349 1350// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 41351// OGCG: %[[ARG_ADDR:.*]] = alloca { float, float }, align 41352// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 01353// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 41354// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 11355// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 41356// OGCG: %[[ARG_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 01357// OGCG: %[[ARG_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 11358// OGCG: store float %[[A_REAL]], ptr %[[ARG_REAL_PTR]], align 41359// OGCG: store float %[[A_IMAG]], ptr %[[ARG_IMAG_PTR]], align 41360// OGCG: %[[TMP_ARG:.*]] = load <2 x float>, ptr %[[ARG_ADDR]], align 41361// OGCG: call void @_Z22complex_type_parameterCf(<2 x float> noundef %[[TMP_ARG]])1362 1363float _Complex complex_type_return_type() {1364  return { 1.0f, 2.0f };1365}1366 1367// CIR: %[[RET_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["__retval"]1368// CIR: %[[RET_VAL:.*]] = cir.const #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float, #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>1369// CIR: cir.store{{.*}} %[[RET_VAL]], %[[RET_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1370// CIR: %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1371// CIR: cir.return %[[TMP_RET]] : !cir.complex<!cir.float>1372 1373// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,1374// LLVM: %[[RET_ADDR:.*]] = alloca { float, float }, i64 1, align 41375// LLVM: store { float, float } { float 1.000000e+00, float 2.000000e+00 }, ptr %[[RET_ADDR]], align 41376// LLVM: %[[TMP_RET:.*]] = load { float, float }, ptr %[[RET_ADDR]], align 41377// LLVM: ret { float, float } %[[TMP_RET]]1378 1379// OGCG: %[[RET_ADDR:.*]] = alloca { float, float }, align 41380// OGCG: %[[RET_VAL_REAL:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RET_ADDR]], i32 0, i32 01381// OGCG: %[[RET_VAL_IMAG:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RET_ADDR]], i32 0, i32 11382// OGCG: store float 1.000000e+00, ptr %[[RET_VAL_REAL]], align 41383// OGCG: store float 2.000000e+00, ptr %[[RET_VAL_IMAG]], align 41384// OGCG: %[[TMP_RET:.*]] = load <2 x float>, ptr %[[RET_ADDR]], align 41385// OGCG: ret <2 x float> %[[TMP_RET]]1386 1387void real_on_scalar_bool() {1388  bool a;1389  bool b = __real__ a;1390}1391 1392// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["a"]1393// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["b", init]1394// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.bool>, !cir.bool1395// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.bool -> !cir.bool1396// CIR: cir.store{{.*}} %[[A_REAL]], %[[B_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>1397 1398// LLVM: %[[A_ADDR:.*]] = alloca i8, i64 1, align 11399// LLVM: %[[B_ADDR:.*]] = alloca i8, i64 1, align 11400// LLVM: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 11401// LLVM: %[[TMP_A_I1:.*]] = trunc i8 %[[TMP_A]] to i11402// LLVM: %[[TMP_A_I8:.*]] = zext i1 %[[TMP_A_I1]] to i81403// LLVM: store i8 %[[TMP_A_I8]], ptr %[[B_ADDR]], align 11404 1405// OGCG: %[[A_ADDR:.*]] = alloca i8, align 11406// OGCG: %[[B_ADDR:.*]] = alloca i8, align 11407// OGCG: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 11408// OGCG: %[[TMP_A_I1:.*]] = trunc i8 %[[TMP_A]] to i11409// OGCG: %[[TMP_A_I8:.*]] = zext i1 %[[TMP_A_I1]] to i81410// OGCG: store i8 %[[TMP_A_I8]], ptr %[[B_ADDR]], align 11411 1412void imag_on_scalar_bool() {1413  bool a;1414  bool b = __imag__ a;1415}1416 1417// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["a"]1418// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["b", init]1419// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.bool>, !cir.bool1420// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.bool -> !cir.bool1421// CIR: cir.store{{.*}} %[[A_IMAG]], %[[B_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>1422 1423// LLVM: %[[A_ADDR:.*]] = alloca i8, i64 1, align 11424// LLVM: %[[B_ADDR:.*]] = alloca i8, i64 1, align 11425// LLVM: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 11426// LLVM: %[[TMP_A_I1:.*]] = trunc i8 %[[TMP_A]] to i11427// LLVM: store i8 0, ptr %[[B_ADDR]], align 11428 1429// OGCG: %[[A_ADDR:.*]] = alloca i8, align 11430// OGCG: %[[B_ADDR:.*]] = alloca i8, align 11431// OGCG: store i8 0, ptr %[[B_ADDR]], align 11432 1433void function_with_complex_default_arg(1434    float _Complex a = __builtin_complex(1.0f, 2.2f)) {}1435 1436// CIR: %[[ARG_0_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]1437// CIR: cir.store %{{.*}}, %[[ARG_0_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1438 1439// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,1440 1441// LLVM: %[[ARG_0_ADDR:.*]] = alloca { float, float }, i64 1, align 41442// LLVM: store { float, float } %{{.*}}, ptr %[[ARG_0_ADDR]], align 41443 1444// OGCG: %[[ARG_0_ADDR:.*]] = alloca { float, float }, align 41445// OGCG: store <2 x float> %{{.*}}, ptr %[[ARG_0_ADDR]], align 41446 1447void calling_function_with_default_arg() {1448  function_with_complex_default_arg();1449}1450 1451// CIR: %[[DEFAULT_ARG_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["coerce"]1452// CIR: %[[DEFAULT_ARG_VAL:.*]] = cir.const #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float, #cir.fp<2.200000e+00> : !cir.float> : !cir.complex<!cir.float>1453// CIR: cir.store{{.*}} %[[DEFAULT_ARG_VAL]], %[[DEFAULT_ARG_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1454// CIR: %[[TMP_DEFAULT_ARG:.*]] = cir.load{{.*}} %[[DEFAULT_ARG_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>1455// CIR: cir.call @_Z33function_with_complex_default_argCf(%[[TMP_DEFAULT_ARG]]) : (!cir.complex<!cir.float>) -> ()1456 1457// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,1458 1459// LLVM: %[[DEFAULT_ARG_ADDR:.*]] = alloca { float, float }, i64 1, align 41460// LLVM: store { float, float } { float 1.000000e+00, float 0x40019999A0000000 }, ptr %[[DEFAULT_ARG_ADDR]], align 41461// LLVM: %[[TMP_DEFAULT_ARG:.*]] = load { float, float }, ptr %[[DEFAULT_ARG_ADDR]], align 41462// LLVM: call void @_Z33function_with_complex_default_argCf({ float, float } %[[TMP_DEFAULT_ARG]])1463 1464// OGCG: %[[DEFAULT_ARG_ADDR:.*]] = alloca { float, float }, align 41465// OGCG: %[[DEFAULT_ARG_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[DEFAULT_ARG_ADDR]], i32 0, i32 01466// OGCG: %[[DEFAULT_ARG_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[DEFAULT_ARG_ADDR]], i32 0, i32 11467// OGCG: store float 1.000000e+00, ptr %[[DEFAULT_ARG_REAL_PTR]], align 41468// OGCG: store float 0x40019999A0000000, ptr %[[DEFAULT_ARG_IMAG_PTR]], align 41469// OGCG: %[[TMP_DEFAULT_ARG:.*]] = load <2 x float>, ptr %[[DEFAULT_ARG_ADDR]], align 41470// OGCG: call void @_Z33function_with_complex_default_argCf(<2 x float> {{.*}} %[[TMP_DEFAULT_ARG]])1471 1472void calling_function_that_return_complex() {1473  float _Complex a = complex_type_return_type();1474}1475 1476// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]1477// CIR: %[[RESULT:.*]] = cir.call @_Z24complex_type_return_typev() : () -> !cir.complex<!cir.float>1478// CIR: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1479 1480// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,1481 1482// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 41483// LLVM: %[[RESULT:.*]] = call { float, float } @_Z24complex_type_return_typev()1484// LLVM: store { float, float } %[[RESULT]], ptr %[[A_ADDR]], align 41485 1486// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 41487// OGCG: %[[RESULT_ADDR:.*]] = alloca { float, float }, align 41488// OGCG: %[[RESULT:.*]] = call noundef <2 x float> @_Z24complex_type_return_typev()1489// OGCG: store <2 x float> %[[RESULT]], ptr %[[RESULT_ADDR]], align 41490// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT_ADDR]], i32 0, i32 01491// OGCG: %[[RESULT_REAL:.*]] = load float, ptr %[[RESULT_REAL_PTR]], align 41492// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT_ADDR]], i32 0, i32 11493// OGCG: %[[RESULT_IMAG:.*]] = load float, ptr %[[RESULT_IMAG_PTR]], align 41494// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 01495// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 11496// OGCG: store float %[[RESULT_REAL]], ptr %[[A_REAL_PTR]], align 41497// OGCG: store float %[[RESULT_IMAG]], ptr %[[A_IMAG_PTR]], align 41498 1499void imag_literal_gnu_extension() {1500  float _Complex a = 3.0fi;1501  double _Complex b = 3.0i;1502  int _Complex c = 3i;1503}1504 1505// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]1506// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["b", init]1507// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]1508// CIR: %[[COMPLEX_A:.*]] = cir.const #cir.const_complex<#cir.fp<0.000000e+00> : !cir.float, #cir.fp<3.000000e+00> : !cir.float> : !cir.complex<!cir.float>1509// CIR: cir.store{{.*}} %[[COMPLEX_A]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>1510// CIR: %[[COMPLEX_B:.*]] = cir.const #cir.const_complex<#cir.fp<0.000000e+00> : !cir.double, #cir.fp<3.000000e+00> : !cir.double> : !cir.complex<!cir.double>1511// CIR: cir.store{{.*}} %[[COMPLEX_B]], %[[B_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>1512// CIR: %[[COMPLEX_C:.*]] = cir.const #cir.const_complex<#cir.int<0> : !s32i, #cir.int<3> : !s32i> : !cir.complex<!s32i>1513// CIR: cir.store{{.*}} %[[COMPLEX_C]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>1514 1515// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 41516// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 81517// LLVM: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 41518// LLVM: store { float, float } { float 0.000000e+00, float 3.000000e+00 }, ptr %[[A_ADDR]], align 41519// LLVM: store { double, double } { double 0.000000e+00, double 3.000000e+00 }, ptr %[[B_ADDR]], align 81520// LLVM: store { i32, i32 } { i32 0, i32 3 }, ptr %[[C_ADDR]], align 41521 1522// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 41523// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 81524// OGCG: %[[C_ADDR:.*]] = alloca { i32, i32 }, align 41525// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 01526// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 11527// OGCG: store float 0.000000e+00, ptr %[[A_REAL_PTR]], align 41528// OGCG: store float 3.000000e+00, ptr %[[A_IMAG_PTR]], align 41529// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 01530// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 11531// OGCG: store double 0.000000e+00, ptr %[[B_REAL_PTR]], align 81532// OGCG: store double 3.000000e+00, ptr %[[B_IMAG_PTR]], align 81533// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 01534// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 11535// OGCG: store i32 0, ptr %[[C_REAL_PTR]], align 41536// OGCG: store i32 3, ptr %[[C_IMAG_PTR]], align 41537 1538void load_store_volatile() {1539  volatile double _Complex a;1540  volatile double _Complex b;1541  a = b;1542 1543  volatile int _Complex c;1544  volatile int _Complex d;1545  c = d;1546}1547 1548// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["a"]1549// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["b"]1550// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c"]1551// CIR: %[[D_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["d"]1552// CIR: %[[TMP_B:.*]] = cir.load volatile {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>1553// CIR: cir.store volatile {{.*}} %[[TMP_B]], %[[A_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>1554// CIR: %[[TMP_D:.*]] = cir.load volatile {{.*}} %[[D_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>1555// CIR: cir.store volatile {{.*}} %[[TMP_D]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>1556 1557// LLVM: %[[A_ADDR:.*]] = alloca { double, double }, i64 1, align 81558// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 81559// LLVM: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 41560// LLVM: %[[D_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 41561// LLVM: %[[TMP_B:.*]] = load volatile { double, double }, ptr %[[B_ADDR]], align 81562// LLVM: store volatile { double, double } %[[TMP_B]], ptr %[[A_ADDR]], align 81563// LLVM: %[[TMP_D:.*]] = load volatile { i32, i32 }, ptr %[[D_ADDR]], align 41564// LLVM: store volatile { i32, i32 } %[[TMP_D]], ptr %[[C_ADDR]], align 41565 1566// OGCG: %[[A_ADDR:.*]] = alloca { double, double }, align 81567// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 81568// OGCG: %[[C_ADDR:.*]] = alloca { i32, i32 }, align 41569// OGCG: %[[D_ADDR:.*]] = alloca { i32, i32 }, align 41570// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 01571// OGCG: %[[B_REAL:.*]] = load volatile double, ptr %[[B_REAL_PTR]], align 81572// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 11573// OGCG: %[[B_IMAG:.*]] = load volatile double, ptr %[[B_IMAG_PTR]], align 81574// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 01575// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 11576// OGCG: store volatile double %[[B_REAL]], ptr %[[A_REAL_PTR]], align 81577// OGCG: store volatile double %[[B_IMAG]], ptr %[[A_IMAG_PTR]], align 81578// OGCG: %[[D_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 01579// OGCG: %[[D_REAL:.*]] = load volatile i32, ptr %[[D_REAL_PTR]], align 41580// OGCG: %[[D_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 11581// OGCG: %[[D_IMAG:.*]] = load volatile i32, ptr %[[D_IMAG_PTR]], align 41582// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 01583// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 11584// OGCG: store volatile i32 %[[D_REAL]], ptr %[[C_REAL_PTR]], align 41585// OGCG: store volatile i32 %[[D_IMAG]], ptr %[[C_IMAG_PTR]], align 41586 1587 1588void load_store_volatile_2() {1589  volatile double _Complex av;1590  double _Complex a;1591  av = a;1592 1593  double _Complex b;1594  volatile double _Complex bv;1595  b = bv;1596 1597  int _Complex c;1598  volatile int _Complex cv;1599  c = cv;1600 1601  volatile int _Complex dv;1602  int _Complex d;1603  dv = d;1604}1605 1606// CIR: %[[AV_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["av"]1607// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["a"]1608// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["b"]1609// CIR: %[[BV_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["bv"]1610// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c"]1611// CIR: %[[CV_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["cv"]1612// CIR: %[[DV_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["dv"]1613// CIR: %[[D_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["d"]1614// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>1615// CIR: cir.store volatile {{.*}} %[[TMP_A]], %[[AV_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>1616// CIR: %[[TMP_BV:.*]] = cir.load volatile {{.*}} %[[BV_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>1617// CIR: cir.store {{.*}} %[[TMP_BV]], %[[B_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>1618// CIR: %[[TMP_CV:.*]] = cir.load volatile {{.*}} %[[CV_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>1619// CIR: cir.store {{.*}} %[[TMP_CV]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>1620// CIR: %[[TMP_D:.*]] = cir.load {{.*}} %[[D_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>1621// CIR: cir.store volatile {{.*}} %[[TMP_D]], %[[DV_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>1622 1623// LLVM: %[[AV_ADDR:.*]] = alloca { double, double }, i64 1, align 81624// LLVM: %[[A_ADDR:.*]] = alloca { double, double }, i64 1, align 81625// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 81626// LLVM: %[[BV_ADDR:.*]] = alloca { double, double }, i64 1, align 81627// LLVM: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 41628// LLVM: %[[CV_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 41629// LLVM: %[[DV_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 41630// LLVM: %[[D_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 41631// LLVM: %[[TMP_A:.*]] = load { double, double }, ptr %[[A_ADDR]], align 81632// LLVM: store volatile { double, double } %[[TMP_A]], ptr %[[AV_ADDR]], align 81633// LLVM: %[[TMP_BV:.*]] = load volatile { double, double }, ptr %[[BV_ADDR]], align 81634// LLVM: store { double, double } %[[TMP_BV]], ptr %[[B_ADDR]], align 81635// LLVM: %[[TMP_CV:.*]] = load volatile { i32, i32 }, ptr %[[CV_ADDR]], align 41636// LLVM: store { i32, i32 } %[[TMP_CV]], ptr %[[C_ADDR]], align 41637// LLVM: %[[TMP_D:.*]] = load { i32, i32 }, ptr %[[D_ADDR]], align 41638// LLVM: store volatile { i32, i32 } %[[TMP_D]], ptr %[[DV_ADDR]], align 41639 1640// OGCG: %[[AV_ADDR:.*]] = alloca { double, double }, align 81641// OGCG: %[[A_ADDR:.*]] = alloca { double, double }, align 81642// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 81643// OGCG: %[[BV_ADDR:.*]] = alloca { double, double }, align 81644// OGCG: %[[C_ADDR:.*]] = alloca { i32, i32 }, align 41645// OGCG: %[[CV_ADDR:.*]] = alloca { i32, i32 }, align 41646// OGCG: %[[DV_ADDR:.*]] = alloca { i32, i32 }, align 41647// OGCG: %[[D_ADDR:.*]] = alloca { i32, i32 }, align 41648// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 01649// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 81650// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 11651// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 81652// OGCG: %[[AV_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[AV_ADDR]], i32 0, i32 01653// OGCG: %[[AV_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[AV_ADDR]], i32 0, i32 11654// OGCG: store volatile double %[[A_REAL]], ptr %[[AV_REAL_PTR]], align 81655// OGCG: store volatile double %[[A_IMAG]], ptr %[[AV_IMAG_PTR]], align 81656// OGCG: %[[BV_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[BV_ADDR]], i32 0, i32 01657// OGCG: %[[BV_REAL:.*]] = load volatile double, ptr %[[BV_REAL_PTR]], align 81658// OGCG: %[[BV_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[BV_ADDR]], i32 0, i32 11659// OGCG: %[[BV_IMAG:.*]] = load volatile double, ptr %[[BV_IMAG_PTR]], align 81660// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 01661// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 11662// OGCG: store double %[[BV_REAL]], ptr %[[B_REAL_PTR]], align 81663// OGCG: store double %[[BV_IMAG]], ptr %[[B_IMAG_PTR]], align 81664// OGCG: %[[CV_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CV_ADDR]], i32 0, i32 01665// OGCG: %[[CV_REAL:.*]] = load volatile i32, ptr %[[CV_REAL_PTR]], align 41666// OGCG: %[[CV_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CV_ADDR]], i32 0, i32 11667// OGCG: %[[CV_IMAG:.*]] = load volatile i32, ptr %[[CV_IMAG_PTR]], align 41668// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 01669// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 11670// OGCG: store i32 %[[CV_REAL]], ptr %[[C_REAL_PTR]], align 41671// OGCG: store i32 %[[CV_IMAG]], ptr %[[C_IMAG_PTR]], align 41672// OGCG: %[[D_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 01673// OGCG: %[[D_REAL:.*]] = load i32, ptr %[[D_REAL_PTR]], align 41674// OGCG: %[[D_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 11675// OGCG: %[[D_IMAG:.*]] = load i32, ptr %[[D_IMAG_PTR]], align 41676// OGCG: %[[DV_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[DV_ADDR]], i32 0, i32 01677// OGCG: %[[DV_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[DV_ADDR]], i32 0, i32 11678// OGCG: store volatile i32 %[[D_REAL]], ptr %[[DV_REAL_PTR]], align 41679// OGCG: store volatile i32 %[[D_IMAG]], ptr %[[DV_IMAG_PTR]], align 41680