Add a target hook to allow changing the tail duplication limit based on the

contents of the block to be duplicated.  Use this for ARM Cortex A8/9 to
be more aggressive tail duplicating indirect branches, since it makes it
much more likely that they will be predicted in the branch target buffer.
Testcase coming soon.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89187 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bob Wilson 2009-11-18 03:34:27 +00:00
parent 5eea342673
commit 834b08af8d
6 changed files with 32 additions and 4 deletions

View File

@ -536,6 +536,13 @@ public:
/// length. /// length.
virtual unsigned getInlineAsmLength(const char *Str, virtual unsigned getInlineAsmLength(const char *Str,
const MCAsmInfo &MAI) const; const MCAsmInfo &MAI) const;
/// TailDuplicationLimit - Returns the limit on the number of instructions
/// in basic block MBB beyond which it will not be tail-duplicated.
virtual unsigned TailDuplicationLimit(const MachineBasicBlock &MBB,
unsigned DefaultLimit) const {
return DefaultLimit;
}
}; };
/// TargetInstrInfoImpl - This is the default implementation of /// TargetInstrInfoImpl - This is the default implementation of

View File

@ -1033,12 +1033,13 @@ bool BranchFolder::TailDuplicate(MachineBasicBlock *TailBB,
if (TailBB->isSuccessor(TailBB)) if (TailBB->isSuccessor(TailBB))
return false; return false;
// Duplicate up to one less than the tail-merge threshold. When optimizing // Set the limit on the number of instructions to duplicate, with a default
// for size, duplicate only one, because one branch instruction can be // of one less than the tail-merge threshold. When optimizing for size,
// eliminated to compensate for the duplication. // duplicate only one, because one branch instruction can be eliminated to
// compensate for the duplication.
unsigned MaxDuplicateCount = unsigned MaxDuplicateCount =
MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize) ? MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize) ?
1 : (TailMergeSize - 1); 1 : TII->TailDuplicationLimit(*TailBB, TailMergeSize - 1);
// Check the instructions in the block to determine whether tail-duplication // Check the instructions in the block to determine whether tail-duplication
// is invalid or unlikely to be profitable. // is invalid or unlikely to be profitable.

View File

@ -1005,6 +1005,16 @@ bool ARMBaseInstrInfo::isIdentical(const MachineInstr *MI0,
return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI); return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI);
} }
unsigned ARMBaseInstrInfo::TailDuplicationLimit(const MachineBasicBlock &MBB,
unsigned DefaultLimit) const {
// If the target processor can predict indirect branches, it is highly
// desirable to duplicate them, since it can often make them predictable.
if (!MBB.empty() && isIndirectBranchOpcode(MBB.back().getOpcode()) &&
getSubtarget().hasBranchTargetBuffer())
return DefaultLimit + 2;
return DefaultLimit;
}
/// getInstrPredicate - If instruction is predicated, returns its predicate /// getInstrPredicate - If instruction is predicated, returns its predicate
/// condition, otherwise returns AL. It also returns the condition code /// condition, otherwise returns AL. It also returns the condition code
/// register by reference. /// register by reference.

View File

@ -272,6 +272,9 @@ public:
virtual bool isIdentical(const MachineInstr *MI, const MachineInstr *Other, virtual bool isIdentical(const MachineInstr *MI, const MachineInstr *Other,
const MachineRegisterInfo *MRI) const; const MachineRegisterInfo *MRI) const;
virtual unsigned TailDuplicationLimit(const MachineBasicBlock &MBB,
unsigned DefaultLimit) const;
}; };
static inline static inline

View File

@ -109,6 +109,8 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
if (UseNEONFP.getPosition() == 0) if (UseNEONFP.getPosition() == 0)
UseNEONForSinglePrecisionFP = true; UseNEONForSinglePrecisionFP = true;
} }
HasBranchTargetBuffer = (CPUString == "cortex-a8" ||
CPUString == "cortex-a9");
} }
/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.

View File

@ -50,6 +50,9 @@ protected:
/// determine if NEON should actually be used. /// determine if NEON should actually be used.
bool UseNEONForSinglePrecisionFP; bool UseNEONForSinglePrecisionFP;
/// HasBranchTargetBuffer - True if processor can predict indirect branches.
bool HasBranchTargetBuffer;
/// IsThumb - True if we are in thumb mode, false if in ARM mode. /// IsThumb - True if we are in thumb mode, false if in ARM mode.
bool IsThumb; bool IsThumb;
@ -123,6 +126,8 @@ protected:
bool isThumb2() const { return IsThumb && (ThumbMode == Thumb2); } bool isThumb2() const { return IsThumb && (ThumbMode == Thumb2); }
bool hasThumb2() const { return ThumbMode >= Thumb2; } bool hasThumb2() const { return ThumbMode >= Thumb2; }
bool hasBranchTargetBuffer() const { return HasBranchTargetBuffer; }
bool isR9Reserved() const { return IsR9Reserved; } bool isR9Reserved() const { return IsR9Reserved; }
const std::string & getCPUString() const { return CPUString; } const std::string & getCPUString() const { return CPUString; }