From 17f7784c5d636d7cbed92440eaa5736e91c2619d Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Sun, 15 May 2005 21:19:45 +0000 Subject: Provide this optimization as well: ffs(x) -> (x == 0 ? 0 : 1+llvm.cttz(x)) llvm-svn: 22068 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp | 50 +++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp b/llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp index c7734a8..f3b28bd 100644 --- a/llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp @@ -27,7 +27,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Target/TargetData.h" #include "llvm/Transforms/IPO.h" -#include "llvm/Config/config.h" #include using namespace llvm; @@ -1673,7 +1672,6 @@ public: } } ToAsciiOptimizer; -#if defined(HAVE_FFSLL) /// This LibCallOptimization will simplify calls to the "ffs" library /// calls which find the first set bit in an int, long, or long long. The /// optimization is to compute the result at compile time if the argument is @@ -1709,13 +1707,43 @@ public: { // ffs(cnst) -> bit# // ffsl(cnst) -> bit# + // ffsll(cnst) -> bit# uint64_t val = CI->getRawValue(); - int result = ffsll(static_cast(val)); + int result = 0; + while (val != 0) { + result +=1; + if (val&1) + break; + val >>= 1; + } ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy, result)); ci->eraseFromParent(); return true; } - return false; + + // ffs(x) -> ( x == 0 ? 0 : llvm.cttz(x)+1) + // ffsl(x) -> ( x == 0 ? 0 : llvm.cttz(x)+1) + // ffsll(x) -> ( x == 0 ? 0 : llvm.cttz(x)+1) + const Type* arg_type = ci->getOperand(1)->getType(); + std::vector args; + args.push_back(arg_type); + FunctionType* llvm_cttz_type = FunctionType::get(arg_type,args,false); + Function* F = + SLC.getModule()->getOrInsertFunction("llvm.cttz",llvm_cttz_type); + std::string inst_name(ci->getName()+".ffs"); + Instruction* call = + new CallInst(F, ci->getOperand(1), inst_name, ci); + if (arg_type != Type::IntTy) + call = new CastInst(call, Type::IntTy, inst_name, ci); + BinaryOperator* add = BinaryOperator::create(Instruction::Add, call, + ConstantSInt::get(Type::IntTy,1), inst_name, ci); + SetCondInst* eq = new SetCondInst(Instruction::SetEQ,ci->getOperand(1), + ConstantSInt::get(ci->getOperand(1)->getType(),0),inst_name,ci); + SelectInst* select = new SelectInst(eq,ConstantSInt::get(Type::IntTy,0),add, + inst_name,ci); + ci->replaceAllUsesWith(select); + ci->eraseFromParent(); + return true; } } FFSOptimizer; @@ -1745,7 +1773,19 @@ public: } FFSLLOptimizer; -#endif +/// This LibCallOptimization will simplify calls to the "__builtin_ffs" +/// function which is generated by the CFE (its GCC specific). +/// It simply uses FFSOptimization for which the transformation is +/// identical. +/// @brief Simplify the ffsl library function. +struct BuiltinFFSOptimization : public FFSOptimization +{ +public: + /// @brief Default Constructor + BuiltinFFSOptimization() : FFSOptimization("__builtin_ffs", + "Number of '__builtin_ffs' calls simplified") {} + +} BuiltinFFSOptimization; /// A function to compute the length of a null-terminated constant array of /// integers. This function can't rely on the size of the constant array -- cgit v1.1