Added target lowering hooks which LSR consults to make more intelligent

transformation decisions.

llvm-svn: 26738
This commit is contained in:
Evan Cheng 2006-03-13 23:14:23 +00:00
parent 2b8eb375d7
commit c567c4efbb
2 changed files with 41 additions and 27 deletions

View File

@ -15,6 +15,8 @@
#ifndef LLVM_TRANSFORMS_SCALAR_H #ifndef LLVM_TRANSFORMS_SCALAR_H
#define LLVM_TRANSFORMS_SCALAR_H #define LLVM_TRANSFORMS_SCALAR_H
#include <cstdlib>
namespace llvm { namespace llvm {
class ModulePass; class ModulePass;
@ -22,6 +24,7 @@ class FunctionPass;
class GetElementPtrInst; class GetElementPtrInst;
class PassInfo; class PassInfo;
class TerminatorInst; class TerminatorInst;
class TargetLowering;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
@ -132,9 +135,12 @@ FunctionPass *createLICMPass();
// a loop's canonical induction variable as one of their indices. The // a loop's canonical induction variable as one of their indices. The
// MaxTargetAMSize is the largest element size that the target architecture // MaxTargetAMSize is the largest element size that the target architecture
// can handle in its addressing modes. Power of two multipliers less than or // can handle in its addressing modes. Power of two multipliers less than or
// equal to this value are not reduced. // equal to this value are not reduced. It also takes an optional second
// parameter used to consult the target machine whether certain transformations
// are profitable.
// //
FunctionPass *createLoopStrengthReducePass(unsigned MaxTargetAMSize = 1); FunctionPass *createLoopStrengthReducePass(unsigned MaxTargetAMSize = 1,
const TargetLowering *TLI = NULL);
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //

View File

@ -31,6 +31,7 @@
#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetData.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Target/TargetLowering.h"
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <set> #include <set>
@ -105,9 +106,14 @@ namespace {
/// DeadInsts - Keep track of instructions we may have made dead, so that /// DeadInsts - Keep track of instructions we may have made dead, so that
/// we can remove them after we are done working. /// we can remove them after we are done working.
std::set<Instruction*> DeadInsts; std::set<Instruction*> DeadInsts;
/// TLI - Keep a pointer of a TargetLowering to consult for determining
/// transformation profitability.
const TargetLowering *TLI;
public: public:
LoopStrengthReduce(unsigned MTAMS = 1) LoopStrengthReduce(unsigned MTAMS = 1, const TargetLowering *tli = NULL)
: MaxTargetAMSize(MTAMS) { : MaxTargetAMSize(MTAMS), TLI(tli) {
} }
virtual bool runOnFunction(Function &) { virtual bool runOnFunction(Function &) {
@ -162,8 +168,9 @@ private:
"Loop Strength Reduction"); "Loop Strength Reduction");
} }
FunctionPass *llvm::createLoopStrengthReducePass(unsigned MaxTargetAMSize) { FunctionPass *llvm::createLoopStrengthReducePass(unsigned MaxTargetAMSize,
return new LoopStrengthReduce(MaxTargetAMSize); const TargetLowering *TLI) {
return new LoopStrengthReduce(MaxTargetAMSize, TLI);
} }
/// getCastedVersionOf - Return the specified value casted to uintptr_t. /// getCastedVersionOf - Return the specified value casted to uintptr_t.
@ -574,25 +581,25 @@ void BasedUser::RewriteInstructionToUseNewBase(const SCEVHandle &NewBase,
/// isTargetConstant - Return true if the following can be referenced by the /// isTargetConstant - Return true if the following can be referenced by the
/// immediate field of a target instruction. /// immediate field of a target instruction.
static bool isTargetConstant(const SCEVHandle &V) { static bool isTargetConstant(const SCEVHandle &V, const TargetLowering *TLI) {
// FIXME: Look at the target to decide if &GV is a legal constant immediate.
if (SCEVConstant *SC = dyn_cast<SCEVConstant>(V)) { if (SCEVConstant *SC = dyn_cast<SCEVConstant>(V)) {
// PPC allows a sign-extended 16-bit immediate field.
int64_t V = SC->getValue()->getSExtValue(); int64_t V = SC->getValue()->getSExtValue();
if (V > -(1 << 16) && V < (1 << 16)-1) if (TLI)
return true; return TLI->isLegalAddressImmediate(V);
return false; else
// Defaults to PPC. PPC allows a sign-extended 16-bit immediate field.
return (V > -(1 << 16) && V < (1 << 16)-1);
} }
return false; // ENABLE this for x86
if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(V)) if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(V))
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(SU->getValue())) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(SU->getValue()))
if (CE->getOpcode() == Instruction::Cast) if (CE->getOpcode() == Instruction::Cast) {
if (isa<GlobalValue>(CE->getOperand(0))) Constant *Op0 = CE->getOperand(0);
// FIXME: should check to see that the dest is uintptr_t! if (isa<GlobalValue>(Op0) &&
TLI &&
TLI->isLegalAddressImmediate(cast<GlobalValue>(Op0)))
return true; return true;
}
return false; return false;
} }
@ -638,7 +645,8 @@ static void MoveLoopVariantsToImediateField(SCEVHandle &Val, SCEVHandle &Imm,
/// MoveImmediateValues - Look at Val, and pull out any additions of constants /// MoveImmediateValues - Look at Val, and pull out any additions of constants
/// that can fit into the immediate field of instructions in the target. /// that can fit into the immediate field of instructions in the target.
/// Accumulate these immediate values into the Imm value. /// Accumulate these immediate values into the Imm value.
static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm, static void MoveImmediateValues(const TargetLowering *TLI,
SCEVHandle &Val, SCEVHandle &Imm,
bool isAddress, Loop *L) { bool isAddress, Loop *L) {
if (SCEVAddExpr *SAE = dyn_cast<SCEVAddExpr>(Val)) { if (SCEVAddExpr *SAE = dyn_cast<SCEVAddExpr>(Val)) {
std::vector<SCEVHandle> NewOps; std::vector<SCEVHandle> NewOps;
@ -646,7 +654,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
for (unsigned i = 0; i != SAE->getNumOperands(); ++i) { for (unsigned i = 0; i != SAE->getNumOperands(); ++i) {
SCEVHandle NewOp = SAE->getOperand(i); SCEVHandle NewOp = SAE->getOperand(i);
MoveImmediateValues(NewOp, Imm, isAddress, L); MoveImmediateValues(TLI, NewOp, Imm, isAddress, L);
if (!NewOp->isLoopInvariant(L)) { if (!NewOp->isLoopInvariant(L)) {
// If this is a loop-variant expression, it must stay in the immediate // If this is a loop-variant expression, it must stay in the immediate
@ -665,7 +673,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
} else if (SCEVAddRecExpr *SARE = dyn_cast<SCEVAddRecExpr>(Val)) { } else if (SCEVAddRecExpr *SARE = dyn_cast<SCEVAddRecExpr>(Val)) {
// Try to pull immediates out of the start value of nested addrec's. // Try to pull immediates out of the start value of nested addrec's.
SCEVHandle Start = SARE->getStart(); SCEVHandle Start = SARE->getStart();
MoveImmediateValues(Start, Imm, isAddress, L); MoveImmediateValues(TLI, Start, Imm, isAddress, L);
if (Start != SARE->getStart()) { if (Start != SARE->getStart()) {
std::vector<SCEVHandle> Ops(SARE->op_begin(), SARE->op_end()); std::vector<SCEVHandle> Ops(SARE->op_begin(), SARE->op_end());
@ -675,12 +683,12 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
return; return;
} else if (SCEVMulExpr *SME = dyn_cast<SCEVMulExpr>(Val)) { } else if (SCEVMulExpr *SME = dyn_cast<SCEVMulExpr>(Val)) {
// Transform "8 * (4 + v)" -> "32 + 8*V" if "32" fits in the immed field. // Transform "8 * (4 + v)" -> "32 + 8*V" if "32" fits in the immed field.
if (isAddress && isTargetConstant(SME->getOperand(0)) && if (isAddress && isTargetConstant(SME->getOperand(0), TLI) &&
SME->getNumOperands() == 2 && SME->isLoopInvariant(L)) { SME->getNumOperands() == 2 && SME->isLoopInvariant(L)) {
SCEVHandle SubImm = SCEVUnknown::getIntegerSCEV(0, Val->getType()); SCEVHandle SubImm = SCEVUnknown::getIntegerSCEV(0, Val->getType());
SCEVHandle NewOp = SME->getOperand(1); SCEVHandle NewOp = SME->getOperand(1);
MoveImmediateValues(NewOp, SubImm, isAddress, L); MoveImmediateValues(TLI, NewOp, SubImm, isAddress, L);
// If we extracted something out of the subexpressions, see if we can // If we extracted something out of the subexpressions, see if we can
// simplify this! // simplify this!
@ -688,7 +696,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
// Scale SubImm up by "8". If the result is a target constant, we are // Scale SubImm up by "8". If the result is a target constant, we are
// good. // good.
SubImm = SCEVMulExpr::get(SubImm, SME->getOperand(0)); SubImm = SCEVMulExpr::get(SubImm, SME->getOperand(0));
if (isTargetConstant(SubImm)) { if (isTargetConstant(SubImm, TLI)) {
// Accumulate the immediate. // Accumulate the immediate.
Imm = SCEVAddExpr::get(Imm, SubImm); Imm = SCEVAddExpr::get(Imm, SubImm);
@ -702,7 +710,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
// Loop-variant expressions must stay in the immediate field of the // Loop-variant expressions must stay in the immediate field of the
// expression. // expression.
if ((isAddress && isTargetConstant(Val)) || if ((isAddress && isTargetConstant(Val, TLI)) ||
!Val->isLoopInvariant(L)) { !Val->isLoopInvariant(L)) {
Imm = SCEVAddExpr::get(Imm, Val); Imm = SCEVAddExpr::get(Imm, Val);
Val = SCEVUnknown::getIntegerSCEV(0, Val->getType()); Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
@ -879,7 +887,7 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
if (SI->getOperand(1) == UsersToProcess[i].OperandValToReplace) if (SI->getOperand(1) == UsersToProcess[i].OperandValToReplace)
isAddress = true; isAddress = true;
MoveImmediateValues(UsersToProcess[i].Base, UsersToProcess[i].Imm, MoveImmediateValues(TLI, UsersToProcess[i].Base, UsersToProcess[i].Imm,
isAddress, L); isAddress, L);
} }
} }
@ -941,7 +949,7 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
// this by forcing a noop cast to be inserted into the preheader in this // this by forcing a noop cast to be inserted into the preheader in this
// case. // case.
if (Constant *C = dyn_cast<Constant>(BaseV)) if (Constant *C = dyn_cast<Constant>(BaseV))
if (!C->isNullValue() && !isTargetConstant(Base)) { if (!C->isNullValue() && !isTargetConstant(Base, TLI)) {
// We want this constant emitted into the preheader! // We want this constant emitted into the preheader!
BaseV = new CastInst(BaseV, BaseV->getType(), "preheaderinsert", BaseV = new CastInst(BaseV, BaseV->getType(), "preheaderinsert",
PreInsertPt); PreInsertPt);