aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2005-05-15 21:19:45 +0000
committerReid Spencer <rspencer@reidspencer.com>2005-05-15 21:19:45 +0000
commit17f7784c5d636d7cbed92440eaa5736e91c2619d (patch)
treefdb08886589437043dbb43977d23f0ccba7c1008
parent4e5a3a6df6e06e458119c63ac2d5a68710b9f7d3 (diff)
downloadllvm-17f7784c5d636d7cbed92440eaa5736e91c2619d.zip
llvm-17f7784c5d636d7cbed92440eaa5736e91c2619d.tar.gz
llvm-17f7784c5d636d7cbed92440eaa5736e91c2619d.tar.bz2
Provide this optimization as well:
ffs(x) -> (x == 0 ? 0 : 1+llvm.cttz(x)) llvm-svn: 22068
-rw-r--r--llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp50
1 files 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 <iostream>
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<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;
@@ -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