| //===-- 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; |
| } |