blob: 91fc9dda72f72ca934c131ebe3c7ecf73f9024ea [file] [log] [blame]
// 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);
}