#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
-#include "llvm/Config/config.h"
#include <iostream>
using namespace llvm;
}
} 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
{
// ffs(cnst) -> bit#
// ffsl(cnst) -> bit#
+ // ffsll(cnst) -> bit#
uint64_t val = CI->getRawValue();
- int result = ffsll(static_cast<long long>(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<const Type*> 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;
} 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