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