diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon')
21 files changed, 1270 insertions, 1432 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/Hexagon.h b/contrib/llvm/lib/Target/Hexagon/Hexagon.h index dfbefc8..a9b00a2 100644 --- a/contrib/llvm/lib/Target/Hexagon/Hexagon.h +++ b/contrib/llvm/lib/Target/Hexagon/Hexagon.h @@ -29,26 +29,25 @@ namespace llvm { class HexagonTargetMachine; class raw_ostream; - FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM, + FunctionPass *createHexagonISelDag(const HexagonTargetMachine &TM, CodeGenOpt::Level OptLevel); - FunctionPass *createHexagonDelaySlotFillerPass(TargetMachine &TM); - FunctionPass *createHexagonFPMoverPass(TargetMachine &TM); - FunctionPass *createHexagonRemoveExtendOps(HexagonTargetMachine &TM); - FunctionPass *createHexagonCFGOptimizer(HexagonTargetMachine &TM); - - FunctionPass *createHexagonSplitTFRCondSets(HexagonTargetMachine &TM); - FunctionPass *createHexagonExpandPredSpillCode(HexagonTargetMachine &TM); + FunctionPass *createHexagonDelaySlotFillerPass(const TargetMachine &TM); + FunctionPass *createHexagonFPMoverPass(const TargetMachine &TM); + FunctionPass *createHexagonRemoveExtendArgs(const HexagonTargetMachine &TM); + FunctionPass *createHexagonCFGOptimizer(const HexagonTargetMachine &TM); + FunctionPass *createHexagonSplitTFRCondSets(const HexagonTargetMachine &TM); + FunctionPass *createHexagonExpandPredSpillCode( + const HexagonTargetMachine &TM); FunctionPass *createHexagonHardwareLoops(); FunctionPass *createHexagonPeephole(); FunctionPass *createHexagonFixupHwLoops(); FunctionPass *createHexagonPacketizer(); FunctionPass *createHexagonNewValueJump(); - /* TODO: object output. MCCodeEmitter *createHexagonMCCodeEmitter(const Target &, - TargetMachine &TM, + const TargetMachine &TM, MCContext &Ctx); */ /* TODO: assembler input. diff --git a/contrib/llvm/lib/Target/Hexagon/Hexagon.td b/contrib/llvm/lib/Target/Hexagon/Hexagon.td index 8a5ee40..9b3a643 100644 --- a/contrib/llvm/lib/Target/Hexagon/Hexagon.td +++ b/contrib/llvm/lib/Target/Hexagon/Hexagon.td @@ -84,12 +84,36 @@ def getPredOpcode : InstrMapping { } //===----------------------------------------------------------------------===// +// Generate mapping table to relate predicate-true instructions with their +// predicate-false forms +// +def getFalsePredOpcode : InstrMapping { + let FilterClass = "PredRel"; + let RowFields = ["BaseOpcode", "PNewValue", "isNVStore", "isBrTaken"]; + let ColFields = ["PredSense"]; + let KeyCol = ["true"]; + let ValueCols = [["false"]]; +} + +//===----------------------------------------------------------------------===// +// Generate mapping table to relate predicate-false instructions with their +// predicate-true forms +// +def getTruePredOpcode : InstrMapping { + let FilterClass = "PredRel"; + let RowFields = ["BaseOpcode", "PNewValue", "isNVStore", "isBrTaken"]; + let ColFields = ["PredSense"]; + let KeyCol = ["false"]; + let ValueCols = [["true"]]; +} + +//===----------------------------------------------------------------------===// // Generate mapping table to relate predicated instructions with their .new // format. // def getPredNewOpcode : InstrMapping { let FilterClass = "PredNewRel"; - let RowFields = ["BaseOpcode", "PredSense", "isNVStore"]; + let RowFields = ["BaseOpcode", "PredSense", "isNVStore", "isBrTaken"]; let ColFields = ["PNewValue"]; let KeyCol = [""]; let ValueCols = [["new"]]; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp index d4078ad..8597f11 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp @@ -26,21 +26,27 @@ using namespace llvm; +namespace llvm { + void initializeHexagonCFGOptimizerPass(PassRegistry&); +} + + namespace { class HexagonCFGOptimizer : public MachineFunctionPass { private: - HexagonTargetMachine& QTM; + const HexagonTargetMachine& QTM; const HexagonSubtarget &QST; void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*); public: static char ID; - HexagonCFGOptimizer(HexagonTargetMachine& TM) : MachineFunctionPass(ID), - QTM(TM), - QST(*TM.getSubtargetImpl()) {} + HexagonCFGOptimizer(const HexagonTargetMachine& TM) + : MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) { + initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry()); + } const char *getPassName() const { return "Hexagon CFG Optimizer"; @@ -52,8 +58,8 @@ private: char HexagonCFGOptimizer::ID = 0; static bool IsConditionalBranch(int Opc) { - return (Opc == Hexagon::JMP_c) || (Opc == Hexagon::JMP_cNot) - || (Opc == Hexagon::JMP_cdnPt) || (Opc == Hexagon::JMP_cdnNotPt); + return (Opc == Hexagon::JMP_t) || (Opc == Hexagon::JMP_f) + || (Opc == Hexagon::JMP_tnew_t) || (Opc == Hexagon::JMP_fnew_t); } @@ -68,20 +74,20 @@ HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI, const HexagonInstrInfo *QII = QTM.getInstrInfo(); int NewOpcode = 0; switch(MI->getOpcode()) { - case Hexagon::JMP_c: - NewOpcode = Hexagon::JMP_cNot; + case Hexagon::JMP_t: + NewOpcode = Hexagon::JMP_f; break; - case Hexagon::JMP_cNot: - NewOpcode = Hexagon::JMP_c; + case Hexagon::JMP_f: + NewOpcode = Hexagon::JMP_t; break; - case Hexagon::JMP_cdnPt: - NewOpcode = Hexagon::JMP_cdnNotPt; + case Hexagon::JMP_tnew_t: + NewOpcode = Hexagon::JMP_fnew_t; break; - case Hexagon::JMP_cdnNotPt: - NewOpcode = Hexagon::JMP_cdnPt; + case Hexagon::JMP_fnew_t: + NewOpcode = Hexagon::JMP_tnew_t; break; default: @@ -156,8 +162,8 @@ bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { // The target of the unconditional branch must be JumpAroundTarget. // TODO: If not, we should not invert the unconditional branch. MachineBasicBlock* CondBranchTarget = NULL; - if ((MI->getOpcode() == Hexagon::JMP_c) || - (MI->getOpcode() == Hexagon::JMP_cNot)) { + if ((MI->getOpcode() == Hexagon::JMP_t) || + (MI->getOpcode() == Hexagon::JMP_f)) { CondBranchTarget = MI->getOperand(1).getMBB(); } @@ -231,6 +237,16 @@ bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { // Public Constructor Functions //===----------------------------------------------------------------------===// -FunctionPass *llvm::createHexagonCFGOptimizer(HexagonTargetMachine &TM) { +static void initializePassOnce(PassRegistry &Registry) { + PassInfo *PI = new PassInfo("Hexagon CFG Optimizer", "hexagon-cfg", + &HexagonCFGOptimizer::ID, 0, false, false); + Registry.registerPass(*PI, true); +} + +void llvm::initializeHexagonCFGOptimizerPass(PassRegistry &Registry) { + CALL_ONCE_INITIALIZATION(initializePassOnce) +} + +FunctionPass *llvm::createHexagonCFGOptimizer(const HexagonTargetMachine &TM) { return new HexagonCFGOptimizer(TM); } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp index 0814421..8a5991f 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp @@ -41,16 +41,24 @@ using namespace llvm; +namespace llvm { + void initializeHexagonExpandPredSpillCodePass(PassRegistry&); +} + + namespace { class HexagonExpandPredSpillCode : public MachineFunctionPass { - HexagonTargetMachine& QTM; + const HexagonTargetMachine& QTM; const HexagonSubtarget &QST; public: static char ID; - HexagonExpandPredSpillCode(HexagonTargetMachine& TM) : - MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} + HexagonExpandPredSpillCode(const HexagonTargetMachine& TM) : + MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) { + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeHexagonExpandPredSpillCodePass(Registry); + } const char *getPassName() const { return "Hexagon Expand Predicate Spill Code"; @@ -175,6 +183,19 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { // Public Constructor Functions //===----------------------------------------------------------------------===// -FunctionPass *llvm::createHexagonExpandPredSpillCode(HexagonTargetMachine &TM) { +static void initializePassOnce(PassRegistry &Registry) { + const char *Name = "Hexagon Expand Predicate Spill Code"; + PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred", + &HexagonExpandPredSpillCode::ID, + 0, false, false); + Registry.registerPass(*PI, true); +} + +void llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) { + CALL_ONCE_INITIALIZATION(initializePassOnce) +} + +FunctionPass* +llvm::createHexagonExpandPredSpillCode(const HexagonTargetMachine &TM) { return new HexagonExpandPredSpillCode(TM); } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp index d6a9329..de993ee 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -189,7 +189,7 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher // versions. - if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR + if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPret && !DisableDeallocRet) { // Remove jumpr node. MBB.erase(MBBI); diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp index 1786624..d002788 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -541,12 +541,6 @@ CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L, case Hexagon::CMPEQrr: Cmp = !Negated ? Comparison::EQ : Comparison::NE; break; - case Hexagon::CMPLTrr: - Cmp = !Negated ? Comparison::LTs : Comparison::GEs; - break; - case Hexagon::CMPLTUrr: - Cmp = !Negated ? Comparison::LTu : Comparison::GEu; - break; case Hexagon::CMPGTUri: case Hexagon::CMPGTUrr: Cmp = !Negated ? Comparison::GTu : Comparison::LEu; @@ -1125,8 +1119,8 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { // The loop ends with either: // - a conditional branch followed by an unconditional branch, or // - a conditional branch to the loop start. - if (LastI->getOpcode() == Hexagon::JMP_c || - LastI->getOpcode() == Hexagon::JMP_cNot) { + if (LastI->getOpcode() == Hexagon::JMP_t || + LastI->getOpcode() == Hexagon::JMP_f) { // Delete one and change/add an uncond. branch to out of the loop. MachineBasicBlock *BranchTarget = LastI->getOperand(1).getMBB(); LastI = LastMBB->erase(LastI); diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 8fc9ba1..54ca2c9 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -49,11 +49,11 @@ class HexagonDAGToDAGISel : public SelectionDAGISel { const HexagonSubtarget &Subtarget; // Keep a reference to HexagonTargetMachine. - HexagonTargetMachine& TM; + const HexagonTargetMachine& TM; const HexagonInstrInfo *TII; DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap; public: - explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine, + explicit HexagonDAGToDAGISel(const HexagonTargetMachine &targetmachine, CodeGenOpt::Level OptLevel) : SelectionDAGISel(targetmachine, OptLevel), Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()), @@ -160,6 +160,17 @@ inline SDValue XformU7ToU7M1Imm(signed Imm) { return CurDAG->getTargetConstant(Imm - 1, MVT::i8); } +// XformS8ToS8M1Imm - Return a target constant decremented by 1. +inline SDValue XformSToSM1Imm(signed Imm) { + return CurDAG->getTargetConstant(Imm - 1, MVT::i32); +} + +// XformU8ToU8M1Imm - Return a target constant decremented by 1. +inline SDValue XformUToUM1Imm(unsigned Imm) { + assert((Imm >= 1) && "Cannot decrement unsigned int less than 1"); + return CurDAG->getTargetConstant(Imm - 1, MVT::i32); +} + // Include the pieces autogenerated from the target description. #include "HexagonGenDAGISel.inc" }; @@ -169,7 +180,7 @@ inline SDValue XformU7ToU7M1Imm(signed Imm) { /// createHexagonISelDag - This pass converts a legalized DAG into a /// Hexagon-specific DAG, ready for instruction scheduling. /// -FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM, +FunctionPass *llvm::createHexagonISelDag(const HexagonTargetMachine &TM, CodeGenOpt::Level OptLevel) { return new HexagonDAGToDAGISel(TM, OptLevel); } @@ -697,7 +708,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { // Build post increment store. SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32, - MVT::Other, Ops, 4); + MVT::Other, Ops); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = ST->getMemOperand(); cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); @@ -723,8 +734,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { // Build regular store. SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); - SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, - 4); + SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops); // Build splitted incriment instruction. SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, Base, @@ -780,7 +790,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, Value, Chain}; // build indexed store SDNode* Result = CurDAG->getMachineNode(Opcode, dl, - MVT::Other, Ops, 4); + MVT::Other, Ops); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = ST->getMemOperand(); cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); @@ -1230,8 +1240,7 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { } EVT ReturnValueVT = N->getValueType(0); SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl, - ReturnValueVT, - Ops.data(), Ops.size()); + ReturnValueVT, Ops); ReplaceUses(N, Result); return Result; } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 15858a9..0e5b8dc 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1002,14 +1002,6 @@ HexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { return FrameAddr; } - -SDValue HexagonTargetLowering::LowerMEMBARRIER(SDValue Op, - SelectionDAG& DAG) const { - DebugLoc dl = Op.getDebugLoc(); - return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0)); -} - - SDValue HexagonTargetLowering::LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const { DebugLoc dl = Op.getDebugLoc(); @@ -1361,7 +1353,6 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine } - setOperationAction(ISD::BRIND, MVT::Other, Expand); if (EmitJumpTables) { setOperationAction(ISD::BR_JT, MVT::Other, Custom); } else { @@ -1377,7 +1368,6 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine setOperationAction(ISD::BR_CC, MVT::i32, Expand); setOperationAction(ISD::BR_CC, MVT::i64, Expand); - setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); setOperationAction(ISD::FSIN , MVT::f64, Expand); @@ -1444,7 +1434,7 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); - setOperationAction(ISD::EH_RETURN, MVT::Other, Expand); + setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); if (TM.getSubtargetImpl()->isSubtargetV2()) { setExceptionPointerRegister(Hexagon::R20); @@ -1499,6 +1489,7 @@ HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { case HexagonISD::RET_FLAG: return "HexagonISD::RET_FLAG"; case HexagonISD::BR_JT: return "HexagonISD::BR_JT"; case HexagonISD::TC_RETURN: return "HexagonISD::TC_RETURN"; + case HexagonISD::EH_RETURN: return "HexagonISD::EH_RETURN"; } } @@ -1520,16 +1511,43 @@ bool HexagonTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { } SDValue +HexagonTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + SDValue Offset = Op.getOperand(1); + SDValue Handler = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + + // Mark function as containing a call to EH_RETURN. + HexagonMachineFunctionInfo *FuncInfo = + DAG.getMachineFunction().getInfo<HexagonMachineFunctionInfo>(); + FuncInfo->setHasEHReturn(); + + unsigned OffsetReg = Hexagon::R28; + + SDValue StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(), + DAG.getRegister(Hexagon::R30, getPointerTy()), + DAG.getIntPtrConstant(4)); + Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo(), + false, false, 0); + Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset); + + // Not needed we already use it as explict input to EH_RETURN. + // MF.getRegInfo().addLiveOut(OffsetReg); + + return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain); +} + +SDValue HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { default: llvm_unreachable("Should not custom lower this!"); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); + case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG); // Frame & Return address. Currently unimplemented. case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::GlobalTLSAddress: llvm_unreachable("TLS not implemented for Hexagon."); - case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h index 3279cc6..bb1acc1 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h @@ -62,7 +62,8 @@ namespace llvm { WrapperShuffEH, WrapperShuffOB, WrapperShuffOH, - TC_RETURN + TC_RETURN, + EH_RETURN }; } @@ -101,6 +102,7 @@ namespace llvm { SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const; SDValue LowerEH_LABEL(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, @@ -122,7 +124,6 @@ namespace llvm { SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp index 60b12ac..f114170 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -23,7 +23,9 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #define GET_INSTRINFO_CTOR #define GET_INSTRMAP_INFO #include "HexagonGenInstrInfo.inc" @@ -118,16 +120,16 @@ HexagonInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, DebugLoc DL) const{ int BOpc = Hexagon::JMP; - int BccOpc = Hexagon::JMP_c; + int BccOpc = Hexagon::JMP_t; assert(TBB && "InsertBranch must not be told to insert a fallthrough"); int regPos = 0; // Check if ReverseBranchCondition has asked to reverse this branch // If we want to reverse the branch an odd number of times, we want - // JMP_cNot. + // JMP_f. if (!Cond.empty() && Cond[0].isImm() && Cond[0].getImm() == 0) { - BccOpc = Hexagon::JMP_cNot; + BccOpc = Hexagon::JMP_f; regPos = 1; } @@ -174,8 +176,8 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, FBB = NULL; // If the block has no terminators, it just falls into the block after it. - MachineBasicBlock::iterator I = MBB.end(); - if (I == MBB.begin()) + MachineBasicBlock::instr_iterator I = MBB.instr_end(); + if (I == MBB.instr_begin()) return false; // A basic block may looks like this: @@ -194,13 +196,24 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, --I; if (I->isEHLabel()) return true; - } while (I != MBB.begin()); + } while (I != MBB.instr_begin()); - I = MBB.end(); + I = MBB.instr_end(); --I; while (I->isDebugValue()) { - if (I == MBB.begin()) + if (I == MBB.instr_begin()) + return false; + --I; + } + + // Delete the JMP if it's equivalent to a fall-through. + if (AllowModify && I->getOpcode() == Hexagon::JMP && + MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { + DEBUG(dbgs()<< "\nErasing the jump to successor block\n";); + I->eraseFromParent(); + I = MBB.instr_end(); + if (I == MBB.instr_begin()) return false; --I; } @@ -209,23 +222,42 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // Get the last instruction in the block. MachineInstr *LastInst = I; + MachineInstr *SecondLastInst = NULL; + // Find one more terminator if present. + do { + if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(I)) { + if (!SecondLastInst) + SecondLastInst = I; + else + // This is a third branch. + return true; + } + if (I == MBB.instr_begin()) + break; + --I; + } while(I); + + int LastOpcode = LastInst->getOpcode(); + + bool LastOpcodeHasJMP_c = PredOpcodeHasJMP_c(LastOpcode); + bool LastOpcodeHasNot = PredOpcodeHasNot(LastOpcode); // If there is only one terminator instruction, process it. - if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { - if (LastInst->getOpcode() == Hexagon::JMP) { + if (LastInst && !SecondLastInst) { + if (LastOpcode == Hexagon::JMP) { TBB = LastInst->getOperand(0).getMBB(); return false; } - if (LastInst->getOpcode() == Hexagon::JMP_c) { - // Block ends with fall-through true condbranch. - TBB = LastInst->getOperand(1).getMBB(); + if (LastOpcode == Hexagon::ENDLOOP0) { + TBB = LastInst->getOperand(0).getMBB(); Cond.push_back(LastInst->getOperand(0)); return false; } - if (LastInst->getOpcode() == Hexagon::JMP_cNot) { - // Block ends with fall-through false condbranch. + if (LastOpcodeHasJMP_c) { TBB = LastInst->getOperand(1).getMBB(); - Cond.push_back(MachineOperand::CreateImm(0)); + if (LastOpcodeHasNot) { + Cond.push_back(MachineOperand::CreateImm(0)); + } Cond.push_back(LastInst->getOperand(0)); return false; } @@ -233,29 +265,14 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, return true; } - // Get the instruction before it if it's a terminator. - MachineInstr *SecondLastInst = I; - - // If there are three terminators, we don't know what sort of block this is. - if (SecondLastInst && I != MBB.begin() && - isUnpredicatedTerminator(--I)) - return true; + int SecLastOpcode = SecondLastInst->getOpcode(); - // If the block ends with Hexagon::BRCOND and Hexagon:JMP, handle it. - if (((SecondLastInst->getOpcode() == Hexagon::BRCOND) || - (SecondLastInst->getOpcode() == Hexagon::JMP_c)) && - LastInst->getOpcode() == Hexagon::JMP) { + bool SecLastOpcodeHasJMP_c = PredOpcodeHasJMP_c(SecLastOpcode); + bool SecLastOpcodeHasNot = PredOpcodeHasNot(SecLastOpcode); + if (SecLastOpcodeHasJMP_c && (LastOpcode == Hexagon::JMP)) { TBB = SecondLastInst->getOperand(1).getMBB(); - Cond.push_back(SecondLastInst->getOperand(0)); - FBB = LastInst->getOperand(0).getMBB(); - return false; - } - - // If the block ends with Hexagon::JMP_cNot and Hexagon:JMP, handle it. - if ((SecondLastInst->getOpcode() == Hexagon::JMP_cNot) && - LastInst->getOpcode() == Hexagon::JMP) { - TBB = SecondLastInst->getOperand(1).getMBB(); - Cond.push_back(MachineOperand::CreateImm(0)); + if (SecLastOpcodeHasNot) + Cond.push_back(MachineOperand::CreateImm(0)); Cond.push_back(SecondLastInst->getOperand(0)); FBB = LastInst->getOperand(0).getMBB(); return false; @@ -263,8 +280,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // If the block ends with two Hexagon:JMPs, handle it. The second one is not // executed, so remove it. - if (SecondLastInst->getOpcode() == Hexagon::JMP && - LastInst->getOpcode() == Hexagon::JMP) { + if (SecLastOpcode == Hexagon::JMP && LastOpcode == Hexagon::JMP) { TBB = SecondLastInst->getOperand(0).getMBB(); I = LastInst; if (AllowModify) @@ -272,6 +288,15 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, return false; } + // If the block ends with an ENDLOOP, and JMP, handle it. + if (SecLastOpcode == Hexagon::ENDLOOP0 && + LastOpcode == Hexagon::JMP) { + TBB = SecondLastInst->getOperand(0).getMBB(); + Cond.push_back(SecondLastInst->getOperand(0)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + // Otherwise, can't handle this. return true; } @@ -279,8 +304,8 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, unsigned HexagonInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { int BOpc = Hexagon::JMP; - int BccOpc = Hexagon::JMP_c; - int BccOpcNot = Hexagon::JMP_cNot; + int BccOpc = Hexagon::JMP_t; + int BccOpcNot = Hexagon::JMP_f; MachineBasicBlock::iterator I = MBB.end(); if (I == MBB.begin()) return 0; @@ -325,8 +350,6 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI, case Hexagon::CMPGTUrr: case Hexagon::CMPGTri: case Hexagon::CMPGTrr: - case Hexagon::CMPLTUrr: - case Hexagon::CMPLTrr: SrcReg = MI->getOperand(1).getReg(); Mask = ~0; break; @@ -366,8 +389,6 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI, case Hexagon::CMPhEQrr_xor_V4: case Hexagon::CMPhGTUrr_V4: case Hexagon::CMPhGTrr_shl_V4: - case Hexagon::CMPLTUrr: - case Hexagon::CMPLTrr: SrcReg2 = MI->getOperand(2).getReg(); return true; @@ -605,110 +626,8 @@ bool HexagonInstrInfo::isExtended(const MachineInstr *MI) const { return false; } -bool HexagonInstrInfo::isNewValueJump(const MachineInstr *MI) const { - switch (MI->getOpcode()) { - default: return false; - // JMP_EQri - case Hexagon::JMP_EQriPt_nv_V4: - case Hexagon::JMP_EQriPnt_nv_V4: - case Hexagon::JMP_EQriNotPt_nv_V4: - case Hexagon::JMP_EQriNotPnt_nv_V4: - case Hexagon::JMP_EQriPt_ie_nv_V4: - case Hexagon::JMP_EQriPnt_ie_nv_V4: - case Hexagon::JMP_EQriNotPt_ie_nv_V4: - case Hexagon::JMP_EQriNotPnt_ie_nv_V4: - - // JMP_EQri - with -1 - case Hexagon::JMP_EQriPtneg_nv_V4: - case Hexagon::JMP_EQriPntneg_nv_V4: - case Hexagon::JMP_EQriNotPtneg_nv_V4: - case Hexagon::JMP_EQriNotPntneg_nv_V4: - case Hexagon::JMP_EQriPtneg_ie_nv_V4: - case Hexagon::JMP_EQriPntneg_ie_nv_V4: - case Hexagon::JMP_EQriNotPtneg_ie_nv_V4: - case Hexagon::JMP_EQriNotPntneg_ie_nv_V4: - - // JMP_EQrr - case Hexagon::JMP_EQrrPt_nv_V4: - case Hexagon::JMP_EQrrPnt_nv_V4: - case Hexagon::JMP_EQrrNotPt_nv_V4: - case Hexagon::JMP_EQrrNotPnt_nv_V4: - case Hexagon::JMP_EQrrPt_ie_nv_V4: - case Hexagon::JMP_EQrrPnt_ie_nv_V4: - case Hexagon::JMP_EQrrNotPt_ie_nv_V4: - case Hexagon::JMP_EQrrNotPnt_ie_nv_V4: - - // JMP_GTri - case Hexagon::JMP_GTriPt_nv_V4: - case Hexagon::JMP_GTriPnt_nv_V4: - case Hexagon::JMP_GTriNotPt_nv_V4: - case Hexagon::JMP_GTriNotPnt_nv_V4: - case Hexagon::JMP_GTriPt_ie_nv_V4: - case Hexagon::JMP_GTriPnt_ie_nv_V4: - case Hexagon::JMP_GTriNotPt_ie_nv_V4: - case Hexagon::JMP_GTriNotPnt_ie_nv_V4: - - // JMP_GTri - with -1 - case Hexagon::JMP_GTriPtneg_nv_V4: - case Hexagon::JMP_GTriPntneg_nv_V4: - case Hexagon::JMP_GTriNotPtneg_nv_V4: - case Hexagon::JMP_GTriNotPntneg_nv_V4: - case Hexagon::JMP_GTriPtneg_ie_nv_V4: - case Hexagon::JMP_GTriPntneg_ie_nv_V4: - case Hexagon::JMP_GTriNotPtneg_ie_nv_V4: - case Hexagon::JMP_GTriNotPntneg_ie_nv_V4: - - // JMP_GTrr - case Hexagon::JMP_GTrrPt_nv_V4: - case Hexagon::JMP_GTrrPnt_nv_V4: - case Hexagon::JMP_GTrrNotPt_nv_V4: - case Hexagon::JMP_GTrrNotPnt_nv_V4: - case Hexagon::JMP_GTrrPt_ie_nv_V4: - case Hexagon::JMP_GTrrPnt_ie_nv_V4: - case Hexagon::JMP_GTrrNotPt_ie_nv_V4: - case Hexagon::JMP_GTrrNotPnt_ie_nv_V4: - - // JMP_GTrrdn - case Hexagon::JMP_GTrrdnPt_nv_V4: - case Hexagon::JMP_GTrrdnPnt_nv_V4: - case Hexagon::JMP_GTrrdnNotPt_nv_V4: - case Hexagon::JMP_GTrrdnNotPnt_nv_V4: - case Hexagon::JMP_GTrrdnPt_ie_nv_V4: - case Hexagon::JMP_GTrrdnPnt_ie_nv_V4: - case Hexagon::JMP_GTrrdnNotPt_ie_nv_V4: - case Hexagon::JMP_GTrrdnNotPnt_ie_nv_V4: - - // JMP_GTUri - case Hexagon::JMP_GTUriPt_nv_V4: - case Hexagon::JMP_GTUriPnt_nv_V4: - case Hexagon::JMP_GTUriNotPt_nv_V4: - case Hexagon::JMP_GTUriNotPnt_nv_V4: - case Hexagon::JMP_GTUriPt_ie_nv_V4: - case Hexagon::JMP_GTUriPnt_ie_nv_V4: - case Hexagon::JMP_GTUriNotPt_ie_nv_V4: - case Hexagon::JMP_GTUriNotPnt_ie_nv_V4: - - // JMP_GTUrr - case Hexagon::JMP_GTUrrPt_nv_V4: - case Hexagon::JMP_GTUrrPnt_nv_V4: - case Hexagon::JMP_GTUrrNotPt_nv_V4: - case Hexagon::JMP_GTUrrNotPnt_nv_V4: - case Hexagon::JMP_GTUrrPt_ie_nv_V4: - case Hexagon::JMP_GTUrrPnt_ie_nv_V4: - case Hexagon::JMP_GTUrrNotPt_ie_nv_V4: - case Hexagon::JMP_GTUrrNotPnt_ie_nv_V4: - - // JMP_GTUrrdn - case Hexagon::JMP_GTUrrdnPt_nv_V4: - case Hexagon::JMP_GTUrrdnPnt_nv_V4: - case Hexagon::JMP_GTUrrdnNotPt_nv_V4: - case Hexagon::JMP_GTUrrdnNotPnt_nv_V4: - case Hexagon::JMP_GTUrrdnPt_ie_nv_V4: - case Hexagon::JMP_GTUrrdnPnt_ie_nv_V4: - case Hexagon::JMP_GTUrrdnNotPt_ie_nv_V4: - case Hexagon::JMP_GTUrrdnNotPnt_ie_nv_V4: - return true; - } +bool HexagonInstrInfo::isBranch (const MachineInstr *MI) const { + return MI->getDesc().isBranch(); } bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { @@ -746,11 +665,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STrib_abs_cdnPt_nv_V4: case Hexagon::STrib_abs_cNotPt_nv_V4: case Hexagon::STrib_abs_cdnNotPt_nv_V4: - case Hexagon::STrib_imm_abs_nv_V4: - case Hexagon::STrib_imm_abs_cPt_nv_V4: - case Hexagon::STrib_imm_abs_cdnPt_nv_V4: - case Hexagon::STrib_imm_abs_cNotPt_nv_V4: - case Hexagon::STrib_imm_abs_cdnNotPt_nv_V4: // Store Halfword case Hexagon::STrih_nv_V4: @@ -784,11 +698,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STrih_abs_cdnPt_nv_V4: case Hexagon::STrih_abs_cNotPt_nv_V4: case Hexagon::STrih_abs_cdnNotPt_nv_V4: - case Hexagon::STrih_imm_abs_nv_V4: - case Hexagon::STrih_imm_abs_cPt_nv_V4: - case Hexagon::STrih_imm_abs_cdnPt_nv_V4: - case Hexagon::STrih_imm_abs_cNotPt_nv_V4: - case Hexagon::STrih_imm_abs_cdnNotPt_nv_V4: // Store Word case Hexagon::STriw_nv_V4: @@ -822,11 +731,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STriw_abs_cdnPt_nv_V4: case Hexagon::STriw_abs_cNotPt_nv_V4: case Hexagon::STriw_abs_cdnNotPt_nv_V4: - case Hexagon::STriw_imm_abs_nv_V4: - case Hexagon::STriw_imm_abs_cPt_nv_V4: - case Hexagon::STriw_imm_abs_cdnPt_nv_V4: - case Hexagon::STriw_imm_abs_cNotPt_nv_V4: - case Hexagon::STriw_imm_abs_cdnNotPt_nv_V4: return true; } } @@ -1003,9 +907,6 @@ bool HexagonInstrInfo::isPredicable(MachineInstr *MI) const { case Hexagon::ZXTB: case Hexagon::ZXTH: return Subtarget.hasV4TOps(); - - case Hexagon::JMPR: - return false; } return true; @@ -1030,6 +931,12 @@ bool HexagonInstrInfo::isPredicable(MachineInstr *MI) const { // cNotPt ---> cNotPt_nv // cPt ---> cPt_nv unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { + int InvPredOpcode; + InvPredOpcode = isPredicatedTrue(Opc) ? Hexagon::getFalsePredOpcode(Opc) + : Hexagon::getTruePredOpcode(Opc); + if (InvPredOpcode >= 0) // Valid instruction with the inverted predicate. + return InvPredOpcode; + switch(Opc) { default: llvm_unreachable("Unexpected predicated instruction"); case Hexagon::TFR_cPt: @@ -1042,10 +949,10 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { case Hexagon::TFRI_cNotPt: return Hexagon::TFRI_cPt; - case Hexagon::JMP_c: - return Hexagon::JMP_cNot; - case Hexagon::JMP_cNot: - return Hexagon::JMP_c; + case Hexagon::JMP_t: + return Hexagon::JMP_f; + case Hexagon::JMP_f: + return Hexagon::JMP_t; case Hexagon::ADD_ri_cPt: return Hexagon::ADD_ri_cNotPt; @@ -1113,10 +1020,10 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { return Hexagon::ZXTH_cPt_V4; - case Hexagon::JMPR_cPt: - return Hexagon::JMPR_cNotPt; - case Hexagon::JMPR_cNotPt: - return Hexagon::JMPR_cPt; + case Hexagon::JMPR_t: + return Hexagon::JMPR_f; + case Hexagon::JMPR_f: + return Hexagon::JMPR_t; // V4 indexed+scaled load. case Hexagon::LDrid_indexed_shl_cPt_V4: @@ -1362,117 +1269,6 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { return Hexagon::DEALLOC_RET_cNotPt_V4; case Hexagon::DEALLOC_RET_cNotPt_V4: return Hexagon::DEALLOC_RET_cPt_V4; - - // New Value Jump. - // JMPEQ_ri - with -1. - case Hexagon::JMP_EQriPtneg_nv_V4: - return Hexagon::JMP_EQriNotPtneg_nv_V4; - case Hexagon::JMP_EQriNotPtneg_nv_V4: - return Hexagon::JMP_EQriPtneg_nv_V4; - - case Hexagon::JMP_EQriPntneg_nv_V4: - return Hexagon::JMP_EQriNotPntneg_nv_V4; - case Hexagon::JMP_EQriNotPntneg_nv_V4: - return Hexagon::JMP_EQriPntneg_nv_V4; - - // JMPEQ_ri. - case Hexagon::JMP_EQriPt_nv_V4: - return Hexagon::JMP_EQriNotPt_nv_V4; - case Hexagon::JMP_EQriNotPt_nv_V4: - return Hexagon::JMP_EQriPt_nv_V4; - - case Hexagon::JMP_EQriPnt_nv_V4: - return Hexagon::JMP_EQriNotPnt_nv_V4; - case Hexagon::JMP_EQriNotPnt_nv_V4: - return Hexagon::JMP_EQriPnt_nv_V4; - - // JMPEQ_rr. - case Hexagon::JMP_EQrrPt_nv_V4: - return Hexagon::JMP_EQrrNotPt_nv_V4; - case Hexagon::JMP_EQrrNotPt_nv_V4: - return Hexagon::JMP_EQrrPt_nv_V4; - - case Hexagon::JMP_EQrrPnt_nv_V4: - return Hexagon::JMP_EQrrNotPnt_nv_V4; - case Hexagon::JMP_EQrrNotPnt_nv_V4: - return Hexagon::JMP_EQrrPnt_nv_V4; - - // JMPGT_ri - with -1. - case Hexagon::JMP_GTriPtneg_nv_V4: - return Hexagon::JMP_GTriNotPtneg_nv_V4; - case Hexagon::JMP_GTriNotPtneg_nv_V4: - return Hexagon::JMP_GTriPtneg_nv_V4; - - case Hexagon::JMP_GTriPntneg_nv_V4: - return Hexagon::JMP_GTriNotPntneg_nv_V4; - case Hexagon::JMP_GTriNotPntneg_nv_V4: - return Hexagon::JMP_GTriPntneg_nv_V4; - - // JMPGT_ri. - case Hexagon::JMP_GTriPt_nv_V4: - return Hexagon::JMP_GTriNotPt_nv_V4; - case Hexagon::JMP_GTriNotPt_nv_V4: - return Hexagon::JMP_GTriPt_nv_V4; - - case Hexagon::JMP_GTriPnt_nv_V4: - return Hexagon::JMP_GTriNotPnt_nv_V4; - case Hexagon::JMP_GTriNotPnt_nv_V4: - return Hexagon::JMP_GTriPnt_nv_V4; - - // JMPGT_rr. - case Hexagon::JMP_GTrrPt_nv_V4: - return Hexagon::JMP_GTrrNotPt_nv_V4; - case Hexagon::JMP_GTrrNotPt_nv_V4: - return Hexagon::JMP_GTrrPt_nv_V4; - - case Hexagon::JMP_GTrrPnt_nv_V4: - return Hexagon::JMP_GTrrNotPnt_nv_V4; - case Hexagon::JMP_GTrrNotPnt_nv_V4: - return Hexagon::JMP_GTrrPnt_nv_V4; - - // JMPGT_rrdn. - case Hexagon::JMP_GTrrdnPt_nv_V4: - return Hexagon::JMP_GTrrdnNotPt_nv_V4; - case Hexagon::JMP_GTrrdnNotPt_nv_V4: - return Hexagon::JMP_GTrrdnPt_nv_V4; - - case Hexagon::JMP_GTrrdnPnt_nv_V4: - return Hexagon::JMP_GTrrdnNotPnt_nv_V4; - case Hexagon::JMP_GTrrdnNotPnt_nv_V4: - return Hexagon::JMP_GTrrdnPnt_nv_V4; - - // JMPGTU_ri. - case Hexagon::JMP_GTUriPt_nv_V4: - return Hexagon::JMP_GTUriNotPt_nv_V4; - case Hexagon::JMP_GTUriNotPt_nv_V4: - return Hexagon::JMP_GTUriPt_nv_V4; - - case Hexagon::JMP_GTUriPnt_nv_V4: - return Hexagon::JMP_GTUriNotPnt_nv_V4; - case Hexagon::JMP_GTUriNotPnt_nv_V4: - return Hexagon::JMP_GTUriPnt_nv_V4; - - // JMPGTU_rr. - case Hexagon::JMP_GTUrrPt_nv_V4: - return Hexagon::JMP_GTUrrNotPt_nv_V4; - case Hexagon::JMP_GTUrrNotPt_nv_V4: - return Hexagon::JMP_GTUrrPt_nv_V4; - - case Hexagon::JMP_GTUrrPnt_nv_V4: - return Hexagon::JMP_GTUrrNotPnt_nv_V4; - case Hexagon::JMP_GTUrrNotPnt_nv_V4: - return Hexagon::JMP_GTUrrPnt_nv_V4; - - // JMPGTU_rrdn. - case Hexagon::JMP_GTUrrdnPt_nv_V4: - return Hexagon::JMP_GTUrrdnNotPt_nv_V4; - case Hexagon::JMP_GTUrrdnNotPt_nv_V4: - return Hexagon::JMP_GTUrrdnPt_nv_V4; - - case Hexagon::JMP_GTUrrdnPnt_nv_V4: - return Hexagon::JMP_GTUrrdnNotPnt_nv_V4; - case Hexagon::JMP_GTUrrdnNotPnt_nv_V4: - return Hexagon::JMP_GTUrrdnPnt_nv_V4; } } @@ -1499,14 +1295,9 @@ getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const { return !invertPredicate ? Hexagon::TFRI_cPt : Hexagon::TFRI_cNotPt; case Hexagon::JMP: - return !invertPredicate ? Hexagon::JMP_c : - Hexagon::JMP_cNot; - case Hexagon::JMP_EQrrPt_nv_V4: - return !invertPredicate ? Hexagon::JMP_EQrrPt_nv_V4 : - Hexagon::JMP_EQrrNotPt_nv_V4; - case Hexagon::JMP_EQriPt_nv_V4: - return !invertPredicate ? Hexagon::JMP_EQriPt_nv_V4 : - Hexagon::JMP_EQriNotPt_nv_V4; + return !invertPredicate ? Hexagon::JMP_t : + Hexagon::JMP_f; + case Hexagon::COMBINE_rr: return !invertPredicate ? Hexagon::COMBINE_rr_cPt : Hexagon::COMBINE_rr_cNotPt; @@ -1530,8 +1321,8 @@ getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const { Hexagon::ZXTH_cNotPt_V4; case Hexagon::JMPR: - return !invertPredicate ? Hexagon::JMPR_cPt : - Hexagon::JMPR_cNotPt; + return !invertPredicate ? Hexagon::JMPR_t : + Hexagon::JMPR_f; // V4 indexed+scaled load. case Hexagon::LDrid_indexed_shl_V4: @@ -1830,11 +1621,15 @@ PredicateInstruction(MachineInstr *MI, // It is better to have an assert here to check this. But I don't know how // to write this assert because findFirstPredOperandIdx() would return -1 if (oper < -1) oper = -1; + MI->getOperand(oper+1).ChangeToRegister(PredMO.getReg(), PredMO.isDef(), - PredMO.isImplicit(), PredMO.isKill(), + PredMO.isImplicit(), false, PredMO.isDead(), PredMO.isUndef(), PredMO.isDebug()); + MachineRegisterInfo &RegInfo = MI->getParent()->getParent()->getRegInfo(); + RegInfo.clearKillFlags(PredMO.getReg()); + if (hasGAOpnd) { unsigned int i; @@ -1883,13 +1678,41 @@ isProfitableToIfCvt(MachineBasicBlock &TMBB, return true; } - +// Returns true if an instruction is predicated irrespective of the predicate +// sense. For example, all of the following will return true. +// if (p0) R1 = add(R2, R3) +// if (!p0) R1 = add(R2, R3) +// if (p0.new) R1 = add(R2, R3) +// if (!p0.new) R1 = add(R2, R3) bool HexagonInstrInfo::isPredicated(const MachineInstr *MI) const { const uint64_t F = MI->getDesc().TSFlags; return ((F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); } +bool HexagonInstrInfo::isPredicated(unsigned Opcode) const { + const uint64_t F = get(Opcode).TSFlags; + + return ((F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); +} + +bool HexagonInstrInfo::isPredicatedTrue(const MachineInstr *MI) const { + const uint64_t F = MI->getDesc().TSFlags; + + assert(isPredicated(MI)); + return (!((F >> HexagonII::PredicatedFalsePos) & + HexagonII::PredicatedFalseMask)); +} + +bool HexagonInstrInfo::isPredicatedTrue(unsigned Opcode) const { + const uint64_t F = get(Opcode).TSFlags; + + // Make sure that the instruction is predicated. + assert((F>> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); + return (!((F >> HexagonII::PredicatedFalsePos) & + HexagonII::PredicatedFalseMask)); +} + bool HexagonInstrInfo::isPredicatedNew(const MachineInstr *MI) const { const uint64_t F = MI->getDesc().TSFlags; @@ -1897,6 +1720,13 @@ bool HexagonInstrInfo::isPredicatedNew(const MachineInstr *MI) const { return ((F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask); } +bool HexagonInstrInfo::isPredicatedNew(unsigned Opcode) const { + const uint64_t F = get(Opcode).TSFlags; + + assert(isPredicated(Opcode)); + return ((F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask); +} + bool HexagonInstrInfo::DefinesPredicate(MachineInstr *MI, std::vector<MachineOperand> &Pred) const { @@ -2129,14 +1959,10 @@ bool HexagonInstrInfo::isNewValueJumpCandidate(const MachineInstr *MI) const { default: return false; case Hexagon::CMPEQrr: case Hexagon::CMPEQri: - case Hexagon::CMPLTrr: case Hexagon::CMPGTrr: case Hexagon::CMPGTri: - case Hexagon::CMPLTUrr: case Hexagon::CMPGTUrr: case Hexagon::CMPGTUri: - case Hexagon::CMPGEri: - case Hexagon::CMPGEUri: return true; } } @@ -2369,6 +2195,18 @@ isConditionalStore (const MachineInstr* MI) const { } } + +bool HexagonInstrInfo::isNewValueJump(const MachineInstr *MI) const { + if (isNewValue(MI) && isBranch(MI)) + return true; + return false; +} + +bool HexagonInstrInfo::isNewValue(const MachineInstr* MI) const { + const uint64_t F = MI->getDesc().TSFlags; + return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); +} + // Returns true, if any one of the operands is a dot new // insn, whether it is predicated dot new or register dot new. bool HexagonInstrInfo::isDotNewInst (const MachineInstr* MI) const { @@ -2470,6 +2308,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 { @@ -2574,3 +2440,18 @@ short HexagonInstrInfo::getNonExtOpcode (const MachineInstr *MI) const { } return -1; } + +bool HexagonInstrInfo::PredOpcodeHasJMP_c(Opcode_t Opcode) const { + return (Opcode == Hexagon::JMP_t) || + (Opcode == Hexagon::JMP_f) || + (Opcode == Hexagon::JMP_tnew_t) || + (Opcode == Hexagon::JMP_fnew_t) || + (Opcode == Hexagon::JMP_tnew_nt) || + (Opcode == Hexagon::JMP_fnew_nt); +} + +bool HexagonInstrInfo::PredOpcodeHasNot(Opcode_t Opcode) const { + return (Opcode == Hexagon::JMP_f) || + (Opcode == Hexagon::JMP_fnew_t) || + (Opcode == Hexagon::JMP_fnew_nt); +} diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h index 5df13a8..b721da4 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h @@ -16,9 +16,9 @@ #include "HexagonRegisterInfo.h" #include "MCTargetDesc/HexagonBaseInfo.h" -#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetInstrInfo.h" - +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #define GET_INSTRINFO_HEADER #include "HexagonGenInstrInfo.inc" @@ -28,6 +28,8 @@ namespace llvm { class HexagonInstrInfo : public HexagonGenInstrInfo { const HexagonRegisterInfo RI; const HexagonSubtarget& Subtarget; + typedef unsigned Opcode_t; + public: explicit HexagonInstrInfo(HexagonSubtarget &ST); @@ -111,6 +113,7 @@ public: unsigned createVR(MachineFunction* MF, MVT VT) const; + virtual bool isBranch(const MachineInstr *MI) const; virtual bool isPredicable(MachineInstr *MI) const; virtual bool PredicateInstruction(MachineInstr *MI, @@ -127,7 +130,11 @@ public: const BranchProbability &Probability) const; virtual bool isPredicated(const MachineInstr *MI) const; + virtual bool isPredicated(unsigned Opcode) const; + virtual bool isPredicatedTrue(const MachineInstr *MI) const; + virtual bool isPredicatedTrue(unsigned Opcode) const; virtual bool isPredicatedNew(const MachineInstr *MI) const; + virtual bool isPredicatedNew(unsigned Opcode) const; virtual bool DefinesPredicate(MachineInstr *MI, std::vector<MachineOperand> &Pred) const; virtual bool @@ -176,6 +183,7 @@ public: bool isConditionalLoad (const MachineInstr* MI) const; bool isConditionalStore(const MachineInstr* MI) const; bool isNewValueInst(const MachineInstr* MI) const; + bool isNewValue(const MachineInstr* MI) const; bool isDotNewInst(const MachineInstr* MI) const; bool isDeallocRet(const MachineInstr *MI) const; unsigned getInvertedPredicatedOpcode(const int Opc) const; @@ -189,6 +197,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; @@ -197,6 +207,9 @@ public: int getMaxValue(const MachineInstr *MI) const; bool NonExtEquivalentExists (const MachineInstr *MI) const; short getNonExtOpcode(const MachineInstr *MI) const; + bool PredOpcodeHasJMP_c(Opcode_t Opcode) const; + bool PredOpcodeHasNot(Opcode_t Opcode) const; + private: int getMatchingCondBranchOpcode(int Opc, bool sense) const; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td index 74dc0ca..2a4b17b 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td @@ -14,6 +14,8 @@ include "HexagonInstrFormats.td" include "HexagonOperands.td" +//===----------------------------------------------------------------------===// + // Multi-class for logical operators. multiclass ALU32_rr_ri<string OpcStr, SDNode OpNode> { def rr : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), @@ -34,12 +36,6 @@ multiclass CMP64_rr<string OpcStr, PatFrag OpNode> { [(set (i1 PredRegs:$dst), (OpNode (i64 DoubleRegs:$b), (i64 DoubleRegs:$c)))]>; } -multiclass CMP32_rr<string OpcStr, PatFrag OpNode> { - def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; -} multiclass CMP32_rr_ri_s10<string OpcStr, string CextOp, PatFrag OpNode> { let CextOpcode = CextOp in { @@ -75,14 +71,6 @@ multiclass CMP32_rr_ri_u9<string OpcStr, string CextOp, PatFrag OpNode> { } } -multiclass CMP32_ri_u8<string OpcStr, PatFrag OpNode> { -let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 8 in - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u8Ext:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), - [(set (i1 PredRegs:$dst), (OpNode (i32 IntRegs:$b), - u8ExtPred:$c))]>; -} - multiclass CMP32_ri_s8<string OpcStr, PatFrag OpNode> { let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s8Ext:$c), @@ -95,22 +83,30 @@ let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in //===----------------------------------------------------------------------===// // ALU32/ALU (Instructions with register-register form) //===----------------------------------------------------------------------===// -multiclass ALU32_Pbase<string mnemonic, bit isNot, - bit isPredNew> { +def SDTHexagonI64I32I32 : SDTypeProfile<1, 2, + [SDTCisVT<0, i64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; + +def HexagonWrapperCombineII : + SDNode<"HexagonISD::WrapperCombineII", SDTHexagonI64I32I32>; - let PNewValue = !if(isPredNew, "new", "") in - def NAME : ALU32_rr<(outs IntRegs:$dst), +def HexagonWrapperCombineRR : + SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>; + +multiclass ALU32_Pbase<string mnemonic, RegisterClass RC, bit isNot, + bit isPredNew> { + let isPredicatedNew = isPredNew in + def NAME : ALU32_rr<(outs RC:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs: $src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", ") $dst = ")#mnemonic#"($src2, $src3)", []>; } -multiclass ALU32_Pred<string mnemonic, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { - defm _c#NAME : ALU32_Pbase<mnemonic, PredNot, 0>; +multiclass ALU32_Pred<string mnemonic, RegisterClass RC, bit PredNot> { + let isPredicatedFalse = PredNot in { + defm _c#NAME : ALU32_Pbase<mnemonic, RC, PredNot, 0>; // Predicate new - defm _cdn#NAME : ALU32_Pbase<mnemonic, PredNot, 1>; + defm _cdn#NAME : ALU32_Pbase<mnemonic, RC, PredNot, 1>; } } @@ -125,8 +121,8 @@ multiclass ALU32_base<string mnemonic, string CextOp, SDNode OpNode> { (i32 IntRegs:$src2)))]>; let neverHasSideEffects = 1, isPredicated = 1 in { - defm Pt : ALU32_Pred<mnemonic, 0>; - defm NotPt : ALU32_Pred<mnemonic, 1>; + defm Pt : ALU32_Pred<mnemonic, IntRegs, 0>; + defm NotPt : ALU32_Pred<mnemonic, IntRegs, 1>; } } } @@ -140,11 +136,42 @@ let isCommutable = 1 in { defm SUB_rr : ALU32_base<"sub", "SUB", sub>, ImmRegRel, PredNewRel; +// Combines the two integer registers SRC1 and SRC2 into a double register. +let isPredicable = 1 in +class T_Combine : ALU32_rr<(outs DoubleRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = combine($src1, $src2)", + [(set (i64 DoubleRegs:$dst), + (i64 (HexagonWrapperCombineRR (i32 IntRegs:$src1), + (i32 IntRegs:$src2))))]>; + +multiclass Combine_base { + let BaseOpcode = "combine" in { + def NAME : T_Combine; + let neverHasSideEffects = 1, isPredicated = 1 in { + defm Pt : ALU32_Pred<"combine", DoubleRegs, 0>; + defm NotPt : ALU32_Pred<"combine", DoubleRegs, 1>; + } + } +} + +defm COMBINE_rr : Combine_base, PredNewRel; + +// Combines the two immediates SRC1 and SRC2 into a double register. +class COMBINE_imm<Operand imm1, Operand imm2, PatLeaf pat1, PatLeaf pat2> : + ALU32_ii<(outs DoubleRegs:$dst), (ins imm1:$src1, imm2:$src2), + "$dst = combine(#$src1, #$src2)", + [(set (i64 DoubleRegs:$dst), + (i64 (HexagonWrapperCombineII (i32 pat1:$src1), (i32 pat2:$src2))))]>; + +let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8 in +def COMBINE_Ii : COMBINE_imm<s8Ext, s8Imm, s8ExtPred, s8ImmPred>; + //===----------------------------------------------------------------------===// // ALU32/ALU (ADD with register-immediate form) //===----------------------------------------------------------------------===// multiclass ALU32ri_Pbase<string mnemonic, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, s8Ext: $src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", @@ -153,7 +180,7 @@ multiclass ALU32ri_Pbase<string mnemonic, bit isNot, bit isPredNew> { } multiclass ALU32ri_Pred<string mnemonic, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ALU32ri_Pbase<mnemonic, PredNot, 0>; // Predicate new defm _cdn#NAME : ALU32ri_Pbase<mnemonic, PredNot, 1>; @@ -189,11 +216,6 @@ def OR_ri : ALU32_ri<(outs IntRegs:$dst), [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1), s10ExtPred:$src2))]>, ImmRegRel; -def NOT_rr : ALU32_rr<(outs IntRegs:$dst), - (ins IntRegs:$src1), - "$dst = not($src1)", - [(set (i32 IntRegs:$dst), (not (i32 IntRegs:$src1)))]>; - let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 10, InputType = "imm", CextOpcode = "AND" in def AND_ri : ALU32_ri<(outs IntRegs:$dst), @@ -201,10 +223,7 @@ def AND_ri : ALU32_ri<(outs IntRegs:$dst), "$dst = and($src1, #$src2)", [(set (i32 IntRegs:$dst), (and (i32 IntRegs:$src1), s10ExtPred:$src2))]>, ImmRegRel; -// Negate. -def NEG : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = neg($src1)", - [(set (i32 IntRegs:$dst), (ineg (i32 IntRegs:$src1)))]>; + // Nop. let neverHasSideEffects = 1 in def NOP : ALU32_rr<(outs), (ins), @@ -220,15 +239,21 @@ def SUB_ri : ALU32_ri<(outs IntRegs:$dst), [(set IntRegs:$dst, (sub s10ExtPred:$src1, IntRegs:$src2))]>, ImmRegRel; +// Rd = not(Rs) gets mapped to Rd=sub(#-1, Rs). +def : Pat<(not (i32 IntRegs:$src1)), + (SUB_ri -1, (i32 IntRegs:$src1))>; + +// Rd = neg(Rs) gets mapped to Rd=sub(#0, Rs). +// Pattern definition for 'neg' was not necessary. multiclass TFR_Pred<bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { def _c#NAME : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), !if(PredNot, "if (!$src1", "if ($src1")#") $dst = $src2", []>; // Predicate new - let PNewValue = "new" in + let isPredicatedNew = 1 in def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = $src2", @@ -274,10 +299,10 @@ class T_TFR64_Pred<bit PredNot, bit isPredNew> } multiclass TFR64_Pred<bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { def _c#NAME : T_TFR64_Pred<PredNot, 0>; - let PNewValue = "new" in + let isPredicatedNew = 1 in def _cdn#NAME : T_TFR64_Pred<PredNot, 1>; // Predicate new } } @@ -309,14 +334,14 @@ multiclass TFR64_base<string BaseName> { } multiclass TFRI_Pred<bit PredNot> { - let isMoveImm = 1, PredSense = !if(PredNot, "false", "true") in { + let isMoveImm = 1, isPredicatedFalse = PredNot in { def _c#NAME : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, s12Ext:$src2), !if(PredNot, "if (!$src1", "if ($src1")#") $dst = #$src2", []>; // Predicate new - let PNewValue = "new" in + let isPredicatedNew = 1 in def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, s12Ext:$src2), !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = #$src2", @@ -359,52 +384,6 @@ def TFCR : CRInst<(outs CRRegs:$dst), (ins IntRegs:$src1), // ALU32/PERM + //===----------------------------------------------------------------------===// -// Combine. - -def SDTHexagonI64I32I32 : SDTypeProfile<1, 2, - [SDTCisVT<0, i64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; - -def HexagonWrapperCombineII : - SDNode<"HexagonISD::WrapperCombineII", SDTHexagonI64I32I32>; -def HexagonWrapperCombineRR : - SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>; - -// Combines the two integer registers SRC1 and SRC2 into a double register. -let isPredicable = 1 in -def COMBINE_rr : ALU32_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, - IntRegs:$src2), - "$dst = combine($src1, $src2)", - [(set (i64 DoubleRegs:$dst), - (i64 (HexagonWrapperCombineRR (i32 IntRegs:$src1), - (i32 IntRegs:$src2))))]>; - -// Rd=combine(Rt.[HL], Rs.[HL]) -class COMBINE_halves<string A, string B>: ALU32_rr<(outs IntRegs:$dst), - (ins IntRegs:$src1, - IntRegs:$src2), - "$dst = combine($src1."# A #", $src2."# B #")", []>; - -let isPredicable = 1 in { - def COMBINE_hh : COMBINE_halves<"H", "H">; - def COMBINE_hl : COMBINE_halves<"H", "L">; - def COMBINE_lh : COMBINE_halves<"L", "H">; - def COMBINE_ll : COMBINE_halves<"L", "L">; -} - -def : Pat<(i32 (trunc (i64 (srl (i64 DoubleRegs:$a), (i32 16))))), - (COMBINE_lh (EXTRACT_SUBREG (i64 DoubleRegs:$a), subreg_hireg), - (EXTRACT_SUBREG (i64 DoubleRegs:$a), subreg_loreg))>; - -// Combines the two immediates SRC1 and SRC2 into a double register. -class COMBINE_imm<Operand imm1, Operand imm2, PatLeaf pat1, PatLeaf pat2> : - ALU32_ii<(outs DoubleRegs:$dst), (ins imm1:$src1, imm2:$src2), - "$dst = combine(#$src1, #$src2)", - [(set (i64 DoubleRegs:$dst), - (i64 (HexagonWrapperCombineII (i32 pat1:$src1), (i32 pat2:$src2))))]>; - -let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8 in -def COMBINE_Ii : COMBINE_imm<s8Ext, s8Imm, s8ExtPred, s8ImmPred>; - // Mux. def VMUX_prr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, DoubleRegs:$src2, @@ -507,40 +486,24 @@ def : Pat <(sext_inreg (i32 IntRegs:$src1), i16), // ALU32/PRED + //===----------------------------------------------------------------------===// -// Conditional combine. -let neverHasSideEffects = 1, isPredicated = 1 in { -def COMBINE_rr_cPt : ALU32_rr<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1) $dst = combine($src2, $src3)", - []>; - -let isPredicatedFalse = 1 in -def COMBINE_rr_cNotPt : ALU32_rr<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1) $dst = combine($src2, $src3)", - []>; - -let isPredicatedNew = 1 in -def COMBINE_rr_cdnPt : ALU32_rr<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1.new) $dst = combine($src2, $src3)", - []>; - -let isPredicatedNew = 1, isPredicatedFalse = 1 in -def COMBINE_rr_cdnNotPt : ALU32_rr<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1.new) $dst = combine($src2, $src3)", - []>; -} - // Compare. defm CMPGTU : CMP32_rr_ri_u9<"cmp.gtu", "CMPGTU", setugt>, ImmRegRel; defm CMPGT : CMP32_rr_ri_s10<"cmp.gt", "CMPGT", setgt>, ImmRegRel; -defm CMPLT : CMP32_rr<"cmp.lt", setlt>; -defm CMPLTU : CMP32_rr<"cmp.ltu", setult>; defm CMPEQ : CMP32_rr_ri_s10<"cmp.eq", "CMPEQ", seteq>, ImmRegRel; -defm CMPGE : CMP32_ri_s8<"cmp.ge", setge>; -defm CMPGEU : CMP32_ri_u8<"cmp.geu", setuge>; + +// SDNode for converting immediate C to C-1. +def DEC_CONST_SIGNED : SDNodeXForm<imm, [{ + // Return the byte immediate const-1 as an SDNode. + int32_t imm = N->getSExtValue(); + return XformSToSM1Imm(imm); +}]>; + +// SDNode for converting immediate C to C-1. +def DEC_CONST_UNSIGNED : SDNodeXForm<imm, [{ + // Return the byte immediate const-1 as an SDNode. + uint32_t imm = N->getZExtValue(); + return XformUToUM1Imm(imm); +}]>; def CTLZ_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1), "$dst = cl0($src1)", @@ -774,112 +737,153 @@ def XOR_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2), // CR - //===----------------------------------------------------------------------===// +def retflag : SDNode<"HexagonISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def eh_return: SDNode<"HexagonISD::EH_RETURN", SDTNone, + [SDNPHasChain]>; -//===----------------------------------------------------------------------===// -// J + -//===----------------------------------------------------------------------===// -// Jump to address. -let isBranch = 1, isTerminator=1, isBarrier = 1, isPredicable = 1 in { - def JMP : JInst< (outs), - (ins brtarget:$offset), - "jump $offset", - [(br bb:$offset)]>; -} +def SDHexagonBR_JT: SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def HexagonBR_JT: SDNode<"HexagonISD::BR_JT", SDHexagonBR_JT, [SDNPHasChain]>; -// if (p0) jump -let isBranch = 1, isTerminator=1, Defs = [PC], - isPredicated = 1 in { - def JMP_c : JInst< (outs), - (ins PredRegs:$src, brtarget:$offset), - "if ($src) jump $offset", - [(brcond (i1 PredRegs:$src), bb:$offset)]>; -} +let InputType = "imm", isBarrier = 1, isPredicable = 1, +Defs = [PC], isExtendable = 1, opExtendable = 0, isExtentSigned = 1, +opExtentBits = 24 in +class T_JMP <dag InsDag, list<dag> JumpList = []> + : JInst<(outs), InsDag, + "jump $dst" , JumpList> { + bits<24> dst; + + let IClass = 0b0101; + + let Inst{27-25} = 0b100; + let Inst{24-16} = dst{23-15}; + let Inst{13-1} = dst{14-2}; +} + +let InputType = "imm", isExtendable = 1, opExtendable = 1, isExtentSigned = 1, +Defs = [PC], isPredicated = 1, opExtentBits = 17 in +class T_JMP_c <bit PredNot, bit isPredNew, bit isTaken>: + JInst<(outs ), (ins PredRegs:$src, brtarget:$dst), + !if(PredNot, "if (!$src", "if ($src")# + !if(isPredNew, ".new) ", ") ")#"jump"# + !if(isPredNew, !if(isTaken, ":t ", ":nt "), " ")#"$dst"> { + + let isBrTaken = !if(isPredNew, !if(isTaken, "true", "false"), ""); + let isPredicatedFalse = PredNot; + let isPredicatedNew = isPredNew; + bits<2> src; + bits<17> dst; + + let IClass = 0b0101; + + let Inst{27-24} = 0b1100; + let Inst{21} = PredNot; + let Inst{12} = !if(isPredNew, isTaken, zero); + let Inst{11} = isPredNew; + let Inst{9-8} = src; + let Inst{23-22} = dst{16-15}; + let Inst{20-16} = dst{14-10}; + let Inst{13} = dst{9}; + let Inst{7-1} = dst{8-2}; + } -// if (!p0) jump -let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC], - isPredicated = 1 in { - def JMP_cNot : JInst< (outs), - (ins PredRegs:$src, brtarget:$offset), - "if (!$src) jump $offset", - []>; +let isBarrier = 1, Defs = [PC], isPredicable = 1, InputType = "reg" in +class T_JMPr<dag InsDag = (ins IntRegs:$dst)> + : JRInst<(outs ), InsDag, + "jumpr $dst" , + []> { + bits<5> dst; + + let IClass = 0b0101; + let Inst{27-21} = 0b0010100; + let Inst{20-16} = dst; } -let isTerminator = 1, isBranch = 1, neverHasSideEffects = 1, Defs = [PC], - isPredicated = 1 in { - def BRCOND : JInst < (outs), (ins PredRegs:$pred, brtarget:$dst), - "if ($pred) jump $dst", - []>; +let Defs = [PC], isPredicated = 1, InputType = "reg" in +class T_JMPr_c <bit PredNot, bit isPredNew, bit isTaken>: + JRInst <(outs ), (ins PredRegs:$src, IntRegs:$dst), + !if(PredNot, "if (!$src", "if ($src")# + !if(isPredNew, ".new) ", ") ")#"jumpr"# + !if(isPredNew, !if(isTaken, ":t ", ":nt "), " ")#"$dst"> { + + let isBrTaken = !if(isPredNew, !if(isTaken, "true", "false"), ""); + let isPredicatedFalse = PredNot; + let isPredicatedNew = isPredNew; + bits<2> src; + bits<5> dst; + + let IClass = 0b0101; + + let Inst{27-22} = 0b001101; + let Inst{21} = PredNot; + let Inst{20-16} = dst; + let Inst{12} = !if(isPredNew, isTaken, zero); + let Inst{11} = isPredNew; + let Inst{9-8} = src; + let Predicates = !if(isPredNew, [HasV3T], [HasV2T]); + let validSubTargets = !if(isPredNew, HasV3SubT, HasV2SubT); } -// Jump to address conditioned on new predicate. -// if (p0) jump:t -let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC], - isPredicated = 1 in { - def JMP_cdnPt : JInst< (outs), - (ins PredRegs:$src, brtarget:$offset), - "if ($src.new) jump:t $offset", - []>; +multiclass JMP_Pred<bit PredNot> { + def _#NAME : T_JMP_c<PredNot, 0, 0>; + // Predicate new + def _#NAME#new_t : T_JMP_c<PredNot, 1, 1>; // taken + def _#NAME#new_nt : T_JMP_c<PredNot, 1, 0>; // not taken } -// if (!p0) jump:t -let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC], - isPredicated = 1 in { - def JMP_cdnNotPt : JInst< (outs), - (ins PredRegs:$src, brtarget:$offset), - "if (!$src.new) jump:t $offset", - []>; +multiclass JMP_base<string BaseOp> { + let BaseOpcode = BaseOp in { + def NAME : T_JMP<(ins brtarget:$dst), [(br bb:$dst)]>; + defm t : JMP_Pred<0>; + defm f : JMP_Pred<1>; + } } -// Not taken. -let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC], - isPredicated = 1 in { - def JMP_cdnPnt : JInst< (outs), - (ins PredRegs:$src, brtarget:$offset), - "if ($src.new) jump:nt $offset", - []>; +multiclass JMPR_Pred<bit PredNot> { + def NAME: T_JMPr_c<PredNot, 0, 0>; + // Predicate new + def NAME#new_tV3 : T_JMPr_c<PredNot, 1, 1>; // taken + def NAME#new_ntV3 : T_JMPr_c<PredNot, 1, 0>; // not taken } -// Not taken. -let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC], - isPredicated = 1 in { - def JMP_cdnNotPnt : JInst< (outs), - (ins PredRegs:$src, brtarget:$offset), - "if (!$src.new) jump:nt $offset", - []>; +multiclass JMPR_base<string BaseOp> { + let BaseOpcode = BaseOp in { + def NAME : T_JMPr; + defm _t : JMPR_Pred<0>; + defm _f : JMPR_Pred<1>; + } } -//===----------------------------------------------------------------------===// -// J - -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// JR + -//===----------------------------------------------------------------------===// -def retflag : SDNode<"HexagonISD::RET_FLAG", SDTNone, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +let isTerminator = 1, neverHasSideEffects = 1 in { +let isBranch = 1 in +defm JMP : JMP_base<"JMP">, PredNewRel; -// Jump to address from register. -let isPredicable =1, isReturn = 1, isTerminator = 1, isBarrier = 1, - Defs = [PC], Uses = [R31] in { - def JMPR: JRInst<(outs), (ins), - "jumpr r31", - [(retflag)]>; -} +let isBranch = 1, isIndirectBranch = 1 in +defm JMPR : JMPR_base<"JMPr">, PredNewRel; -// Jump to address from register. -let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicated = 1, - Defs = [PC], Uses = [R31] in { - def JMPR_cPt: JRInst<(outs), (ins PredRegs:$src1), - "if ($src1) jumpr r31", - []>; +let isReturn = 1, isCodeGenOnly = 1 in +defm JMPret : JMPR_base<"JMPret">, PredNewRel; } -// Jump to address from register. -let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicated = 1, - Defs = [PC], Uses = [R31] in { - def JMPR_cNotPt: JRInst<(outs), (ins PredRegs:$src1), - "if (!$src1) jumpr r31", - []>; -} +def : Pat<(retflag), + (JMPret (i32 R31))>; + +def : Pat <(brcond (i1 PredRegs:$src1), bb:$offset), + (JMP_t (i1 PredRegs:$src1), bb:$offset)>; + +// A return through builtin_eh_return. +let isReturn = 1, isTerminator = 1, isBarrier = 1, neverHasSideEffects = 1, +isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in +def EH_RETURN_JMPR : T_JMPr; + +def : Pat<(eh_return), + (EH_RETURN_JMPR (i32 R31))>; + +def : Pat<(HexagonBR_JT (i32 IntRegs:$dst)), + (JMPR (i32 IntRegs:$dst))>; + +def : Pat<(brind (i32 IntRegs:$dst)), + (JMPR (i32 IntRegs:$dst))>; //===----------------------------------------------------------------------===// // JR - @@ -892,7 +896,7 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicated = 1, // Load -- MEMri operand multiclass LD_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : LDInst2<(outs RC:$dst), (ins PredRegs:$src1, MEMri:$addr), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -901,7 +905,7 @@ multiclass LD_MEMri_Pbase<string mnemonic, RegisterClass RC, } multiclass LD_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 0>; // Predicate new defm _cdn#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 1>; @@ -958,7 +962,7 @@ def : Pat < (i64 (load ADDRriS11_3:$addr)), // Load - Base with Immediate offset addressing mode multiclass LD_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : LDInst2<(outs RC:$dst), (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -968,7 +972,7 @@ multiclass LD_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, multiclass LD_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; // Predicate new defm _cdn#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>; @@ -1038,7 +1042,7 @@ def : Pat < (i64 (load (add IntRegs:$src1, s11_3ExtPred:$offset))), multiclass LD_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -1049,7 +1053,7 @@ multiclass LD_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, multiclass LD_PostInc_Pred<string mnemonic, RegisterClass RC, Operand ImmOp, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>; // Predicate new let Predicates = [HasV4T], validSubTargets = HasV4SubT in @@ -1366,7 +1370,7 @@ def SUBri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, multiclass ST_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : STInst2PI<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -1377,7 +1381,7 @@ multiclass ST_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, multiclass ST_PostInc_Pred<string mnemonic, RegisterClass RC, Operand ImmOp, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME# : ST_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>; // Predicate new let Predicates = [HasV4T], validSubTargets = HasV4SubT in @@ -1431,7 +1435,7 @@ def : Pat<(post_store (i64 DoubleRegs:$src1), IntRegs:$src2, //===----------------------------------------------------------------------===// multiclass ST_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : STInst2<(outs), (ins PredRegs:$src1, MEMri:$addr, RC: $src2), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -1440,7 +1444,7 @@ multiclass ST_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_MEMri_Pbase<mnemonic, RC, PredNot, 0>; // Predicate new @@ -1497,7 +1501,7 @@ def : Pat<(store (i64 DoubleRegs:$src1), ADDRriS11_3:$addr), //===----------------------------------------------------------------------===// multiclass ST_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : STInst2<(outs), (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -1507,7 +1511,7 @@ multiclass ST_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, multiclass ST_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp, bit PredNot> { - let PredSense = !if(PredNot, "false", "true"), isPredicated = 1 in { + let isPredicatedFalse = PredNot, isPredicated = 1 in { defm _c#NAME : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; // Predicate new @@ -2023,20 +2027,18 @@ let isCall = 1, neverHasSideEffects = 1, []>; } -// Tail Calls. -let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1 in { - def TCRETURNtg : JInst<(outs), (ins calltarget:$dst), - "jump $dst // TAILCALL", []>; -} -let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1 in { - def TCRETURNtext : JInst<(outs), (ins calltarget:$dst), - "jump $dst // TAILCALL", []>; -} -let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1 in { - def TCRETURNR : JInst<(outs), (ins IntRegs:$dst), - "jumpr $dst // TAILCALL", []>; +// Indirect tail-call. +let isCodeGenOnly = 1, isCall = 1, isReturn = 1 in +def TCRETURNR : T_JMPr; + +// Direct tail-calls. +let isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, +isTerminator = 1, isCodeGenOnly = 1 in { + def TCRETURNtg : T_JMP<(ins calltarget:$dst)>; + def TCRETURNtext : T_JMP<(ins calltarget:$dst)>; } + // Map call instruction. def : Pat<(call (i32 IntRegs:$dst)), (CALLR (i32 IntRegs:$dst))>, Requires<[HasV2TOnly]>; @@ -2133,10 +2135,11 @@ def : Pat <(add (i1 PredRegs:$src1), -1), // Map from p0 = setlt(r0, r1) r2 = mux(p0, r3, r4) => // p0 = cmp.lt(r0, r1), r0 = mux(p0, r2, r1). +// cmp.lt(r0, r1) -> cmp.gt(r1, r0) def : Pat <(select (i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))), (i32 IntRegs:$src3), (i32 IntRegs:$src4)), - (i32 (TFR_condset_rr (CMPLTrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), + (i32 (TFR_condset_rr (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)), (i32 IntRegs:$src4), (i32 IntRegs:$src3)))>, Requires<[HasV2TOnly]>; @@ -2154,18 +2157,25 @@ def : Pat <(select (not (i1 PredRegs:$src1)), s12ImmPred:$src2, // Map from p0 = pnot(p0); r0 = mux(p0, r1, #i) // => r0 = TFR_condset_ir(p0, #i, r1) -def : Pat <(select (not PredRegs:$src1), IntRegs:$src2, s12ImmPred:$src3), +def : Pat <(select (not (i1 PredRegs:$src1)), IntRegs:$src2, s12ImmPred:$src3), (i32 (TFR_condset_ir (i1 PredRegs:$src1), s12ImmPred:$src3, (i32 IntRegs:$src2)))>; // Map from p0 = pnot(p0); if (p0) jump => if (!p0) jump. -def : Pat <(brcond (not PredRegs:$src1), bb:$offset), - (JMP_cNot (i1 PredRegs:$src1), bb:$offset)>; +def : Pat <(brcond (not (i1 PredRegs:$src1)), bb:$offset), + (JMP_f (i1 PredRegs:$src1), bb:$offset)>; // Map from p2 = pnot(p2); p1 = and(p0, p2) => p1 = and(p0, !p2). -def : Pat <(and PredRegs:$src1, (not PredRegs:$src2)), +def : Pat <(and (i1 PredRegs:$src1), (not (i1 PredRegs:$src2))), (i1 (AND_pnotp (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>; + +let AddedComplexity = 100 in +def : Pat <(i64 (zextloadi1 (HexagonCONST32 tglobaladdr:$global))), + (i64 (COMBINE_rr (TFRI 0), + (LDriub_indexed (CONST32_set tglobaladdr:$global), 0)))>, + Requires<[NoV4T]>; + // Map from i1 loads to 32 bits. This assumes that the i1* is byte aligned. let AddedComplexity = 10 in def : Pat <(i32 (zextloadi1 ADDRriS11_0:$addr)), @@ -2186,43 +2196,46 @@ def : Pat <(i64 (sext_inreg (i64 DoubleRegs:$src1), i8)), subreg_loreg))))))>; // We want to prevent emitting pnot's as much as possible. -// Map brcond with an unsupported setcc to a JMP_cNot. +// Map brcond with an unsupported setcc to a JMP_f. def : Pat <(brcond (i1 (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2))), bb:$offset), - (JMP_cNot (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), + (JMP_f (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), bb:$offset)>; def : Pat <(brcond (i1 (setne (i32 IntRegs:$src1), s10ImmPred:$src2)), bb:$offset), - (JMP_cNot (CMPEQri (i32 IntRegs:$src1), s10ImmPred:$src2), bb:$offset)>; + (JMP_f (CMPEQri (i32 IntRegs:$src1), s10ImmPred:$src2), bb:$offset)>; def : Pat <(brcond (i1 (setne (i1 PredRegs:$src1), (i1 -1))), bb:$offset), - (JMP_cNot (i1 PredRegs:$src1), bb:$offset)>; + (JMP_f (i1 PredRegs:$src1), bb:$offset)>; def : Pat <(brcond (i1 (setne (i1 PredRegs:$src1), (i1 0))), bb:$offset), - (JMP_c (i1 PredRegs:$src1), bb:$offset)>; + (JMP_t (i1 PredRegs:$src1), bb:$offset)>; +// cmp.lt(Rs, Imm) -> !cmp.ge(Rs, Imm) -> !cmp.gt(Rs, Imm-1) def : Pat <(brcond (i1 (setlt (i32 IntRegs:$src1), s8ImmPred:$src2)), bb:$offset), - (JMP_cNot (CMPGEri (i32 IntRegs:$src1), s8ImmPred:$src2), bb:$offset)>; + (JMP_f (CMPGTri (i32 IntRegs:$src1), + (DEC_CONST_SIGNED s8ImmPred:$src2)), bb:$offset)>; +// cmp.lt(r0, r1) -> cmp.gt(r1, r0) def : Pat <(brcond (i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))), bb:$offset), - (JMP_c (CMPLTrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), bb:$offset)>; + (JMP_t (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)), bb:$offset)>; def : Pat <(brcond (i1 (setuge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), bb:$offset), - (JMP_cNot (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)), + (JMP_f (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)), bb:$offset)>; def : Pat <(brcond (i1 (setule (i32 IntRegs:$src1), (i32 IntRegs:$src2))), bb:$offset), - (JMP_cNot (CMPGTUrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), + (JMP_f (CMPGTUrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), bb:$offset)>; def : Pat <(brcond (i1 (setule (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), bb:$offset), - (JMP_cNot (CMPGTU64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), + (JMP_f (CMPGTU64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), bb:$offset)>; // Map from a 64-bit select to an emulated 64-bit mux. @@ -2300,8 +2313,8 @@ def : Pat<(i64 (anyext (i32 IntRegs:$src1))), // Map cmple -> cmpgt. // rs <= rt -> !(rs > rt). -def : Pat<(i1 (setle (i32 IntRegs:$src1), s10ImmPred:$src2)), - (i1 (NOT_p (CMPGTri (i32 IntRegs:$src1), s10ImmPred:$src2)))>; +def : Pat<(i1 (setle (i32 IntRegs:$src1), s10ExtPred:$src2)), + (i1 (NOT_p (CMPGTri (i32 IntRegs:$src1), s10ExtPred:$src2)))>; // rs <= rt -> !(rs > rt). def : Pat<(i1 (setle (i32 IntRegs:$src1), (i32 IntRegs:$src2))), @@ -2314,8 +2327,8 @@ def : Pat<(i1 (setle (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), // Map cmpne -> cmpeq. // Hexagon_TODO: We should improve on this. // rs != rt -> !(rs == rt). -def : Pat <(i1 (setne (i32 IntRegs:$src1), s10ImmPred:$src2)), - (i1 (NOT_p(i1 (CMPEQri (i32 IntRegs:$src1), s10ImmPred:$src2))))>; +def : Pat <(i1 (setne (i32 IntRegs:$src1), s10ExtPred:$src2)), + (i1 (NOT_p(i1 (CMPEQri (i32 IntRegs:$src1), s10ExtPred:$src2))))>; // Map cmpne(Rs) -> !cmpeqe(Rs). // rs != rt -> !(rs == rt). @@ -2337,8 +2350,9 @@ def : Pat <(i1 (setne (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), def : Pat <(i1 (setge (i32 IntRegs:$src1), (i32 IntRegs:$src2))), (i1 (NOT_p (i1 (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)))))>; -def : Pat <(i1 (setge (i32 IntRegs:$src1), s8ImmPred:$src2)), - (i1 (CMPGEri (i32 IntRegs:$src1), s8ImmPred:$src2))>; +// cmpge(Rs, Imm) -> cmpgt(Rs, Imm-1) +def : Pat <(i1 (setge (i32 IntRegs:$src1), s8ExtPred:$src2)), + (i1 (CMPGTri (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2)))>; // Map cmpge(Rss, Rtt) -> !cmpgt(Rtt, Rss). // rss >= rtt -> !(rtt > rss). @@ -2347,9 +2361,10 @@ def : Pat <(i1 (setge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), (i64 DoubleRegs:$src1)))))>; // Map cmplt(Rs, Imm) -> !cmpge(Rs, Imm). +// !cmpge(Rs, Imm) -> !cmpgt(Rs, Imm-1). // rs < rt -> !(rs >= rt). -def : Pat <(i1 (setlt (i32 IntRegs:$src1), s8ImmPred:$src2)), - (i1 (NOT_p (CMPGEri (i32 IntRegs:$src1), s8ImmPred:$src2)))>; +def : Pat <(i1 (setlt (i32 IntRegs:$src1), s8ExtPred:$src2)), + (i1 (NOT_p (CMPGTri (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2))))>; // Map cmplt(Rs, Rt) -> cmpgt(Rt, Rs). // rs < rt -> rt > rs. @@ -2373,13 +2388,17 @@ def : Pat <(i1 (setult (i32 IntRegs:$src1), (i32 IntRegs:$src2))), def : Pat <(i1 (setult (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), (i1 (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))>; -// Generate cmpgeu(Rs, #u8) -def : Pat <(i1 (setuge (i32 IntRegs:$src1), u8ImmPred:$src2)), - (i1 (CMPGEUri (i32 IntRegs:$src1), u8ImmPred:$src2))>; +// Generate cmpgeu(Rs, #0) -> cmpeq(Rs, Rs) +def : Pat <(i1 (setuge (i32 IntRegs:$src1), 0)), + (i1 (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src1)))>; + +// Generate cmpgeu(Rs, #u8) -> cmpgtu(Rs, #u8 -1) +def : Pat <(i1 (setuge (i32 IntRegs:$src1), u8ExtPred:$src2)), + (i1 (CMPGTUri (i32 IntRegs:$src1), (DEC_CONST_UNSIGNED u8ExtPred:$src2)))>; // Generate cmpgtu(Rs, #u9) -def : Pat <(i1 (setugt (i32 IntRegs:$src1), u9ImmPred:$src2)), - (i1 (CMPGTUri (i32 IntRegs:$src1), u9ImmPred:$src2))>; +def : Pat <(i1 (setugt (i32 IntRegs:$src1), u9ExtPred:$src2)), + (i1 (CMPGTUri (i32 IntRegs:$src1), u9ExtPred:$src2))>; // Map from Rs >= Rt -> !(Rt > Rs). // rs >= rt -> !(rt > rs). @@ -2391,7 +2410,7 @@ def : Pat <(i1 (setuge (i32 IntRegs:$src1), (i32 IntRegs:$src2))), def : Pat <(i1 (setuge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), (i1 (NOT_p (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1))))>; -// Map from cmpleu(Rs, Rs) -> !cmpgtu(Rs, Rs). +// Map from cmpleu(Rs, Rt) -> !cmpgtu(Rs, Rt). // Map from (Rs <= Rt) -> !(Rs > Rt). def : Pat <(i1 (setule (i32 IntRegs:$src1), (i32 IntRegs:$src2))), (i1 (NOT_p (CMPGTUrr (i32 IntRegs:$src1), (i32 IntRegs:$src2))))>; @@ -2487,6 +2506,13 @@ def: Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)), (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>, Requires<[NoV4T]>; +let AddedComplexity = 100 in +def: Pat <(i64 (zextloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), + (i64 (COMBINE_rr (TFRI 0), (LDriw_indexed IntRegs:$src1, + s11_2ExtPred:$offset)))>, + Requires<[NoV4T]>; + +let AddedComplexity = 10 in def: Pat <(i32 (zextloadi1 ADDRriS11_0:$src1)), (i32 (LDriw ADDRriS11_0:$src1))>; @@ -2503,6 +2529,48 @@ def : Pat <(i64 (anyext (i1 PredRegs:$src1))), (i64 (SXTW (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))))>; +let AddedComplexity = 100 in +def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), + (i32 32))), + (i64 (zextloadi32 (i32 (add IntRegs:$src2, + s11_2ExtPred:$offset2)))))), + (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (LDriw_indexed IntRegs:$src2, + s11_2ExtPred:$offset2)))>; + +def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), + (i32 32))), + (i64 (zextloadi32 ADDRriS11_2:$srcLow)))), + (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (LDriw ADDRriS11_2:$srcLow)))>; + +def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), + (i32 32))), + (i64 (zext (i32 IntRegs:$srcLow))))), + (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + IntRegs:$srcLow))>; + +let AddedComplexity = 100 in +def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), + (i32 32))), + (i64 (zextloadi32 (i32 (add IntRegs:$src2, + s11_2ExtPred:$offset2)))))), + (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (LDriw_indexed IntRegs:$src2, + s11_2ExtPred:$offset2)))>; + +def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), + (i32 32))), + (i64 (zextloadi32 ADDRriS11_2:$srcLow)))), + (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (LDriw ADDRriS11_2:$srcLow)))>; + +def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), + (i32 32))), + (i64 (zext (i32 IntRegs:$srcLow))))), + (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + IntRegs:$srcLow))>; + // Any extended 64-bit load. // anyext i32 -> i64 def: Pat <(i64 (extloadi32 ADDRriS11_2:$src1)), @@ -2637,19 +2705,6 @@ let AddedComplexity = 100 in def : Pat<(i32 (sext_inreg (Hexagon_ARGEXTEND (i32 IntRegs:$src1)), i16)), (COPY (i32 IntRegs:$src1))>; -def SDHexagonBR_JT: SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; -def HexagonBR_JT: SDNode<"HexagonISD::BR_JT", SDHexagonBR_JT, [SDNPHasChain]>; - -let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in -def BR_JT : JRInst<(outs), (ins IntRegs:$src), - "jumpr $src", - [(HexagonBR_JT (i32 IntRegs:$src))]>; - -let isBranch=1, isIndirectBranch=1, isTerminator=1 in -def BRIND : JRInst<(outs), (ins IntRegs:$src), - "jumpr $src", - [(brind (i32 IntRegs:$src))]>; - def HexagonWrapperJT: SDNode<"HexagonISD::WrapperJT", SDTIntUnaryOp>; def : Pat<(HexagonWrapperJT tjumptable:$dst), diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV3.td b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV3.td index 157ab3d..7e75554 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV3.td +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV3.td @@ -11,6 +11,11 @@ // //===----------------------------------------------------------------------===// +def callv3 : SDNode<"HexagonISD::CALLv3", SDT_SPCall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; + +def callv3nr : SDNode<"HexagonISD::CALLv3nr", SDT_SPCall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; //===----------------------------------------------------------------------===// // J + @@ -40,41 +45,6 @@ let isCall = 1, neverHasSideEffects = 1, []>, Requires<[HasV3TOnly]>; } - -// Jump to address from register -// if(p?.new) jumpr:t r? -let isReturn = 1, isTerminator = 1, isBarrier = 1, - Defs = [PC], Uses = [R31] in { - def JMPR_cdnPt_V3: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), - "if ($src1.new) jumpr:t $src2", - []>, Requires<[HasV3T]>; -} - -// if (!p?.new) jumpr:t r? -let isReturn = 1, isTerminator = 1, isBarrier = 1, - Defs = [PC], Uses = [R31] in { - def JMPR_cdnNotPt_V3: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), - "if (!$src1.new) jumpr:t $src2", - []>, Requires<[HasV3T]>; -} - -// Not taken. -// if(p?.new) jumpr:nt r? -let isReturn = 1, isTerminator = 1, isBarrier = 1, - Defs = [PC], Uses = [R31] in { - def JMPR_cdnPnt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), - "if ($src1.new) jumpr:nt $src2", - []>, Requires<[HasV3T]>; -} - -// if (!p?.new) jumpr:nt r? -let isReturn = 1, isTerminator = 1, isBarrier = 1, - Defs = [PC], Uses = [R31] in { - def JMPR_cdnNotPnt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), - "if (!$src1.new) jumpr:nt $src2", - []>, Requires<[HasV3T]>; -} - //===----------------------------------------------------------------------===// // JR - //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV4.td b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV4.td index cd0e475..933239d 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV4.td +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV4.td @@ -209,105 +209,31 @@ def COMBINE_iI_V4 : ALU32_ii<(outs DoubleRegs:$dst), //===----------------------------------------------------------------------===// // LD + //===----------------------------------------------------------------------===// -// -// These absolute set addressing mode instructions accept immediate as -// an operand. We have duplicated these patterns to take global address. - +//===----------------------------------------------------------------------===// +// Template class for load instructions with Absolute set addressing mode. +//===----------------------------------------------------------------------===// let isExtended = 1, opExtendable = 2, neverHasSideEffects = 1, -validSubTargets = HasV4SubT in { -def LDrid_abs_setimm_V4 : LDInst2<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins u0AlwaysExt:$addr), - "$dst1 = memd($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memb(Re=#U6) -def LDrib_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u0AlwaysExt:$addr), - "$dst1 = memb($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memh(Re=#U6) -def LDrih_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u0AlwaysExt:$addr), - "$dst1 = memh($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memub(Re=#U6) -def LDriub_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), +validSubTargets = HasV4SubT in +class T_LD_abs_set<string mnemonic, RegisterClass RC>: + LDInst2<(outs RC:$dst1, IntRegs:$dst2), (ins u0AlwaysExt:$addr), - "$dst1 = memub($dst2=##$addr)", + "$dst1 = "#mnemonic#"($dst2=##$addr)", []>, Requires<[HasV4T]>; -// Rd=memuh(Re=#U6) -def LDriuh_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u0AlwaysExt:$addr), - "$dst1 = memuh($dst2=##$addr)", - []>, - Requires<[HasV4T]>; +def LDrid_abs_set_V4 : T_LD_abs_set <"memd", DoubleRegs>; +def LDrib_abs_set_V4 : T_LD_abs_set <"memb", IntRegs>; +def LDriub_abs_set_V4 : T_LD_abs_set <"memub", IntRegs>; +def LDrih_abs_set_V4 : T_LD_abs_set <"memh", IntRegs>; +def LDriw_abs_set_V4 : T_LD_abs_set <"memw", IntRegs>; +def LDriuh_abs_set_V4 : T_LD_abs_set <"memuh", IntRegs>; -// Rd=memw(Re=#U6) -def LDriw_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u0AlwaysExt:$addr), - "$dst1 = memw($dst2=##$addr)", - []>, - Requires<[HasV4T]>; -} - -// Following patterns are defined for absolute set addressing mode -// instruction which take global address as operand. -let isExtended = 1, opExtendable = 2, neverHasSideEffects = 1, -validSubTargets = HasV4SubT in { -def LDrid_abs_set_V4 : LDInst2<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins globaladdressExt:$addr), - "$dst1 = memd($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memb(Re=#U6) -def LDrib_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdressExt:$addr), - "$dst1 = memb($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memh(Re=#U6) -def LDrih_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdressExt:$addr), - "$dst1 = memh($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memub(Re=#U6) -def LDriub_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdressExt:$addr), - "$dst1 = memub($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memuh(Re=#U6) -def LDriuh_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdressExt:$addr), - "$dst1 = memuh($dst2=##$addr)", - []>, - Requires<[HasV4T]>; - -// Rd=memw(Re=#U6) -def LDriw_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdressExt:$addr), - "$dst1 = memw($dst2=##$addr)", - []>, - Requires<[HasV4T]>; -} // multiclass for load instructions with base + register offset // addressing mode multiclass ld_idxd_shl_pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : LDInst2<(outs RC:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$offset), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -316,7 +242,7 @@ multiclass ld_idxd_shl_pbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass ld_idxd_shl_pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 0>; // Predicate new defm _cdn#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 1>; @@ -527,78 +453,29 @@ def: Pat <(i64 (extloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), // ST + //===----------------------------------------------------------------------===// /// -/// Assumptions::: ****** DO NOT IGNORE ******** -/// 1. Make sure that in post increment store, the zero'th operand is always the -/// post increment operand. -/// 2. Make sure that the store value operand(Rt/Rtt) in a store is always the -/// last operand. -/// - -// memd(Re=#U)=Rtt -let isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in { -def STrid_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins DoubleRegs:$src1, u0AlwaysExt:$src2), - "memd($dst1=##$src2) = $src1", - []>, - Requires<[HasV4T]>; - -// memb(Re=#U)=Rs -def STrib_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, u0AlwaysExt:$src2), - "memb($dst1=##$src2) = $src1", - []>, - Requires<[HasV4T]>; - -// memh(Re=#U)=Rs -def STrih_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, u0AlwaysExt:$src2), - "memh($dst1=##$src2) = $src1", - []>, - Requires<[HasV4T]>; - -// memw(Re=#U)=Rs -def STriw_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, u0AlwaysExt:$src2), - "memw($dst1=##$src2) = $src1", - []>, - Requires<[HasV4T]>; -} - -// memd(Re=#U)=Rtt -let isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in { -def STrid_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins DoubleRegs:$src1, globaladdressExt:$src2), - "memd($dst1=##$src2) = $src1", - []>, - Requires<[HasV4T]>; - -// memb(Re=#U)=Rs -def STrib_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, globaladdressExt:$src2), - "memb($dst1=##$src2) = $src1", +//===----------------------------------------------------------------------===// +// Template class for store instructions with Absolute set addressing mode. +//===----------------------------------------------------------------------===// +let isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in +class T_ST_abs_set<string mnemonic, RegisterClass RC>: + STInst2<(outs IntRegs:$dst1), + (ins RC:$src1, u0AlwaysExt:$src2), + mnemonic#"($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; -// memh(Re=#U)=Rs -def STrih_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, globaladdressExt:$src2), - "memh($dst1=##$src2) = $src1", - []>, - Requires<[HasV4T]>; - -// memw(Re=#U)=Rs -def STriw_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, globaladdressExt:$src2), - "memw($dst1=##$src2) = $src1", - []>, - Requires<[HasV4T]>; -} +def STrid_abs_set_V4 : T_ST_abs_set <"memd", DoubleRegs>; +def STrib_abs_set_V4 : T_ST_abs_set <"memb", IntRegs>; +def STrih_abs_set_V4 : T_ST_abs_set <"memh", IntRegs>; +def STriw_abs_set_V4 : T_ST_abs_set <"memw", IntRegs>; +//===----------------------------------------------------------------------===// // multiclass for store instructions with base + register offset addressing // mode +//===----------------------------------------------------------------------===// multiclass ST_Idxd_shl_Pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : STInst2<(outs), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, RC:$src5), @@ -609,7 +486,7 @@ multiclass ST_Idxd_shl_Pbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_Idxd_shl_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 0>; // Predicate new defm _cdn#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 1>; @@ -637,7 +514,7 @@ multiclass ST_Idxd_shl<string mnemonic, string CextOp, RegisterClass RC> { // addressing mode. multiclass ST_Idxd_shl_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME#_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, RC:$src5), @@ -648,7 +525,7 @@ multiclass ST_Idxd_shl_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_Idxd_shl_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 0>; // Predicate new defm _cdn#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 1>; @@ -711,17 +588,59 @@ def : Pat<(store (i64 DoubleRegs:$src4), u2ImmPred:$src3, DoubleRegs:$src4)>; } -// memd(Ru<<#u2+#U6)=Rtt -let isExtended = 1, opExtendable = 2, AddedComplexity = 10, -validSubTargets = HasV4SubT in -def STrid_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, DoubleRegs:$src4), - "memd($src1<<#$src2+#$src3) = $src4", - [(store (i64 DoubleRegs:$src4), +let isExtended = 1, opExtendable = 2 in +class T_ST_LongOff <string mnemonic, PatFrag stOp, RegisterClass RC, ValueType VT> : + STInst<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, RC:$src4), + mnemonic#"($src1<<#$src2+##$src3) = $src4", + [(stOp (VT RC:$src4), (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), u0AlwaysExtPred:$src3))]>, Requires<[HasV4T]>; +let isExtended = 1, opExtendable = 2, mayStore = 1, isNVStore = 1 in +class T_ST_LongOff_nv <string mnemonic> : + NVInst_V4<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), + mnemonic#"($src1<<#$src2+##$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +multiclass ST_LongOff <string mnemonic, string BaseOp, PatFrag stOp> { + let BaseOpcode = BaseOp#"_shl" in { + let isNVStorable = 1 in + def NAME#_V4 : T_ST_LongOff<mnemonic, stOp, IntRegs, i32>; + + def NAME#_nv_V4 : T_ST_LongOff_nv<mnemonic>; + } +} + +let AddedComplexity = 10, validSubTargets = HasV4SubT in { + def STrid_shl_V4 : T_ST_LongOff<"memd", store, DoubleRegs, i64>; + defm STrib_shl : ST_LongOff <"memb", "STrib", truncstorei8>, NewValueRel; + defm STrih_shl : ST_LongOff <"memh", "Strih", truncstorei16>, NewValueRel; + defm STriw_shl : ST_LongOff <"memw", "STriw", store>, NewValueRel; +} + +let AddedComplexity = 40 in +multiclass T_ST_LOff_Pats <InstHexagon I, RegisterClass RC, ValueType VT, + PatFrag stOp> { + def : Pat<(stOp (VT RC:$src4), + (add (shl IntRegs:$src1, u2ImmPred:$src2), + (NumUsesBelowThresCONST32 tglobaladdr:$src3))), + (I IntRegs:$src1, u2ImmPred:$src2, tglobaladdr:$src3, RC:$src4)>; + + def : Pat<(stOp (VT RC:$src4), + (add IntRegs:$src1, + (NumUsesBelowThresCONST32 tglobaladdr:$src3))), + (I IntRegs:$src1, 0, tglobaladdr:$src3, RC:$src4)>; +} + +defm : T_ST_LOff_Pats<STrid_shl_V4, DoubleRegs, i64, store>; +defm : T_ST_LOff_Pats<STriw_shl_V4, IntRegs, i32, store>; +defm : T_ST_LOff_Pats<STrib_shl_V4, IntRegs, i32, truncstorei8>; +defm : T_ST_LOff_Pats<STrih_shl_V4, IntRegs, i32, truncstorei16>; + // memd(Rx++#s4:3)=Rtt // memd(Rx++#s4:3:circ(Mu))=Rtt // memd(Rx++I:circ(Mu))=Rtt @@ -741,7 +660,7 @@ def STrid_shl_V4 : STInst<(outs), //===----------------------------------------------------------------------===// multiclass ST_Imm_Pbase<string mnemonic, Operand OffsetOp, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : STInst2<(outs), (ins PredRegs:$src1, IntRegs:$src2, OffsetOp:$src3, s6Ext:$src4), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -751,7 +670,7 @@ multiclass ST_Imm_Pbase<string mnemonic, Operand OffsetOp, bit isNot, } multiclass ST_Imm_Pred<string mnemonic, Operand OffsetOp, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 0>; // Predicate new defm _cdn#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 1>; @@ -799,17 +718,6 @@ def : Pat <(truncstorei8 s8ExtPred:$src2, (i32 IntRegs:$src1)), (STrib_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, Requires<[HasV4T]>; -// memb(Ru<<#u2+#U6)=Rt -let isExtended = 1, opExtendable = 2, AddedComplexity = 10, isNVStorable = 1, -validSubTargets = HasV4SubT in -def STrib_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), - "memb($src1<<#$src2+#$src3) = $src4", - [(truncstorei8 (i32 IntRegs:$src4), - (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), - u0AlwaysExtPred:$src3))]>, - Requires<[HasV4T]>; - // memb(Rx++#s4:0:circ(Mu))=Rt // memb(Rx++I:circ(Mu))=Rt // memb(Rx++Mu)=Rt @@ -830,17 +738,6 @@ def : Pat <(truncstorei16 s8ExtPred:$src2, (i32 IntRegs:$src1)), // TODO: needs to be implemented. // memh(Ru<<#u2+#U6)=Rt.H -// memh(Ru<<#u2+#U6)=Rt -let isExtended = 1, opExtendable = 2, AddedComplexity = 10, isNVStorable = 1, -validSubTargets = HasV4SubT in -def STrih_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), - "memh($src1<<#$src2+#$src3) = $src4", - [(truncstorei16 (i32 IntRegs:$src4), - (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), - u0AlwaysExtPred:$src3))]>, - Requires<[HasV4T]>; - // memh(Rx++#s4:1:circ(Mu))=Rt.H // memh(Rx++#s4:1:circ(Mu))=Rt // memh(Rx++I:circ(Mu))=Rt.H @@ -877,17 +774,6 @@ def : Pat <(store s8ExtPred:$src2, (i32 IntRegs:$src1)), (STriw_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, Requires<[HasV4T]>; -// memw(Ru<<#u2+#U6)=Rt -let isExtended = 1, opExtendable = 2, AddedComplexity = 10, isNVStorable = 1, -validSubTargets = HasV4SubT in -def STriw_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), - "memw($src1<<#$src2+#$src3) = $src4", - [(store (i32 IntRegs:$src4), - (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), - u0AlwaysExtPred:$src3))]>, - Requires<[HasV4T]>; - // memw(Rx++#s4:2)=Rt // memw(Rx++#s4:2:circ(Mu))=Rt // memw(Rx++I:circ(Mu))=Rt @@ -907,7 +793,7 @@ def STriw_shl_V4 : STInst<(outs), // multiclass ST_Idxd_Pbase_nv<string mnemonic, RegisterClass RC, Operand predImmOp, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME#_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -918,7 +804,7 @@ multiclass ST_Idxd_Pbase_nv<string mnemonic, RegisterClass RC, multiclass ST_Idxd_Pred_nv<string mnemonic, RegisterClass RC, Operand predImmOp, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 0>; // Predicate new defm _cdn#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 1>; @@ -960,7 +846,7 @@ let addrMode = BaseImmOffset, validSubTargets = HasV4SubT in { // and MEMri operand. multiclass ST_MEMri_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME#_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, MEMri:$addr, RC: $src2), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -970,7 +856,7 @@ multiclass ST_MEMri_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_MEMri_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 0>; // Predicate new @@ -1006,15 +892,6 @@ mayStore = 1 in { defm STriw: ST_MEMri_nv<"memw", "STriw", IntRegs, 13, 8>, AddrModeRel; } -// memb(Ru<<#u2+#U6)=Nt.new -let isExtended = 1, opExtendable = 2, mayStore = 1, AddedComplexity = 10, -isNVStore = 1, validSubTargets = HasV4SubT in -def STrib_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), - "memb($src1<<#$src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - //===----------------------------------------------------------------------===// // Post increment store // mem[bhwd](Rx++#s4:[0123])=Nt.new @@ -1022,7 +899,7 @@ def STrib_shl_nv_V4 : NVInst_V4<(outs), multiclass ST_PostInc_Pbase_nv<string mnemonic, RegisterClass RC, Operand ImmOp, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME#_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -1034,7 +911,7 @@ multiclass ST_PostInc_Pbase_nv<string mnemonic, RegisterClass RC, Operand ImmOp, multiclass ST_PostInc_Pred_nv<string mnemonic, RegisterClass RC, Operand ImmOp, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_PostInc_Pbase_nv<mnemonic, RC, ImmOp, PredNot, 0>; // Predicate new let Predicates = [HasV4T], validSubTargets = HasV4SubT in @@ -1072,29 +949,11 @@ defm POST_STwri: ST_PostInc_nv <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel; // memb(Rx++I:circ(Mu))=Nt.new // memb(Rx++Mu)=Nt.new // memb(Rx++Mu:brev)=Nt.new -// memh(Ru<<#u2+#U6)=Nt.new -let isExtended = 1, opExtendable = 2, mayStore = 1, AddedComplexity = 10, -isNVStore = 1, validSubTargets = HasV4SubT in -def STrih_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), - "memh($src1<<#$src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - // memh(Rx++#s4:1:circ(Mu))=Nt.new // memh(Rx++I:circ(Mu))=Nt.new // memh(Rx++Mu)=Nt.new // memh(Rx++Mu:brev)=Nt.new -// memw(Ru<<#u2+#U6)=Nt.new -let isExtended = 1, opExtendable = 2, mayStore = 1, AddedComplexity = 10, -isNVStore = 1, validSubTargets = HasV4SubT in -def STriw_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), - "memw($src1<<#$src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - // memw(Rx++#s4:2:circ(Mu))=Nt.new // memw(Rx++I:circ(Mu))=Nt.new // memw(Rx++Mu)=Nt.new @@ -1108,179 +967,193 @@ def STriw_shl_nv_V4 : NVInst_V4<(outs), // NV/J + //===----------------------------------------------------------------------===// -multiclass NVJ_type_basic_reg<string NotStr, string OpcStr, string TakenStr> { - def _ie_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, $src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// multiclass/template class for the new-value compare jumps with the register +// operands. +//===----------------------------------------------------------------------===// - def _nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, $src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; -} +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11 in +class NVJrr_template<string mnemonic, bits<3> majOp, bit NvOpNum, + bit isNegCond, bit isTaken> + : NVInst_V4<(outs), + (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset), + "if ("#!if(isNegCond, "!","")#mnemonic# + "($src1"#!if(!eq(NvOpNum, 0),".new, ",", ")# + "$src2"#!if(!eq(NvOpNum, 1),".new))","))")#" jump:" + #!if(isTaken, "t","nt")#" $offset", + []>, Requires<[HasV4T]> { -multiclass NVJ_type_basic_2ndDotNew<string NotStr, string OpcStr, - string TakenStr> { - def _ie_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1, $src2.new)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; + bits<5> src1; + bits<5> src2; + bits<3> Ns; // New-Value Operand + bits<5> RegOp; // Non New-Value Operand + bits<11> offset; - def _nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1, $src2.new)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; -} + let isBrTaken = !if(isTaken, "true", "false"); + let isPredicatedFalse = isNegCond; -multiclass NVJ_type_basic_imm<string NotStr, string OpcStr, string TakenStr> { - def _ie_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, #$src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; + let Ns = !if(!eq(NvOpNum, 0), src1{2-0}, src2{2-0}); + let RegOp = !if(!eq(NvOpNum, 0), src2, src1); - def _nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, #$src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; + let IClass = 0b0010; + let Inst{26} = 0b0; + let Inst{25-23} = majOp; + let Inst{22} = isNegCond; + let Inst{18-16} = Ns; + let Inst{13} = isTaken; + let Inst{12-8} = RegOp; + let Inst{21-20} = offset{10-9}; + let Inst{7-1} = offset{8-2}; } -multiclass NVJ_type_basic_neg<string NotStr, string OpcStr, string TakenStr> { - def _ie_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, nOneImm:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, #$src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; - def _nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, nOneImm:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, #$src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; +multiclass NVJrr_cond<string mnemonic, bits<3> majOp, bit NvOpNum, + bit isNegCond> { + // Branch not taken: + def _nt_V4: NVJrr_template<mnemonic, majOp, NvOpNum, isNegCond, 0>; + // Branch taken: + def _t_V4: NVJrr_template<mnemonic, majOp, NvOpNum, isNegCond, 1>; } -multiclass NVJ_type_basic_tstbit<string NotStr, string OpcStr, - string TakenStr> { - def _ie_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u1Imm:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, #$src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; +// NvOpNum = 0 -> First Operand is a new-value Register +// NvOpNum = 1 -> Second Operand is a new-value Register - def _nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u1Imm:$src2, brtarget:$offset), - !strconcat("if (", !strconcat(NotStr, !strconcat(OpcStr, - !strconcat("($src1.new, #$src2)) jump:", - !strconcat(TakenStr, " $offset"))))), - []>, - Requires<[HasV4T]>; +multiclass NVJrr_base<string mnemonic, string BaseOp, bits<3> majOp, + bit NvOpNum> { + let BaseOpcode = BaseOp#_NVJ in { + defm _t_Jumpnv : NVJrr_cond<mnemonic, majOp, NvOpNum, 0>; // True cond + defm _f_Jumpnv : NVJrr_cond<mnemonic, majOp, NvOpNum, 1>; // False cond + } } -// Multiclass for regular dot new of Ist operand register. -multiclass NVJ_type_br_pred_reg<string NotStr, string OpcStr> { - defm Pt : NVJ_type_basic_reg<NotStr, OpcStr, "t">; - defm Pnt : NVJ_type_basic_reg<NotStr, OpcStr, "nt">; -} +// if ([!]cmp.eq(Ns.new,Rt)) jump:[n]t #r9:2 +// if ([!]cmp.gt(Ns.new,Rt)) jump:[n]t #r9:2 +// if ([!]cmp.gtu(Ns.new,Rt)) jump:[n]t #r9:2 +// if ([!]cmp.gt(Rt,Ns.new)) jump:[n]t #r9:2 +// if ([!]cmp.gtu(Rt,Ns.new)) jump:[n]t #r9:2 -// Multiclass for dot new of 2nd operand register. -multiclass NVJ_type_br_pred_2ndDotNew<string NotStr, string OpcStr> { - defm Pt : NVJ_type_basic_2ndDotNew<NotStr, OpcStr, "t">; - defm Pnt : NVJ_type_basic_2ndDotNew<NotStr, OpcStr, "nt">; +let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1, + Defs = [PC], neverHasSideEffects = 1, validSubTargets = HasV4SubT in { + defm CMPEQrr : NVJrr_base<"cmp.eq", "CMPEQ", 0b000, 0>, PredRel; + defm CMPGTrr : NVJrr_base<"cmp.gt", "CMPGT", 0b001, 0>, PredRel; + defm CMPGTUrr : NVJrr_base<"cmp.gtu", "CMPGTU", 0b010, 0>, PredRel; + defm CMPLTrr : NVJrr_base<"cmp.gt", "CMPLT", 0b011, 1>, PredRel; + defm CMPLTUrr : NVJrr_base<"cmp.gtu", "CMPLTU", 0b100, 1>, PredRel; } -// Multiclass for 2nd operand immediate, including -1. -multiclass NVJ_type_br_pred_imm<string NotStr, string OpcStr> { - defm Pt : NVJ_type_basic_imm<NotStr, OpcStr, "t">; - defm Pnt : NVJ_type_basic_imm<NotStr, OpcStr, "nt">; - defm Ptneg : NVJ_type_basic_neg<NotStr, OpcStr, "t">; - defm Pntneg : NVJ_type_basic_neg<NotStr, OpcStr, "nt">; -} +//===----------------------------------------------------------------------===// +// multiclass/template class for the new-value compare jumps instruction +// with a register and an unsigned immediate (U5) operand. +//===----------------------------------------------------------------------===// -// Multiclass for 2nd operand immediate, excluding -1. -multiclass NVJ_type_br_pred_imm_only<string NotStr, string OpcStr> { - defm Pt : NVJ_type_basic_imm<NotStr, OpcStr, "t">; - defm Pnt : NVJ_type_basic_imm<NotStr, OpcStr, "nt">; -} +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11 in +class NVJri_template<string mnemonic, bits<3> majOp, bit isNegCond, + bit isTaken> + : NVInst_V4<(outs), + (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset), + "if ("#!if(isNegCond, "!","")#mnemonic#"($src1.new, #$src2)) jump:" + #!if(isTaken, "t","nt")#" $offset", + []>, Requires<[HasV4T]> { -// Multiclass for tstbit, where 2nd operand is always #0. -multiclass NVJ_type_br_pred_tstbit<string NotStr, string OpcStr> { - defm Pt : NVJ_type_basic_tstbit<NotStr, OpcStr, "t">; - defm Pnt : NVJ_type_basic_tstbit<NotStr, OpcStr, "nt">; + let isPredicatedFalse = isNegCond; + let isBrTaken = !if(isTaken, "true", "false"); + + bits<3> src1; + bits<5> src2; + bits<11> offset; + + let IClass = 0b0010; + let Inst{26} = 0b1; + let Inst{25-23} = majOp; + let Inst{22} = isNegCond; + let Inst{18-16} = src1; + let Inst{13} = isTaken; + let Inst{12-8} = src2; + let Inst{21-20} = offset{10-9}; + let Inst{7-1} = offset{8-2}; } -// Multiclass for GT. -multiclass NVJ_type_rr_ri<string OpcStr> { - defm rrNot : NVJ_type_br_pred_reg<"!", OpcStr>; - defm rr : NVJ_type_br_pred_reg<"", OpcStr>; - defm rrdnNot : NVJ_type_br_pred_2ndDotNew<"!", OpcStr>; - defm rrdn : NVJ_type_br_pred_2ndDotNew<"", OpcStr>; - defm riNot : NVJ_type_br_pred_imm<"!", OpcStr>; - defm ri : NVJ_type_br_pred_imm<"", OpcStr>; +multiclass NVJri_cond<string mnemonic, bits<3> majOp, bit isNegCond> { + // Branch not taken: + def _nt_V4: NVJri_template<mnemonic, majOp, isNegCond, 0>; + // Branch taken: + def _t_V4: NVJri_template<mnemonic, majOp, isNegCond, 1>; } -// Multiclass for EQ. -multiclass NVJ_type_rr_ri_no_2ndDotNew<string OpcStr> { - defm rrNot : NVJ_type_br_pred_reg<"!", OpcStr>; - defm rr : NVJ_type_br_pred_reg<"", OpcStr>; - defm riNot : NVJ_type_br_pred_imm<"!", OpcStr>; - defm ri : NVJ_type_br_pred_imm<"", OpcStr>; +multiclass NVJri_base<string mnemonic, string BaseOp, bits<3> majOp> { + let BaseOpcode = BaseOp#_NVJri in { + defm _t_Jumpnv : NVJri_cond<mnemonic, majOp, 0>; // True Cond + defm _f_Jumpnv : NVJri_cond<mnemonic, majOp, 1>; // False cond + } } -// Multiclass for GTU. -multiclass NVJ_type_rr_ri_no_nOne<string OpcStr> { - defm rrNot : NVJ_type_br_pred_reg<"!", OpcStr>; - defm rr : NVJ_type_br_pred_reg<"", OpcStr>; - defm rrdnNot : NVJ_type_br_pred_2ndDotNew<"!", OpcStr>; - defm rrdn : NVJ_type_br_pred_2ndDotNew<"", OpcStr>; - defm riNot : NVJ_type_br_pred_imm_only<"!", OpcStr>; - defm ri : NVJ_type_br_pred_imm_only<"", OpcStr>; +// if ([!]cmp.eq(Ns.new,#U5)) jump:[n]t #r9:2 +// if ([!]cmp.gt(Ns.new,#U5)) jump:[n]t #r9:2 +// if ([!]cmp.gtu(Ns.new,#U5)) jump:[n]t #r9:2 + +let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1, + Defs = [PC], neverHasSideEffects = 1, validSubTargets = HasV4SubT in { + defm CMPEQri : NVJri_base<"cmp.eq", "CMPEQ", 0b000>, PredRel; + defm CMPGTri : NVJri_base<"cmp.gt", "CMPGT", 0b001>, PredRel; + defm CMPGTUri : NVJri_base<"cmp.gtu", "CMPGTU", 0b010>, PredRel; } -// Multiclass for tstbit. -multiclass NVJ_type_r0<string OpcStr> { - defm r0Not : NVJ_type_br_pred_tstbit<"!", OpcStr>; - defm r0 : NVJ_type_br_pred_tstbit<"", OpcStr>; - } +//===----------------------------------------------------------------------===// +// multiclass/template class for the new-value compare jumps instruction +// with a register and an hardcoded 0/-1 immediate value. +//===----------------------------------------------------------------------===// + +let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 11 in +class NVJ_ConstImm_template<string mnemonic, bits<3> majOp, string ImmVal, + bit isNegCond, bit isTaken> + : NVInst_V4<(outs), + (ins IntRegs:$src1, brtarget:$offset), + "if ("#!if(isNegCond, "!","")#mnemonic + #"($src1.new, #"#ImmVal#")) jump:" + #!if(isTaken, "t","nt")#" $offset", + []>, Requires<[HasV4T]> { -// Base Multiclass for New Value Jump. -multiclass NVJ_type { - defm GT : NVJ_type_rr_ri<"cmp.gt">; - defm EQ : NVJ_type_rr_ri_no_2ndDotNew<"cmp.eq">; - defm GTU : NVJ_type_rr_ri_no_nOne<"cmp.gtu">; - defm TSTBIT : NVJ_type_r0<"tstbit">; + let isPredicatedFalse = isNegCond; + let isBrTaken = !if(isTaken, "true", "false"); + + bits<3> src1; + bits<11> offset; + let IClass = 0b0010; + let Inst{26} = 0b1; + let Inst{25-23} = majOp; + let Inst{22} = isNegCond; + let Inst{18-16} = src1; + let Inst{13} = isTaken; + let Inst{21-20} = offset{10-9}; + let Inst{7-1} = offset{8-2}; } -let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC] in { - defm JMP_ : NVJ_type; +multiclass NVJ_ConstImm_cond<string mnemonic, bits<3> majOp, string ImmVal, + bit isNegCond> { + // Branch not taken: + def _nt_V4: NVJ_ConstImm_template<mnemonic, majOp, ImmVal, isNegCond, 0>; + // Branch taken: + def _t_V4: NVJ_ConstImm_template<mnemonic, majOp, ImmVal, isNegCond, 1>; } -//===----------------------------------------------------------------------===// -// NV/J - -//===----------------------------------------------------------------------===// +multiclass NVJ_ConstImm_base<string mnemonic, string BaseOp, bits<3> majOp, + string ImmVal> { + let BaseOpcode = BaseOp#_NVJ_ConstImm in { + defm _t_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 0>; // True cond + defm _f_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 1>; // False Cond + } +} + +// if ([!]tstbit(Ns.new,#0)) jump:[n]t #r9:2 +// if ([!]cmp.eq(Ns.new,#-1)) jump:[n]t #r9:2 +// if ([!]cmp.gt(Ns.new,#-1)) jump:[n]t #r9:2 + +let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator=1, + Defs = [PC], neverHasSideEffects = 1 in { + defm TSTBIT0 : NVJ_ConstImm_base<"tstbit", "TSTBIT", 0b011, "0">, PredRel; + defm CMPEQn1 : NVJ_ConstImm_base<"cmp.eq", "CMPEQ", 0b100, "-1">, PredRel; + defm CMPGTn1 : NVJ_ConstImm_base<"cmp.gt", "CMPGT", 0b101, "-1">, PredRel; +} //===----------------------------------------------------------------------===// // XTYPE/ALU + @@ -2286,7 +2159,7 @@ def CMPbEQri_V4 : MInst<(outs PredRegs:$dst), def : Pat <(brcond (i1 (setne (and (i32 IntRegs:$src1), 255), u8ImmPred:$src2)), bb:$offset), - (JMP_cNot (CMPbEQri_V4 (i32 IntRegs:$src1), u8ImmPred:$src2), + (JMP_f (CMPbEQri_V4 (i32 IntRegs:$src1), u8ImmPred:$src2), bb:$offset)>, Requires<[HasV4T]>; @@ -2769,9 +2642,9 @@ let isReturn = 1, isTerminator = 1, multiclass ST_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME#_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdressExt:$absaddr, RC: $src2), + (ins PredRegs:$src1, u0AlwaysExt:$absaddr, RC: $src2), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#mnemonic#"(##$absaddr) = $src2", []>, @@ -2779,7 +2652,7 @@ multiclass ST_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 0>; // Predicate new defm _cdn#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 1>; @@ -2791,7 +2664,7 @@ multiclass ST_Abs<string mnemonic, string CextOp, RegisterClass RC> { let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { let opExtendable = 0, isPredicable = 1 in def NAME#_V4 : STInst2<(outs), - (ins globaladdressExt:$absaddr, RC:$src), + (ins u0AlwaysExt:$absaddr, RC:$src), mnemonic#"(##$absaddr) = $src", []>, Requires<[HasV4T]>; @@ -2805,9 +2678,9 @@ multiclass ST_Abs<string mnemonic, string CextOp, RegisterClass RC> { multiclass ST_Abs_Predbase_nv<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME#_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdressExt:$absaddr, RC: $src2), + (ins PredRegs:$src1, u0AlwaysExt:$absaddr, RC: $src2), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#mnemonic#"(##$absaddr) = $src2.new", []>, @@ -2815,7 +2688,7 @@ multiclass ST_Abs_Predbase_nv<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_Abs_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 0>; // Predicate new defm _cdn#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 1>; @@ -2827,7 +2700,7 @@ multiclass ST_Abs_nv<string mnemonic, string CextOp, RegisterClass RC> { let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { let opExtendable = 0, isPredicable = 1 in def NAME#_nv_V4 : NVInst_V4<(outs), - (ins globaladdressExt:$absaddr, RC:$src), + (ins u0AlwaysExt:$absaddr, RC:$src), mnemonic#"(##$absaddr) = $src.new", []>, Requires<[HasV4T]>; @@ -2840,16 +2713,19 @@ multiclass ST_Abs_nv<string mnemonic, string CextOp, RegisterClass RC> { } let addrMode = Absolute in { + let accessSize = ByteAccess in defm STrib_abs : ST_Abs<"memb", "STrib", IntRegs>, ST_Abs_nv<"memb", "STrib", IntRegs>, AddrModeRel; + let accessSize = HalfWordAccess in defm STrih_abs : ST_Abs<"memh", "STrih", IntRegs>, ST_Abs_nv<"memh", "STrih", IntRegs>, AddrModeRel; + let accessSize = WordAccess in defm STriw_abs : ST_Abs<"memw", "STriw", IntRegs>, ST_Abs_nv<"memw", "STriw", IntRegs>, AddrModeRel; - let isNVStorable = 0 in + let accessSize = DoubleWordAccess, isNVStorable = 0 in defm STrid_abs : ST_Abs<"memd", "STrid", DoubleRegs>, AddrModeRel; } @@ -2875,6 +2751,7 @@ def : Pat<(store (i64 DoubleRegs:$src1), // mem[bhwd](#global)=Rt // if ([!]Pv[.new]) mem[bhwd](##global) = Rt //===----------------------------------------------------------------------===// +let mayStore = 1, isNVStorable = 1 in multiclass ST_GP<string mnemonic, string BaseOp, RegisterClass RC> { let BaseOpcode = BaseOp, isPredicable = 1 in def NAME#_V4 : STInst2<(outs), @@ -2909,15 +2786,16 @@ multiclass ST_GP_nv<string mnemonic, string BaseOp, RegisterClass RC> { } } -let validSubTargets = HasV4SubT, validSubTargets = HasV4SubT in { -defm STd_GP : ST_GP <"memd", "STd_GP", DoubleRegs>, - ST_GP_nv<"memd", "STd_GP", DoubleRegs>, NewValueRel ; -defm STb_GP : ST_GP<"memb", "STb_GP", IntRegs>, - ST_GP_nv<"memb", "STb_GP", IntRegs>, NewValueRel ; -defm STh_GP : ST_GP<"memh", "STh_GP", IntRegs>, - ST_GP_nv<"memh", "STh_GP", IntRegs>, NewValueRel ; -defm STw_GP : ST_GP<"memw", "STw_GP", IntRegs>, - ST_GP_nv<"memw", "STw_GP", IntRegs>, NewValueRel ; +let validSubTargets = HasV4SubT, neverHasSideEffects = 1 in { + let isNVStorable = 0 in + defm STd_GP : ST_GP <"memd", "STd_GP", DoubleRegs>, PredNewRel; + + defm STb_GP : ST_GP<"memb", "STb_GP", IntRegs>, + ST_GP_nv<"memb", "STb_GP", IntRegs>, NewValueRel; + defm STh_GP : ST_GP<"memh", "STh_GP", IntRegs>, + ST_GP_nv<"memh", "STh_GP", IntRegs>, NewValueRel; + defm STw_GP : ST_GP<"memw", "STw_GP", IntRegs>, + ST_GP_nv<"memw", "STw_GP", IntRegs>, NewValueRel; } // 64 bit atomic store @@ -2974,9 +2852,9 @@ def : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), //===----------------------------------------------------------------------===// multiclass LD_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = !if(isPredNew, "new", "") in + let isPredicatedNew = isPredNew in def NAME : LDInst2<(outs RC:$dst), - (ins PredRegs:$src1, globaladdressExt:$absaddr), + (ins PredRegs:$src1, u0AlwaysExt:$absaddr), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#"$dst = "#mnemonic#"(##$absaddr)", []>, @@ -2984,7 +2862,7 @@ multiclass LD_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass LD_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = !if(PredNot, "false", "true") in { + let isPredicatedFalse = PredNot in { defm _c#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 0>; // Predicate new defm _cdn#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 1>; @@ -2996,7 +2874,7 @@ multiclass LD_Abs<string mnemonic, string CextOp, RegisterClass RC> { let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { let opExtendable = 1, isPredicable = 1 in def NAME#_V4 : LDInst2<(outs RC:$dst), - (ins globaladdressExt:$absaddr), + (ins u0AlwaysExt:$absaddr), "$dst = "#mnemonic#"(##$absaddr)", []>, Requires<[HasV4T]>; @@ -3009,33 +2887,37 @@ multiclass LD_Abs<string mnemonic, string CextOp, RegisterClass RC> { } let addrMode = Absolute in { + let accessSize = ByteAccess in { defm LDrib_abs : LD_Abs<"memb", "LDrib", IntRegs>, AddrModeRel; defm LDriub_abs : LD_Abs<"memub", "LDriub", IntRegs>, AddrModeRel; + } + let accessSize = HalfWordAccess in { defm LDrih_abs : LD_Abs<"memh", "LDrih", IntRegs>, AddrModeRel; defm LDriuh_abs : LD_Abs<"memuh", "LDriuh", IntRegs>, AddrModeRel; + } + let accessSize = WordAccess in defm LDriw_abs : LD_Abs<"memw", "LDriw", IntRegs>, AddrModeRel; + + let accessSize = DoubleWordAccess in defm LDrid_abs : LD_Abs<"memd", "LDrid", DoubleRegs>, AddrModeRel; } -let Predicates = [HasV4T], AddedComplexity = 30 in +let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(i32 (load (HexagonCONST32 tglobaladdr:$absaddr))), (LDriw_abs_V4 tglobaladdr: $absaddr)>; -let Predicates = [HasV4T], AddedComplexity=30 in def : Pat<(i32 (sextloadi8 (HexagonCONST32 tglobaladdr:$absaddr))), (LDrib_abs_V4 tglobaladdr:$absaddr)>; -let Predicates = [HasV4T], AddedComplexity=30 in def : Pat<(i32 (zextloadi8 (HexagonCONST32 tglobaladdr:$absaddr))), (LDriub_abs_V4 tglobaladdr:$absaddr)>; -let Predicates = [HasV4T], AddedComplexity=30 in def : Pat<(i32 (sextloadi16 (HexagonCONST32 tglobaladdr:$absaddr))), (LDrih_abs_V4 tglobaladdr:$absaddr)>; -let Predicates = [HasV4T], AddedComplexity=30 in def : Pat<(i32 (zextloadi16 (HexagonCONST32 tglobaladdr:$absaddr))), (LDriuh_abs_V4 tglobaladdr:$absaddr)>; +} //===----------------------------------------------------------------------===// // multiclass for load instructions with GP-relative addressing mode. @@ -3058,12 +2940,12 @@ multiclass LD_GP<string mnemonic, string BaseOp, RegisterClass RC> { } } -defm LDd_GP : LD_GP<"memd", "LDd_GP", DoubleRegs>; -defm LDb_GP : LD_GP<"memb", "LDb_GP", IntRegs>; -defm LDub_GP : LD_GP<"memub", "LDub_GP", IntRegs>; -defm LDh_GP : LD_GP<"memh", "LDh_GP", IntRegs>; -defm LDuh_GP : LD_GP<"memuh", "LDuh_GP", IntRegs>; -defm LDw_GP : LD_GP<"memw", "LDw_GP", IntRegs>; +defm LDd_GP : LD_GP<"memd", "LDd_GP", DoubleRegs>, PredNewRel; +defm LDb_GP : LD_GP<"memb", "LDb_GP", IntRegs>, PredNewRel; +defm LDub_GP : LD_GP<"memub", "LDub_GP", IntRegs>, PredNewRel; +defm LDh_GP : LD_GP<"memh", "LDh_GP", IntRegs>, PredNewRel; +defm LDuh_GP : LD_GP<"memuh", "LDuh_GP", IntRegs>, PredNewRel; +defm LDw_GP : LD_GP<"memw", "LDw_GP", IntRegs>, PredNewRel; def : Pat <(atomic_load_64 (HexagonCONST32_GP tglobaladdr:$global)), (i64 (LDd_GP_V4 tglobaladdr:$global))>; @@ -3139,9 +3021,10 @@ def : Pat <(i32 (load (HexagonCONST32_GP tglobaladdr:$global))), // Transfer global address into a register -let AddedComplexity=50, isMoveImm = 1, isReMaterializable = 1 in -def TFRI_V4 : ALU32_ri<(outs IntRegs:$dst), (ins globaladdress:$src1), - "$dst = ##$src1", +let isExtended = 1, opExtendable = 1, AddedComplexity=50, isMoveImm = 1, +isAsCheapAsAMove = 1, isReMaterializable = 1, validSubTargets = HasV4SubT in +def TFRI_V4 : ALU32_ri<(outs IntRegs:$dst), (ins s16Ext:$src1), + "$dst = #$src1", [(set IntRegs:$dst, (HexagonCONST32 tglobaladdr:$src1))]>, Requires<[HasV4T]>; @@ -3185,19 +3068,21 @@ def : Pat<(HexagonCONST32_GP tglobaladdr:$src1), // Load - Indirect with long offset: These instructions take global address // as an operand -let AddedComplexity = 10 in +let isExtended = 1, opExtendable = 3, AddedComplexity = 40, +validSubTargets = HasV4SubT in def LDrid_ind_lo_V4 : LDInst<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, u2Imm:$src2, globaladdress:$offset), + (ins IntRegs:$src1, u2Imm:$src2, globaladdressExt:$offset), "$dst=memd($src1<<#$src2+##$offset)", [(set (i64 DoubleRegs:$dst), (load (add (shl IntRegs:$src1, u2ImmPred:$src2), (HexagonCONST32 tglobaladdr:$offset))))]>, Requires<[HasV4T]>; -let AddedComplexity = 10 in +let AddedComplexity = 40 in multiclass LD_indirect_lo<string OpcStr, PatFrag OpNode> { +let isExtended = 1, opExtendable = 3, validSubTargets = HasV4SubT in def _lo_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, u2Imm:$src2, globaladdress:$offset), + (ins IntRegs:$src1, u2Imm:$src2, globaladdressExt:$offset), !strconcat("$dst = ", !strconcat(OpcStr, "($src1<<#$src2+##$offset)")), [(set IntRegs:$dst, @@ -3208,202 +3093,53 @@ multiclass LD_indirect_lo<string OpcStr, PatFrag OpNode> { defm LDrib_ind : LD_indirect_lo<"memb", sextloadi8>; defm LDriub_ind : LD_indirect_lo<"memub", zextloadi8>; +defm LDriub_ind_anyext : LD_indirect_lo<"memub", extloadi8>; defm LDrih_ind : LD_indirect_lo<"memh", sextloadi16>; defm LDriuh_ind : LD_indirect_lo<"memuh", zextloadi16>; +defm LDriuh_ind_anyext : LD_indirect_lo<"memuh", extloadi16>; defm LDriw_ind : LD_indirect_lo<"memw", load>; -// Store - Indirect with long offset: These instructions take global address -// as an operand -let AddedComplexity = 10 in -def STrid_ind_lo_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, globaladdress:$src3, - DoubleRegs:$src4), - "memd($src1<<#$src2+#$src3) = $src4", - [(store (i64 DoubleRegs:$src4), - (add (shl IntRegs:$src1, u2ImmPred:$src2), - (HexagonCONST32 tglobaladdr:$src3)))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 10 in -multiclass ST_indirect_lo<string OpcStr, PatFrag OpNode> { - def _lo_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, globaladdress:$src3, - IntRegs:$src4), - !strconcat(OpcStr, "($src1<<#$src2+##$src3) = $src4"), - [(OpNode (i32 IntRegs:$src4), - (add (shl IntRegs:$src1, u2ImmPred:$src2), - (HexagonCONST32 tglobaladdr:$src3)))]>, - Requires<[HasV4T]>; -} - -defm STrib_ind : ST_indirect_lo<"memb", truncstorei8>; -defm STrih_ind : ST_indirect_lo<"memh", truncstorei16>; -defm STriw_ind : ST_indirect_lo<"memw", store>; - -// Store - absolute addressing mode: These instruction take constant -// value as the extended operand. -multiclass ST_absimm<string OpcStr> { -let isExtended = 1, opExtendable = 0, isPredicable = 1, -validSubTargets = HasV4SubT in - def _abs_V4 : STInst2<(outs), - (ins u0AlwaysExt:$src1, IntRegs:$src2), - !strconcat(OpcStr, "(##$src1) = $src2"), - []>, - Requires<[HasV4T]>; - -let isExtended = 1, opExtendable = 1, isPredicated = 1, -validSubTargets = HasV4SubT in { - def _abs_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if ($src1)", !strconcat(OpcStr, "(##$src2) = $src3")), - []>, - Requires<[HasV4T]>; - - def _abs_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if (!$src1)", !strconcat(OpcStr, "(##$src2) = $src3")), - []>, - Requires<[HasV4T]>; - - def _abs_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if ($src1.new)", - !strconcat(OpcStr, "(##$src2) = $src3")), - []>, - Requires<[HasV4T]>; - - def _abs_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if (!$src1.new)", - !strconcat(OpcStr, "(##$src2) = $src3")), - []>, - Requires<[HasV4T]>; -} - -let isExtended = 1, opExtendable = 0, mayStore = 1, isNVStore = 1, -validSubTargets = HasV4SubT in - def _abs_nv_V4 : NVInst_V4<(outs), - (ins u0AlwaysExt:$src1, IntRegs:$src2), - !strconcat(OpcStr, "(##$src1) = $src2.new"), - []>, - Requires<[HasV4T]>; - -let isExtended = 1, opExtendable = 1, mayStore = 1, isPredicated = 1, -isNVStore = 1, validSubTargets = HasV4SubT in { - def _abs_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if ($src1)", - !strconcat(OpcStr, "(##$src2) = $src3.new")), - []>, - Requires<[HasV4T]>; - - def _abs_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if (!$src1)", - !strconcat(OpcStr, "(##$src2) = $src3.new")), - []>, - Requires<[HasV4T]>; - - def _abs_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if ($src1.new)", - !strconcat(OpcStr, "(##$src2) = $src3.new")), - []>, - Requires<[HasV4T]>; - - def _abs_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), - !strconcat("if (!$src1.new)", - !strconcat(OpcStr, "(##$src2) = $src3.new")), - []>, - Requires<[HasV4T]>; -} -} +let AddedComplexity = 40 in +def : Pat <(i32 (sextloadi8 (add IntRegs:$src1, + (NumUsesBelowThresCONST32 tglobaladdr:$offset)))), + (i32 (LDrib_ind_lo_V4 IntRegs:$src1, 0, tglobaladdr:$offset))>, + Requires<[HasV4T]>; -defm STrib_imm : ST_absimm<"memb">; -defm STrih_imm : ST_absimm<"memh">; -defm STriw_imm : ST_absimm<"memw">; +let AddedComplexity = 40 in +def : Pat <(i32 (zextloadi8 (add IntRegs:$src1, + (NumUsesBelowThresCONST32 tglobaladdr:$offset)))), + (i32 (LDriub_ind_lo_V4 IntRegs:$src1, 0, tglobaladdr:$offset))>, + Requires<[HasV4T]>; let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(truncstorei8 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), - (STrib_imm_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; + (STrib_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; def : Pat<(truncstorei16 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), - (STrih_imm_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; + (STrih_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; def : Pat<(store (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), - (STriw_imm_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; -} - -// Load - absolute addressing mode: These instruction take constant -// value as the extended operand - -multiclass LD_absimm<string OpcStr> { -let isExtended = 1, opExtendable = 1, isPredicable = 1, -validSubTargets = HasV4SubT in - def _abs_V4 : LDInst2<(outs IntRegs:$dst), - (ins u0AlwaysExt:$src), - !strconcat("$dst = ", - !strconcat(OpcStr, "(##$src)")), - []>, - Requires<[HasV4T]>; - -let isExtended = 1, opExtendable = 2, isPredicated = 1, -validSubTargets = HasV4SubT in { - def _abs_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u0AlwaysExt:$src2), - !strconcat("if ($src1) $dst = ", - !strconcat(OpcStr, "(##$src2)")), - []>, - Requires<[HasV4T]>; - - def _abs_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u0AlwaysExt:$src2), - !strconcat("if (!$src1) $dst = ", - !strconcat(OpcStr, "(##$src2)")), - []>, - Requires<[HasV4T]>; - - def _abs_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u0AlwaysExt:$src2), - !strconcat("if ($src1.new) $dst = ", - !strconcat(OpcStr, "(##$src2)")), - []>, - Requires<[HasV4T]>; - - def _abs_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u0AlwaysExt:$src2), - !strconcat("if (!$src1.new) $dst = ", - !strconcat(OpcStr, "(##$src2)")), - []>, - Requires<[HasV4T]>; + (STriw_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; } -} - -defm LDrib_imm : LD_absimm<"memb">; -defm LDriub_imm : LD_absimm<"memub">; -defm LDrih_imm : LD_absimm<"memh">; -defm LDriuh_imm : LD_absimm<"memuh">; -defm LDriw_imm : LD_absimm<"memw">; let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(i32 (load u0AlwaysExtPred:$src)), - (LDriw_imm_abs_V4 u0AlwaysExtPred:$src)>; + (LDriw_abs_V4 u0AlwaysExtPred:$src)>; def : Pat<(i32 (sextloadi8 u0AlwaysExtPred:$src)), - (LDrib_imm_abs_V4 u0AlwaysExtPred:$src)>; + (LDrib_abs_V4 u0AlwaysExtPred:$src)>; def : Pat<(i32 (zextloadi8 u0AlwaysExtPred:$src)), - (LDriub_imm_abs_V4 u0AlwaysExtPred:$src)>; + (LDriub_abs_V4 u0AlwaysExtPred:$src)>; def : Pat<(i32 (sextloadi16 u0AlwaysExtPred:$src)), - (LDrih_imm_abs_V4 u0AlwaysExtPred:$src)>; + (LDrih_abs_V4 u0AlwaysExtPred:$src)>; def : Pat<(i32 (zextloadi16 u0AlwaysExtPred:$src)), - (LDriuh_imm_abs_V4 u0AlwaysExtPred:$src)>; + (LDriuh_abs_V4 u0AlwaysExtPred:$src)>; } -// Indexed store double word - global address. +// Indexed store word - global address. // memw(Rs+#u6:2)=#S8 let AddedComplexity = 10 in def STriw_offset_ext_V4 : STInst<(outs), diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonMachineFunctionInfo.h b/contrib/llvm/lib/Target/Hexagon/HexagonMachineFunctionInfo.h index 0318c519..bd7b26a 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonMachineFunctionInfo.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonMachineFunctionInfo.h @@ -29,15 +29,18 @@ class HexagonMachineFunctionInfo : public MachineFunctionInfo { std::vector<MachineInstr*> AllocaAdjustInsts; int VarArgsFrameIndex; bool HasClobberLR; + bool HasEHReturn; std::map<const MachineInstr*, unsigned> PacketInfo; public: - HexagonMachineFunctionInfo() : SRetReturnReg(0), HasClobberLR(0) {} + HexagonMachineFunctionInfo() : SRetReturnReg(0), HasClobberLR(0), + HasEHReturn(false) {} HexagonMachineFunctionInfo(MachineFunction &MF) : SRetReturnReg(0), - HasClobberLR(0) {} + HasClobberLR(0), + HasEHReturn(false) {} unsigned getSRetReturnReg() const { return SRetReturnReg; } void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } @@ -69,6 +72,8 @@ public: void setHasClobberLR(bool v) { HasClobberLR = v; } bool hasClobberLR() const { return HasClobberLR; } + bool hasEHReturn() const { return HasEHReturn; }; + void setHasEHReturn(bool H = true) { HasEHReturn = H; }; }; } // End llvm namespace diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp index 5e80e48..05e6968 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp @@ -22,29 +22,31 @@ // //===----------------------------------------------------------------------===// #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"); @@ -57,6 +59,11 @@ static cl::opt<bool> DisableNewValueJumps("disable-nvjump", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable New Value Jumps")); +namespace llvm { + void initializeHexagonNewValueJumpPass(PassRegistry&); +} + + namespace { struct HexagonNewValueJump : public MachineFunctionPass { const HexagonInstrInfo *QII; @@ -65,9 +72,12 @@ namespace { 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); } @@ -78,6 +88,8 @@ namespace { virtual bool runOnMachineFunction(MachineFunction &Fn); private: + /// \brief A handle to the branch probability pass. + const MachineBranchProbabilityInfo *MBPI; }; @@ -85,6 +97,13 @@ namespace { 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, @@ -208,19 +227,15 @@ static bool canCompareBeNewValueJump(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) { @@ -271,58 +286,63 @@ 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::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."); @@ -346,6 +366,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) { @@ -393,12 +414,12 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { 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; @@ -434,9 +455,9 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { 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; @@ -525,10 +546,8 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { 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; @@ -582,42 +601,34 @@ 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); - // 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!"); if (cmpInstr->getOperand(0).isReg() && diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp index 576f1d7..89e3406 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp @@ -61,10 +61,6 @@ static cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Peephole Optimization")); -static cl::opt<int> -DbgPNPCount("pnp-count", cl::init(-1), cl::Hidden, - cl::desc("Maximum number of P=NOT(P) to be optimized")); - static cl::opt<bool> DisablePNotP("disable-hexagon-pnotp", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Optimization of PNotP")); @@ -73,6 +69,14 @@ static cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Optimization of Sign/Zero Extends")); +static cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64", + cl::Hidden, cl::ZeroOrMore, cl::init(false), + cl::desc("Disable Optimization of extensions to i64.")); + +namespace llvm { + void initializeHexagonPeepholePass(PassRegistry&); +} + namespace { struct HexagonPeephole : public MachineFunctionPass { const HexagonInstrInfo *QII; @@ -81,7 +85,9 @@ namespace { public: static char ID; - HexagonPeephole() : MachineFunctionPass(ID) { } + HexagonPeephole() : MachineFunctionPass(ID) { + initializeHexagonPeepholePass(*PassRegistry::getPassRegistry()); + } bool runOnMachineFunction(MachineFunction &MF); @@ -100,8 +106,10 @@ namespace { char HexagonPeephole::ID = 0; -bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { +INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole", + false, false) +bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { QII = static_cast<const HexagonInstrInfo *>(MF.getTarget(). getInstrInfo()); QRI = static_cast<const HexagonRegisterInfo *>(MF.getTarget(). @@ -142,6 +150,21 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { } } + // Look for %vreg170<def> = COMBINE_ir_V4 (0, %vreg169) + // %vreg170:DoublRegs, %vreg169:IntRegs + if (!DisableOptExtTo64 && + MI->getOpcode () == Hexagon::COMBINE_Ir_V4) { + assert (MI->getNumOperands() == 3); + MachineOperand &Dst = MI->getOperand(0); + MachineOperand &Src1 = MI->getOperand(1); + MachineOperand &Src2 = MI->getOperand(2); + if (Src1.getImm() != 0) + continue; + unsigned DstReg = Dst.getReg(); + unsigned SrcReg = Src2.getReg(); + PeepholeMap[DstReg] = SrcReg; + } + // Look for this sequence below // %vregDoubleReg1 = LSRd_ri %vregDoubleReg0, 32 // %vregIntReg = COPY %vregDoubleReg1:subreg_loreg. diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp index 34bf4ea..44234e8 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp @@ -21,11 +21,18 @@ #include "llvm/Transforms/Scalar.h" using namespace llvm; + +namespace llvm { + void initializeHexagonRemoveExtendArgsPass(PassRegistry&); +} + namespace { struct HexagonRemoveExtendArgs : public FunctionPass { public: static char ID; - HexagonRemoveExtendArgs() : FunctionPass(ID) {} + HexagonRemoveExtendArgs() : FunctionPass(ID) { + initializeHexagonRemoveExtendArgsPass(*PassRegistry::getPassRegistry()); + } virtual bool runOnFunction(Function &F); const char *getPassName() const { @@ -41,11 +48,9 @@ namespace { } char HexagonRemoveExtendArgs::ID = 0; -RegisterPass<HexagonRemoveExtendArgs> X("reargs", - "Remove Sign and Zero Extends for Args" - ); - +INITIALIZE_PASS(HexagonRemoveExtendArgs, "reargs", + "Remove Sign and Zero Extends for Args", false, false) bool HexagonRemoveExtendArgs::runOnFunction(Function &F) { unsigned Idx = 1; @@ -78,6 +83,7 @@ bool HexagonRemoveExtendArgs::runOnFunction(Function &F) { -FunctionPass *llvm::createHexagonRemoveExtendOps(HexagonTargetMachine &TM) { +FunctionPass* +llvm::createHexagonRemoveExtendArgs(const HexagonTargetMachine &TM) { return new HexagonRemoveExtendArgs(); } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp index 814249f..8608e08 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp @@ -49,16 +49,23 @@ using namespace llvm; +namespace llvm { + void initializeHexagonSplitTFRCondSetsPass(PassRegistry&); +} + + namespace { class HexagonSplitTFRCondSets : public MachineFunctionPass { - HexagonTargetMachine& QTM; + const HexagonTargetMachine &QTM; const HexagonSubtarget &QST; public: static char ID; - HexagonSplitTFRCondSets(HexagonTargetMachine& TM) : - MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} + HexagonSplitTFRCondSets(const HexagonTargetMachine& TM) : + MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) { + initializeHexagonSplitTFRCondSetsPass(*PassRegistry::getPassRegistry()); + } const char *getPassName() const { return "Hexagon Split TFRCondSets"; @@ -211,6 +218,18 @@ bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { // Public Constructor Functions //===----------------------------------------------------------------------===// -FunctionPass *llvm::createHexagonSplitTFRCondSets(HexagonTargetMachine &TM) { +static void initializePassOnce(PassRegistry &Registry) { + const char *Name = "Hexagon Split TFRCondSets"; + PassInfo *PI = new PassInfo(Name, "hexagon-split-tfr", + &HexagonSplitTFRCondSets::ID, 0, false, false); + Registry.registerPass(*PI, true); +} + +void llvm::initializeHexagonSplitTFRCondSetsPass(PassRegistry &Registry) { + CALL_ONCE_INITIALIZATION(initializePassOnce) +} + +FunctionPass* +llvm::createHexagonSplitTFRCondSets(const HexagonTargetMachine &TM) { return new HexagonSplitTFRCondSets(TM); } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp index ce45c62..caa1ba4 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -25,19 +25,17 @@ using namespace llvm; -static cl:: -opt<bool> DisableHardwareLoops( - "disable-hexagon-hwloops", cl::Hidden, - cl::desc("Disable Hardware Loops for Hexagon target")); +static cl:: opt<bool> DisableHardwareLoops("disable-hexagon-hwloops", + cl::Hidden, cl::desc("Disable Hardware Loops for Hexagon target")); -static cl:: -opt<bool> DisableHexagonMISched("disable-hexagon-misched", - cl::Hidden, cl::ZeroOrMore, cl::init(false), - cl::desc("Disable Hexagon MI Scheduling")); +static cl::opt<bool> DisableHexagonMISched("disable-hexagon-misched", + cl::Hidden, cl::ZeroOrMore, cl::init(false), + cl::desc("Disable Hexagon MI Scheduling")); static cl::opt<bool> DisableHexagonCFGOpt("disable-hexagon-cfgopt", - cl::Hidden, cl::ZeroOrMore, cl::init(false), - cl::desc("Disable Hexagon CFG Optimization")); + cl::Hidden, cl::ZeroOrMore, cl::init(false), + cl::desc("Disable Hexagon CFG Optimization")); + /// HexagonTargetMachineModule - Note that this is used on hosts that /// cannot link in a library unless there are references into the @@ -126,55 +124,62 @@ TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) { } bool HexagonPassConfig::addInstSelector() { + const HexagonTargetMachine &TM = getHexagonTargetMachine(); + bool NoOpt = (getOptLevel() == CodeGenOpt::None); - if (getOptLevel() != CodeGenOpt::None) - addPass(createHexagonRemoveExtendOps(getHexagonTargetMachine())); + if (!NoOpt) + addPass(createHexagonRemoveExtendArgs(TM)); - addPass(createHexagonISelDag(getHexagonTargetMachine(), getOptLevel())); + addPass(createHexagonISelDag(TM, getOptLevel())); - if (getOptLevel() != CodeGenOpt::None) + if (!NoOpt) { addPass(createHexagonPeephole()); + printAndVerify("After hexagon peephole pass"); + } return false; } - bool HexagonPassConfig::addPreRegAlloc() { - if (!DisableHardwareLoops && getOptLevel() != CodeGenOpt::None) - addPass(createHexagonHardwareLoops()); + if (getOptLevel() != CodeGenOpt::None) + if (!DisableHardwareLoops) + addPass(createHexagonHardwareLoops()); return false; } bool HexagonPassConfig::addPostRegAlloc() { - if (!DisableHexagonCFGOpt && getOptLevel() != CodeGenOpt::None) - addPass(createHexagonCFGOptimizer(getHexagonTargetMachine())); - return true; + const HexagonTargetMachine &TM = getHexagonTargetMachine(); + if (getOptLevel() != CodeGenOpt::None) + if (!DisableHexagonCFGOpt) + addPass(createHexagonCFGOptimizer(TM)); + return false; } - bool HexagonPassConfig::addPreSched2() { if (getOptLevel() != CodeGenOpt::None) addPass(&IfConverterID); - return true; + return false; } bool HexagonPassConfig::addPreEmitPass() { + const HexagonTargetMachine &TM = getHexagonTargetMachine(); + bool NoOpt = (getOptLevel() == CodeGenOpt::None); - if (!DisableHardwareLoops && getOptLevel() != CodeGenOpt::None) - addPass(createHexagonFixupHwLoops()); - - if (getOptLevel() != CodeGenOpt::None) + if (!NoOpt) addPass(createHexagonNewValueJump()); // Expand Spill code for predicate registers. - addPass(createHexagonExpandPredSpillCode(getHexagonTargetMachine())); + addPass(createHexagonExpandPredSpillCode(TM)); // Split up TFRcondsets into conditional transfers. - addPass(createHexagonSplitTFRCondSets(getHexagonTargetMachine())); + addPass(createHexagonSplitTFRCondSets(TM)); // Create Packets. - if (getOptLevel() != CodeGenOpt::None) + if (!NoOpt) { + if (!DisableHardwareLoops) + addPass(createHexagonFixupHwLoops()); addPass(createHexagonPacketizer()); + } return false; } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index c0d86da..39995e1 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -48,19 +48,32 @@ #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")); + +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 +109,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 +143,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 +172,32 @@ namespace { }; } +INITIALIZE_PASS_BEGIN(HexagonPacketizer, "packets", "Hexagon Packetizer", + false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +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 +743,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 @@ -857,17 +892,15 @@ static int GetDotNewPredOp(const int opc) { return Hexagon::STw_GP_cdnNotPt_V4; // Condtional Jumps - case Hexagon::JMP_c: - return Hexagon::JMP_cdnPt; + case Hexagon::JMP_t: + case Hexagon::JMP_f: + return QII->getDotNewPredJumpOp(MI, MBPI); - case Hexagon::JMP_cNot: - return Hexagon::JMP_cdnNotPt; + case Hexagon::JMPR_t: + return Hexagon::JMPR_tnew_tV3; - case Hexagon::JMPR_cPt: - return Hexagon::JMPR_cdnPt_V3; - - case Hexagon::JMPR_cNotPt: - return Hexagon::JMPR_cdnNotPt_V3; + case Hexagon::JMPR_f: + return Hexagon::JMPR_fnew_tV3; // Conditional Transfers case Hexagon::TFR_cPt: @@ -1261,7 +1294,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)); @@ -1306,17 +1339,17 @@ static int GetDotOldOp(const int opc) { case Hexagon::TFRI_cdnNotPt: return Hexagon::TFRI_cNotPt; - case Hexagon::JMP_cdnPt: - return Hexagon::JMP_c; + case Hexagon::JMP_tnew_t: + return Hexagon::JMP_t; - case Hexagon::JMP_cdnNotPt: - return Hexagon::JMP_cNot; + case Hexagon::JMP_fnew_t: + return Hexagon::JMP_f; - case Hexagon::JMPR_cdnPt_V3: - return Hexagon::JMPR_cPt; + case Hexagon::JMPR_tnew_tV3: + return Hexagon::JMPR_t; - case Hexagon::JMPR_cdnNotPt_V3: - return Hexagon::JMPR_cNotPt; + case Hexagon::JMPR_fnew_tV3: + return Hexagon::JMPR_f; // Load double word @@ -1912,7 +1945,7 @@ static bool GetPredicateSense(MachineInstr* MI, case Hexagon::STrih_imm_cdnPt_V4 : case Hexagon::STriw_imm_cPt_V4 : case Hexagon::STriw_imm_cdnPt_V4 : - case Hexagon::JMP_cdnPt : + case Hexagon::JMP_tnew_t : case Hexagon::LDrid_cPt : case Hexagon::LDrid_cdnPt : case Hexagon::LDrid_indexed_cPt : @@ -2051,7 +2084,7 @@ static bool GetPredicateSense(MachineInstr* MI, case Hexagon::STrih_imm_cdnNotPt_V4 : case Hexagon::STriw_imm_cNotPt_V4 : case Hexagon::STriw_imm_cdnNotPt_V4 : - case Hexagon::JMP_cdnNotPt : + case Hexagon::JMP_fnew_t : case Hexagon::LDrid_cNotPt : case Hexagon::LDrid_cdnNotPt : case Hexagon::LDrid_indexed_cNotPt : @@ -2739,9 +2772,8 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { // If an instruction feeds new value jump, glue it. MachineBasicBlock::iterator NextMII = I; ++NextMII; - MachineInstr *NextMI = NextMII; - - if (QII->isNewValueJump(NextMI)) { + if (NextMII != I->getParent()->end() && QII->isNewValueJump(NextMII)) { + MachineInstr *NextMI = NextMII; bool secondRegMatch = false; bool maintainNewValueJump = false; |