mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
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:
parent
6f9f86852b
commit
c909ae62a5
@ -2472,6 +2472,34 @@ bool HexagonInstrInfo::isConstExtended(MachineInstr *MI) const {
|
|||||||
return (ImmValue < MinValue || ImmValue > MaxValue);
|
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.
|
// Returns true if a particular operand is extendable for an instruction.
|
||||||
bool HexagonInstrInfo::isOperandExtended(const MachineInstr *MI,
|
bool HexagonInstrInfo::isOperandExtended(const MachineInstr *MI,
|
||||||
unsigned short OperandNum) const {
|
unsigned short OperandNum) const {
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
#include "MCTargetDesc/HexagonBaseInfo.h"
|
#include "MCTargetDesc/HexagonBaseInfo.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
#include "llvm/Target/TargetFrameLowering.h"
|
#include "llvm/Target/TargetFrameLowering.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
|
||||||
|
|
||||||
|
|
||||||
#define GET_INSTRINFO_HEADER
|
#define GET_INSTRINFO_HEADER
|
||||||
#include "HexagonGenInstrInfo.inc"
|
#include "HexagonGenInstrInfo.inc"
|
||||||
@ -192,6 +191,8 @@ public:
|
|||||||
|
|
||||||
void immediateExtend(MachineInstr *MI) const;
|
void immediateExtend(MachineInstr *MI) const;
|
||||||
bool isConstExtended(MachineInstr *MI) const;
|
bool isConstExtended(MachineInstr *MI) const;
|
||||||
|
int getDotNewPredJumpOp(MachineInstr *MI,
|
||||||
|
const MachineBranchProbabilityInfo *MBPI) const;
|
||||||
unsigned getAddrMode(const MachineInstr* MI) const;
|
unsigned getAddrMode(const MachineInstr* MI) const;
|
||||||
bool isOperandExtended(const MachineInstr *MI,
|
bool isOperandExtended(const MachineInstr *MI,
|
||||||
unsigned short OperandNum) const;
|
unsigned short OperandNum) const;
|
||||||
|
@ -68,6 +68,7 @@ namespace {
|
|||||||
HexagonNewValueJump() : MachineFunctionPass(ID) { }
|
HexagonNewValueJump() : MachineFunctionPass(ID) { }
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
|
AU.addRequired<MachineBranchProbabilityInfo>();
|
||||||
MachineFunctionPass::getAnalysisUsage(AU);
|
MachineFunctionPass::getAnalysisUsage(AU);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +79,8 @@ namespace {
|
|||||||
virtual bool runOnMachineFunction(MachineFunction &Fn);
|
virtual bool runOnMachineFunction(MachineFunction &Fn);
|
||||||
|
|
||||||
private:
|
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
|
// Given a compare operator, return a matching New Value Jump
|
||||||
// compare operator. Make sure that MI here is included in
|
// compare operator. Make sure that MI here is included in
|
||||||
// HexagonInstrInfo.cpp::isNewValueJumpCandidate
|
// HexagonInstrInfo.cpp::isNewValueJumpCandidate
|
||||||
static unsigned getNewValueJumpOpcode(const MachineInstr *MI, int reg,
|
static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg,
|
||||||
bool secondRegNewified) {
|
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()) {
|
switch (MI->getOpcode()) {
|
||||||
case Hexagon::CMPEQrr:
|
case Hexagon::CMPEQrr:
|
||||||
return Hexagon::JMP_EQrrPt_nv_V4;
|
return taken ? Hexagon::JMP_EQrrPt_nv_V4 : Hexagon::JMP_EQrrPnt_nv_V4;
|
||||||
|
|
||||||
case Hexagon::CMPEQri: {
|
case Hexagon::CMPEQri: {
|
||||||
if (reg >= 0)
|
if (reg >= 0)
|
||||||
return Hexagon::JMP_EQriPt_nv_V4;
|
return taken ? Hexagon::JMP_EQriPt_nv_V4 : Hexagon::JMP_EQriPnt_nv_V4;
|
||||||
else
|
else
|
||||||
return Hexagon::JMP_EQriPtneg_nv_V4;
|
return taken ? Hexagon::JMP_EQriPtneg_nv_V4
|
||||||
|
: Hexagon::JMP_EQriPntneg_nv_V4;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Hexagon::CMPGTrr: {
|
case Hexagon::CMPGTrr: {
|
||||||
if (secondRegNewified)
|
if (secondRegNewified)
|
||||||
return Hexagon::JMP_GTrrdnPt_nv_V4;
|
return taken ? Hexagon::JMP_GTrrdnPt_nv_V4
|
||||||
|
: Hexagon::JMP_GTrrdnPnt_nv_V4;
|
||||||
else
|
else
|
||||||
return Hexagon::JMP_GTrrPt_nv_V4;
|
return taken ? Hexagon::JMP_GTrrPt_nv_V4
|
||||||
|
: Hexagon::JMP_GTrrPnt_nv_V4;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Hexagon::CMPGTri: {
|
case Hexagon::CMPGTri: {
|
||||||
if (reg >= 0)
|
if (reg >= 0)
|
||||||
return Hexagon::JMP_GTriPt_nv_V4;
|
return taken ? Hexagon::JMP_GTriPt_nv_V4 : Hexagon::JMP_GTriPnt_nv_V4;
|
||||||
else
|
else
|
||||||
return Hexagon::JMP_GTriPtneg_nv_V4;
|
return taken ? Hexagon::JMP_GTriPtneg_nv_V4
|
||||||
|
: Hexagon::JMP_GTriPntneg_nv_V4;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Hexagon::CMPGTUrr: {
|
case Hexagon::CMPGTUrr: {
|
||||||
if (secondRegNewified)
|
if (secondRegNewified)
|
||||||
return Hexagon::JMP_GTUrrdnPt_nv_V4;
|
return taken ? Hexagon::JMP_GTUrrdnPt_nv_V4
|
||||||
|
: Hexagon::JMP_GTUrrdnPnt_nv_V4;
|
||||||
else
|
else
|
||||||
return Hexagon::JMP_GTUrrPt_nv_V4;
|
return taken ? Hexagon::JMP_GTUrrPt_nv_V4 : Hexagon::JMP_GTUrrPnt_nv_V4;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Hexagon::CMPGTUri:
|
case Hexagon::CMPGTUri:
|
||||||
return Hexagon::JMP_GTUriPt_nv_V4;
|
return taken ? Hexagon::JMP_GTUriPt_nv_V4 : Hexagon::JMP_GTUriPnt_nv_V4;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Could not find matching New Value Jump instruction.");
|
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());
|
QII = static_cast<const HexagonInstrInfo *>(MF.getTarget().getInstrInfo());
|
||||||
QRI =
|
QRI =
|
||||||
static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
|
static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
|
||||||
|
MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
|
||||||
|
|
||||||
if (!QRI->Subtarget.hasV4TOps() ||
|
if (!QRI->Subtarget.hasV4TOps() ||
|
||||||
DisableNewValueJumps) {
|
DisableNewValueJumps) {
|
||||||
@ -560,7 +580,8 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
assert((QII->isNewValueJumpCandidate(cmpInstr)) &&
|
assert((QII->isNewValueJumpCandidate(cmpInstr)) &&
|
||||||
"This compare is not a New Value Jump candidate.");
|
"This compare is not a New Value Jump candidate.");
|
||||||
unsigned opc = getNewValueJumpOpcode(cmpInstr, cmpOp2,
|
unsigned opc = getNewValueJumpOpcode(cmpInstr, cmpOp2,
|
||||||
isSecondOpNewified);
|
isSecondOpNewified,
|
||||||
|
jmpTarget, MBPI);
|
||||||
if (invertPredicate)
|
if (invertPredicate)
|
||||||
opc = QII->getInvertedPredicatedOpcode(opc);
|
opc = QII->getInvertedPredicatedOpcode(opc);
|
||||||
|
|
||||||
|
@ -48,19 +48,35 @@
|
|||||||
#include "HexagonMachineFunctionInfo.h"
|
#include "HexagonMachineFunctionInfo.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace llvm;
|
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 {
|
namespace {
|
||||||
class HexagonPacketizer : public MachineFunctionPass {
|
class HexagonPacketizer : public MachineFunctionPass {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID;
|
static char ID;
|
||||||
HexagonPacketizer() : MachineFunctionPass(ID) {}
|
HexagonPacketizer() : MachineFunctionPass(ID) {
|
||||||
|
initializeHexagonPacketizerPass(*PassRegistry::getPassRegistry());
|
||||||
|
}
|
||||||
|
|
||||||
void getAnalysisUsage(AnalysisUsage &AU) const {
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesCFG();
|
AU.setPreservesCFG();
|
||||||
AU.addRequired<MachineDominatorTree>();
|
AU.addRequired<MachineDominatorTree>();
|
||||||
|
AU.addRequired<MachineBranchProbabilityInfo>();
|
||||||
AU.addPreserved<MachineDominatorTree>();
|
AU.addPreserved<MachineDominatorTree>();
|
||||||
AU.addRequired<MachineLoopInfo>();
|
AU.addRequired<MachineLoopInfo>();
|
||||||
AU.addPreserved<MachineLoopInfo>();
|
AU.addPreserved<MachineLoopInfo>();
|
||||||
@ -96,10 +112,17 @@ namespace {
|
|||||||
// schedule this instruction.
|
// schedule this instruction.
|
||||||
bool FoundSequentialDependence;
|
bool FoundSequentialDependence;
|
||||||
|
|
||||||
|
/// \brief A handle to the branch probability pass.
|
||||||
|
const MachineBranchProbabilityInfo *MBPI;
|
||||||
|
|
||||||
|
// Track MIs with ignored dependece.
|
||||||
|
std::vector<MachineInstr*> IgnoreDepMIs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Ctor.
|
// Ctor.
|
||||||
HexagonPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI,
|
HexagonPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI,
|
||||||
MachineDominatorTree &MDT);
|
MachineDominatorTree &MDT,
|
||||||
|
const MachineBranchProbabilityInfo *MBPI);
|
||||||
|
|
||||||
// initPacketizerState - initialize some internal flags.
|
// initPacketizerState - initialize some internal flags.
|
||||||
void initPacketizerState();
|
void initPacketizerState();
|
||||||
@ -123,20 +146,20 @@ namespace {
|
|||||||
private:
|
private:
|
||||||
bool IsCallDependent(MachineInstr* MI, SDep::Kind DepType, unsigned DepReg);
|
bool IsCallDependent(MachineInstr* MI, SDep::Kind DepType, unsigned DepReg);
|
||||||
bool PromoteToDotNew(MachineInstr* MI, SDep::Kind DepType,
|
bool PromoteToDotNew(MachineInstr* MI, SDep::Kind DepType,
|
||||||
MachineBasicBlock::iterator &MII,
|
MachineBasicBlock::iterator &MII,
|
||||||
const TargetRegisterClass* RC);
|
const TargetRegisterClass* RC);
|
||||||
bool CanPromoteToDotNew(MachineInstr* MI, SUnit* PacketSU,
|
bool CanPromoteToDotNew(MachineInstr* MI, SUnit* PacketSU,
|
||||||
unsigned DepReg,
|
unsigned DepReg,
|
||||||
std::map <MachineInstr*, SUnit*> MIToSUnit,
|
std::map <MachineInstr*, SUnit*> MIToSUnit,
|
||||||
MachineBasicBlock::iterator &MII,
|
MachineBasicBlock::iterator &MII,
|
||||||
const TargetRegisterClass* RC);
|
const TargetRegisterClass* RC);
|
||||||
bool CanPromoteToNewValue(MachineInstr* MI, SUnit* PacketSU,
|
bool CanPromoteToNewValue(MachineInstr* MI, SUnit* PacketSU,
|
||||||
unsigned DepReg,
|
unsigned DepReg,
|
||||||
std::map <MachineInstr*, SUnit*> MIToSUnit,
|
std::map <MachineInstr*, SUnit*> MIToSUnit,
|
||||||
MachineBasicBlock::iterator &MII);
|
MachineBasicBlock::iterator &MII);
|
||||||
bool CanPromoteToNewValueStore(MachineInstr* MI, MachineInstr* PacketMI,
|
bool CanPromoteToNewValueStore(MachineInstr* MI, MachineInstr* PacketMI,
|
||||||
unsigned DepReg,
|
unsigned DepReg,
|
||||||
std::map <MachineInstr*, SUnit*> MIToSUnit);
|
std::map <MachineInstr*, SUnit*> MIToSUnit);
|
||||||
bool DemoteToDotOld(MachineInstr* MI);
|
bool DemoteToDotOld(MachineInstr* MI);
|
||||||
bool ArePredicatesComplements(MachineInstr* MI1, MachineInstr* MI2,
|
bool ArePredicatesComplements(MachineInstr* MI1, MachineInstr* MI2,
|
||||||
std::map <MachineInstr*, SUnit*> MIToSUnit);
|
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 Ctor.
|
||||||
HexagonPacketizerList::HexagonPacketizerList(
|
HexagonPacketizerList::HexagonPacketizerList(
|
||||||
MachineFunction &MF, MachineLoopInfo &MLI,MachineDominatorTree &MDT)
|
MachineFunction &MF, MachineLoopInfo &MLI,MachineDominatorTree &MDT,
|
||||||
|
const MachineBranchProbabilityInfo *MBPI)
|
||||||
: VLIWPacketizerList(MF, MLI, MDT, true){
|
: VLIWPacketizerList(MF, MLI, MDT, true){
|
||||||
|
this->MBPI = MBPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HexagonPacketizer::runOnMachineFunction(MachineFunction &Fn) {
|
bool HexagonPacketizer::runOnMachineFunction(MachineFunction &Fn) {
|
||||||
const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
|
const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
|
||||||
MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
|
MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
|
||||||
MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
|
MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
|
||||||
|
const MachineBranchProbabilityInfo *MBPI =
|
||||||
|
&getAnalysis<MachineBranchProbabilityInfo>();
|
||||||
// Instantiate the packetizer.
|
// Instantiate the packetizer.
|
||||||
HexagonPacketizerList Packetizer(Fn, MLI, MDT);
|
HexagonPacketizerList Packetizer(Fn, MLI, MDT, MBPI);
|
||||||
|
|
||||||
// DFA state table should not be empty.
|
// DFA state table should not be empty.
|
||||||
assert(Packetizer.getResourceTracker() && "Empty DFA table!");
|
assert(Packetizer.getResourceTracker() && "Empty DFA table!");
|
||||||
@ -710,8 +745,10 @@ static int GetDotNewOp(const int opc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return .new predicate version for an instruction
|
// Return .new predicate version for an instruction
|
||||||
static int GetDotNewPredOp(const int opc) {
|
static int GetDotNewPredOp(MachineInstr *MI,
|
||||||
switch (opc) {
|
const MachineBranchProbabilityInfo *MBPI,
|
||||||
|
const HexagonInstrInfo *QII) {
|
||||||
|
switch (MI->getOpcode()) {
|
||||||
default: llvm_unreachable("Unknown .new type");
|
default: llvm_unreachable("Unknown .new type");
|
||||||
// Conditional stores
|
// Conditional stores
|
||||||
// Store byte conditionally
|
// Store byte conditionally
|
||||||
@ -858,10 +895,8 @@ static int GetDotNewPredOp(const int opc) {
|
|||||||
|
|
||||||
// Condtional Jumps
|
// Condtional Jumps
|
||||||
case Hexagon::JMP_t:
|
case Hexagon::JMP_t:
|
||||||
return Hexagon::JMP_f;
|
|
||||||
|
|
||||||
case Hexagon::JMP_f:
|
case Hexagon::JMP_f:
|
||||||
return Hexagon::JMP_fnew_t;
|
return QII->getDotNewPredJumpOp(MI, MBPI);
|
||||||
|
|
||||||
case Hexagon::JMPR_t:
|
case Hexagon::JMPR_t:
|
||||||
return Hexagon::JMPR_tnew_tV3;
|
return Hexagon::JMPR_tnew_tV3;
|
||||||
@ -1261,7 +1296,7 @@ bool HexagonPacketizerList::PromoteToDotNew(MachineInstr* MI,
|
|||||||
|
|
||||||
int NewOpcode;
|
int NewOpcode;
|
||||||
if (RC == &Hexagon::PredRegsRegClass)
|
if (RC == &Hexagon::PredRegsRegClass)
|
||||||
NewOpcode = GetDotNewPredOp(MI->getOpcode());
|
NewOpcode = GetDotNewPredOp(MI, MBPI, QII);
|
||||||
else
|
else
|
||||||
NewOpcode = GetDotNewOp(MI->getOpcode());
|
NewOpcode = GetDotNewOp(MI->getOpcode());
|
||||||
MI->setDesc(QII->get(NewOpcode));
|
MI->setDesc(QII->get(NewOpcode));
|
||||||
|
Loading…
Reference in New Issue
Block a user