diff options
author | Chris Lattner <sabre@nondot.org> | 2010-05-06 05:35:16 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-05-06 05:35:16 +0000 |
commit | 420b11850d3f4557421f43f519b59d528329c668 (patch) | |
tree | 9a1ff33edad7446822b2d71c6c39a8a55b88bfdf /lib/CodeGen/CGBuiltin.cpp | |
parent | a8426972609c908b529ab26c69c35586d8bc06a8 (diff) |
implement part of PR6083: codegen support for isinf. Like isnan,
this is generating correct but suboptimal (extra extend to double)
code for the float case. Will investigate next.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103166 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGBuiltin.cpp')
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 95c41db86e..651539f019 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -71,7 +71,7 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF, /// Utility to insert an atomic instruction based Instrinsic::ID and // the expression node, where the return value is the result of the // operation. -static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF, +static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, Intrinsic::ID Id, const CallExpr *E, Instruction::BinaryOps Op) { const llvm::Type *ResType[2]; @@ -88,6 +88,30 @@ static llvm::ConstantInt *getInt32(llvm::LLVMContext &Context, int32_t Value) { return llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), Value); } + +/// EmitFAbs - Emit a call to fabs/fabsf/fabsl, depending on the type of ValTy, +/// which must be a scalar floating point type. +static Value *EmitFAbs(CodeGenFunction &CGF, Value *V, QualType ValTy) { + const BuiltinType *ValTyP = ValTy->getAs<BuiltinType>(); + assert(ValTyP && "isn't scalar fp type!"); + + StringRef FnName; + switch (ValTyP->getKind()) { + default: assert(0 && "Isn't a scalar fp type!"); + case BuiltinType::Float: FnName = "fabsf"; break; + case BuiltinType::Double: FnName = "fabs"; break; + case BuiltinType::LongDouble: FnName = "fabsl"; break; + } + + // The prototype is something that takes and returns whatever V's type is. + std::vector<const llvm::Type*> Args; + Args.push_back(V->getType()); + llvm::FunctionType *FT = llvm::FunctionType::get(V->getType(), Args, false); + llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(FT, FnName); + + return CGF.Builder.CreateCall(Fn, V, "abs"); +} + RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E) { // See if we can constant fold this builtin. If so, don't emit it at all. @@ -328,6 +352,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, V = Builder.CreateFCmpUNO(V, V, "cmp"); return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp")); } + + case Builtin::BI__builtin_isinf: { + // isinf(x) --> fabs(x) == infinity + Value *V = EmitScalarExpr(E->getArg(0)); + V = EmitFAbs(*this, V, E->getArg(0)->getType()); + + V = Builder.CreateFCmpOEQ(V, ConstantFP::getInfinity(V->getType()),"isinf"); + return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp")); + } + case Builtin::BIalloca: case Builtin::BI__builtin_alloca: { // FIXME: LLVM IR Should allow alloca with an i64 size! |