Hexagon: Honor __builtin_expect by using branch probabilities.

* lib/Target/Hexagon/HexagonInstrInfo.cpp (GetDotNewPredOp):
  Given a jump opcode return the right pred.new jump opcode with
  a taken vs not-taken hint based on branch probabilities provided
  by the target independent module.
  * lib/Target/Hexagon/HexagonVLIWPacketizer.cpp: Use the above function.
  * lib/Target/Hexagon/HexagonNewValueJump.cpp(getNewvalueJumpOpcode):
  Enhance existing function use branch probabilities like
  HexagonInstrInfo::GetDotNewPredOp but for New Value (GPR) Jumps.

llvm-svn: 180923
This commit is contained in:
Jyotsna Verma 2013-05-02 15:39:30 +00:00
parent 40b7f1f6c3
commit 1d29750b7d
4 changed files with 122 additions and 37 deletions

View File

@ -2472,6 +2472,34 @@ bool HexagonInstrInfo::isConstExtended(MachineInstr *MI) const {
return (ImmValue < MinValue || ImmValue > MaxValue);
}
// Returns the opcode to use when converting MI, which is a conditional jump,
// into a conditional instruction which uses the .new value of the predicate.
// We also use branch probabilities to add a hint to the jump.
int
HexagonInstrInfo::getDotNewPredJumpOp(MachineInstr *MI,
const
MachineBranchProbabilityInfo *MBPI) const {
// We assume that block can have at most two successors.
bool taken = false;
MachineBasicBlock *Src = MI->getParent();
MachineOperand *BrTarget = &MI->getOperand(1);
MachineBasicBlock *Dst = BrTarget->getMBB();
const BranchProbability Prediction = MBPI->getEdgeProbability(Src, Dst);
if (Prediction >= BranchProbability(1,2))
taken = true;
switch (MI->getOpcode()) {
case Hexagon::JMP_t:
return taken ? Hexagon::JMP_tnew_t : Hexagon::JMP_tnew_nt;
case Hexagon::JMP_f:
return taken ? Hexagon::JMP_fnew_t : Hexagon::JMP_fnew_nt;
default:
llvm_unreachable("Unexpected jump instruction.");
}
}
// Returns true if a particular operand is extendable for an instruction.
bool HexagonInstrInfo::isOperandExtended(const MachineInstr *MI,
unsigned short OperandNum) const {

View File

@ -18,8 +18,7 @@
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#define GET_INSTRINFO_HEADER
#include "HexagonGenInstrInfo.inc"
@ -192,6 +191,8 @@ public:
void immediateExtend(MachineInstr *MI) const;
bool isConstExtended(MachineInstr *MI) const;
int getDotNewPredJumpOp(MachineInstr *MI,
const MachineBranchProbabilityInfo *MBPI) const;
unsigned getAddrMode(const MachineInstr* MI) const;
bool isOperandExtended(const MachineInstr *MI,
unsigned short OperandNum) const;

View File

@ -68,6 +68,7 @@ namespace {
HexagonNewValueJump() : MachineFunctionPass(ID) { }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<MachineBranchProbabilityInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
@ -78,6 +79,8 @@ namespace {
virtual bool runOnMachineFunction(MachineFunction &Fn);
private:
/// \brief A handle to the branch probability pass.
const MachineBranchProbabilityInfo *MBPI;
};
@ -267,42 +270,58 @@ static bool canCompareBeNewValueJump(const HexagonInstrInfo *QII,
// Given a compare operator, return a matching New Value Jump
// compare operator. Make sure that MI here is included in
// HexagonInstrInfo.cpp::isNewValueJumpCandidate
static unsigned getNewValueJumpOpcode(const MachineInstr *MI, int reg,
bool secondRegNewified) {
static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg,
bool secondRegNewified,
MachineBasicBlock *jmpTarget,
const MachineBranchProbabilityInfo
*MBPI) {
bool taken = false;
MachineBasicBlock *Src = MI->getParent();
const BranchProbability Prediction =
MBPI->getEdgeProbability(Src, jmpTarget);
if (Prediction >= BranchProbability(1,2))
taken = true;
switch (MI->getOpcode()) {
case Hexagon::CMPEQrr:
return Hexagon::JMP_EQrrPt_nv_V4;
return taken ? Hexagon::JMP_EQrrPt_nv_V4 : Hexagon::JMP_EQrrPnt_nv_V4;
case Hexagon::CMPEQri: {
if (reg >= 0)
return Hexagon::JMP_EQriPt_nv_V4;
return taken ? Hexagon::JMP_EQriPt_nv_V4 : Hexagon::JMP_EQriPnt_nv_V4;
else
return Hexagon::JMP_EQriPtneg_nv_V4;
return taken ? Hexagon::JMP_EQriPtneg_nv_V4
: Hexagon::JMP_EQriPntneg_nv_V4;
}
case Hexagon::CMPGTrr: {
if (secondRegNewified)
return Hexagon::JMP_GTrrdnPt_nv_V4;
return taken ? Hexagon::JMP_GTrrdnPt_nv_V4
: Hexagon::JMP_GTrrdnPnt_nv_V4;
else
return Hexagon::JMP_GTrrPt_nv_V4;
return taken ? Hexagon::JMP_GTrrPt_nv_V4
: Hexagon::JMP_GTrrPnt_nv_V4;
}
case Hexagon::CMPGTri: {
if (reg >= 0)
return Hexagon::JMP_GTriPt_nv_V4;
return taken ? Hexagon::JMP_GTriPt_nv_V4 : Hexagon::JMP_GTriPnt_nv_V4;
else
return Hexagon::JMP_GTriPtneg_nv_V4;
return taken ? Hexagon::JMP_GTriPtneg_nv_V4
: Hexagon::JMP_GTriPntneg_nv_V4;
}
case Hexagon::CMPGTUrr: {
if (secondRegNewified)
return Hexagon::JMP_GTUrrdnPt_nv_V4;
return taken ? Hexagon::JMP_GTUrrdnPt_nv_V4
: Hexagon::JMP_GTUrrdnPnt_nv_V4;
else
return Hexagon::JMP_GTUrrPt_nv_V4;
return taken ? Hexagon::JMP_GTUrrPt_nv_V4 : Hexagon::JMP_GTUrrPnt_nv_V4;
}
case Hexagon::CMPGTUri:
return Hexagon::JMP_GTUriPt_nv_V4;
return taken ? Hexagon::JMP_GTUriPt_nv_V4 : Hexagon::JMP_GTUriPnt_nv_V4;
default:
llvm_unreachable("Could not find matching New Value Jump instruction.");
@ -326,6 +345,7 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
QII = static_cast<const HexagonInstrInfo *>(MF.getTarget().getInstrInfo());
QRI =
static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
if (!QRI->Subtarget.hasV4TOps() ||
DisableNewValueJumps) {
@ -560,7 +580,8 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
assert((QII->isNewValueJumpCandidate(cmpInstr)) &&
"This compare is not a New Value Jump candidate.");
unsigned opc = getNewValueJumpOpcode(cmpInstr, cmpOp2,
isSecondOpNewified);
isSecondOpNewified,
jmpTarget, MBPI);
if (invertPredicate)
opc = QII->getInvertedPredicatedOpcode(opc);

View File

@ -48,19 +48,35 @@
#include "HexagonMachineFunctionInfo.h"
#include <map>
#include <vector>
using namespace llvm;
static cl::opt<bool> PacketizeVolatiles("hexagon-packetize-volatiles",
cl::ZeroOrMore, cl::Hidden, cl::init(true),
cl::desc("Allow non-solo packetization of volatile memory references"));
extern cl::opt<bool> ScheduleInlineAsm;
extern cl::opt<bool> CountDeadOutput;
namespace llvm {
void initializeHexagonPacketizerPass(PassRegistry&);
}
namespace {
class HexagonPacketizer : public MachineFunctionPass {
public:
static char ID;
HexagonPacketizer() : MachineFunctionPass(ID) {}
HexagonPacketizer() : MachineFunctionPass(ID) {
initializeHexagonPacketizerPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<MachineDominatorTree>();
AU.addRequired<MachineBranchProbabilityInfo>();
AU.addPreserved<MachineDominatorTree>();
AU.addRequired<MachineLoopInfo>();
AU.addPreserved<MachineLoopInfo>();
@ -96,10 +112,17 @@ namespace {
// schedule this instruction.
bool FoundSequentialDependence;
/// \brief A handle to the branch probability pass.
const MachineBranchProbabilityInfo *MBPI;
// Track MIs with ignored dependece.
std::vector<MachineInstr*> IgnoreDepMIs;
public:
// Ctor.
HexagonPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI,
MachineDominatorTree &MDT);
MachineDominatorTree &MDT,
const MachineBranchProbabilityInfo *MBPI);
// initPacketizerState - initialize some internal flags.
void initPacketizerState();
@ -123,20 +146,20 @@ namespace {
private:
bool IsCallDependent(MachineInstr* MI, SDep::Kind DepType, unsigned DepReg);
bool PromoteToDotNew(MachineInstr* MI, SDep::Kind DepType,
MachineBasicBlock::iterator &MII,
const TargetRegisterClass* RC);
MachineBasicBlock::iterator &MII,
const TargetRegisterClass* RC);
bool CanPromoteToDotNew(MachineInstr* MI, SUnit* PacketSU,
unsigned DepReg,
std::map <MachineInstr*, SUnit*> MIToSUnit,
MachineBasicBlock::iterator &MII,
const TargetRegisterClass* RC);
unsigned DepReg,
std::map <MachineInstr*, SUnit*> MIToSUnit,
MachineBasicBlock::iterator &MII,
const TargetRegisterClass* RC);
bool CanPromoteToNewValue(MachineInstr* MI, SUnit* PacketSU,
unsigned DepReg,
std::map <MachineInstr*, SUnit*> MIToSUnit,
MachineBasicBlock::iterator &MII);
unsigned DepReg,
std::map <MachineInstr*, SUnit*> MIToSUnit,
MachineBasicBlock::iterator &MII);
bool CanPromoteToNewValueStore(MachineInstr* MI, MachineInstr* PacketMI,
unsigned DepReg,
std::map <MachineInstr*, SUnit*> MIToSUnit);
unsigned DepReg,
std::map <MachineInstr*, SUnit*> MIToSUnit);
bool DemoteToDotOld(MachineInstr* MI);
bool ArePredicatesComplements(MachineInstr* MI1, MachineInstr* MI2,
std::map <MachineInstr*, SUnit*> MIToSUnit);
@ -152,19 +175,31 @@ namespace {
};
}
INITIALIZE_PASS_BEGIN(HexagonPacketizer, "packets", "Hexagon Packetizer",
false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_END(HexagonPacketizer, "packets", "Hexagon Packetizer",
false, false)
// HexagonPacketizerList Ctor.
HexagonPacketizerList::HexagonPacketizerList(
MachineFunction &MF, MachineLoopInfo &MLI,MachineDominatorTree &MDT)
MachineFunction &MF, MachineLoopInfo &MLI,MachineDominatorTree &MDT,
const MachineBranchProbabilityInfo *MBPI)
: VLIWPacketizerList(MF, MLI, MDT, true){
this->MBPI = MBPI;
}
bool HexagonPacketizer::runOnMachineFunction(MachineFunction &Fn) {
const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
const MachineBranchProbabilityInfo *MBPI =
&getAnalysis<MachineBranchProbabilityInfo>();
// Instantiate the packetizer.
HexagonPacketizerList Packetizer(Fn, MLI, MDT);
HexagonPacketizerList Packetizer(Fn, MLI, MDT, MBPI);
// DFA state table should not be empty.
assert(Packetizer.getResourceTracker() && "Empty DFA table!");
@ -710,8 +745,10 @@ static int GetDotNewOp(const int opc) {
}
// Return .new predicate version for an instruction
static int GetDotNewPredOp(const int opc) {
switch (opc) {
static int GetDotNewPredOp(MachineInstr *MI,
const MachineBranchProbabilityInfo *MBPI,
const HexagonInstrInfo *QII) {
switch (MI->getOpcode()) {
default: llvm_unreachable("Unknown .new type");
// Conditional stores
// Store byte conditionally
@ -858,10 +895,8 @@ static int GetDotNewPredOp(const int opc) {
// Condtional Jumps
case Hexagon::JMP_t:
return Hexagon::JMP_f;
case Hexagon::JMP_f:
return Hexagon::JMP_fnew_t;
return QII->getDotNewPredJumpOp(MI, MBPI);
case Hexagon::JMPR_t:
return Hexagon::JMPR_tnew_tV3;
@ -1261,7 +1296,7 @@ bool HexagonPacketizerList::PromoteToDotNew(MachineInstr* MI,
int NewOpcode;
if (RC == &Hexagon::PredRegsRegClass)
NewOpcode = GetDotNewPredOp(MI->getOpcode());
NewOpcode = GetDotNewPredOp(MI, MBPI, QII);
else
NewOpcode = GetDotNewOp(MI->getOpcode());
MI->setDesc(QII->get(NewOpcode));