On Thursday, March 19, 2015, Chandler Carruth <[email protected]> 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 > [email protected] <javascript:;> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
