forked from OSchip/llvm-project
Implement ffs, parity, and popcount builtins.
+ test case llvm-svn: 53851
This commit is contained in:
parent
b0e3938651
commit
d93abc3bb0
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// RUN: clang -emit-llvm -o - %s > %t
|
||||
// RUN: ! grep "__builtin" %t
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
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));
|
||||
}
|
Loading…
Reference in New Issue