//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "hexagon-nvj"
-#include "Hexagon.h"
-#include "HexagonInstrInfo.h"
-#include "HexagonMachineFunctionInfo.h"
-#include "HexagonRegisterInfo.h"
-#include "HexagonSubtarget.h"
-#include "HexagonTargetMachine.h"
+#include "llvm/PassSupport.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/CodeGen/LiveVariables.h"
-#include "llvm/CodeGen/MachineFunctionAnalysis.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
-#include "llvm/PassSupport.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/LiveVariables.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "Hexagon.h"
+#include "HexagonTargetMachine.h"
+#include "HexagonRegisterInfo.h"
+#include "HexagonSubtarget.h"
+#include "HexagonInstrInfo.h"
+#include "HexagonMachineFunctionInfo.h"
+
#include <map>
+
+#include "llvm/Support/CommandLine.h"
using namespace llvm;
STATISTIC(NumNVJGenerated, "Number of New Value Jump Instructions created");
cl::ZeroOrMore, cl::init(false),
cl::desc("Disable New Value Jumps"));
+namespace llvm {
+ void initializeHexagonNewValueJumpPass(PassRegistry&);
+}
+
+
namespace {
struct HexagonNewValueJump : public MachineFunctionPass {
const HexagonInstrInfo *QII;
public:
static char ID;
- HexagonNewValueJump() : MachineFunctionPass(ID) { }
+ HexagonNewValueJump() : MachineFunctionPass(ID) {
+ initializeHexagonNewValueJumpPass(*PassRegistry::getPassRegistry());
+ }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<MachineBranchProbabilityInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
virtual bool runOnMachineFunction(MachineFunction &Fn);
private:
+ /// \brief A handle to the branch probability pass.
+ const MachineBranchProbabilityInfo *MBPI;
};
char HexagonNewValueJump::ID = 0;
+INITIALIZE_PASS_BEGIN(HexagonNewValueJump, "hexagon-nvj",
+ "Hexagon NewValueJump", false, false)
+INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
+INITIALIZE_PASS_END(HexagonNewValueJump, "hexagon-nvj",
+ "Hexagon NewValueJump", false, false)
+
+
// We have identified this II could be feeder to NVJ,
// verify that it can be.
static bool canBeFeederToNewValueJump(const HexagonInstrInfo *QII,
// range specified by the arch.
if (!secondReg) {
int64_t v = MI->getOperand(2).getImm();
- if (MI->getOpcode() == Hexagon::CMPGEri ||
- (MI->getOpcode() == Hexagon::CMPGEUri && v > 0))
- --v;
if (!(isUInt<5>(v) ||
((MI->getOpcode() == Hexagon::CMPEQri ||
- MI->getOpcode() == Hexagon::CMPGTri ||
- MI->getOpcode() == Hexagon::CMPGEri) &&
+ MI->getOpcode() == Hexagon::CMPGTri) &&
(v == -1))))
return false;
}
- unsigned cmpReg1, cmpOp2;
+ unsigned cmpReg1, cmpOp2 = 0; // cmpOp2 assignment silences compiler warning.
cmpReg1 = MI->getOperand(1).getReg();
if (secondReg) {
// 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::CMPEQrr_t_Jumpnv_t_V4
+ : Hexagon::CMPEQrr_t_Jumpnv_nt_V4;
case Hexagon::CMPEQri: {
if (reg >= 0)
- return Hexagon::JMP_EQriPt_nv_V4;
+ return taken ? Hexagon::CMPEQri_t_Jumpnv_t_V4
+ : Hexagon::CMPEQri_t_Jumpnv_nt_V4;
else
- return Hexagon::JMP_EQriPtneg_nv_V4;
+ return taken ? Hexagon::CMPEQn1_t_Jumpnv_t_V4
+ : Hexagon::CMPEQn1_t_Jumpnv_nt_V4;
}
- case Hexagon::CMPLTrr:
case Hexagon::CMPGTrr: {
if (secondRegNewified)
- return Hexagon::JMP_GTrrdnPt_nv_V4;
+ return taken ? Hexagon::CMPLTrr_t_Jumpnv_t_V4
+ : Hexagon::CMPLTrr_t_Jumpnv_nt_V4;
else
- return Hexagon::JMP_GTrrPt_nv_V4;
- }
-
- case Hexagon::CMPGEri: {
- if (reg >= 1)
- return Hexagon::JMP_GTriPt_nv_V4;
- else
- return Hexagon::JMP_GTriPtneg_nv_V4;
+ return taken ? Hexagon::CMPGTrr_t_Jumpnv_t_V4
+ : Hexagon::CMPGTrr_t_Jumpnv_nt_V4;
}
case Hexagon::CMPGTri: {
if (reg >= 0)
- return Hexagon::JMP_GTriPt_nv_V4;
+ return taken ? Hexagon::CMPGTri_t_Jumpnv_t_V4
+ : Hexagon::CMPGTri_t_Jumpnv_nt_V4;
else
- return Hexagon::JMP_GTriPtneg_nv_V4;
+ return taken ? Hexagon::CMPGTn1_t_Jumpnv_t_V4
+ : Hexagon::CMPGTn1_t_Jumpnv_nt_V4;
}
- case Hexagon::CMPLTUrr:
case Hexagon::CMPGTUrr: {
if (secondRegNewified)
- return Hexagon::JMP_GTUrrdnPt_nv_V4;
+ return taken ? Hexagon::CMPLTUrr_t_Jumpnv_t_V4
+ : Hexagon::CMPLTUrr_t_Jumpnv_nt_V4;
else
- return Hexagon::JMP_GTUrrPt_nv_V4;
+ return taken ? Hexagon::CMPGTUrr_t_Jumpnv_t_V4
+ : Hexagon::CMPGTUrr_t_Jumpnv_nt_V4;
}
case Hexagon::CMPGTUri:
- return Hexagon::JMP_GTUriPt_nv_V4;
-
- case Hexagon::CMPGEUri: {
- if (reg == 0)
- return Hexagon::JMP_EQrrPt_nv_V4;
- else
- return Hexagon::JMP_GTUriPt_nv_V4;
- }
+ return taken ? Hexagon::CMPGTUri_t_Jumpnv_t_V4
+ : Hexagon::CMPGTUri_t_Jumpnv_nt_V4;
default:
llvm_unreachable("Could not find matching New Value Jump instruction.");
QII = static_cast<const HexagonInstrInfo *>(MF.getTarget().getInstrInfo());
QRI =
static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
+ MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
if (!QRI->Subtarget.hasV4TOps() ||
DisableNewValueJumps) {
DEBUG(dbgs() << "Instr: "; MI->dump(); dbgs() << "\n");
if (!foundJump &&
- (MI->getOpcode() == Hexagon::JMP_c ||
- MI->getOpcode() == Hexagon::JMP_cNot ||
- MI->getOpcode() == Hexagon::JMP_cdnPt ||
- MI->getOpcode() == Hexagon::JMP_cdnPnt ||
- MI->getOpcode() == Hexagon::JMP_cdnNotPt ||
- MI->getOpcode() == Hexagon::JMP_cdnNotPnt)) {
+ (MI->getOpcode() == Hexagon::JMP_t ||
+ MI->getOpcode() == Hexagon::JMP_f ||
+ MI->getOpcode() == Hexagon::JMP_tnew_t ||
+ MI->getOpcode() == Hexagon::JMP_tnew_nt ||
+ MI->getOpcode() == Hexagon::JMP_fnew_t ||
+ MI->getOpcode() == Hexagon::JMP_fnew_nt)) {
// This is where you would insert your compare and
// instr that feeds compare
jmpPos = MII;
jmpTarget = MI->getOperand(1).getMBB();
foundJump = true;
- if (MI->getOpcode() == Hexagon::JMP_cNot ||
- MI->getOpcode() == Hexagon::JMP_cdnNotPt ||
- MI->getOpcode() == Hexagon::JMP_cdnNotPnt) {
+ if (MI->getOpcode() == Hexagon::JMP_f ||
+ MI->getOpcode() == Hexagon::JMP_fnew_t ||
+ MI->getOpcode() == Hexagon::JMP_fnew_nt) {
invertPredicate = true;
}
continue;
if (isSecondOpReg) {
// In case of CMPLT, or CMPLTU, or EQ with the second register
// to newify, swap the operands.
- if (cmpInstr->getOpcode() == Hexagon::CMPLTrr ||
- cmpInstr->getOpcode() == Hexagon::CMPLTUrr ||
- (cmpInstr->getOpcode() == Hexagon::CMPEQrr &&
- feederReg == (unsigned) cmpOp2)) {
+ if (cmpInstr->getOpcode() == Hexagon::CMPEQrr &&
+ feederReg == (unsigned) cmpOp2) {
unsigned tmp = cmpReg1;
bool tmpIsKill = MO1IsKill;
cmpReg1 = cmpOp2;
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);
- // Manage the conversions from CMPGEUri to either CMPEQrr
- // or CMPGTUri properly. See Arch spec for CMPGEUri instructions.
- // This has to be after the getNewValueJumpOpcode function call as
- // second operand of the compare could be modified in this logic.
- if (cmpInstr->getOpcode() == Hexagon::CMPGEUri) {
- if (cmpOp2 == 0) {
- cmpOp2 = cmpReg1;
- MO2IsKill = MO1IsKill;
- isSecondOpReg = true;
- } else
- --cmpOp2;
- }
-
- // Manage the conversions from CMPGEri to CMPGTUri properly.
- // See Arch spec for CMPGEri instructions.
- if (cmpInstr->getOpcode() == Hexagon::CMPGEri)
- --cmpOp2;
-
- if (isSecondOpReg) {
+ if (isSecondOpReg)
NewMI = BuildMI(*MBB, jmpPos, dl,
QII->get(opc))
.addReg(cmpReg1, getKillRegState(MO1IsKill))
.addReg(cmpOp2, getKillRegState(MO2IsKill))
.addMBB(jmpTarget);
- }
- else {
+
+ else if ((cmpInstr->getOpcode() == Hexagon::CMPEQri ||
+ cmpInstr->getOpcode() == Hexagon::CMPGTri) &&
+ cmpOp2 == -1 )
+ // Corresponding new-value compare jump instructions don't have the
+ // operand for -1 immediate value.
+ NewMI = BuildMI(*MBB, jmpPos, dl,
+ QII->get(opc))
+ .addReg(cmpReg1, getKillRegState(MO1IsKill))
+ .addMBB(jmpTarget);
+
+ else
NewMI = BuildMI(*MBB, jmpPos, dl,
QII->get(opc))
.addReg(cmpReg1, getKillRegState(MO1IsKill))
.addImm(cmpOp2)
.addMBB(jmpTarget);
- }
assert(NewMI && "New Value Jump Instruction Not created!");
+ (void)NewMI;
if (cmpInstr->getOperand(0).isReg() &&
cmpInstr->getOperand(0).isKill())
cmpInstr->getOperand(0).setIsKill(false);