r274370 - Emit more intrinsics for builtin functions
Matt Arsenault via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 1 10:38:15 PDT 2016
Author: arsenm
Date: Fri Jul 1 12:38:14 2016
New Revision: 274370
URL: http://llvm.org/viewvc/llvm-project?rev=274370&view=rev
Log:
Emit more intrinsics for builtin functions
This is important for building libclc. Since r273039 tests are failing
due to now emitting calls to these functions instead of emitting the
DAG node. The libm function names are implemented for OpenCL, and should
call the locally defined versions, so -fno-builtin is used. The IR
Some functions use the __builtins and expect the intrinsics to be
emitted. Without this we end up with nobuiltin calls to intrinsics
or to unsupported library calls.
Modified:
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/test/CodeGen/builtins.c
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=274370&r1=274369&r2=274370&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Fri Jul 1 12:38:14 2016
@@ -217,6 +217,51 @@ static Value *MakeAtomicCmpXchgValue(Cod
ValueType);
}
+// Emit a simple mangled intrinsic that has 1 argument and a return type
+// matching the argument type.
+static Value *emitUnaryBuiltin(CodeGenFunction &CGF,
+ const CallExpr *E,
+ unsigned IntrinsicID) {
+ llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
+
+ Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
+ return CGF.Builder.CreateCall(F, Src0);
+}
+
+// Emit an intrinsic that has 2 operands of the same type as its result.
+static Value *emitBinaryBuiltin(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.CreateCall(F, { Src0, Src1 });
+}
+
+// Emit an intrinsic that has 3 operands of the same type as its result.
+static Value *emitTernaryBuiltin(CodeGenFunction &CGF,
+ const CallExpr *E,
+ unsigned IntrinsicID) {
+ llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
+ llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
+ llvm::Value *Src2 = CGF.EmitScalarExpr(E->getArg(2));
+
+ Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
+ return CGF.Builder.CreateCall(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.CreateCall(F, {Src0, Src1});
+}
+
/// EmitFAbs - Emit a call to @llvm.fabs().
static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) {
Value *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType());
@@ -286,40 +331,6 @@ static llvm::Value *EmitOverflowIntrinsi
return CGF.Builder.CreateExtractValue(Tmp, 0);
}
-// Emit a simple mangled intrinsic that has 1 argument and a return type
-// matching the argument type.
-static Value *emitUnaryBuiltin(CodeGenFunction &CGF,
- const CallExpr *E,
- unsigned IntrinsicID) {
- llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
-
- Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
- return CGF.Builder.CreateCall(F, Src0);
-}
-
-// Emit an intrinsic that has 3 float or double operands.
-static Value *emitTernaryFPBuiltin(CodeGenFunction &CGF,
- const CallExpr *E,
- unsigned IntrinsicID) {
- llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
- llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
- llvm::Value *Src2 = CGF.EmitScalarExpr(E->getArg(2));
-
- Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
- return CGF.Builder.CreateCall(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.CreateCall(F, {Src0, Src1});
-}
-
namespace {
struct WidthAndSignedness {
unsigned Width;
@@ -497,9 +508,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(
case Builtin::BI__builtin_fabs:
case Builtin::BI__builtin_fabsf:
case Builtin::BI__builtin_fabsl: {
- Value *Arg1 = EmitScalarExpr(E->getArg(0));
- Value *Result = EmitFAbs(*this, Arg1);
- return RValue::get(Result);
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs));
}
case Builtin::BI__builtin_fmod:
case Builtin::BI__builtin_fmodf:
@@ -509,7 +518,51 @@ RValue CodeGenFunction::EmitBuiltinExpr(
Value *Result = Builder.CreateFRem(Arg1, Arg2, "fmod");
return RValue::get(Result);
}
-
+ case Builtin::BI__builtin_copysign:
+ case Builtin::BI__builtin_copysignf:
+ case Builtin::BI__builtin_copysignl: {
+ return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::copysign));
+ }
+ case Builtin::BI__builtin_ceil:
+ case Builtin::BI__builtin_ceilf:
+ case Builtin::BI__builtin_ceill: {
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::ceil));
+ }
+ case Builtin::BI__builtin_floor:
+ case Builtin::BI__builtin_floorf:
+ case Builtin::BI__builtin_floorl: {
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::floor));
+ }
+ case Builtin::BI__builtin_trunc:
+ case Builtin::BI__builtin_truncf:
+ case Builtin::BI__builtin_truncl: {
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::trunc));
+ }
+ case Builtin::BI__builtin_rint:
+ case Builtin::BI__builtin_rintf:
+ case Builtin::BI__builtin_rintl: {
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::rint));
+ }
+ case Builtin::BI__builtin_nearbyint:
+ case Builtin::BI__builtin_nearbyintf:
+ case Builtin::BI__builtin_nearbyintl: {
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::nearbyint));
+ }
+ case Builtin::BI__builtin_round:
+ case Builtin::BI__builtin_roundf:
+ case Builtin::BI__builtin_roundl: {
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::round));
+ }
+ case Builtin::BI__builtin_fmin:
+ case Builtin::BI__builtin_fminf:
+ case Builtin::BI__builtin_fminl: {
+ return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::minnum));
+ }
+ case Builtin::BI__builtin_fmax:
+ case Builtin::BI__builtin_fmaxf:
+ case Builtin::BI__builtin_fmaxl: {
+ return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::maxnum));
+ }
case Builtin::BI__builtin_conj:
case Builtin::BI__builtin_conjf:
case Builtin::BI__builtin_conjl: {
@@ -7380,7 +7433,7 @@ Value *CodeGenFunction::EmitAMDGPUBuilti
}
case AMDGPU::BI__builtin_amdgcn_div_fixup:
case AMDGPU::BI__builtin_amdgcn_div_fixupf:
- return emitTernaryFPBuiltin(*this, E, Intrinsic::amdgcn_div_fixup);
+ return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_div_fixup);
case AMDGPU::BI__builtin_amdgcn_trig_preop:
case AMDGPU::BI__builtin_amdgcn_trig_preopf:
return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_trig_preop);
Modified: cfe/trunk/test/CodeGen/builtins.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins.c?rev=274370&r1=274369&r2=274370&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/builtins.c (original)
+++ cfe/trunk/test/CodeGen/builtins.c Fri Jul 1 12:38:14 2016
@@ -257,6 +257,98 @@ void test_float_builtin_ops(float F, dou
// CHECK: call float @llvm.canonicalize.f32(float
// CHECK: call double @llvm.canonicalize.f64(double
// CHECK: call x86_fp80 @llvm.canonicalize.f80(x86_fp80
+
+ resf = __builtin_fminf(F, F);
+ // CHECK: call float @llvm.minnum.f32
+
+ resd = __builtin_fmin(D, D);
+ // CHECK: call double @llvm.minnum.f64
+
+ resld = __builtin_fminl(LD, LD);
+ // CHECK: call x86_fp80 @llvm.minnum.f80
+
+ resf = __builtin_fmaxf(F, F);
+ // CHECK: call float @llvm.maxnum.f32
+
+ resd = __builtin_fmax(D, D);
+ // CHECK: call double @llvm.maxnum.f64
+
+ resld = __builtin_fmaxl(LD, LD);
+ // CHECK: call x86_fp80 @llvm.maxnum.f80
+
+ resf = __builtin_fabsf(F);
+ // CHECK: call float @llvm.fabs.f32
+
+ resd = __builtin_fabs(D);
+ // CHECK: call double @llvm.fabs.f64
+
+ resld = __builtin_fabsl(LD);
+ // CHECK: call x86_fp80 @llvm.fabs.f80
+
+ resf = __builtin_copysignf(F, F);
+ // CHECK: call float @llvm.copysign.f32
+
+ resd = __builtin_copysign(D, D);
+ // CHECK: call double @llvm.copysign.f64
+
+ resld = __builtin_copysignl(LD, LD);
+ // CHECK: call x86_fp80 @llvm.copysign.f80
+
+
+ resf = __builtin_ceilf(F);
+ // CHECK: call float @llvm.ceil.f32
+
+ resd = __builtin_ceil(D);
+ // CHECK: call double @llvm.ceil.f64
+
+ resld = __builtin_ceill(LD);
+ // CHECK: call x86_fp80 @llvm.ceil.f80
+
+ resf = __builtin_floorf(F);
+ // CHECK: call float @llvm.floor.f32
+
+ resd = __builtin_floor(D);
+ // CHECK: call double @llvm.floor.f64
+
+ resld = __builtin_floorl(LD);
+ // CHECK: call x86_fp80 @llvm.floor.f80
+
+ resf = __builtin_truncf(F);
+ // CHECK: call float @llvm.trunc.f32
+
+ resd = __builtin_trunc(D);
+ // CHECK: call double @llvm.trunc.f64
+
+ resld = __builtin_truncl(LD);
+ // CHECK: call x86_fp80 @llvm.trunc.f80
+
+ resf = __builtin_rintf(F);
+ // CHECK: call float @llvm.rint.f32
+
+ resd = __builtin_rint(D);
+ // CHECK: call double @llvm.rint.f64
+
+ resld = __builtin_rintl(LD);
+ // CHECK: call x86_fp80 @llvm.rint.f80
+
+ resf = __builtin_nearbyintf(F);
+ // CHECK: call float @llvm.nearbyint.f32
+
+ resd = __builtin_nearbyint(D);
+ // CHECK: call double @llvm.nearbyint.f64
+
+ resld = __builtin_nearbyintl(LD);
+ // CHECK: call x86_fp80 @llvm.nearbyint.f80
+
+ resf = __builtin_roundf(F);
+ // CHECK: call float @llvm.round.f32
+
+ resd = __builtin_round(D);
+ // CHECK: call double @llvm.round.f64
+
+ resld = __builtin_roundl(LD);
+ // CHECK: call x86_fp80 @llvm.round.f80
+
}
// __builtin_longjmp isn't supported on all platforms, so only test it on X86.
More information about the cfe-commits
mailing list