// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll // RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s // frexp: float, double, long double float test_frexpf(float x) { int exp; return __builtin_frexpf(x, &exp); } // CIR-LABEL: cir.func {{.*}} @test_frexpf // CIR: %{{.*}}, %{{.*}} = cir.frexp %{{.*}} : !cir.float -> !cir.float, !s32i // CIR: cir.store // CIR: cir.return // LLVM-LABEL: define {{.*}} float @test_frexpf // LLVM: %{{.*}} = call { float, i32 } @llvm.frexp.f32.i32(float %{{.*}}) // LLVM: %{{.*}} = extractvalue { float, i32 } %{{.*}}, 0 // LLVM: %{{.*}} = extractvalue { float, i32 } %{{.*}}, 1 // LLVM: ret float // OGCG-LABEL: define {{.*}} float @test_frexpf // OGCG: %{{.*}} = call { float, i32 } @llvm.frexp.f32.i32(float %{{.*}}) // OGCG: %{{.*}} = extractvalue { float, i32 } %{{.*}}, 1 // OGCG: %{{.*}} = extractvalue { float, i32 } %{{.*}}, 0 // OGCG: ret float double test_frexp(double x) { int exp; return __builtin_frexp(x, &exp); } // CIR-LABEL: cir.func {{.*}} @test_frexp // CIR: %{{.*}}, %{{.*}} = cir.frexp %{{.*}} : !cir.double -> !cir.double, !s32i // CIR: cir.store // CIR: cir.return // LLVM-LABEL: define {{.*}} double @test_frexp // LLVM: %{{.*}} = call { double, i32 } @llvm.frexp.f64.i32(double %{{.*}}) // LLVM: %{{.*}} = extractvalue { double, i32 } %{{.*}}, 0 // LLVM: %{{.*}} = extractvalue { double, i32 } %{{.*}}, 1 // LLVM: ret double // OGCG-LABEL: define {{.*}} double @test_frexp // OGCG: %{{.*}} = call { double, i32 } @llvm.frexp.f64.i32(double %{{.*}}) // OGCG: %{{.*}} = extractvalue { double, i32 } %{{.*}}, 1 // OGCG: %{{.*}} = extractvalue { double, i32 } %{{.*}}, 0 // OGCG: ret double long double test_frexpl(long double x) { int exp; return __builtin_frexpl(x, &exp); } // CIR-LABEL: cir.func {{.*}} @test_frexpl // CIR: %{{.*}}, %{{.*}} = cir.frexp %{{.*}} : !cir.long_double -> !cir.long_double, !s32i // CIR: cir.store // CIR: cir.return // LLVM-LABEL: define {{.*}} x86_fp80 @test_frexpl // LLVM: %{{.*}} = call { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80 %{{.*}}) // LLVM: %{{.*}} = extractvalue { x86_fp80, i32 } %{{.*}}, 0 // LLVM: %{{.*}} = extractvalue { x86_fp80, i32 } %{{.*}}, 1 // LLVM: ret x86_fp80 // OGCG-LABEL: define {{.*}} x86_fp80 @test_frexpl // OGCG: %{{.*}} = call { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80 %{{.*}}) // OGCG: %{{.*}} = extractvalue { x86_fp80, i32 } %{{.*}}, 1 // OGCG: %{{.*}} = extractvalue { x86_fp80, i32 } %{{.*}}, 0 // OGCG: ret x86_fp80 __float128 test_frexpf128(__float128 x) { int exp; return __builtin_frexpf128(x, &exp); } // CIR-LABEL: cir.func {{.*}} @test_frexpf128 // CIR: %{{.*}}, %{{.*}} = cir.frexp %{{.*}} : !cir.f128 -> !cir.f128, !s32i // CIR: cir.store // CIR: cir.return // LLVM-LABEL: define {{.*}} fp128 @test_frexpf128 // LLVM: %{{.*}} = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %{{.*}}) // LLVM: %{{.*}} = extractvalue { fp128, i32 } %{{.*}}, 0 // LLVM: %{{.*}} = extractvalue { fp128, i32 } %{{.*}}, 1 // LLVM: ret fp128 // OGCG-LABEL: define {{.*}} fp128 @test_frexpf128 // OGCG: %{{.*}} = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %{{.*}}) // OGCG: %{{.*}} = extractvalue { fp128, i32 } %{{.*}}, 1 // OGCG: %{{.*}} = extractvalue { fp128, i32 } %{{.*}}, 0 // OGCG: ret fp128 // modf: float, double, long double float test_modff(float x) { float ipart; return __builtin_modff(x, &ipart); } // CIR-LABEL: cir.func {{.*}} @test_modff // CIR: %{{.*}}, %{{.*}} = cir.modf %{{.*}} : !cir.float -> !cir.float, !cir.float // CIR: cir.store // CIR: cir.return // LLVM-LABEL: define {{.*}} float @test_modff // LLVM: %{{.*}} = call { float, float } @llvm.modf.f32(float %{{.*}}) // LLVM: %{{.*}} = extractvalue { float, float } %{{.*}}, 0 // LLVM: %{{.*}} = extractvalue { float, float } %{{.*}}, 1 // LLVM: ret float // OGCG-LABEL: define {{.*}} float @test_modff // OGCG: %{{.*}} = call { float, float } @llvm.modf.f32(float %{{.*}}) // OGCG: %{{.*}} = extractvalue { float, float } %{{.*}}, 0 // OGCG: %{{.*}} = extractvalue { float, float } %{{.*}}, 1 // OGCG: ret float double test_modf(double x) { double ipart; return __builtin_modf(x, &ipart); } // CIR-LABEL: cir.func {{.*}} @test_modf // CIR: %{{.*}}, %{{.*}} = cir.modf %{{.*}} : !cir.double -> !cir.double, !cir.double // CIR: cir.store // CIR: cir.return // LLVM-LABEL: define {{.*}} double @test_modf // LLVM: %{{.*}} = call { double, double } @llvm.modf.f64(double %{{.*}}) // LLVM: %{{.*}} = extractvalue { double, double } %{{.*}}, 0 // LLVM: %{{.*}} = extractvalue { double, double } %{{.*}}, 1 // LLVM: ret double // OGCG-LABEL: define {{.*}} double @test_modf // OGCG: %{{.*}} = call { double, double } @llvm.modf.f64(double %{{.*}}) // OGCG: %{{.*}} = extractvalue { double, double } %{{.*}}, 0 // OGCG: %{{.*}} = extractvalue { double, double } %{{.*}}, 1 // OGCG: ret double long double test_modfl(long double x) { long double ipart; return __builtin_modfl(x, &ipart); } // CIR-LABEL: cir.func {{.*}} @test_modfl // CIR: %{{.*}}, %{{.*}} = cir.modf %{{.*}} : !cir.long_double -> !cir.long_double, !cir.long_double // CIR: cir.store // CIR: cir.return // LLVM-LABEL: define {{.*}} x86_fp80 @test_modfl // LLVM: %{{.*}} = call { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80 %{{.*}}) // LLVM: %{{.*}} = extractvalue { x86_fp80, x86_fp80 } %{{.*}}, 0 // LLVM: %{{.*}} = extractvalue { x86_fp80, x86_fp80 } %{{.*}}, 1 // LLVM: ret x86_fp80 // OGCG-LABEL: define {{.*}} x86_fp80 @test_modfl // OGCG: %{{.*}} = call { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80 %{{.*}}) // OGCG: %{{.*}} = extractvalue { x86_fp80, x86_fp80 } %{{.*}}, 0 // OGCG: %{{.*}} = extractvalue { x86_fp80, x86_fp80 } %{{.*}}, 1 // OGCG: ret x86_fp80 __float128 test_modff128(__float128 x) { __float128 ipart; return __builtin_modff128(x, &ipart); } // CIR-LABEL: cir.func {{.*}} @test_modff128 // CIR: cir.call @modff128 // CIR: cir.return // LLVM-LABEL: define {{.*}} fp128 @test_modff128 // LLVM: call fp128 @modff128(fp128 {{.*}}, ptr {{.*}}) // LLVM: ret fp128 // OGCG-LABEL: define {{.*}} fp128 @test_modff128 // OGCG: call fp128 @modff128(fp128 {{.*}}, ptr {{.*}}) // OGCG: ret fp128 // powi: float, double, long double float test_powif(float x, int y) { return __builtin_powif(x, y); } // CIR-LABEL: cir.func {{.*}} @test_powif // CIR: %{{.*}} = cir.call_llvm_intrinsic "powi" %{{.*}}, %{{.*}} : (!cir.float, !s32i) -> !cir.float // CIR: cir.return // LLVM-LABEL: define {{.*}} float @test_powif // LLVM: call float @llvm.powi.f32.i32(float %{{.*}}, i32 %{{.*}}) // LLVM: ret float // OGCG-LABEL: define {{.*}} float @test_powif // OGCG: call float @llvm.powi.f32.i32(float %{{.*}}, i32 %{{.*}}) // OGCG: ret float double test_powi(double x, int y) { return __builtin_powi(x, y); } // CIR-LABEL: cir.func {{.*}} @test_powi // CIR: %{{.*}} = cir.call_llvm_intrinsic "powi" %{{.*}}, %{{.*}} : (!cir.double, !s32i) -> !cir.double // CIR: cir.return // LLVM-LABEL: define {{.*}} double @test_powi // LLVM: call double @llvm.powi.f64.i32(double %{{.*}}, i32 %{{.*}}) // LLVM: ret double // OGCG-LABEL: define {{.*}} double @test_powi // OGCG: call double @llvm.powi.f64.i32(double %{{.*}}, i32 %{{.*}}) // OGCG: ret double long double test_powil(long double x, int y) { return __builtin_powil(x, y); } // CIR-LABEL: cir.func {{.*}} @test_powil // CIR: %{{.*}} = cir.call_llvm_intrinsic "powi" %{{.*}}, %{{.*}} : (!cir.long_double, !s32i) -> !cir.long_double // CIR: cir.return // LLVM-LABEL: define {{.*}} x86_fp80 @test_powil // LLVM: call x86_fp80 @llvm.powi.f80.i32(x86_fp80 %{{.*}}, i32 %{{.*}}) // LLVM: ret x86_fp80 // OGCG-LABEL: define {{.*}} x86_fp80 @test_powil // OGCG: call x86_fp80 @llvm.powi.f80.i32(x86_fp80 %{{.*}}, i32 %{{.*}}) // OGCG: ret x86_fp80 // FP comparison builtins: float void test_floats(float x, float y, int *out) { out[0] = __builtin_isgreater(x, y); // CIR: cir.cmp gt %{{.*}}, %{{.*}} : !cir.float // LLVM: fcmp ogt float // OGCG: fcmp ogt float out[1] = __builtin_isgreaterequal(x, y); // CIR: cir.cmp ge %{{.*}}, %{{.*}} : !cir.float // LLVM: fcmp oge float // OGCG: fcmp oge float out[2] = __builtin_isless(x, y); // CIR: cir.cmp lt %{{.*}}, %{{.*}} : !cir.float // LLVM: fcmp olt float // OGCG: fcmp olt float out[3] = __builtin_islessequal(x, y); // CIR: cir.cmp le %{{.*}}, %{{.*}} : !cir.float // LLVM: fcmp ole float // OGCG: fcmp ole float out[4] = __builtin_islessgreater(x, y); // CIR: cir.cmp one %{{.*}}, %{{.*}} : !cir.float // LLVM: fcmp one float // OGCG: fcmp one float out[5] = __builtin_isunordered(x, y); // CIR: cir.cmp uno %{{.*}}, %{{.*}} : !cir.float // LLVM: fcmp uno float // OGCG: fcmp uno float } // FP comparison builtins: double void test_doubles(double x, double y, int *out) { out[0] = __builtin_isgreater(x, y); // CIR: cir.cmp gt %{{.*}}, %{{.*}} : !cir.double // LLVM: fcmp ogt double // OGCG: fcmp ogt double out[1] = __builtin_isgreaterequal(x, y); // CIR: cir.cmp ge %{{.*}}, %{{.*}} : !cir.double // LLVM: fcmp oge double // OGCG: fcmp oge double out[2] = __builtin_isless(x, y); // CIR: cir.cmp lt %{{.*}}, %{{.*}} : !cir.double // LLVM: fcmp olt double // OGCG: fcmp olt double out[3] = __builtin_islessequal(x, y); // CIR: cir.cmp le %{{.*}}, %{{.*}} : !cir.double // LLVM: fcmp ole double // OGCG: fcmp ole double out[4] = __builtin_islessgreater(x, y); // CIR: cir.cmp one %{{.*}}, %{{.*}} : !cir.double // LLVM: fcmp one double // OGCG: fcmp one double out[5] = __builtin_isunordered(x, y); // CIR: cir.cmp uno %{{.*}}, %{{.*}} : !cir.double // LLVM: fcmp uno double // OGCG: fcmp uno double } // FP comparison builtins: mixed double + float (fpext) void test_mixed(double x, float y, int *out) { out[0] = __builtin_isgreater(x, y); // CIR: cir.cast floating %{{.*}} : !cir.float -> !cir.double // CIR: cir.cmp gt %{{.*}}, %{{.*}} : !cir.double // LLVM: fpext float %{{.*}} to double // LLVM: fcmp ogt double // OGCG: fpext float %{{.*}} to double // OGCG: fcmp ogt double out[1] = __builtin_isgreaterequal(x, y); // CIR: cir.cast floating %{{.*}} : !cir.float -> !cir.double // CIR: cir.cmp ge %{{.*}}, %{{.*}} : !cir.double // LLVM: fpext float %{{.*}} to double // LLVM: fcmp oge double // OGCG: fpext float %{{.*}} to double // OGCG: fcmp oge double out[2] = __builtin_isless(x, y); // CIR: cir.cast floating %{{.*}} : !cir.float -> !cir.double // CIR: cir.cmp lt %{{.*}}, %{{.*}} : !cir.double // LLVM: fpext float %{{.*}} to double // LLVM: fcmp olt double // OGCG: fpext float %{{.*}} to double // OGCG: fcmp olt double out[3] = __builtin_islessequal(x, y); // CIR: cir.cast floating %{{.*}} : !cir.float -> !cir.double // CIR: cir.cmp le %{{.*}}, %{{.*}} : !cir.double // LLVM: fpext float %{{.*}} to double // LLVM: fcmp ole double // OGCG: fpext float %{{.*}} to double // OGCG: fcmp ole double out[4] = __builtin_islessgreater(x, y); // CIR: cir.cast floating %{{.*}} : !cir.float -> !cir.double // CIR: cir.cmp one %{{.*}}, %{{.*}} : !cir.double // LLVM: fpext float %{{.*}} to double // LLVM: fcmp one double // OGCG: fpext float %{{.*}} to double // OGCG: fcmp one double out[5] = __builtin_isunordered(x, y); // CIR: cir.cast floating %{{.*}} : !cir.float -> !cir.double // CIR: cir.cmp uno %{{.*}}, %{{.*}} : !cir.double // LLVM: fpext float %{{.*}} to double // LLVM: fcmp uno double // OGCG: fpext float %{{.*}} to double // OGCG: fcmp uno double } // FP comparison builtins: __fp16 (promoted to float) int test_isgreater_half(__fp16 *a, __fp16 *b) { return __builtin_isgreater(*a, *b); } // CIR-LABEL: cir.func {{.*}} @test_isgreater_half // CIR: cir.cast floating %{{.*}} : !cir.f16 -> !cir.float // CIR: cir.cast floating %{{.*}} : !cir.f16 -> !cir.float // CIR: cir.cmp gt %{{.*}}, %{{.*}} : !cir.float // LLVM-LABEL: define {{.*}} i32 @test_isgreater_half // LLVM: fpext half %{{.*}} to float // LLVM: fpext half %{{.*}} to float // LLVM: fcmp ogt float // LLVM: zext i1 %{{.*}} to i32 // LLVM: ret i32 // OGCG-LABEL: define {{.*}} i32 @test_isgreater_half // OGCG: fpext half %{{.*}} to float // OGCG: fpext half %{{.*}} to float // OGCG: fcmp ogt float // OGCG: zext i1 %{{.*}} to i32 // OGCG: ret i32