From: Daniel Dunbar Date: Mon, 21 Jul 2008 17:19:41 +0000 (+0000) Subject: Implement ffs, parity, and popcount builtins. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04b290030eee33295600728450f348989d1a627e;p=clang Implement ffs, parity, and popcount builtins. + test case git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53851 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Builtins.def b/include/clang/AST/Builtins.def index 7bdcd6dd8d..c3113a9148 100644 --- a/include/clang/AST/Builtins.def +++ b/include/clang/AST/Builtins.def @@ -55,6 +55,8 @@ // Standard libc/libm functions: BUILTIN(__builtin_huge_val, "d", "nc") +BUILTIN(__builtin_huge_valf, "f", "nc") +BUILTIN(__builtin_huge_vall, "Ld", "nc") BUILTIN(__builtin_inf , "d" , "nc") BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") @@ -86,6 +88,15 @@ BUILTIN(__builtin_ctz , "iUi" , "nc") BUILTIN(__builtin_ctzl , "iULi" , "nc") BUILTIN(__builtin_ctzll, "iULLi", "nc") // TODO: int ctzimax(uintmax_t) +BUILTIN(__builtin_ffs , "iUi" , "nc") +BUILTIN(__builtin_ffsl , "iULi" , "nc") +BUILTIN(__builtin_ffsll, "iULLi", "nc") +BUILTIN(__builtin_parity , "iUi" , "nc") +BUILTIN(__builtin_parityl , "iULi" , "nc") +BUILTIN(__builtin_parityll, "iULLi", "nc") +BUILTIN(__builtin_popcount , "iUi" , "nc") +BUILTIN(__builtin_popcountl , "iULi" , "nc") +BUILTIN(__builtin_popcountll, "iULLi", "nc") // FIXME: These type signatures are not correct for targets with int != 32-bits // or with ULL != 64-bits. diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index fb6b0caa3d..d186a71619 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -140,6 +140,57 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Result = Builder.CreateIntCast(Result, ResultType, "cast"); return RValue::get(Result); } + case Builtin::BI__builtin_ffs: + case Builtin::BI__builtin_ffsl: + case Builtin::BI__builtin_ffsll: { + // ffs(x) -> x ? cttz(x) + 1 : 0 + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + + const llvm::Type *ArgType = ArgValue->getType(); + Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1); + + const llvm::Type *ResultType = ConvertType(E->getType()); + Value *Tmp = Builder.CreateAdd(Builder.CreateCall(F, ArgValue, "tmp"), + ConstantInt::get(ArgType, 1), "tmp"); + Value *Zero = llvm::Constant::getNullValue(ArgType); + Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero"); + Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs"); + if (Result->getType() != ResultType) + Result = Builder.CreateIntCast(Result, ResultType, "cast"); + return RValue::get(Result); + } + case Builtin::BI__builtin_parity: + case Builtin::BI__builtin_parityl: + case Builtin::BI__builtin_parityll: { + // parity(x) -> ctpop(x) & 1 + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + + const llvm::Type *ArgType = ArgValue->getType(); + Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1); + + const llvm::Type *ResultType = ConvertType(E->getType()); + Value *Tmp = Builder.CreateCall(F, ArgValue, "tmp"); + Value *Result = Builder.CreateAnd(Tmp, ConstantInt::get(ArgType, 1), + "tmp"); + if (Result->getType() != ResultType) + Result = Builder.CreateIntCast(Result, ResultType, "cast"); + return RValue::get(Result); + } + case Builtin::BI__builtin_popcount: + case Builtin::BI__builtin_popcountl: + case Builtin::BI__builtin_popcountll: { + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + + const llvm::Type *ArgType = ArgValue->getType(); + Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1); + + const llvm::Type *ResultType = ConvertType(E->getType()); + Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); + if (Result->getType() != ResultType) + Result = Builder.CreateIntCast(Result, ResultType, "cast"); + return RValue::get(Result); + } + case Builtin::BI__builtin_expect: return RValue::get(EmitScalarExpr(E->getArg(0))); case Builtin::BI__builtin_bswap32: @@ -149,16 +200,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1); return RValue::get(Builder.CreateCall(F, ArgValue, "tmp")); } - case Builtin::BI__builtin_inff: case Builtin::BI__builtin_huge_val: + case Builtin::BI__builtin_huge_valf: + case Builtin::BI__builtin_huge_vall: case Builtin::BI__builtin_inf: + case Builtin::BI__builtin_inff: case Builtin::BI__builtin_infl: { const llvm::fltSemantics &Sem = CGM.getContext().getFloatTypeSemantics(E->getType()); return RValue::get(ConstantFP::get(APFloat::getInf(Sem))); } - case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nan: + case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: { // If this is __builtin_nan("") turn this into a simple nan, otherwise just // call libm nan. diff --git a/test/CodeGen/builtins-ffs_parity_popcount.c b/test/CodeGen/builtins-ffs_parity_popcount.c new file mode 100644 index 0000000000..19a5cf9a67 --- /dev/null +++ b/test/CodeGen/builtins-ffs_parity_popcount.c @@ -0,0 +1,15 @@ +// RUN: clang -emit-llvm -o - %s > %t +// RUN: ! grep "__builtin" %t + +#include + +void test(int M, long long N) { + printf("%d %lld: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + M, N, + __builtin_ffs(M), __builtin_ffsl(M), __builtin_ffsll(M), + __builtin_parity(M), __builtin_parityl(M), __builtin_parityll(M), + __builtin_popcount(M), __builtin_popcountl(M), __builtin_popcountll(M), + __builtin_ffs(N), __builtin_ffsl(N), __builtin_ffsll(N), + __builtin_parity(N), __builtin_parityl(N), __builtin_parityll(N), + __builtin_popcount(N), __builtin_popcountl(N), __builtin_popcountll(N)); +}