forked from OSchip/llvm-project
Added target lowering hooks which LSR consults to make more intelligent
transformation decisions. llvm-svn: 26738
This commit is contained in:
parent
2b8eb375d7
commit
c567c4efbb
|
@ -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);
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue