| // 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); |
| } |