diff --git a/include/clang/Basic/BuiltinsR600.def b/include/clang/Basic/BuiltinsR600.def index 49135ccb056da344f384645b631ba17e90470ece..61df903047dd11d94493469fbd961bdbc030ab3f 100644 --- a/include/clang/Basic/BuiltinsR600.def +++ b/include/clang/Basic/BuiltinsR600.def @@ -28,5 +28,7 @@ BUILTIN(__builtin_amdgpu_rsq, "dd", "nc") BUILTIN(__builtin_amdgpu_rsqf, "ff", "nc") BUILTIN(__builtin_amdgpu_rsq_clamped, "dd", "nc") BUILTIN(__builtin_amdgpu_rsq_clampedf, "ff", "nc") +BUILTIN(__builtin_amdgpu_ldexp, "ddi", "nc") +BUILTIN(__builtin_amdgpu_ldexpf, "ffi", "nc") #undef BUILTIN diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 99f4b21ff7e4ad192b98a49823533b596affed89..9dd13c15ebcbd7f46d0e37c4e734d2109f2d57b6 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -6055,6 +6055,17 @@ static Value *emitTernaryFPBuiltin(CodeGenFunction &CGF, return CGF.Builder.CreateCall3(F, Src0, Src1, Src2); } +// Emit an intrinsic that has 1 float or double operand, and 1 integer. +static Value *emitFPIntBuiltin(CodeGenFunction &CGF, + const CallExpr *E, + unsigned IntrinsicID) { + llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); + + Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); + return CGF.Builder.CreateCall2(F, Src0, Src1); +} + Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { switch (BuiltinID) { @@ -6093,12 +6104,8 @@ Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID, case R600::BI__builtin_amdgpu_div_fixupf: return emitTernaryFPBuiltin(*this, E, Intrinsic::AMDGPU_div_fixup); case R600::BI__builtin_amdgpu_trig_preop: - case R600::BI__builtin_amdgpu_trig_preopf: { - Value *Src0 = EmitScalarExpr(E->getArg(0)); - Value *Src1 = EmitScalarExpr(E->getArg(1)); - Value *F = CGM.getIntrinsic(Intrinsic::AMDGPU_trig_preop, Src0->getType()); - return Builder.CreateCall2(F, Src0, Src1); - } + case R600::BI__builtin_amdgpu_trig_preopf: + return emitFPIntBuiltin(*this, E, Intrinsic::AMDGPU_trig_preop); case R600::BI__builtin_amdgpu_rcp: case R600::BI__builtin_amdgpu_rcpf: return emitUnaryFPBuiltin(*this, E, Intrinsic::AMDGPU_rcp); @@ -6108,6 +6115,9 @@ Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID, case R600::BI__builtin_amdgpu_rsq_clamped: case R600::BI__builtin_amdgpu_rsq_clampedf: return emitUnaryFPBuiltin(*this, E, Intrinsic::AMDGPU_rsq_clamped); + case R600::BI__builtin_amdgpu_ldexp: + case R600::BI__builtin_amdgpu_ldexpf: + return emitFPIntBuiltin(*this, E, Intrinsic::AMDGPU_ldexp); default: return nullptr; } diff --git a/test/CodeGenOpenCL/builtins-r600.cl b/test/CodeGenOpenCL/builtins-r600.cl index cebeba185ea3fc473fde9e684461703a818e953d..7167e64f7fe87e764c60fb17d1aa81891ac309f0 100644 --- a/test/CodeGenOpenCL/builtins-r600.cl +++ b/test/CodeGenOpenCL/builtins-r600.cl @@ -112,3 +112,17 @@ void test_rsq_clamped_f64(global double* out, double a) { *out = __builtin_amdgpu_rsq_clamped(a); } + +// CHECK-LABEL: @test_ldexp_f32 +// CHECK: call float @llvm.AMDGPU.ldexp.f32 +void test_ldexp_f32(global float* out, float a, int b) +{ + *out = __builtin_amdgpu_ldexpf(a, b); +} + +// CHECK-LABEL: @test_ldexp_f64 +// CHECK: call double @llvm.AMDGPU.ldexp.f64 +void test_ldexp_f64(global double* out, double a, int b) +{ + *out = __builtin_amdgpu_ldexp(a, b); +}