|
27 | 27 | #include "llvm/Support/Debug.h"
|
28 | 28 | #include "llvm/Target/TargetData.h"
|
29 | 29 | #include "llvm/Transforms/IPO.h"
|
30 |
| -#include "llvm/Config/config.h" |
31 | 30 | #include <iostream>
|
32 | 31 | using namespace llvm;
|
33 | 32 |
|
@@ -1673,7 +1672,6 @@ struct ToAsciiOptimization : public LibCallOptimization
|
1673 | 1672 | }
|
1674 | 1673 | } ToAsciiOptimizer;
|
1675 | 1674 |
|
1676 |
| -#if defined(HAVE_FFSLL) |
1677 | 1675 | /// This LibCallOptimization will simplify calls to the "ffs" library
|
1678 | 1676 | /// calls which find the first set bit in an int, long, or long long. The
|
1679 | 1677 | /// optimization is to compute the result at compile time if the argument is
|
@@ -1709,13 +1707,43 @@ struct FFSOptimization : public LibCallOptimization
|
1709 | 1707 | {
|
1710 | 1708 | // ffs(cnst) -> bit#
|
1711 | 1709 | // ffsl(cnst) -> bit#
|
| 1710 | + // ffsll(cnst) -> bit# |
1712 | 1711 | 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 | + } |
1714 | 1719 | ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy, result));
|
1715 | 1720 | ci->eraseFromParent();
|
1716 | 1721 | return true;
|
1717 | 1722 | }
|
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; |
1719 | 1747 | }
|
1720 | 1748 | } FFSOptimizer;
|
1721 | 1749 |
|
@@ -1745,7 +1773,19 @@ struct FFSLLOptimization : public FFSOptimization
|
1745 | 1773 |
|
1746 | 1774 | } FFSLLOptimizer;
|
1747 | 1775 |
|
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; |
1749 | 1789 |
|
1750 | 1790 | /// A function to compute the length of a null-terminated constant array of
|
1751 | 1791 | /// integers. This function can't rely on the size of the constant array
|
|
0 commit comments