// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 // RUN: %clang_cc1 %s -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s // CHECK-LABEL: define dso_local i32 @main( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[A:%.*]] = alloca { double, double }, align 8 // CHECK-NEXT: [[B:%.*]] = alloca { double, double }, align 8 // CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 // CHECK-NEXT: store double 5.000000e+00, ptr [[A_REALP]], align 8 // CHECK-NEXT: store double 0.000000e+00, ptr [[A_IMAGP]], align 8 // CHECK-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // CHECK-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 // CHECK-NEXT: store double 4.200000e+01, ptr [[B_REALP]], align 8 // CHECK-NEXT: store double 0.000000e+00, ptr [[B_IMAGP]], align 8 // CHECK-NEXT: [[A_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP1]], align 8 // CHECK-NEXT: [[A_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 // CHECK-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP2]], align 8 // CHECK-NEXT: [[B_REALP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // CHECK-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP3]], align 8 // CHECK-NEXT: [[B_IMAGP4:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 // CHECK-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP4]], align 8 // CHECK-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] // CHECK-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] // CHECK-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] // CHECK-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] // CHECK-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] // CHECK-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] // CHECK-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno double [[MUL_R]], [[MUL_R]] // CHECK-NEXT: br i1 [[ISNAN_CMP]], label %[[COMPLEX_MUL_IMAG_NAN:.*]], label %[[COMPLEX_MUL_CONT:.*]], !prof [[PROF2:![0-9]+]] // CHECK: [[COMPLEX_MUL_IMAG_NAN]]: // CHECK-NEXT: [[ISNAN_CMP5:%.*]] = fcmp uno double [[MUL_I]], [[MUL_I]] // CHECK-NEXT: br i1 [[ISNAN_CMP5]], label %[[COMPLEX_MUL_LIBCALL:.*]], label %[[COMPLEX_MUL_CONT]], !prof [[PROF2]] // CHECK: [[COMPLEX_MUL_LIBCALL]]: // CHECK-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef [[A_REAL]], double noundef [[A_IMAG]], double noundef [[B_REAL]], double noundef [[B_IMAG]]) #[[ATTR4:[0-9]+]] // CHECK-NEXT: [[TMP0:%.*]] = extractvalue { double, double } [[CALL]], 0 // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { double, double } [[CALL]], 1 // CHECK-NEXT: br label %[[COMPLEX_MUL_CONT]] // CHECK: [[COMPLEX_MUL_CONT]]: // CHECK-NEXT: [[REAL_MUL_PHI:%.*]] = phi double [ [[MUL_R]], %[[ENTRY]] ], [ [[MUL_R]], %[[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP0]], %[[COMPLEX_MUL_LIBCALL]] ] // CHECK-NEXT: [[IMAG_MUL_PHI:%.*]] = phi double [ [[MUL_I]], %[[ENTRY]] ], [ [[MUL_I]], %[[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP1]], %[[COMPLEX_MUL_LIBCALL]] ] // CHECK-NEXT: [[B_REALP6:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // CHECK-NEXT: [[B_REAL7:%.*]] = load double, ptr [[B_REALP6]], align 8 // CHECK-NEXT: [[B_IMAGP8:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 // CHECK-NEXT: [[B_IMAG9:%.*]] = load double, ptr [[B_IMAGP8]], align 8 // CHECK-NEXT: [[A_REALP10:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[A_REAL11:%.*]] = load double, ptr [[A_REALP10]], align 8 // CHECK-NEXT: [[A_IMAGP12:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 // CHECK-NEXT: [[A_IMAG13:%.*]] = load double, ptr [[A_IMAGP12]], align 8 // CHECK-NEXT: [[MUL_AC14:%.*]] = fmul double [[B_REAL7]], [[A_REAL11]] // CHECK-NEXT: [[MUL_BD15:%.*]] = fmul double [[B_IMAG9]], [[A_IMAG13]] // CHECK-NEXT: [[MUL_AD16:%.*]] = fmul double [[B_REAL7]], [[A_IMAG13]] // CHECK-NEXT: [[MUL_BC17:%.*]] = fmul double [[B_IMAG9]], [[A_REAL11]] // CHECK-NEXT: [[MUL_R18:%.*]] = fsub double [[MUL_AC14]], [[MUL_BD15]] // CHECK-NEXT: [[MUL_I19:%.*]] = fadd double [[MUL_AD16]], [[MUL_BC17]] // CHECK-NEXT: [[ISNAN_CMP20:%.*]] = fcmp uno double [[MUL_R18]], [[MUL_R18]] // CHECK-NEXT: br i1 [[ISNAN_CMP20]], label %[[COMPLEX_MUL_IMAG_NAN21:.*]], label %[[COMPLEX_MUL_CONT25:.*]], !prof [[PROF2]] // CHECK: [[COMPLEX_MUL_IMAG_NAN21]]: // CHECK-NEXT: [[ISNAN_CMP22:%.*]] = fcmp uno double [[MUL_I19]], [[MUL_I19]] // CHECK-NEXT: br i1 [[ISNAN_CMP22]], label %[[COMPLEX_MUL_LIBCALL23:.*]], label %[[COMPLEX_MUL_CONT25]], !prof [[PROF2]] // CHECK: [[COMPLEX_MUL_LIBCALL23]]: // CHECK-NEXT: [[CALL24:%.*]] = call { double, double } @__muldc3(double noundef [[B_REAL7]], double noundef [[B_IMAG9]], double noundef [[A_REAL11]], double noundef [[A_IMAG13]]) #[[ATTR4]] // CHECK-NEXT: [[TMP2:%.*]] = extractvalue { double, double } [[CALL24]], 0 // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { double, double } [[CALL24]], 1 // CHECK-NEXT: br label %[[COMPLEX_MUL_CONT25]] // CHECK: [[COMPLEX_MUL_CONT25]]: // CHECK-NEXT: [[REAL_MUL_PHI26:%.*]] = phi double [ [[MUL_R18]], %[[COMPLEX_MUL_CONT]] ], [ [[MUL_R18]], %[[COMPLEX_MUL_IMAG_NAN21]] ], [ [[TMP2]], %[[COMPLEX_MUL_LIBCALL23]] ] // CHECK-NEXT: [[IMAG_MUL_PHI27:%.*]] = phi double [ [[MUL_I19]], %[[COMPLEX_MUL_CONT]] ], [ [[MUL_I19]], %[[COMPLEX_MUL_IMAG_NAN21]] ], [ [[TMP3]], %[[COMPLEX_MUL_LIBCALL23]] ] // CHECK-NEXT: [[CMP_R:%.*]] = fcmp une double [[REAL_MUL_PHI]], [[REAL_MUL_PHI26]] // CHECK-NEXT: [[CMP_I:%.*]] = fcmp une double [[IMAG_MUL_PHI]], [[IMAG_MUL_PHI27]] // CHECK-NEXT: [[OR_RI:%.*]] = or i1 [[CMP_R]], [[CMP_I]] // CHECK-NEXT: [[CONV:%.*]] = zext i1 [[OR_RI]] to i32 // CHECK-NEXT: ret i32 [[CONV]] // int main(void) { double _Complex a = 5; double _Complex b = 42; return a * b != b * a; } _Complex double bar(int); void test(_Complex double*); void takecomplex(_Complex double); // CHECK-LABEL: define dso_local void @test2( // CHECK-SAME: i32 noundef [[C:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[C_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[X:%.*]] = alloca { double, double }, align 8 // CHECK-NEXT: [[COERCE:%.*]] = alloca { double, double }, align 8 // CHECK-NEXT: store i32 [[C]], ptr [[C_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call { double, double } @bar(i32 noundef 1) // CHECK-NEXT: [[TMP0:%.*]] = extractvalue { double, double } [[CALL]], 0 // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { double, double } [[CALL]], 1 // CHECK-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 // CHECK-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 // CHECK-NEXT: store double [[TMP0]], ptr [[X_REALP]], align 8 // CHECK-NEXT: store double [[TMP1]], ptr [[X_IMAGP]], align 8 // CHECK-NEXT: call void @test(ptr noundef [[X]]) // CHECK-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 // CHECK-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8 // CHECK-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 // CHECK-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8 // CHECK-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0 // CHECK-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 // CHECK-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8 // CHECK-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8 // CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0 // CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[TMP2]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 // CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[TMP4]], align 8 // CHECK-NEXT: call void @takecomplex(double noundef [[TMP3]], double noundef [[TMP5]]) // CHECK-NEXT: ret void // void test2(int c) { _Complex double X; X = bar(1); test(&X); takecomplex(X); } _Complex double g1, g2; _Complex float cf; double D; // CHECK-LABEL: define dso_local void @test3( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[GR:%.*]] = alloca double, align 8 // CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G2_REAL:%.*]] = load double, ptr @g2, align 8 // CHECK-NEXT: [[G2_IMAG:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g2, i32 0, i32 1), align 8 // CHECK-NEXT: [[ADD_R:%.*]] = fadd double [[G1_REAL]], [[G2_REAL]] // CHECK-NEXT: [[ADD_I:%.*]] = fadd double [[G1_IMAG]], [[G2_IMAG]] // CHECK-NEXT: store double [[ADD_R]], ptr @g1, align 8 // CHECK-NEXT: store double [[ADD_I]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G1_REAL1:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG2:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G2_REAL3:%.*]] = load double, ptr @g2, align 8 // CHECK-NEXT: [[G2_IMAG4:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g2, i32 0, i32 1), align 8 // CHECK-NEXT: [[SUB_R:%.*]] = fsub double [[G1_REAL1]], [[G2_REAL3]] // CHECK-NEXT: [[SUB_I:%.*]] = fsub double [[G1_IMAG2]], [[G2_IMAG4]] // CHECK-NEXT: store double [[SUB_R]], ptr @g1, align 8 // CHECK-NEXT: store double [[SUB_I]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G1_REAL5:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG6:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G2_REAL7:%.*]] = load double, ptr @g2, align 8 // CHECK-NEXT: [[G2_IMAG8:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g2, i32 0, i32 1), align 8 // CHECK-NEXT: [[MUL_AC:%.*]] = fmul double [[G1_REAL5]], [[G2_REAL7]] // CHECK-NEXT: [[MUL_BD:%.*]] = fmul double [[G1_IMAG6]], [[G2_IMAG8]] // CHECK-NEXT: [[MUL_AD:%.*]] = fmul double [[G1_REAL5]], [[G2_IMAG8]] // CHECK-NEXT: [[MUL_BC:%.*]] = fmul double [[G1_IMAG6]], [[G2_REAL7]] // CHECK-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] // CHECK-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] // CHECK-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno double [[MUL_R]], [[MUL_R]] // CHECK-NEXT: br i1 [[ISNAN_CMP]], label %[[COMPLEX_MUL_IMAG_NAN:.*]], label %[[COMPLEX_MUL_CONT:.*]], !prof [[PROF2]] // CHECK: [[COMPLEX_MUL_IMAG_NAN]]: // CHECK-NEXT: [[ISNAN_CMP9:%.*]] = fcmp uno double [[MUL_I]], [[MUL_I]] // CHECK-NEXT: br i1 [[ISNAN_CMP9]], label %[[COMPLEX_MUL_LIBCALL:.*]], label %[[COMPLEX_MUL_CONT]], !prof [[PROF2]] // CHECK: [[COMPLEX_MUL_LIBCALL]]: // CHECK-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef [[G1_REAL5]], double noundef [[G1_IMAG6]], double noundef [[G2_REAL7]], double noundef [[G2_IMAG8]]) #[[ATTR4]] // CHECK-NEXT: [[TMP0:%.*]] = extractvalue { double, double } [[CALL]], 0 // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { double, double } [[CALL]], 1 // CHECK-NEXT: br label %[[COMPLEX_MUL_CONT]] // CHECK: [[COMPLEX_MUL_CONT]]: // CHECK-NEXT: [[REAL_MUL_PHI:%.*]] = phi double [ [[MUL_R]], %[[ENTRY]] ], [ [[MUL_R]], %[[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP0]], %[[COMPLEX_MUL_LIBCALL]] ] // CHECK-NEXT: [[IMAG_MUL_PHI:%.*]] = phi double [ [[MUL_I]], %[[ENTRY]] ], [ [[MUL_I]], %[[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP1]], %[[COMPLEX_MUL_LIBCALL]] ] // CHECK-NEXT: store double [[REAL_MUL_PHI]], ptr @g1, align 8 // CHECK-NEXT: store double [[IMAG_MUL_PHI]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G1_REAL10:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG11:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[CONJ_I:%.*]] = fneg double [[G1_IMAG11]] // CHECK-NEXT: [[NEG_R:%.*]] = fneg double [[G1_REAL10]] // CHECK-NEXT: [[NEG_I:%.*]] = fneg double [[CONJ_I]] // CHECK-NEXT: store double [[NEG_R]], ptr @g1, align 8 // CHECK-NEXT: store double [[NEG_I]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: store double [[TMP2]], ptr [[GR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load double, ptr @D, align 8 // CHECK-NEXT: [[CF_REAL:%.*]] = load float, ptr @cf, align 4 // CHECK-NEXT: [[CF_IMAG:%.*]] = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr @cf, i32 0, i32 1), align 4 // CHECK-NEXT: [[CONV:%.*]] = fpext float [[CF_REAL]] to double // CHECK-NEXT: [[CONV12:%.*]] = fpext float [[CF_IMAG]] to double // CHECK-NEXT: [[ADD_R13:%.*]] = fadd double [[CONV]], [[TMP3]] // CHECK-NEXT: [[CONV14:%.*]] = fptrunc double [[ADD_R13]] to float // CHECK-NEXT: [[CONV15:%.*]] = fptrunc double [[CONV12]] to float // CHECK-NEXT: store float [[CONV14]], ptr @cf, align 4 // CHECK-NEXT: store float [[CONV15]], ptr getelementptr inbounds nuw ({ float, float }, ptr @cf, i32 0, i32 1), align 4 // CHECK-NEXT: [[CF_REAL16:%.*]] = load float, ptr @cf, align 4 // CHECK-NEXT: [[CF_IMAG17:%.*]] = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr @cf, i32 0, i32 1), align 4 // CHECK-NEXT: [[CONV18:%.*]] = fpext float [[CF_REAL16]] to double // CHECK-NEXT: [[CONV19:%.*]] = fpext float [[CF_IMAG17]] to double // CHECK-NEXT: [[TMP4:%.*]] = load double, ptr @D, align 8 // CHECK-NEXT: [[ADD_R20:%.*]] = fadd double [[TMP4]], [[CONV18]] // CHECK-NEXT: store double [[ADD_R20]], ptr @D, align 8 // CHECK-NEXT: [[G1_REAL21:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG22:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[CF_REAL23:%.*]] = load float, ptr @cf, align 4 // CHECK-NEXT: [[CF_IMAG24:%.*]] = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr @cf, i32 0, i32 1), align 4 // CHECK-NEXT: [[CONV25:%.*]] = fpext float [[CF_REAL23]] to double // CHECK-NEXT: [[CONV26:%.*]] = fpext float [[CF_IMAG24]] to double // CHECK-NEXT: [[CALL27:%.*]] = call { double, double } @__divdc3(double noundef [[CONV25]], double noundef [[CONV26]], double noundef [[G1_REAL21]], double noundef [[G1_IMAG22]]) #[[ATTR4]] // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { double, double } [[CALL27]], 0 // CHECK-NEXT: [[TMP6:%.*]] = extractvalue { double, double } [[CALL27]], 1 // CHECK-NEXT: [[CONV28:%.*]] = fptrunc double [[TMP5]] to float // CHECK-NEXT: [[CONV29:%.*]] = fptrunc double [[TMP6]] to float // CHECK-NEXT: store float [[CONV28]], ptr @cf, align 4 // CHECK-NEXT: store float [[CONV29]], ptr getelementptr inbounds nuw ({ float, float }, ptr @cf, i32 0, i32 1), align 4 // CHECK-NEXT: [[G1_REAL30:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG31:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[TMP7:%.*]] = load double, ptr @D, align 8 // CHECK-NEXT: [[ADD_R32:%.*]] = fadd double [[G1_REAL30]], [[TMP7]] // CHECK-NEXT: store double [[ADD_R32]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG31]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[TMP8:%.*]] = load double, ptr @D, align 8 // CHECK-NEXT: [[G1_REAL33:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG34:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[ADD_R35:%.*]] = fadd double [[TMP8]], [[G1_REAL33]] // CHECK-NEXT: store double [[ADD_R35]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG34]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: ret void // void test3(void) { g1 = g1 + g2; g1 = g1 - g2; g1 = g1 * g2; g1 = +-~g1; double Gr = __real g1; cf += D; D += cf; cf /= g1; g1 = g1 + D; g1 = D + g1; } __complex__ int ci1, ci2; __complex__ short cs; int i; // CHECK-LABEL: define dso_local void @test3int( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[CI1_REAL:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI2_REAL:%.*]] = load i32, ptr @ci2, align 4 // CHECK-NEXT: [[CI2_IMAG:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci2, i32 0, i32 1), align 4 // CHECK-NEXT: [[ADD_R:%.*]] = add i32 [[CI1_REAL]], [[CI2_REAL]] // CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[CI1_IMAG]], [[CI2_IMAG]] // CHECK-NEXT: store i32 [[ADD_R]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[ADD_I]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI1_REAL1:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG2:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI2_REAL3:%.*]] = load i32, ptr @ci2, align 4 // CHECK-NEXT: [[CI2_IMAG4:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci2, i32 0, i32 1), align 4 // CHECK-NEXT: [[SUB_R:%.*]] = sub i32 [[CI1_REAL1]], [[CI2_REAL3]] // CHECK-NEXT: [[SUB_I:%.*]] = sub i32 [[CI1_IMAG2]], [[CI2_IMAG4]] // CHECK-NEXT: store i32 [[SUB_R]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[SUB_I]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI1_REAL5:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG6:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI2_REAL7:%.*]] = load i32, ptr @ci2, align 4 // CHECK-NEXT: [[CI2_IMAG8:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci2, i32 0, i32 1), align 4 // CHECK-NEXT: [[MUL_RL:%.*]] = mul i32 [[CI1_REAL5]], [[CI2_REAL7]] // CHECK-NEXT: [[MUL_RR:%.*]] = mul i32 [[CI1_IMAG6]], [[CI2_IMAG8]] // CHECK-NEXT: [[MUL_R:%.*]] = sub i32 [[MUL_RL]], [[MUL_RR]] // CHECK-NEXT: [[MUL_IL:%.*]] = mul i32 [[CI1_IMAG6]], [[CI2_REAL7]] // CHECK-NEXT: [[MUL_IR:%.*]] = mul i32 [[CI1_REAL5]], [[CI2_IMAG8]] // CHECK-NEXT: [[MUL_I:%.*]] = add i32 [[MUL_IL]], [[MUL_IR]] // CHECK-NEXT: store i32 [[MUL_R]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[MUL_I]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI1_REAL9:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG10:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CONJ_I:%.*]] = sub i32 0, [[CI1_IMAG10]] // CHECK-NEXT: [[NEG_R:%.*]] = sub i32 0, [[CI1_REAL9]] // CHECK-NEXT: [[NEG_I:%.*]] = sub i32 0, [[CONJ_I]] // CHECK-NEXT: store i32 [[NEG_R]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[NEG_I]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr @i, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @i, align 4 // CHECK-NEXT: [[CS_REAL:%.*]] = load i16, ptr @cs, align 2 // CHECK-NEXT: [[CS_IMAG:%.*]] = load i16, ptr getelementptr inbounds nuw ({ i16, i16 }, ptr @cs, i32 0, i32 1), align 2 // CHECK-NEXT: [[CONV:%.*]] = sext i16 [[CS_REAL]] to i32 // CHECK-NEXT: [[CONV11:%.*]] = sext i16 [[CS_IMAG]] to i32 // CHECK-NEXT: [[ADD_R12:%.*]] = add i32 [[CONV]], [[TMP1]] // CHECK-NEXT: [[ADD_I13:%.*]] = add i32 [[CONV11]], 0 // CHECK-NEXT: [[CONV14:%.*]] = trunc i32 [[ADD_R12]] to i16 // CHECK-NEXT: [[CONV15:%.*]] = trunc i32 [[ADD_I13]] to i16 // CHECK-NEXT: store i16 [[CONV14]], ptr @cs, align 2 // CHECK-NEXT: store i16 [[CONV15]], ptr getelementptr inbounds nuw ({ i16, i16 }, ptr @cs, i32 0, i32 1), align 2 // CHECK-NEXT: [[CF_REAL:%.*]] = load float, ptr @cf, align 4 // CHECK-NEXT: [[CF_IMAG:%.*]] = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr @cf, i32 0, i32 1), align 4 // CHECK-NEXT: [[CONV16:%.*]] = fpext float [[CF_REAL]] to double // CHECK-NEXT: [[CONV17:%.*]] = fpext float [[CF_IMAG]] to double // CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @D, align 8 // CHECK-NEXT: [[ADD_R18:%.*]] = fadd double [[TMP2]], [[CONV16]] // CHECK-NEXT: store double [[ADD_R18]], ptr @D, align 8 // CHECK-NEXT: [[CI1_REAL19:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG20:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CS_REAL21:%.*]] = load i16, ptr @cs, align 2 // CHECK-NEXT: [[CS_IMAG22:%.*]] = load i16, ptr getelementptr inbounds nuw ({ i16, i16 }, ptr @cs, i32 0, i32 1), align 2 // CHECK-NEXT: [[CONV23:%.*]] = sext i16 [[CS_REAL21]] to i32 // CHECK-NEXT: [[CONV24:%.*]] = sext i16 [[CS_IMAG22]] to i32 // CHECK-NEXT: [[TMP3:%.*]] = mul i32 [[CONV23]], [[CI1_REAL19]] // CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[CONV24]], [[CI1_IMAG20]] // CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP3]], [[TMP4]] // CHECK-NEXT: [[TMP6:%.*]] = mul i32 [[CI1_REAL19]], [[CI1_REAL19]] // CHECK-NEXT: [[TMP7:%.*]] = mul i32 [[CI1_IMAG20]], [[CI1_IMAG20]] // CHECK-NEXT: [[TMP8:%.*]] = add i32 [[TMP6]], [[TMP7]] // CHECK-NEXT: [[TMP9:%.*]] = mul i32 [[CONV24]], [[CI1_REAL19]] // CHECK-NEXT: [[TMP10:%.*]] = mul i32 [[CONV23]], [[CI1_IMAG20]] // CHECK-NEXT: [[TMP11:%.*]] = sub i32 [[TMP9]], [[TMP10]] // CHECK-NEXT: [[TMP12:%.*]] = sdiv i32 [[TMP5]], [[TMP8]] // CHECK-NEXT: [[TMP13:%.*]] = sdiv i32 [[TMP11]], [[TMP8]] // CHECK-NEXT: [[CONV25:%.*]] = trunc i32 [[TMP12]] to i16 // CHECK-NEXT: [[CONV26:%.*]] = trunc i32 [[TMP13]] to i16 // CHECK-NEXT: store i16 [[CONV25]], ptr @cs, align 2 // CHECK-NEXT: store i16 [[CONV26]], ptr getelementptr inbounds nuw ({ i16, i16 }, ptr @cs, i32 0, i32 1), align 2 // CHECK-NEXT: [[CI1_REAL27:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG28:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[TMP14:%.*]] = load i32, ptr @i, align 4 // CHECK-NEXT: [[ADD_R29:%.*]] = add i32 [[CI1_REAL27]], [[TMP14]] // CHECK-NEXT: [[ADD_I30:%.*]] = add i32 [[CI1_IMAG28]], 0 // CHECK-NEXT: store i32 [[ADD_R29]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[ADD_I30]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr @i, align 4 // CHECK-NEXT: [[CI1_REAL31:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG32:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[ADD_R33:%.*]] = add i32 [[TMP15]], [[CI1_REAL31]] // CHECK-NEXT: [[ADD_I34:%.*]] = add i32 0, [[CI1_IMAG32]] // CHECK-NEXT: store i32 [[ADD_R33]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[ADD_I34]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: ret void // void test3int(void) { ci1 = ci1 + ci2; ci1 = ci1 - ci2; ci1 = ci1 * ci2; ci1 = +-~ci1; i = __real ci1; cs += i; D += cf; cs /= ci1; ci1 = ci1 + i; ci1 = i + ci1; } // CHECK-LABEL: define dso_local void @t1( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: store float 4.000000e+00, ptr @cf, align 4 // CHECK-NEXT: ret void // void t1(void) { (__real__ cf) = 4.0; } // CHECK-LABEL: define dso_local void @t2( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: store float 4.000000e+00, ptr getelementptr inbounds nuw ({ float, float }, ptr @cf, i32 0, i32 1), align 4 // CHECK-NEXT: ret void // void t2(void) { (__imag__ cf) = 4.0; } // PR1960 // CHECK-LABEL: define dso_local void @t3( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[V:%.*]] = alloca { i64, i64 }, align 8 // CHECK-NEXT: [[V_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[V]], i32 0, i32 0 // CHECK-NEXT: [[V_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[V]], i32 0, i32 1 // CHECK-NEXT: store i64 2, ptr [[V_REALP]], align 8 // CHECK-NEXT: store i64 0, ptr [[V_IMAGP]], align 8 // CHECK-NEXT: ret void // void t3(void) { __complex__ long long v = 2; } // PR3131 float _Complex t4(void); // CHECK-LABEL: define dso_local void @t5( // CHECK-SAME: ) #[[ATTR2:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[X:%.*]] = alloca { float, float }, align 4 // CHECK-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 // CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @t4() // CHECK-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 // CHECK-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 // CHECK-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 // CHECK-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 // CHECK-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 // CHECK-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 // CHECK-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 // CHECK-NEXT: store float [[COERCE_REAL]], ptr [[X_REALP]], align 4 // CHECK-NEXT: store float [[COERCE_IMAG]], ptr [[X_IMAGP]], align 4 // CHECK-NEXT: ret void // void t5(void) { float _Complex x = t4(); } // CHECK-LABEL: define dso_local void @t6( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[INC:%.*]] = fadd double [[G1_REAL]], 1.000000e+00 // CHECK-NEXT: store double [[INC]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G1_REAL1:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG2:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[DEC:%.*]] = fadd double [[G1_REAL1]], -1.000000e+00 // CHECK-NEXT: store double [[DEC]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG2]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G1_REAL3:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG4:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[INC5:%.*]] = fadd double [[G1_REAL3]], 1.000000e+00 // CHECK-NEXT: store double [[INC5]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG4]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[G1_REAL6:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG7:%.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[DEC8:%.*]] = fadd double [[G1_REAL6]], -1.000000e+00 // CHECK-NEXT: store double [[DEC8]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG7]], ptr getelementptr inbounds nuw ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[CI1_REAL:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[INC9:%.*]] = add i32 [[CI1_REAL]], 1 // CHECK-NEXT: store i32 [[INC9]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[CI1_IMAG]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI1_REAL10:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG11:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[DEC12:%.*]] = add i32 [[CI1_REAL10]], -1 // CHECK-NEXT: store i32 [[DEC12]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[CI1_IMAG11]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI1_REAL13:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG14:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[INC15:%.*]] = add i32 [[CI1_REAL13]], 1 // CHECK-NEXT: store i32 [[INC15]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[CI1_IMAG14]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[CI1_REAL16:%.*]] = load i32, ptr @ci1, align 4 // CHECK-NEXT: [[CI1_IMAG17:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: [[DEC18:%.*]] = add i32 [[CI1_REAL16]], -1 // CHECK-NEXT: store i32 [[DEC18]], ptr @ci1, align 4 // CHECK-NEXT: store i32 [[CI1_IMAG17]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci1, i32 0, i32 1), align 4 // CHECK-NEXT: ret void // void t6(void) { g1++; g1--; ++g1; --g1; ci1++; ci1--; ++ci1; --ci1; } // CHECK-LABEL: define dso_local double @t7( // CHECK-SAME: double noundef [[C_COERCE0:%.*]], double noundef [[C_COERCE1:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[C:%.*]] = alloca { double, double }, align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[C]], i32 0, i32 0 // CHECK-NEXT: store double [[C_COERCE0]], ptr [[TMP0]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[C]], i32 0, i32 1 // CHECK-NEXT: store double [[C_COERCE1]], ptr [[TMP1]], align 8 // CHECK-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[C]], i32 0, i32 0 // CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[C_REALP]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.fabs.f64(double [[TMP2]]) // CHECK-NEXT: ret double [[TMP3]] // double t7(double _Complex c) { return __builtin_fabs(__real__(c)); } // CHECK-LABEL: define dso_local void @t8( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[X:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca { i32, i32 }, align 4 // CHECK-NEXT: [[DOTCOMPOUNDLITERAL_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 0 // CHECK-NEXT: [[DOTCOMPOUNDLITERAL_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[DOTCOMPOUNDLITERAL_REALP]], align 4 // CHECK-NEXT: store i32 0, ptr [[DOTCOMPOUNDLITERAL_IMAGP]], align 4 // CHECK-NEXT: store ptr [[DOTCOMPOUNDLITERAL]], ptr [[X]], align 8 // CHECK-NEXT: ret void // void t8(void) { __complex__ int *x = &(__complex__ int){1}; } const _Complex double test9const = 0; // CHECK-LABEL: define dso_local { double, double } @test9func( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 // CHECK-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 // CHECK-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 // CHECK-NEXT: store double 0.000000e+00, ptr [[RETVAL_REALP]], align 8 // CHECK-NEXT: store double 0.000000e+00, ptr [[RETVAL_IMAGP]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 // CHECK-NEXT: ret { double, double } [[TMP0]] // _Complex double test9func(void) { return test9const; } // D6217 // CHECK-LABEL: define dso_local void @t91( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[C:%.*]] = alloca [0 x i8], align 1 // CHECK-NEXT: br i1 false, label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]] // CHECK: [[COND_TRUE]]: // CHECK-NEXT: br label %[[COND_END:.*]] // CHECK: [[COND_FALSE]]: // CHECK-NEXT: br label %[[COND_END]] // CHECK: [[COND_END]]: // CHECK-NEXT: [[COND_R:%.*]] = phi double [ 2.000000e+00, %[[COND_TRUE]] ], [ 2.000000e+00, %[[COND_FALSE]] ] // CHECK-NEXT: [[COND_I:%.*]] = phi double [ 0.000000e+00, %[[COND_TRUE]] ], [ 0.000000e+00, %[[COND_FALSE]] ] // CHECK-NEXT: ret void // void t91(void) { // Check for proper type promotion of conditional expression char c[(int)(sizeof(typeof((0 ? 2.0f : (_Complex double) 2.0f))) - sizeof(_Complex double))]; // Check for proper codegen (0 ? 2.0f : (_Complex double) 2.0f); } // CHECK-LABEL: define dso_local void @t92( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[C:%.*]] = alloca [0 x i8], align 1 // CHECK-NEXT: br i1 false, label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]] // CHECK: [[COND_TRUE]]: // CHECK-NEXT: br label %[[COND_END:.*]] // CHECK: [[COND_FALSE]]: // CHECK-NEXT: br label %[[COND_END]] // CHECK: [[COND_END]]: // CHECK-NEXT: [[COND_R:%.*]] = phi double [ 2.000000e+00, %[[COND_TRUE]] ], [ 2.000000e+00, %[[COND_FALSE]] ] // CHECK-NEXT: [[COND_I:%.*]] = phi double [ 0.000000e+00, %[[COND_TRUE]] ], [ 0.000000e+00, %[[COND_FALSE]] ] // CHECK-NEXT: ret void // void t92(void) { // Check for proper type promotion of conditional expression char c[(int)(sizeof(typeof((0 ? (_Complex double) 2.0f : 2.0f))) - sizeof(_Complex double))]; // Check for proper codegen (0 ? (_Complex double) 2.0f : 2.0f); } // CHECK-LABEL: define dso_local void @real_on_scalar_with_type_promotion( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[A:%.*]] = alloca { half, half }, align 2 // CHECK-NEXT: [[B:%.*]] = alloca half, align 2 // CHECK-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // CHECK-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float // CHECK-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[EXT]] to half // CHECK-NEXT: store half [[UNPROMOTION]], ptr [[B]], align 2 // CHECK-NEXT: ret void // void real_on_scalar_with_type_promotion() { _Float16 _Complex a; _Float16 b = __real__(__real__ a); } // CHECK-LABEL: define dso_local void @imag_on_scalar_with_type_promotion( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[A:%.*]] = alloca { half, half }, align 2 // CHECK-NEXT: [[B:%.*]] = alloca half, align 2 // CHECK-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // CHECK-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 // CHECK-NEXT: [[EXT:%.*]] = fpext half [[A_IMAG]] to float // CHECK-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[EXT]] to half // CHECK-NEXT: store half [[UNPROMOTION]], ptr [[B]], align 2 // CHECK-NEXT: ret void // void imag_on_scalar_with_type_promotion() { _Float16 _Complex a; _Float16 b = __real__(__imag__ a); }