//===-- TargetInstrInfo.cpp - Target Instruction Information --------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the TargetInstrInfo class. // //===----------------------------------------------------------------------===// #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/ErrorHandling.h" #include <cctype> using namespace llvm; //===----------------------------------------------------------------------===// // TargetInstrInfo //===----------------------------------------------------------------------===// TargetInstrInfo::~TargetInstrInfo() { } const TargetRegisterClass* TargetInstrInfo::getRegClass(const MCInstrDesc &MCID, unsigned OpNum, const TargetRegisterInfo *TRI) const { if (OpNum >= MCID.getNumOperands()) return 0; short RegClass = MCID.OpInfo[OpNum].RegClass; if (MCID.OpInfo[OpNum].isLookupPtrRegClass()) return TRI->getPointerRegClass(RegClass); // Instructions like INSERT_SUBREG do not have fixed register classes. if (RegClass < 0) return 0; // Otherwise just look it up normally. return TRI->getRegClass(RegClass); } unsigned TargetInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr *MI) const { if (!ItinData || ItinData->isEmpty()) return 1; unsigned Class = MI->getDesc().getSchedClass(); unsigned UOps = ItinData->Itineraries[Class].NumMicroOps; if (UOps) return UOps; // The # of u-ops is dynamically determined. The specific target should // override this function to return the right number. return 1; } int TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, unsigned UseIdx) const { if (!ItinData || ItinData->isEmpty()) return -1; unsigned DefClass = DefMI->getDesc().getSchedClass(); unsigned UseClass = UseMI->getDesc().getSchedClass(); return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx); } int TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, SDNode *DefNode, unsigned DefIdx, SDNode *UseNode, unsigned UseIdx) const { if (!ItinData || ItinData->isEmpty()) return -1; if (!DefNode->isMachineOpcode()) return -1; unsigned DefClass = get(DefNode->getMachineOpcode()).getSchedClass(); if (!UseNode->isMachineOpcode()) return ItinData->getOperandCycle(DefClass, DefIdx); unsigned UseClass = get(UseNode->getMachineOpcode()).getSchedClass(); return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx); } int TargetInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr *MI, unsigned *PredCost) const { if (!ItinData || ItinData->isEmpty()) return 1; return ItinData->getStageLatency(MI->getDesc().getSchedClass()); } int TargetInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, SDNode *N) const { if (!ItinData || ItinData->isEmpty()) return 1; if (!N->isMachineOpcode()) return 1; return ItinData->getStageLatency(get(N->getMachineOpcode()).getSchedClass()); } bool TargetInstrInfo::hasLowDefLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx) const { if (!ItinData || ItinData->isEmpty()) return false; unsigned DefClass = DefMI->getDesc().getSchedClass(); int DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); return (DefCycle != -1 && DefCycle <= 1); } /// insertNoop - Insert a noop into the instruction stream at the specified /// point. void TargetInstrInfo::insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { llvm_unreachable("Target didn't implement insertNoop!"); } bool TargetInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { const MCInstrDesc &MCID = MI->getDesc(); if (!MCID.isTerminator()) return false; // Conditional branch is a special case. if (MCID.isBranch() && !MCID.isBarrier()) return true; if (!MCID.isPredicable()) return true; return !isPredicated(MI); } /// Measure the specified inline asm to determine an approximation of its /// length. /// Comments (which run till the next SeparatorString or newline) do not /// count as an instruction. /// Any other non-whitespace text is considered an instruction, with /// multiple instructions separated by SeparatorString or newlines. /// Variable-length instructions are not handled here; this function /// may be overloaded in the target code to do that. unsigned TargetInstrInfo::getInlineAsmLength(const char *Str, const MCAsmInfo &MAI) const { // Count the number of instructions in the asm. bool atInsnStart = true; unsigned Length = 0; for (; *Str; ++Str) { if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(), strlen(MAI.getSeparatorString())) == 0) atInsnStart = true; if (atInsnStart && !std::isspace(*Str)) { Length += MAI.getMaxInstLength(); atInsnStart = false; } if (atInsnStart && strncmp(Str, MAI.getCommentString(), strlen(MAI.getCommentString())) == 0) atInsnStart = false; } return Length; }