void HexagonInstrInfo::anchor() {}
HexagonInstrInfo::HexagonInstrInfo(HexagonSubtarget &ST)
- : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP),
- RI(ST), Subtarget(ST) {
-}
-
+ : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP),
+ RI(), Subtarget(ST) {}
/// isLoadFromStackSlot - If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
}
BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB);
} else {
- BuildMI(&MBB, DL,
- get(BccOpc)).addReg(Cond[regPos].getReg()).addMBB(TBB);
+ // If Cond[0] is a basic block, insert ENDLOOP0.
+ if (Cond[0].isMBB())
+ BuildMI(&MBB, DL, get(Hexagon::ENDLOOP0)).addMBB(Cond[0].getMBB());
+ else
+ BuildMI(&MBB, DL,
+ get(BccOpc)).addReg(Cond[regPos].getReg()).addMBB(TBB);
}
return 1;
}
+ // We don't handle ENDLOOP0 with a conditional branch in AnalyzeBranch.
BuildMI(&MBB, DL, get(BccOpc)).addReg(Cond[regPos].getReg()).addMBB(TBB);
BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB);
-
return 2;
}
return false;
--I;
}
-
+
+ bool JumpToBlock = I->getOpcode() == Hexagon::J2_jump &&
+ I->getOperand(0).isMBB();
// Delete the JMP if it's equivalent to a fall-through.
- if (AllowModify && I->getOpcode() == Hexagon::J2_jump &&
+ if (AllowModify && JumpToBlock &&
MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
DEBUG(dbgs()<< "\nErasing the jump to successor block\n";);
I->eraseFromParent();
} while(I);
int LastOpcode = LastInst->getOpcode();
+ int SecLastOpcode = SecondLastInst ? SecondLastInst->getOpcode() : 0;
+ // If the branch target is not a basic block, it could be a tail call.
+ // (It is, if the target is a function.)
+ if (LastOpcode == Hexagon::J2_jump && !LastInst->getOperand(0).isMBB())
+ return true;
+ if (SecLastOpcode == Hexagon::J2_jump &&
+ !SecondLastInst->getOperand(0).isMBB())
+ return true;
bool LastOpcodeHasJMP_c = PredOpcodeHasJMP_c(LastOpcode);
bool LastOpcodeHasNot = PredOpcodeHasNot(LastOpcode);
return true;
}
- int SecLastOpcode = SecondLastInst->getOpcode();
-
bool SecLastOpcodeHasJMP_c = PredOpcodeHasJMP_c(SecLastOpcode);
bool SecLastOpcodeHasNot = PredOpcodeHasNot(SecLastOpcode);
if (SecLastOpcodeHasJMP_c && (LastOpcode == Hexagon::J2_jump)) {
unsigned HexagonInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
- int BOpc = Hexagon::J2_jump;
- int BccOpc = Hexagon::J2_jumpt;
- int BccOpcNot = Hexagon::J2_jumpf;
-
MachineBasicBlock::iterator I = MBB.end();
if (I == MBB.begin()) return 0;
--I;
- if (I->getOpcode() != BOpc && I->getOpcode() != BccOpc &&
- I->getOpcode() != BccOpcNot)
- return 0;
-
- // Remove the branch.
- I->eraseFromParent();
+ unsigned Opc1 = I->getOpcode();
+ switch (Opc1) {
+ case Hexagon::J2_jump:
+ case Hexagon::J2_jumpt:
+ case Hexagon::J2_jumpf:
+ case Hexagon::ENDLOOP0:
+ I->eraseFromParent();
+ break;
+ default:
+ return 0;
+ }
I = MBB.end();
if (I == MBB.begin()) return 1;
--I;
- if (I->getOpcode() != BccOpc && I->getOpcode() != BccOpcNot)
- return 1;
-
- // Remove the branch.
- I->eraseFromParent();
- return 2;
+ unsigned Opc2 = I->getOpcode();
+ switch (Opc2) {
+ case Hexagon::J2_jumpt:
+ case Hexagon::J2_jumpf:
+ case Hexagon::ENDLOOP0:
+ I->eraseFromParent();
+ return 2;
+ default:
+ return 1;
+ }
}
SrcReg = MI->getOperand(1).getReg();
Mask = ~0;
break;
- case Hexagon::CMPbEQri_V4:
- case Hexagon::CMPbEQrr_sbsb_V4:
- case Hexagon::CMPbEQrr_ubub_V4:
- case Hexagon::CMPbGTUri_V4:
- case Hexagon::CMPbGTUrr_V4:
- case Hexagon::CMPbGTrr_V4:
+ case Hexagon::A4_cmpbeqi:
+ case Hexagon::A4_cmpbeq:
+ case Hexagon::A4_cmpbgtui:
+ case Hexagon::A4_cmpbgtu:
+ case Hexagon::A4_cmpbgt:
SrcReg = MI->getOperand(1).getReg();
Mask = 0xFF;
break;
- case Hexagon::CMPhEQri_V4:
- case Hexagon::CMPhEQrr_shl_V4:
- case Hexagon::CMPhEQrr_xor_V4:
- case Hexagon::CMPhGTUri_V4:
- case Hexagon::CMPhGTUrr_V4:
- case Hexagon::CMPhGTrr_shl_V4:
+ case Hexagon::A4_cmpheqi:
+ case Hexagon::A4_cmpheq:
+ case Hexagon::A4_cmphgtui:
+ case Hexagon::A4_cmphgtu:
+ case Hexagon::A4_cmphgt:
SrcReg = MI->getOperand(1).getReg();
Mask = 0xFFFF;
break;
case Hexagon::C2_cmpgtup:
case Hexagon::C2_cmpgtu:
case Hexagon::C2_cmpgt:
- case Hexagon::CMPbEQrr_sbsb_V4:
- case Hexagon::CMPbEQrr_ubub_V4:
- case Hexagon::CMPbGTUrr_V4:
- case Hexagon::CMPbGTrr_V4:
- case Hexagon::CMPhEQrr_shl_V4:
- case Hexagon::CMPhEQrr_xor_V4:
- case Hexagon::CMPhGTUrr_V4:
- case Hexagon::CMPhGTrr_shl_V4:
+ case Hexagon::A4_cmpbeq:
+ case Hexagon::A4_cmpbgtu:
+ case Hexagon::A4_cmpbgt:
+ case Hexagon::A4_cmpheq:
+ case Hexagon::A4_cmphgtu:
+ case Hexagon::A4_cmphgt:
SrcReg2 = MI->getOperand(2).getReg();
return true;
case Hexagon::C2_cmpeqi:
case Hexagon::C2_cmpgtui:
case Hexagon::C2_cmpgti:
- case Hexagon::CMPbEQri_V4:
- case Hexagon::CMPbGTUri_V4:
- case Hexagon::CMPhEQri_V4:
- case Hexagon::CMPhGTUri_V4:
+ case Hexagon::A4_cmpbeqi:
+ case Hexagon::A4_cmpbgtui:
+ case Hexagon::A4_cmpheqi:
+ case Hexagon::A4_cmphgtui:
SrcReg2 = 0;
Value = MI->getOperand(2).getImm();
return true;
SmallVectorImpl<MachineInstr*> &NewMIs) const {
llvm_unreachable("Unimplemented");
}
+bool
+HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
+ const HexagonRegisterInfo &TRI = getRegisterInfo();
+ MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo();
+ MachineBasicBlock &MBB = *MI->getParent();
+ DebugLoc DL = MI->getDebugLoc();
+ unsigned Opc = MI->getOpcode();
+
+ switch (Opc) {
+ case Hexagon::ALIGNA:
+ BuildMI(MBB, MI, DL, get(Hexagon::A2_andir), MI->getOperand(0).getReg())
+ .addReg(TRI.getFrameRegister())
+ .addImm(-MI->getOperand(1).getImm());
+ MBB.erase(MI);
+ return true;
+ case Hexagon::TFR_PdTrue: {
+ unsigned Reg = MI->getOperand(0).getReg();
+ BuildMI(MBB, MI, DL, get(Hexagon::C2_orn), Reg)
+ .addReg(Reg, RegState::Undef)
+ .addReg(Reg, RegState::Undef);
+ MBB.erase(MI);
+ return true;
+ }
+ case Hexagon::TFR_PdFalse: {
+ unsigned Reg = MI->getOperand(0).getReg();
+ BuildMI(MBB, MI, DL, get(Hexagon::C2_andn), Reg)
+ .addReg(Reg, RegState::Undef)
+ .addReg(Reg, RegState::Undef);
+ MBB.erase(MI);
+ return true;
+ }
+ case Hexagon::VMULW: {
+ // Expand a 64-bit vector multiply into 2 32-bit scalar multiplies.
+ unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned Src1Reg = MI->getOperand(1).getReg();
+ unsigned Src2Reg = MI->getOperand(2).getReg();
+ unsigned Src1SubHi = TRI.getSubReg(Src1Reg, Hexagon::subreg_hireg);
+ unsigned Src1SubLo = TRI.getSubReg(Src1Reg, Hexagon::subreg_loreg);
+ unsigned Src2SubHi = TRI.getSubReg(Src2Reg, Hexagon::subreg_hireg);
+ unsigned Src2SubLo = TRI.getSubReg(Src2Reg, Hexagon::subreg_loreg);
+ BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_mpyi),
+ TRI.getSubReg(DstReg, Hexagon::subreg_hireg)).addReg(Src1SubHi)
+ .addReg(Src2SubHi);
+ BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_mpyi),
+ TRI.getSubReg(DstReg, Hexagon::subreg_loreg)).addReg(Src1SubLo)
+ .addReg(Src2SubLo);
+ MBB.erase(MI);
+ MRI.clearKillFlags(Src1SubHi);
+ MRI.clearKillFlags(Src1SubLo);
+ MRI.clearKillFlags(Src2SubHi);
+ MRI.clearKillFlags(Src2SubLo);
+ return true;
+ }
+ case Hexagon::VMULW_ACC: {
+ // Expand 64-bit vector multiply with addition into 2 scalar multiplies.
+ unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned Src1Reg = MI->getOperand(1).getReg();
+ unsigned Src2Reg = MI->getOperand(2).getReg();
+ unsigned Src3Reg = MI->getOperand(3).getReg();
+ unsigned Src1SubHi = TRI.getSubReg(Src1Reg, Hexagon::subreg_hireg);
+ unsigned Src1SubLo = TRI.getSubReg(Src1Reg, Hexagon::subreg_loreg);
+ unsigned Src2SubHi = TRI.getSubReg(Src2Reg, Hexagon::subreg_hireg);
+ unsigned Src2SubLo = TRI.getSubReg(Src2Reg, Hexagon::subreg_loreg);
+ unsigned Src3SubHi = TRI.getSubReg(Src3Reg, Hexagon::subreg_hireg);
+ unsigned Src3SubLo = TRI.getSubReg(Src3Reg, Hexagon::subreg_loreg);
+ BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_maci),
+ TRI.getSubReg(DstReg, Hexagon::subreg_hireg)).addReg(Src1SubHi)
+ .addReg(Src2SubHi).addReg(Src3SubHi);
+ BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_maci),
+ TRI.getSubReg(DstReg, Hexagon::subreg_loreg)).addReg(Src1SubLo)
+ .addReg(Src2SubLo).addReg(Src3SubLo);
+ MBB.erase(MI);
+ MRI.clearKillFlags(Src1SubHi);
+ MRI.clearKillFlags(Src1SubLo);
+ MRI.clearKillFlags(Src2SubHi);
+ MRI.clearKillFlags(Src2SubLo);
+ MRI.clearKillFlags(Src3SubHi);
+ MRI.clearKillFlags(Src3SubLo);
+ return true;
+ }
+ case Hexagon::TCRETURNi:
+ MI->setDesc(get(Hexagon::J2_jump));
+ return true;
+ case Hexagon::TCRETURNr:
+ MI->setDesc(get(Hexagon::J2_jumpr));
+ return true;
+ }
+ return false;
+}
MachineInstr *HexagonInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
- MachineInstr* MI,
- const SmallVectorImpl<unsigned> &Ops,
- int FI) const {
+ MachineInstr *MI,
+ ArrayRef<unsigned> Ops,
+ int FI) const {
// Hexagon_TODO: Implement.
return nullptr;
}
}
bool HexagonInstrInfo::isExtendable(const MachineInstr *MI) const {
- // Constant extenders are allowed only for V4 and above.
- if (!Subtarget.hasV4TOps())
- return false;
-
const MCInstrDesc &MID = MI->getDesc();
const uint64_t F = MID.TSFlags;
if ((F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask)
switch(Opc) {
case Hexagon::A2_tfrsi:
- return isInt<12>(MI->getOperand(1).getImm());
+ return (isOperandExtended(MI, 1) && isConstExtended(MI)) || isInt<12>(MI->getOperand(1).getImm());
case Hexagon::S2_storerd_io:
return isShiftedUInt<6,3>(MI->getOperand(1).getImm());
case Hexagon::S2_storeri_io:
- case Hexagon::STriw_nv_V4:
+ case Hexagon::S2_storerinew_io:
return isShiftedUInt<6,2>(MI->getOperand(1).getImm());
case Hexagon::S2_storerh_io:
- case Hexagon::STrih_nv_V4:
+ case Hexagon::S2_storerhnew_io:
return isShiftedUInt<6,1>(MI->getOperand(1).getImm());
case Hexagon::S2_storerb_io:
- case Hexagon::STrib_nv_V4:
+ case Hexagon::S2_storerbnew_io:
return isUInt<6>(MI->getOperand(1).getImm());
case Hexagon::L2_loadrd_io:
case Hexagon::L2_loadrub_pi:
return isInt<4>(MI->getOperand(3).getImm());
- case Hexagon::STrib_imm_V4:
- case Hexagon::STrih_imm_V4:
- case Hexagon::STriw_imm_V4:
+ case Hexagon::S4_storeirb_io:
+ case Hexagon::S4_storeirh_io:
+ case Hexagon::S4_storeiri_io:
return (isUInt<6>(MI->getOperand(1).getImm()) &&
isInt<6>(MI->getOperand(2).getImm()));
- case Hexagon::ADD_ri:
+ case Hexagon::A2_addi:
return isInt<8>(MI->getOperand(2).getImm());
case Hexagon::A2_aslh:
case Hexagon::A2_sxth:
case Hexagon::A2_zxtb:
case Hexagon::A2_zxth:
- return Subtarget.hasV4TOps();
+ return true;
}
return true;
return Hexagon::C2_ccombinewt;
// Dealloc_return.
- case Hexagon::DEALLOC_RET_cPt_V4:
- return Hexagon::DEALLOC_RET_cNotPt_V4;
- case Hexagon::DEALLOC_RET_cNotPt_V4:
- return Hexagon::DEALLOC_RET_cPt_V4;
+ case Hexagon::L4_return_t:
+ return Hexagon::L4_return_f;
+ case Hexagon::L4_return_f:
+ return Hexagon::L4_return_t;
}
}
return ((F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask);
}
-int HexagonInstrInfo::
-getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const {
+int HexagonInstrInfo::getCondOpcode(int Opc, bool invertPredicate) const {
enum Hexagon::PredSense inPredSense;
inPredSense = invertPredicate ? Hexagon::PredSense_false :
Hexagon::PredSense_true;
return !invertPredicate ? Hexagon::C2_ccombinewt :
Hexagon::C2_ccombinewf;
- // Word.
- case Hexagon::STriw_f:
- return !invertPredicate ? Hexagon::S2_pstorerit_io:
- Hexagon::S2_pstorerif_io;
- case Hexagon::STriw_indexed_f:
- return !invertPredicate ? Hexagon::S2_pstorerit_io:
- Hexagon::S2_pstorerif_io;
-
// DEALLOC_RETURN.
- case Hexagon::DEALLOC_RET_V4:
- return !invertPredicate ? Hexagon::DEALLOC_RET_cPt_V4 :
- Hexagon::DEALLOC_RET_cNotPt_V4;
+ case Hexagon::L4_return:
+ return !invertPredicate ? Hexagon::L4_return_t:
+ Hexagon::L4_return_f;
}
llvm_unreachable("Unexpected predicable instruction");
}
// This will change MI's opcode to its predicate version.
// However, its operand list is still the old one, i.e. the
// non-predicate one.
- MI->setDesc(get(getMatchingCondBranchOpcode(Opc, invertJump)));
+ MI->setDesc(get(getCondOpcode(Opc, invertJump)));
int oper = -1;
unsigned int GAIdx = 0;
continue;
}
else {
- assert(false && "Unexpected operand type");
+ llvm_unreachable("Unexpected operand type");
}
}
}
// Returns true, if a ST insn can be promoted to a new-value store.
bool HexagonInstrInfo::mayBeNewStore(const MachineInstr *MI) const {
- const HexagonRegisterInfo& QRI = getRegisterInfo();
const uint64_t F = MI->getDesc().TSFlags;
return ((F >> HexagonII::mayNVStorePos) &
- HexagonII::mayNVStoreMask &
- QRI.Subtarget.hasV4TOps());
+ HexagonII::mayNVStoreMask);
}
bool
//
bool HexagonInstrInfo::
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+ if (!Cond.empty() && Cond[0].isMBB())
+ return true;
if (!Cond.empty() && Cond[0].isImm() && Cond[0].getImm() == 0) {
Cond.erase(Cond.begin());
} else {
bool HexagonInstrInfo::isDeallocRet(const MachineInstr *MI) const {
switch (MI->getOpcode()) {
default: return false;
- case Hexagon::DEALLOC_RET_V4 :
- case Hexagon::DEALLOC_RET_cPt_V4 :
- case Hexagon::DEALLOC_RET_cNotPt_V4 :
- case Hexagon::DEALLOC_RET_cdnPnt_V4 :
- case Hexagon::DEALLOC_RET_cNotdnPnt_V4 :
- case Hexagon::DEALLOC_RET_cdnPt_V4 :
- case Hexagon::DEALLOC_RET_cNotdnPt_V4 :
+ case Hexagon::L4_return:
+ case Hexagon::L4_return_t:
+ case Hexagon::L4_return_f:
+ case Hexagon::L4_return_tnew_pnt:
+ case Hexagon::L4_return_fnew_pnt:
+ case Hexagon::L4_return_tnew_pt:
+ case Hexagon::L4_return_fnew_pt:
return true;
}
}
-bool HexagonInstrInfo::
-isValidOffset(const int Opcode, const int Offset) const {
+bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
+ bool Extend) const {
// This function is to check whether the "Offset" is in the correct range of
- // the given "Opcode". If "Offset" is not in the correct range, "ADD_ri" is
+ // the given "Opcode". If "Offset" is not in the correct range, "A2_addi" is
// inserted to calculate the final address. Due to this reason, the function
// assumes that the "Offset" has correct alignment.
// We used to assert if the offset was not properly aligned, however,
// problem, and we need to allow for it. The front end warns of such
// misaligns with respect to load size.
- switch(Opcode) {
+ switch (Opcode) {
+ case Hexagon::J2_loop0i:
+ case Hexagon::J2_loop1i:
+ return isUInt<10>(Offset);
+ }
+
+ if (Extend)
+ return true;
+ switch (Opcode) {
case Hexagon::L2_loadri_io:
- case Hexagon::LDriw_f:
case Hexagon::S2_storeri_io:
- case Hexagon::STriw_f:
return (Offset >= Hexagon_MEMW_OFFSET_MIN) &&
(Offset <= Hexagon_MEMW_OFFSET_MAX);
case Hexagon::L2_loadrd_io:
- case Hexagon::LDrid_f:
case Hexagon::S2_storerd_io:
- case Hexagon::STrid_f:
return (Offset >= Hexagon_MEMD_OFFSET_MIN) &&
(Offset <= Hexagon_MEMD_OFFSET_MAX);
return (Offset >= Hexagon_MEMB_OFFSET_MIN) &&
(Offset <= Hexagon_MEMB_OFFSET_MAX);
- case Hexagon::ADD_ri:
- case Hexagon::TFR_FI:
+ case Hexagon::A2_addi:
return (Offset >= Hexagon_ADDI_OFFSET_MIN) &&
(Offset <= Hexagon_ADDI_OFFSET_MAX);
- case Hexagon::MemOPw_ADDi_V4 :
- case Hexagon::MemOPw_SUBi_V4 :
- case Hexagon::MemOPw_ADDr_V4 :
- case Hexagon::MemOPw_SUBr_V4 :
- case Hexagon::MemOPw_ANDr_V4 :
- case Hexagon::MemOPw_ORr_V4 :
+ case Hexagon::L4_iadd_memopw_io:
+ case Hexagon::L4_isub_memopw_io:
+ case Hexagon::L4_add_memopw_io:
+ case Hexagon::L4_sub_memopw_io:
+ case Hexagon::L4_and_memopw_io:
+ case Hexagon::L4_or_memopw_io:
return (0 <= Offset && Offset <= 255);
- case Hexagon::MemOPh_ADDi_V4 :
- case Hexagon::MemOPh_SUBi_V4 :
- case Hexagon::MemOPh_ADDr_V4 :
- case Hexagon::MemOPh_SUBr_V4 :
- case Hexagon::MemOPh_ANDr_V4 :
- case Hexagon::MemOPh_ORr_V4 :
+ case Hexagon::L4_iadd_memoph_io:
+ case Hexagon::L4_isub_memoph_io:
+ case Hexagon::L4_add_memoph_io:
+ case Hexagon::L4_sub_memoph_io:
+ case Hexagon::L4_and_memoph_io:
+ case Hexagon::L4_or_memoph_io:
return (0 <= Offset && Offset <= 127);
- case Hexagon::MemOPb_ADDi_V4 :
- case Hexagon::MemOPb_SUBi_V4 :
- case Hexagon::MemOPb_ADDr_V4 :
- case Hexagon::MemOPb_SUBr_V4 :
- case Hexagon::MemOPb_ANDr_V4 :
- case Hexagon::MemOPb_ORr_V4 :
+ case Hexagon::L4_iadd_memopb_io:
+ case Hexagon::L4_isub_memopb_io:
+ case Hexagon::L4_add_memopb_io:
+ case Hexagon::L4_sub_memopb_io:
+ case Hexagon::L4_and_memopb_io:
+ case Hexagon::L4_or_memopb_io:
return (0 <= Offset && Offset <= 63);
// LDri_pred and STriw_pred are pseudo operations, so it has to take offset of
case Hexagon::LDriw_pred:
return true;
- case Hexagon::J2_loop0i:
- return isUInt<10>(Offset);
-
- // INLINEASM is very special.
+ case Hexagon::TFR_FI:
+ case Hexagon::TFR_FIA:
case Hexagon::INLINEASM:
return true;
}
switch (MI->getOpcode())
{
- default: return false;
- case Hexagon::MemOPw_ADDi_V4 :
- case Hexagon::MemOPw_SUBi_V4 :
- case Hexagon::MemOPw_ADDr_V4 :
- case Hexagon::MemOPw_SUBr_V4 :
- case Hexagon::MemOPw_ANDr_V4 :
- case Hexagon::MemOPw_ORr_V4 :
- case Hexagon::MemOPh_ADDi_V4 :
- case Hexagon::MemOPh_SUBi_V4 :
- case Hexagon::MemOPh_ADDr_V4 :
- case Hexagon::MemOPh_SUBr_V4 :
- case Hexagon::MemOPh_ANDr_V4 :
- case Hexagon::MemOPh_ORr_V4 :
- case Hexagon::MemOPb_ADDi_V4 :
- case Hexagon::MemOPb_SUBi_V4 :
- case Hexagon::MemOPb_ADDr_V4 :
- case Hexagon::MemOPb_SUBr_V4 :
- case Hexagon::MemOPb_ANDr_V4 :
- case Hexagon::MemOPb_ORr_V4 :
- case Hexagon::MemOPb_SETBITi_V4:
- case Hexagon::MemOPh_SETBITi_V4:
- case Hexagon::MemOPw_SETBITi_V4:
- case Hexagon::MemOPb_CLRBITi_V4:
- case Hexagon::MemOPh_CLRBITi_V4:
- case Hexagon::MemOPw_CLRBITi_V4:
+ default: return false;
+ case Hexagon::L4_iadd_memopw_io:
+ case Hexagon::L4_isub_memopw_io:
+ case Hexagon::L4_add_memopw_io:
+ case Hexagon::L4_sub_memopw_io:
+ case Hexagon::L4_and_memopw_io:
+ case Hexagon::L4_or_memopw_io:
+ case Hexagon::L4_iadd_memoph_io:
+ case Hexagon::L4_isub_memoph_io:
+ case Hexagon::L4_add_memoph_io:
+ case Hexagon::L4_sub_memoph_io:
+ case Hexagon::L4_and_memoph_io:
+ case Hexagon::L4_or_memoph_io:
+ case Hexagon::L4_iadd_memopb_io:
+ case Hexagon::L4_isub_memopb_io:
+ case Hexagon::L4_add_memopb_io:
+ case Hexagon::L4_sub_memopb_io:
+ case Hexagon::L4_and_memopb_io:
+ case Hexagon::L4_or_memopb_io:
+ case Hexagon::L4_ior_memopb_io:
+ case Hexagon::L4_ior_memoph_io:
+ case Hexagon::L4_ior_memopw_io:
+ case Hexagon::L4_iand_memopb_io:
+ case Hexagon::L4_iand_memoph_io:
+ case Hexagon::L4_iand_memopw_io:
return true;
}
return false;
case Hexagon::A4_pzxthfnew:
case Hexagon::A4_pzxtht:
case Hexagon::A4_pzxthtnew:
- case Hexagon::ADD_ri_cPt:
- case Hexagon::ADD_ri_cNotPt:
+ case Hexagon::A2_paddit:
+ case Hexagon::A2_paddif:
case Hexagon::C2_ccombinewt:
case Hexagon::C2_ccombinewf:
return true;
bool HexagonInstrInfo::
isConditionalLoad (const MachineInstr* MI) const {
- const HexagonRegisterInfo& QRI = getRegisterInfo();
switch (MI->getOpcode())
{
default: return false;
case Hexagon::L2_ploadruhf_io:
case Hexagon::L2_ploadrubt_io:
case Hexagon::L2_ploadrubf_io:
- return true;
case Hexagon::L2_ploadrdt_pi:
case Hexagon::L2_ploadrdf_pi:
case Hexagon::L2_ploadrit_pi:
case Hexagon::L2_ploadruhf_pi:
case Hexagon::L2_ploadrubt_pi:
case Hexagon::L2_ploadrubf_pi:
- return QRI.Subtarget.hasV4TOps();
case Hexagon::L4_ploadrdt_rr:
case Hexagon::L4_ploadrdf_rr:
case Hexagon::L4_ploadrbt_rr:
case Hexagon::L4_ploadruhf_rr:
case Hexagon::L4_ploadrit_rr:
case Hexagon::L4_ploadrif_rr:
- return QRI.Subtarget.hasV4TOps();
+ return true;
}
}
// is not valid for new-value stores.
bool HexagonInstrInfo::
isConditionalStore (const MachineInstr* MI) const {
- const HexagonRegisterInfo& QRI = getRegisterInfo();
switch (MI->getOpcode())
{
default: return false;
- case Hexagon::STrib_imm_cPt_V4 :
- case Hexagon::STrib_imm_cNotPt_V4 :
- case Hexagon::STrib_indexed_shl_cPt_V4 :
- case Hexagon::STrib_indexed_shl_cNotPt_V4 :
+ case Hexagon::S4_storeirbt_io:
+ case Hexagon::S4_storeirbf_io:
+ case Hexagon::S4_pstorerbt_rr:
+ case Hexagon::S4_pstorerbf_rr:
case Hexagon::S2_pstorerbt_io:
case Hexagon::S2_pstorerbf_io:
case Hexagon::S2_pstorerbt_pi:
case Hexagon::S2_pstorerbf_pi:
case Hexagon::S2_pstorerdt_io:
case Hexagon::S2_pstorerdf_io:
- case Hexagon::STrid_indexed_shl_cPt_V4 :
+ case Hexagon::S4_pstorerdt_rr:
+ case Hexagon::S4_pstorerdf_rr:
case Hexagon::S2_pstorerdt_pi:
case Hexagon::S2_pstorerdf_pi:
case Hexagon::S2_pstorerht_io:
case Hexagon::S2_pstorerhf_io:
- case Hexagon::STrih_imm_cPt_V4 :
- case Hexagon::STrih_imm_cNotPt_V4 :
- case Hexagon::STrih_indexed_shl_cPt_V4 :
- case Hexagon::STrih_indexed_shl_cNotPt_V4 :
+ case Hexagon::S4_storeirht_io:
+ case Hexagon::S4_storeirhf_io:
+ case Hexagon::S4_pstorerht_rr:
+ case Hexagon::S4_pstorerhf_rr:
case Hexagon::S2_pstorerht_pi:
case Hexagon::S2_pstorerhf_pi:
case Hexagon::S2_pstorerit_io:
case Hexagon::S2_pstorerif_io:
- case Hexagon::STriw_imm_cPt_V4 :
- case Hexagon::STriw_imm_cNotPt_V4 :
- case Hexagon::STriw_indexed_shl_cPt_V4 :
- case Hexagon::STriw_indexed_shl_cNotPt_V4 :
+ case Hexagon::S4_storeirit_io:
+ case Hexagon::S4_storeirif_io:
+ case Hexagon::S4_pstorerit_rr:
+ case Hexagon::S4_pstorerif_rr:
case Hexagon::S2_pstorerit_pi:
case Hexagon::S2_pstorerif_pi:
- return QRI.Subtarget.hasV4TOps();
// V4 global address store before promoting to dot new.
- case Hexagon::STd_GP_cPt_V4 :
- case Hexagon::STd_GP_cNotPt_V4 :
- case Hexagon::STb_GP_cPt_V4 :
- case Hexagon::STb_GP_cNotPt_V4 :
- case Hexagon::STh_GP_cPt_V4 :
- case Hexagon::STh_GP_cNotPt_V4 :
- case Hexagon::STw_GP_cPt_V4 :
- case Hexagon::STw_GP_cNotPt_V4 :
- return QRI.Subtarget.hasV4TOps();
+ case Hexagon::S4_pstorerdt_abs:
+ case Hexagon::S4_pstorerdf_abs:
+ case Hexagon::S4_pstorerbt_abs:
+ case Hexagon::S4_pstorerbf_abs:
+ case Hexagon::S4_pstorerht_abs:
+ case Hexagon::S4_pstorerhf_abs:
+ case Hexagon::S4_pstorerit_abs:
+ case Hexagon::S4_pstorerif_abs:
+ return true;
// Predicated new value stores (i.e. if (p0) memw(..)=r0.new) are excluded
// from the "Conditional Store" list. Because a predicated new value store
switch (MI->getOpcode()) {
default: llvm_unreachable("Unknown .new type");
- // store new value byte
- case Hexagon::STrib_shl_V4:
- return Hexagon::STrib_shl_nv_V4;
+ case Hexagon::S4_storerb_ur:
+ return Hexagon::S4_storerbnew_ur;
+
+ case Hexagon::S4_storerh_ur:
+ return Hexagon::S4_storerhnew_ur;
- case Hexagon::STrih_shl_V4:
- return Hexagon::STrih_shl_nv_V4;
+ case Hexagon::S4_storeri_ur:
+ return Hexagon::S4_storerinew_ur;
- case Hexagon::STriw_f:
- return Hexagon::STriw_nv_V4;
+ case Hexagon::S2_storerb_pci:
+ return Hexagon::S2_storerb_pci;
- case Hexagon::STriw_indexed_f:
- return Hexagon::STriw_indexed_nv_V4;
+ case Hexagon::S2_storeri_pci:
+ return Hexagon::S2_storeri_pci;
- case Hexagon::STriw_shl_V4:
- return Hexagon::STriw_shl_nv_V4;
+ case Hexagon::S2_storerh_pci:
+ return Hexagon::S2_storerh_pci;
+ case Hexagon::S2_storerd_pci:
+ return Hexagon::S2_storerd_pci;
+
+ case Hexagon::S2_storerf_pci:
+ return Hexagon::S2_storerf_pci;
}
return 0;
}
return false;
}
-bool HexagonInstrInfo::isConstExtended(MachineInstr *MI) const {
-
- // Constant extenders are allowed only for V4 and above.
- if (!Subtarget.hasV4TOps())
- return false;
-
+bool HexagonInstrInfo::isConstExtended(const MachineInstr *MI) const {
const uint64_t F = MI->getDesc().TSFlags;
unsigned isExtended = (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
if (isExtended) // Instruction must be extended.
return true;
- unsigned isExtendable = (F >> HexagonII::ExtendablePos)
- & HexagonII::ExtendableMask;
+ unsigned isExtendable =
+ (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
if (!isExtendable)
return false;
// We currently only handle isGlobal() because it is the only kind of
// object we are going to end up with here for now.
// In the future we probably should add isSymbol(), etc.
- if (MO.isGlobal() || MO.isSymbol())
+ if (MO.isGlobal() || MO.isSymbol() || MO.isBlockAddress() ||
+ MO.isJTI() || MO.isCPI())
return true;
// If the extendable operand is not 'Immediate' type, the instruction should
return (ImmValue < MinValue || ImmValue > MaxValue);
}
+// Return the number of bytes required to encode the instruction.
+// Hexagon instructions are fixed length, 4 bytes, unless they
+// use a constant extender, which requires another 4 bytes.
+// For debug instructions and prolog labels, return 0.
+unsigned HexagonInstrInfo::getSize(const MachineInstr *MI) const {
+
+ if (MI->isDebugValue() || MI->isPosition())
+ return 0;
+
+ unsigned Size = MI->getDesc().getSize();
+ if (!Size)
+ // Assume the default insn size in case it cannot be determined
+ // for whatever reason.
+ Size = HEXAGON_INSTR_SIZE;
+
+ if (isConstExtended(MI) || isExtended(MI))
+ Size += HEXAGON_INSTR_SIZE;
+
+ return Size;
+}
+
// 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.
// Returns true if a particular operand is extendable for an instruction.
bool HexagonInstrInfo::isOperandExtended(const MachineInstr *MI,
unsigned short OperandNum) const {
- // Constant extenders are allowed only for V4 and above.
- if (!Subtarget.hasV4TOps())
- return false;
-
const uint64_t F = MI->getDesc().TSFlags;
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask)