diff options
Diffstat (limited to 'clang/lib/CodeGen/CGBuiltin.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 266 |
1 files changed, 173 insertions, 93 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 34adc640b4e..76b6db13513 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -854,6 +854,179 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Result.Val.getFloat())); } + // Math builtins have the same semantics as their math library twins. + // There are LLVM math intrinsics corresponding to math library functions + // except the intrinsic will never set errno while the math library might. + // Thus, we can transform math library and builtin calls to their + // semantically-equivalent LLVM intrinsic counterparts if the call is marked + // 'const' (it is known to never set errno). + if (FD->hasAttr<ConstAttr>()) { + switch (BuiltinID) { + case Builtin::BIceil: + case Builtin::BIceilf: + case Builtin::BIceill: + 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::BIcopysign: + case Builtin::BIcopysignf: + case Builtin::BIcopysignl: + 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::BIcos: + case Builtin::BIcosf: + case Builtin::BIcosl: + case Builtin::BI__builtin_cos: + case Builtin::BI__builtin_cosf: + case Builtin::BI__builtin_cosl: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::cos)); + + case Builtin::BIexp: + case Builtin::BIexpf: + case Builtin::BIexpl: + case Builtin::BI__builtin_exp: + case Builtin::BI__builtin_expf: + case Builtin::BI__builtin_expl: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::exp)); + + case Builtin::BIexp2: + case Builtin::BIexp2f: + case Builtin::BIexp2l: + case Builtin::BI__builtin_exp2: + case Builtin::BI__builtin_exp2f: + case Builtin::BI__builtin_exp2l: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::exp2)); + + case Builtin::BIfabs: + case Builtin::BIfabsf: + case Builtin::BIfabsl: + case Builtin::BI__builtin_fabs: + case Builtin::BI__builtin_fabsf: + case Builtin::BI__builtin_fabsl: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs)); + + case Builtin::BIfloor: + case Builtin::BIfloorf: + case Builtin::BIfloorl: + 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::BIfma: + case Builtin::BIfmaf: + case Builtin::BIfmal: + case Builtin::BI__builtin_fma: + case Builtin::BI__builtin_fmaf: + case Builtin::BI__builtin_fmal: + return RValue::get(emitTernaryBuiltin(*this, E, Intrinsic::fma)); + + case Builtin::BIfmax: + case Builtin::BIfmaxf: + case Builtin::BIfmaxl: + 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::BIfmin: + case Builtin::BIfminf: + case Builtin::BIfminl: + 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::BIlog: + case Builtin::BIlogf: + case Builtin::BIlogl: + case Builtin::BI__builtin_log: + case Builtin::BI__builtin_logf: + case Builtin::BI__builtin_logl: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log)); + + case Builtin::BIlog10: + case Builtin::BIlog10f: + case Builtin::BIlog10l: + case Builtin::BI__builtin_log10: + case Builtin::BI__builtin_log10f: + case Builtin::BI__builtin_log10l: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log10)); + + case Builtin::BIlog2: + case Builtin::BIlog2f: + case Builtin::BIlog2l: + case Builtin::BI__builtin_log2: + case Builtin::BI__builtin_log2f: + case Builtin::BI__builtin_log2l: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log2)); + + case Builtin::BInearbyint: + case Builtin::BInearbyintf: + case Builtin::BInearbyintl: + 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::BIpow: + case Builtin::BIpowf: + case Builtin::BIpowl: + case Builtin::BI__builtin_pow: + case Builtin::BI__builtin_powf: + case Builtin::BI__builtin_powl: + return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::pow)); + + case Builtin::BIrint: + case Builtin::BIrintf: + case Builtin::BIrintl: + 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::BIround: + case Builtin::BIroundf: + case Builtin::BIroundl: + 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::BIsin: + case Builtin::BIsinf: + case Builtin::BIsinl: + case Builtin::BI__builtin_sin: + case Builtin::BI__builtin_sinf: + case Builtin::BI__builtin_sinl: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::sin)); + + case Builtin::BIsqrt: + case Builtin::BIsqrtf: + case Builtin::BIsqrtl: + case Builtin::BI__builtin_sqrt: + case Builtin::BI__builtin_sqrtf: + case Builtin::BI__builtin_sqrtl: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::sqrt)); + + case Builtin::BItrunc: + case Builtin::BItruncf: + case Builtin::BItruncl: + case Builtin::BI__builtin_trunc: + case Builtin::BI__builtin_truncf: + case Builtin::BI__builtin_truncl: + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::trunc)); + + default: + break; + } + } + switch (BuiltinID) { default: break; // Handle intrinsics and libm functions below. case Builtin::BI__builtin___CFStringMakeConstantString: @@ -894,11 +1067,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Result); } - case Builtin::BI__builtin_fabs: - case Builtin::BI__builtin_fabsf: - case Builtin::BI__builtin_fabsl: { - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs)); - } case Builtin::BI__builtin_fmod: case Builtin::BI__builtin_fmodf: case Builtin::BI__builtin_fmodl: { @@ -907,51 +1075,6 @@ 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: { @@ -2073,49 +2196,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(nullptr); } - case Builtin::BIsqrt: - case Builtin::BIsqrtf: - case Builtin::BIsqrtl: - // Builtins have the same semantics as library functions. The LLVM intrinsic - // has the same semantics as the library function except it does not set - // errno. Thus, we can transform either sqrt or __builtin_sqrt to @llvm.sqrt - // if the call is 'const' (the call must not set errno). - // - // FIXME: The builtin cases are not here because they are marked 'const' in - // Builtins.def. So that means they are wrongly defined to have different - // semantics than the library functions. If we included them here, we would - // turn them into LLVM intrinsics regardless of whether -fmath-errno was on. - if (FD->hasAttr<ConstAttr>()) - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::sqrt)); - break; - - case Builtin::BI__builtin_pow: - case Builtin::BI__builtin_powf: - case Builtin::BI__builtin_powl: - case Builtin::BIpow: - case Builtin::BIpowf: - case Builtin::BIpowl: { - // Transform a call to pow* into a @llvm.pow.* intrinsic call. - if (!FD->hasAttr<ConstAttr>()) - break; - Value *Base = EmitScalarExpr(E->getArg(0)); - Value *Exponent = EmitScalarExpr(E->getArg(1)); - llvm::Type *ArgType = Base->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::pow, ArgType); - return RValue::get(Builder.CreateCall(F, {Base, Exponent})); - } - - case Builtin::BIfma: - case Builtin::BIfmaf: - case Builtin::BIfmal: - case Builtin::BI__builtin_fma: - case Builtin::BI__builtin_fmaf: - case Builtin::BI__builtin_fmal: - // A constant libcall or builtin is equivalent to the LLVM intrinsic. - if (FD->hasAttr<ConstAttr>()) - return RValue::get(emitTernaryBuiltin(*this, E, Intrinsic::fma)); - break; - case Builtin::BI__builtin_signbit: case Builtin::BI__builtin_signbitf: case Builtin::BI__builtin_signbitl: { |