]> granicus.if.org Git - clang/commitdiff
Emit more intrinsics for builtin functions
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Fri, 1 Jul 2016 17:38:14 +0000 (17:38 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Fri, 1 Jul 2016 17:38:14 +0000 (17:38 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274370 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBuiltin.cpp
test/CodeGen/builtins.c

index 7c024340025fba8cd4f10998b8db0331e14cab97..8a5e2919f68d7e74da811c1c1aa8a31ba476790e 100644 (file)
@@ -217,6 +217,51 @@ static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E,
                        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 *EmitOverflowIntrinsic(CodeGenFunction &CGF,
   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(const FunctionDecl *FD,
   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(const FunctionDecl *FD,
     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::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
   }
   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);
index 43ce8f13ade60c7f084c08ca4d763b618bee7338..405f2199af19a335914d6306b3bc665eae895398 100644 (file)
@@ -257,6 +257,98 @@ void test_float_builtin_ops(float F, double D, long double LD) {
   // 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.