r232778 - [Modules] Implement __builtin_isinf_sign in Clang.
Gabriel Dos Reis
gdr at integrable-solutions.net
Thu Mar 19 15:59:07 PDT 2015
On Thursday, March 19, 2015, Chandler Carruth <chandlerc at gmail.com> wrote:
> Author: chandlerc
> Date: Thu Mar 19 17:39:51 2015
> New Revision: 232778
>
> URL: http://llvm.org/viewvc/llvm-project?rev=232778&view=rev
> Log:
> [Modules] Implement __builtin_isinf_sign in Clang.
>
> Somehow, we never managed to implement this fully. We could constant
> fold it like crazy, including constant folding complex arguments, etc.
> But if you actually needed to generate code for it, error.
>
> I've implemented it using the somewhat obvious lowering. Happy for
> suggestions on a more clever way to lower this.
>
> Now, what you might ask does this have to do with modules? Fun story. So
> it turns out that libstdc++ actually uses __builtin_isinf_sign to
> implement std::isinf when in C++98 mode, but only inside of a template.
> So if we're lucky, and we never instantiate that, everything is good.
> But once we try to instantiate that template function, we need this
> builtin. All of my customers at least are using C++11 and so they never
> hit this code path.
>
> But what does that have to do with modules? Fun story. So it turns out
> that with modules we actually observe a bunch of bugs
Yes, with modules, many bugs like this get exposed.
-- Gaby
> in libstdc++ where
> their <cmath> header clobbers things exposed by <math.h>. To fix these,
> we have to provide global function definitions to replace the macros
> that C99 would have used. And it turns out that ::isinf needs to be
> implemented using the exact semantics used by the C++98 variant of
> std::isinf. And so I started to fix this bug in libstdc++ and ceased to
> be able to compile libstdc++ with Clang.
>
> The yaks are legion.
>
> 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=232778&r1=232777&r2=232778&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Mar 19 17:39:51 2015
> @@ -158,6 +158,27 @@ static Value *EmitFAbs(CodeGenFunction &
> return Call;
> }
>
> +/// Emit the computation of the sign bit for a floating point value.
> Returns
> +/// the i1 sign bit value.
> +static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
> + LLVMContext &C = CGF.CGM.getLLVMContext();
> +
> + llvm::Type *Ty = V->getType();
> + int Width = Ty->getPrimitiveSizeInBits();
> + llvm::Type *IntTy = llvm::IntegerType::get(C, Width);
> + V = CGF.Builder.CreateBitCast(V, IntTy);
> + if (Ty->isPPC_FP128Ty()) {
> + // The higher-order double comes first, and so we need to truncate the
> + // pair to extract the overall sign. The order of the pair is the same
> + // in both little- and big-Endian modes.
> + Width >>= 1;
> + IntTy = llvm::IntegerType::get(C, Width);
> + V = CGF.Builder.CreateTrunc(V, IntTy);
> + }
> + Value *Zero = llvm::Constant::getNullValue(IntTy);
> + return CGF.Builder.CreateICmpSLT(V, Zero);
> +}
> +
> static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl
> *Fn,
> const CallExpr *E, llvm::Value
> *calleeValue) {
> return CGF.EmitCall(E->getCallee()->getType(), calleeValue, E,
> @@ -558,8 +579,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(
> return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
> }
>
> - // TODO: BI__builtin_isinf_sign
> - // isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0
> + case Builtin::BI__builtin_isinf_sign: {
> + // isinf_sign(x) -> fabs(x) == infinity ? (signbit(x) ? -1 : 1) : 0
> + Value *Arg = EmitScalarExpr(E->getArg(0));
> + Value *AbsArg = EmitFAbs(*this, Arg);
> + Value *IsInf = Builder.CreateFCmpOEQ(
> + AbsArg, ConstantFP::getInfinity(Arg->getType()), "isinf");
> + Value *IsNeg = EmitSignBit(*this, Arg);
> +
> + llvm::Type *IntTy = ConvertType(E->getType());
> + Value *Zero = Constant::getNullValue(IntTy);
> + Value *One = ConstantInt::get(IntTy, 1);
> + Value *NegativeOne = ConstantInt::get(IntTy, -1);
> + Value *SignResult = Builder.CreateSelect(IsNeg, NegativeOne, One);
> + Value *Result = Builder.CreateSelect(IsInf, SignResult, Zero);
> + return RValue::get(Result);
> + }
>
> case Builtin::BI__builtin_isnormal: {
> // isnormal(x) --> x == x && fabsf(x) < infinity && fabsf(x) >=
> float_min
> @@ -1398,24 +1433,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(
> case Builtin::BI__builtin_signbit:
> case Builtin::BI__builtin_signbitf:
> case Builtin::BI__builtin_signbitl: {
> - LLVMContext &C = CGM.getLLVMContext();
> -
> - Value *Arg = EmitScalarExpr(E->getArg(0));
> - llvm::Type *ArgTy = Arg->getType();
> - int ArgWidth = ArgTy->getPrimitiveSizeInBits();
> - llvm::Type *ArgIntTy = llvm::IntegerType::get(C, ArgWidth);
> - Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy);
> - if (ArgTy->isPPC_FP128Ty()) {
> - // The higher-order double comes first, and so we need to truncate
> the
> - // pair to extract the overall sign. The order of the pair is the
> same
> - // in both little- and big-Endian modes.
> - ArgWidth >>= 1;
> - ArgIntTy = llvm::IntegerType::get(C, ArgWidth);
> - BCArg = Builder.CreateTrunc(BCArg, ArgIntTy);
> - }
> - Value *ZeroCmp = llvm::Constant::getNullValue(ArgIntTy);
> - Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp);
> - return RValue::get(Builder.CreateZExt(Result,
> ConvertType(E->getType())));
> + return RValue::get(
> + Builder.CreateZExt(EmitSignBit(*this,
> EmitScalarExpr(E->getArg(0))),
> + ConvertType(E->getType())));
> }
> case Builtin::BI__builtin_annotation: {
> llvm::Value *AnnVal = EmitScalarExpr(E->getArg(0));
>
> Modified: cfe/trunk/test/CodeGen/builtins.c
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins.c?rev=232778&r1=232777&r2=232778&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGen/builtins.c (original)
> +++ cfe/trunk/test/CodeGen/builtins.c Thu Mar 19 17:39:51 2015
> @@ -42,8 +42,6 @@ int main() {
> P(fpclassify, (0, 1, 2, 3, 4, 1.0));
> P(fpclassify, (0, 1, 2, 3, 4, 1.0f));
> P(fpclassify, (0, 1, 2, 3, 4, 1.0l));
> - // FIXME:
> - // P(isinf_sign, (1.0));
>
> Q(nan, (""));
> Q(nanf, (""));
> @@ -61,6 +59,8 @@ int main() {
> P(islessgreater, (1., 2.));
> P(isunordered, (1., 2.));
>
> + P(isinf, (1.));
> + P(isinf_sign, (1.));
> P(isnan, (1.));
>
> // Bitwise & Numeric Functions
> @@ -177,11 +177,35 @@ void test_float_builtins(float F, double
> res = __builtin_isinf(D);
> // CHECK: call double @llvm.fabs.f64(double
> // CHECK: fcmp oeq double {{.*}}, 0x7FF0000000000000
> -
> +
> res = __builtin_isinf(LD);
> // CHECK: call x86_fp80 @llvm.fabs.f80(x86_fp80
> // CHECK: fcmp oeq x86_fp80 {{.*}}, 0xK7FFF8000000000000000
> -
> +
> + res = __builtin_isinf_sign(F);
> + // CHECK: %[[ABS:.*]] = call float @llvm.fabs.f32(float %[[ARG:.*]])
> + // CHECK: %[[ISINF:.*]] = fcmp oeq float %[[ABS]], 0x7FF0000000000000
> + // CHECK: %[[BITCAST:.*]] = bitcast float %[[ARG]] to i32
> + // CHECK: %[[ISNEG:.*]] = icmp slt i32 %[[BITCAST]], 0
> + // CHECK: %[[SIGN:.*]] = select i1 %[[ISNEG]], i32 -1, i32 1
> + // CHECK: select i1 %[[ISINF]], i32 %[[SIGN]], i32 0
> +
> + res = __builtin_isinf_sign(D);
> + // CHECK: %[[ABS:.*]] = call double @llvm.fabs.f64(double %[[ARG:.*]])
> + // CHECK: %[[ISINF:.*]] = fcmp oeq double %[[ABS]], 0x7FF0000000000000
> + // CHECK: %[[BITCAST:.*]] = bitcast double %[[ARG]] to i64
> + // CHECK: %[[ISNEG:.*]] = icmp slt i64 %[[BITCAST]], 0
> + // CHECK: %[[SIGN:.*]] = select i1 %[[ISNEG]], i32 -1, i32 1
> + // CHECK: select i1 %[[ISINF]], i32 %[[SIGN]], i32 0
> +
> + res = __builtin_isinf_sign(LD);
> + // CHECK: %[[ABS:.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80
> %[[ARG:.*]])
> + // CHECK: %[[ISINF:.*]] = fcmp oeq x86_fp80 %[[ABS]],
> 0xK7FFF8000000000000000
> + // CHECK: %[[BITCAST:.*]] = bitcast x86_fp80 %[[ARG]] to i80
> + // CHECK: %[[ISNEG:.*]] = icmp slt i80 %[[BITCAST]], 0
> + // CHECK: %[[SIGN:.*]] = select i1 %[[ISNEG]], i32 -1, i32 1
> + // CHECK: select i1 %[[ISINF]], i32 %[[SIGN]], i32 0
> +
> res = __builtin_isfinite(F);
> // CHECK: fcmp oeq float
> // CHECK: call float @llvm.fabs.f32(float
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu <javascript:;>
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150319/64a0047d/attachment.html>
More information about the cfe-commits
mailing list