Skip to content

Commit 17f7784

Browse files
author
Reid Spencer
committed
Provide this optimization as well:
ffs(x) -> (x == 0 ? 0 : 1+llvm.cttz(x)) llvm-svn: 22068
1 parent 4e5a3a6 commit 17f7784

File tree

1 file changed

+45
-5
lines changed

1 file changed

+45
-5
lines changed

llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include "llvm/Support/Debug.h"
2828
#include "llvm/Target/TargetData.h"
2929
#include "llvm/Transforms/IPO.h"
30-
#include "llvm/Config/config.h"
3130
#include <iostream>
3231
using namespace llvm;
3332

@@ -1673,7 +1672,6 @@ struct ToAsciiOptimization : public LibCallOptimization
16731672
}
16741673
} ToAsciiOptimizer;
16751674

1676-
#if defined(HAVE_FFSLL)
16771675
/// This LibCallOptimization will simplify calls to the "ffs" library
16781676
/// calls which find the first set bit in an int, long, or long long. The
16791677
/// optimization is to compute the result at compile time if the argument is
@@ -1709,13 +1707,43 @@ struct FFSOptimization : public LibCallOptimization
17091707
{
17101708
// ffs(cnst) -> bit#
17111709
// ffsl(cnst) -> bit#
1710+
// ffsll(cnst) -> bit#
17121711
uint64_t val = CI->getRawValue();
1713-
int result = ffsll(static_cast<long long>(val));
1712+
int result = 0;
1713+
while (val != 0) {
1714+
result +=1;
1715+
if (val&1)
1716+
break;
1717+
val >>= 1;
1718+
}
17141719
ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy, result));
17151720
ci->eraseFromParent();
17161721
return true;
17171722
}
1718-
return false;
1723+
1724+
// ffs(x) -> ( x == 0 ? 0 : llvm.cttz(x)+1)
1725+
// ffsl(x) -> ( x == 0 ? 0 : llvm.cttz(x)+1)
1726+
// ffsll(x) -> ( x == 0 ? 0 : llvm.cttz(x)+1)
1727+
const Type* arg_type = ci->getOperand(1)->getType();
1728+
std::vector<const Type*> args;
1729+
args.push_back(arg_type);
1730+
FunctionType* llvm_cttz_type = FunctionType::get(arg_type,args,false);
1731+
Function* F =
1732+
SLC.getModule()->getOrInsertFunction("llvm.cttz",llvm_cttz_type);
1733+
std::string inst_name(ci->getName()+".ffs");
1734+
Instruction* call =
1735+
new CallInst(F, ci->getOperand(1), inst_name, ci);
1736+
if (arg_type != Type::IntTy)
1737+
call = new CastInst(call, Type::IntTy, inst_name, ci);
1738+
BinaryOperator* add = BinaryOperator::create(Instruction::Add, call,
1739+
ConstantSInt::get(Type::IntTy,1), inst_name, ci);
1740+
SetCondInst* eq = new SetCondInst(Instruction::SetEQ,ci->getOperand(1),
1741+
ConstantSInt::get(ci->getOperand(1)->getType(),0),inst_name,ci);
1742+
SelectInst* select = new SelectInst(eq,ConstantSInt::get(Type::IntTy,0),add,
1743+
inst_name,ci);
1744+
ci->replaceAllUsesWith(select);
1745+
ci->eraseFromParent();
1746+
return true;
17191747
}
17201748
} FFSOptimizer;
17211749

@@ -1745,7 +1773,19 @@ struct FFSLLOptimization : public FFSOptimization
17451773

17461774
} FFSLLOptimizer;
17471775

1748-
#endif
1776+
/// This LibCallOptimization will simplify calls to the "__builtin_ffs"
1777+
/// function which is generated by the CFE (its GCC specific).
1778+
/// It simply uses FFSOptimization for which the transformation is
1779+
/// identical.
1780+
/// @brief Simplify the ffsl library function.
1781+
struct BuiltinFFSOptimization : public FFSOptimization
1782+
{
1783+
public:
1784+
/// @brief Default Constructor
1785+
BuiltinFFSOptimization() : FFSOptimization("__builtin_ffs",
1786+
"Number of '__builtin_ffs' calls simplified") {}
1787+
1788+
} BuiltinFFSOptimization;
17491789

17501790
/// A function to compute the length of a null-terminated constant array of
17511791
/// integers. This function can't rely on the size of the constant array

0 commit comments

Comments
 (0)