From: Evan Cheng Date: Wed, 29 Jun 2011 01:14:12 +0000 (+0000) Subject: Sink SubtargetFeature and TargetInstrItineraries (renamed MCInstrItineraries) into MC. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=ab8be96fd30ca9396e6b84fdddf1ac6208984cad;p=oota-llvm.git Sink SubtargetFeature and TargetInstrItineraries (renamed MCInstrItineraries) into MC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134049 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h new file mode 100644 index 00000000000..e942892da13 --- /dev/null +++ b/include/llvm/MC/MCInstrItineraries.h @@ -0,0 +1,253 @@ +//===-- llvm/MC/MCInstrItineraries.h - Scheduling ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the structures used for instruction +// itineraries, stages, and operand reads/writes. This is used by +// schedulers to determine instruction stages and latencies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRITINERARIES_H +#define LLVM_MC_MCINSTRITINERARIES_H + +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// Instruction stage - These values represent a non-pipelined step in +/// the execution of an instruction. Cycles represents the number of +/// discrete time slots needed to complete the stage. Units represent +/// the choice of functional units that can be used to complete the +/// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +/// cycles should elapse from the start of this stage to the start of +/// the next stage in the itinerary. A value of -1 indicates that the +/// next stage should start immediately after the current one. +/// For example: +/// +/// { 1, x, -1 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts immediately after this one. +/// +/// { 2, x|y, 1 } +/// indicates that the stage occupies either FU x or FU y for 2 +/// consecuative cycles and that the next stage starts one cycle +/// after this stage starts. That is, the stage requirements +/// overlap in time. +/// +/// { 1, x, 0 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts in this same cycle. This can be used to +/// indicate that the instruction requires multiple stages at the +/// same time. +/// +/// FU reservation can be of two different kinds: +/// - FUs which instruction actually requires +/// - FUs which instruction just reserves. Reserved unit is not available for +/// execution of other instruction. However, several instructions can reserve +/// the same unit several times. +/// Such two types of units reservation is used to model instruction domain +/// change stalls, FUs using the same resource (e.g. same register file), etc. + +struct InstrStage { + enum ReservationKinds { + Required = 0, + Reserved = 1 + }; + + unsigned Cycles_; ///< Length of stage in machine cycles + unsigned Units_; ///< Choice of functional units + int NextCycles_; ///< Number of machine cycles to next stage + ReservationKinds Kind_; ///< Kind of the FU reservation + + /// getCycles - returns the number of cycles the stage is occupied + unsigned getCycles() const { + return Cycles_; + } + + /// getUnits - returns the choice of FUs + unsigned getUnits() const { + return Units_; + } + + ReservationKinds getReservationKind() const { + return Kind_; + } + + /// getNextCycles - returns the number of cycles from the start of + /// this stage to the start of the next stage in the itinerary + unsigned getNextCycles() const { + return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; + } +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary - An itinerary represents the scheduling +/// information for an instruction. This includes a set of stages +/// occupies by the instruction, and the pipeline cycle in which +/// operands are read and written. +/// +struct InstrItinerary { + unsigned NumMicroOps; ///< # of micro-ops, 0 means it's variable + unsigned FirstStage; ///< Index of first stage in itinerary + unsigned LastStage; ///< Index of last + 1 stage in itinerary + unsigned FirstOperandCycle; ///< Index of first operand rd/wr + unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be +/// used by a target. +/// +class InstrItineraryData { +public: + const InstrStage *Stages; ///< Array of stages selected + const unsigned *OperandCycles; ///< Array of operand cycles selected + const unsigned *Forwardings; ///< Array of pipeline forwarding pathes + const InstrItinerary *Itineraries; ///< Array of itineraries selected + unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. + + /// Ctors. + /// + InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), + Itineraries(0), IssueWidth(0) {} + + InstrItineraryData(const InstrStage *S, const unsigned *OS, + const unsigned *F, const InstrItinerary *I) + : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I), + IssueWidth(0) {} + + /// isEmpty - Returns true if there are no itineraries. + /// + bool isEmpty() const { return Itineraries == 0; } + + /// isEndMarker - Returns true if the index is for the end marker + /// itinerary. + /// + bool isEndMarker(unsigned ItinClassIndx) const { + return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && + (Itineraries[ItinClassIndx].LastStage == ~0U)); + } + + /// beginStage - Return the first stage of the itinerary. + /// + const InstrStage *beginStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; + return Stages + StageIdx; + } + + /// endStage - Return the last+1 stage of the itinerary. + /// + const InstrStage *endStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; + return Stages + StageIdx; + } + + /// getStageLatency - Return the total stage latency of the given + /// class. The latency is the maximum completion time for any stage + /// in the itinerary. + /// + unsigned getStageLatency(unsigned ItinClassIndx) const { + // If the target doesn't provide itinerary information, use a simple + // non-zero default value for all instructions. Some target's provide a + // dummy (Generic) itinerary which should be handled as if it's itinerary is + // empty. We identify this by looking for a reference to stage zero (invalid + // stage). This is different from beginStage == endState != 0, which could + // be used for zero-latency pseudo ops. + if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0) + return 1; + + // Calculate the maximum completion time for any stage. + unsigned Latency = 0, StartCycle = 0; + for (const InstrStage *IS = beginStage(ItinClassIndx), + *E = endStage(ItinClassIndx); IS != E; ++IS) { + Latency = std::max(Latency, StartCycle + IS->getCycles()); + StartCycle += IS->getNextCycles(); + } + + return Latency; + } + + /// getOperandCycle - Return the cycle for the given class and + /// operand. Return -1 if no cycle is specified for the operand. + /// + int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { + if (isEmpty()) + return -1; + + unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle; + unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle; + if ((FirstIdx + OperandIdx) >= LastIdx) + return -1; + + return (int)OperandCycles[FirstIdx + OperandIdx]; + } + + /// hasPipelineForwarding - Return true if there is a pipeline forwarding + /// between instructions of itinerary classes DefClass and UseClasses so that + /// value produced by an instruction of itinerary class DefClass, operand + /// index DefIdx can be bypassed when it's read by an instruction of + /// itinerary class UseClass, operand index UseIdx. + bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; + unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle; + if ((FirstDefIdx + DefIdx) >= LastDefIdx) + return false; + if (Forwardings[FirstDefIdx + DefIdx] == 0) + return false; + + unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle; + unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle; + if ((FirstUseIdx + UseIdx) >= LastUseIdx) + return false; + + return Forwardings[FirstDefIdx + DefIdx] == + Forwardings[FirstUseIdx + UseIdx]; + } + + /// getOperandLatency - Compute and return the use operand latency of a given + /// itinerary class and operand index if the value is produced by an + /// instruction of the specified itinerary class and def operand index. + int getOperandLatency(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + if (isEmpty()) + return -1; + + int DefCycle = getOperandCycle(DefClass, DefIdx); + if (DefCycle == -1) + return -1; + + int UseCycle = getOperandCycle(UseClass, UseIdx); + if (UseCycle == -1) + return -1; + + UseCycle = DefCycle - UseCycle + 1; + if (UseCycle > 0 && + hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx)) + // FIXME: This assumes one cycle benefit for every pipeline forwarding. + --UseCycle; + return UseCycle; + } + + /// isMicroCoded - Return true if the instructions in the given class decode + /// to more than one micro-ops. + bool isMicroCoded(unsigned ItinClassIndx) const { + if (isEmpty()) + return false; + return Itineraries[ItinClassIndx].NumMicroOps != 1; + } +}; + + +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h new file mode 100644 index 00000000000..cc56576c74a --- /dev/null +++ b/include/llvm/MC/SubtargetFeature.h @@ -0,0 +1,118 @@ +//===-- llvm/MC/SubtargetFeature.h - CPU characteristics --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines and manages user or tool specified CPU characteristics. +// The intent is to be able to package specific features that should or should +// not be used on a specific target processor. A tool, such as llc, could, as +// as example, gather chip info from the command line, a long with features +// that should be used on that chip. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_SUBTARGETFEATURE_H +#define LLVM_MC_SUBTARGETFEATURE_H + +#include +#include +#include "llvm/ADT/Triple.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class raw_ostream; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatureKV - Used to provide key value pairs for feature and +/// CPU bit flags. +// +struct SubtargetFeatureKV { + const char *Key; // K-V key string + const char *Desc; // Help descriptor + uint64_t Value; // K-V integer value + uint64_t Implies; // K-V bit mask + + // Compare routine for std binary search + bool operator<(const SubtargetFeatureKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary +/// pointers. +// +struct SubtargetInfoKV { + const char *Key; // K-V key string + void *Value; // K-V pointer value + + // Compare routine for std binary search + bool operator<(const SubtargetInfoKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatures - Manages the enabling and disabling of subtarget +/// specific features. Features are encoded as a string of the form +/// "cpu,+attr1,+attr2,-attr3,...,+attrN" +/// A comma separates each feature from the next (all lowercase.) +/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU +/// value is "generic" then the CPU subtype should be generic for the target. +/// Each of the remaining features is prefixed with + or - indicating whether +/// that feature should be enabled or disabled contrary to the cpu +/// specification. +/// + +class SubtargetFeatures { + std::vector Features; // Subtarget features as a vector +public: + explicit SubtargetFeatures(const std::string &Initial = std::string()); + + /// Features string accessors. + std::string getString() const; + void setString(const std::string &Initial); + + /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. + void setCPU(const std::string &String); + + /// Setting CPU string only if no string is set. + void setCPUIfNone(const std::string &String); + + /// Returns current CPU string. + const std::string & getCPU() const; + + /// Adding Features. + void AddFeature(const std::string &String, bool IsEnabled = true); + + /// Get feature bits. + uint64_t getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize); + + /// Get info pointer + void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); + + /// Print feature string. + void print(raw_ostream &OS) const; + + // Dump feature info. + void dump() const; + + /// Retrieve a formatted string of the default features for the specified + /// target triple. + void getDefaultSubtargetFeatures(const std::string &CPU, + const Triple& Triple); +}; + +} // End namespace llvm + +#endif diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h deleted file mode 100644 index cbd2c3b6302..00000000000 --- a/include/llvm/Target/SubtargetFeature.h +++ /dev/null @@ -1,118 +0,0 @@ -//===-- llvm/Target/SubtargetFeature.h - CPU characteristics ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines and manages user or tool specified CPU characteristics. -// The intent is to be able to package specific features that should or should -// not be used on a specific target processor. A tool, such as llc, could, as -// as example, gather chip info from the command line, a long with features -// that should be used on that chip. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_SUBTARGETFEATURE_H -#define LLVM_TARGET_SUBTARGETFEATURE_H - -#include -#include -#include "llvm/ADT/Triple.h" -#include "llvm/Support/DataTypes.h" - -namespace llvm { - class raw_ostream; - -//===----------------------------------------------------------------------===// -/// -/// SubtargetFeatureKV - Used to provide key value pairs for feature and -/// CPU bit flags. -// -struct SubtargetFeatureKV { - const char *Key; // K-V key string - const char *Desc; // Help descriptor - uint64_t Value; // K-V integer value - uint64_t Implies; // K-V bit mask - - // Compare routine for std binary search - bool operator<(const SubtargetFeatureKV &S) const { - return strcmp(Key, S.Key) < 0; - } -}; - -//===----------------------------------------------------------------------===// -/// -/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary -/// pointers. -// -struct SubtargetInfoKV { - const char *Key; // K-V key string - void *Value; // K-V pointer value - - // Compare routine for std binary search - bool operator<(const SubtargetInfoKV &S) const { - return strcmp(Key, S.Key) < 0; - } -}; - -//===----------------------------------------------------------------------===// -/// -/// SubtargetFeatures - Manages the enabling and disabling of subtarget -/// specific features. Features are encoded as a string of the form -/// "cpu,+attr1,+attr2,-attr3,...,+attrN" -/// A comma separates each feature from the next (all lowercase.) -/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU -/// value is "generic" then the CPU subtype should be generic for the target. -/// Each of the remaining features is prefixed with + or - indicating whether -/// that feature should be enabled or disabled contrary to the cpu -/// specification. -/// - -class SubtargetFeatures { - std::vector Features; // Subtarget features as a vector -public: - explicit SubtargetFeatures(const std::string &Initial = std::string()); - - /// Features string accessors. - std::string getString() const; - void setString(const std::string &Initial); - - /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. - void setCPU(const std::string &String); - - /// Setting CPU string only if no string is set. - void setCPUIfNone(const std::string &String); - - /// Returns current CPU string. - const std::string & getCPU() const; - - /// Adding Features. - void AddFeature(const std::string &String, bool IsEnabled = true); - - /// Get feature bits. - uint64_t getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize); - - /// Get info pointer - void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); - - /// Print feature string. - void print(raw_ostream &OS) const; - - // Dump feature info. - void dump() const; - - /// Retrieve a formatted string of the default features for the specified - /// target triple. - void getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple); -}; - -} // End namespace llvm - -#endif diff --git a/include/llvm/Target/TargetInstrItineraries.h b/include/llvm/Target/TargetInstrItineraries.h deleted file mode 100644 index 6011402d9e4..00000000000 --- a/include/llvm/Target/TargetInstrItineraries.h +++ /dev/null @@ -1,253 +0,0 @@ -//===-- llvm/Target/TargetInstrItineraries.h - Scheduling -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the structures used for instruction -// itineraries, stages, and operand reads/writes. This is used by -// schedulers to determine instruction stages and latencies. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H -#define LLVM_TARGET_TARGETINSTRITINERARIES_H - -#include - -namespace llvm { - -//===----------------------------------------------------------------------===// -/// Instruction stage - These values represent a non-pipelined step in -/// the execution of an instruction. Cycles represents the number of -/// discrete time slots needed to complete the stage. Units represent -/// the choice of functional units that can be used to complete the -/// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many -/// cycles should elapse from the start of this stage to the start of -/// the next stage in the itinerary. A value of -1 indicates that the -/// next stage should start immediately after the current one. -/// For example: -/// -/// { 1, x, -1 } -/// indicates that the stage occupies FU x for 1 cycle and that -/// the next stage starts immediately after this one. -/// -/// { 2, x|y, 1 } -/// indicates that the stage occupies either FU x or FU y for 2 -/// consecuative cycles and that the next stage starts one cycle -/// after this stage starts. That is, the stage requirements -/// overlap in time. -/// -/// { 1, x, 0 } -/// indicates that the stage occupies FU x for 1 cycle and that -/// the next stage starts in this same cycle. This can be used to -/// indicate that the instruction requires multiple stages at the -/// same time. -/// -/// FU reservation can be of two different kinds: -/// - FUs which instruction actually requires -/// - FUs which instruction just reserves. Reserved unit is not available for -/// execution of other instruction. However, several instructions can reserve -/// the same unit several times. -/// Such two types of units reservation is used to model instruction domain -/// change stalls, FUs using the same resource (e.g. same register file), etc. - -struct InstrStage { - enum ReservationKinds { - Required = 0, - Reserved = 1 - }; - - unsigned Cycles_; ///< Length of stage in machine cycles - unsigned Units_; ///< Choice of functional units - int NextCycles_; ///< Number of machine cycles to next stage - ReservationKinds Kind_; ///< Kind of the FU reservation - - /// getCycles - returns the number of cycles the stage is occupied - unsigned getCycles() const { - return Cycles_; - } - - /// getUnits - returns the choice of FUs - unsigned getUnits() const { - return Units_; - } - - ReservationKinds getReservationKind() const { - return Kind_; - } - - /// getNextCycles - returns the number of cycles from the start of - /// this stage to the start of the next stage in the itinerary - unsigned getNextCycles() const { - return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; - } -}; - - -//===----------------------------------------------------------------------===// -/// Instruction itinerary - An itinerary represents the scheduling -/// information for an instruction. This includes a set of stages -/// occupies by the instruction, and the pipeline cycle in which -/// operands are read and written. -/// -struct InstrItinerary { - unsigned NumMicroOps; ///< # of micro-ops, 0 means it's variable - unsigned FirstStage; ///< Index of first stage in itinerary - unsigned LastStage; ///< Index of last + 1 stage in itinerary - unsigned FirstOperandCycle; ///< Index of first operand rd/wr - unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr -}; - - -//===----------------------------------------------------------------------===// -/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be -/// used by a target. -/// -class InstrItineraryData { -public: - const InstrStage *Stages; ///< Array of stages selected - const unsigned *OperandCycles; ///< Array of operand cycles selected - const unsigned *Forwardings; ///< Array of pipeline forwarding pathes - const InstrItinerary *Itineraries; ///< Array of itineraries selected - unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. - - /// Ctors. - /// - InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), - Itineraries(0), IssueWidth(0) {} - - InstrItineraryData(const InstrStage *S, const unsigned *OS, - const unsigned *F, const InstrItinerary *I) - : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I), - IssueWidth(0) {} - - /// isEmpty - Returns true if there are no itineraries. - /// - bool isEmpty() const { return Itineraries == 0; } - - /// isEndMarker - Returns true if the index is for the end marker - /// itinerary. - /// - bool isEndMarker(unsigned ItinClassIndx) const { - return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && - (Itineraries[ItinClassIndx].LastStage == ~0U)); - } - - /// beginStage - Return the first stage of the itinerary. - /// - const InstrStage *beginStage(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; - return Stages + StageIdx; - } - - /// endStage - Return the last+1 stage of the itinerary. - /// - const InstrStage *endStage(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; - return Stages + StageIdx; - } - - /// getStageLatency - Return the total stage latency of the given - /// class. The latency is the maximum completion time for any stage - /// in the itinerary. - /// - unsigned getStageLatency(unsigned ItinClassIndx) const { - // If the target doesn't provide itinerary information, use a simple - // non-zero default value for all instructions. Some target's provide a - // dummy (Generic) itinerary which should be handled as if it's itinerary is - // empty. We identify this by looking for a reference to stage zero (invalid - // stage). This is different from beginStage == endState != 0, which could - // be used for zero-latency pseudo ops. - if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0) - return 1; - - // Calculate the maximum completion time for any stage. - unsigned Latency = 0, StartCycle = 0; - for (const InstrStage *IS = beginStage(ItinClassIndx), - *E = endStage(ItinClassIndx); IS != E; ++IS) { - Latency = std::max(Latency, StartCycle + IS->getCycles()); - StartCycle += IS->getNextCycles(); - } - - return Latency; - } - - /// getOperandCycle - Return the cycle for the given class and - /// operand. Return -1 if no cycle is specified for the operand. - /// - int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { - if (isEmpty()) - return -1; - - unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle; - unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle; - if ((FirstIdx + OperandIdx) >= LastIdx) - return -1; - - return (int)OperandCycles[FirstIdx + OperandIdx]; - } - - /// hasPipelineForwarding - Return true if there is a pipeline forwarding - /// between instructions of itinerary classes DefClass and UseClasses so that - /// value produced by an instruction of itinerary class DefClass, operand - /// index DefIdx can be bypassed when it's read by an instruction of - /// itinerary class UseClass, operand index UseIdx. - bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, - unsigned UseClass, unsigned UseIdx) const { - unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; - unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle; - if ((FirstDefIdx + DefIdx) >= LastDefIdx) - return false; - if (Forwardings[FirstDefIdx + DefIdx] == 0) - return false; - - unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle; - unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle; - if ((FirstUseIdx + UseIdx) >= LastUseIdx) - return false; - - return Forwardings[FirstDefIdx + DefIdx] == - Forwardings[FirstUseIdx + UseIdx]; - } - - /// getOperandLatency - Compute and return the use operand latency of a given - /// itinerary class and operand index if the value is produced by an - /// instruction of the specified itinerary class and def operand index. - int getOperandLatency(unsigned DefClass, unsigned DefIdx, - unsigned UseClass, unsigned UseIdx) const { - if (isEmpty()) - return -1; - - int DefCycle = getOperandCycle(DefClass, DefIdx); - if (DefCycle == -1) - return -1; - - int UseCycle = getOperandCycle(UseClass, UseIdx); - if (UseCycle == -1) - return -1; - - UseCycle = DefCycle - UseCycle + 1; - if (UseCycle > 0 && - hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx)) - // FIXME: This assumes one cycle benefit for every pipeline forwarding. - --UseCycle; - return UseCycle; - } - - /// isMicroCoded - Return true if the instructions in the given class decode - /// to more than one micro-ops. - bool isMicroCoded(unsigned ItinClassIndx) const { - if (isEmpty()) - return false; - return Itineraries[ItinClassIndx].NumMicroOps != 1; - } -}; - - -} // End llvm namespace - -#endif diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 78f770cc41c..6544ce25f86 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -14,29 +14,29 @@ #ifndef LLVM_TARGET_TARGETMACHINE_H #define LLVM_TARGET_TARGETMACHINE_H -#include "llvm/Target/TargetInstrItineraries.h" #include #include namespace llvm { -class Target; +class InstrItineraryData; +class JITCodeEmitter; class MCAsmInfo; +class MCContext; +class Pass; +class PassManager; +class PassManagerBase; +class Target; class TargetData; -class TargetSubtarget; +class TargetELFWriterInfo; +class TargetFrameLowering; class TargetInstrInfo; class TargetIntrinsicInfo; class TargetJITInfo; class TargetLowering; -class TargetSelectionDAGInfo; -class TargetFrameLowering; -class JITCodeEmitter; -class MCContext; class TargetRegisterInfo; -class PassManagerBase; -class PassManager; -class Pass; -class TargetELFWriterInfo; +class TargetSelectionDAGInfo; +class TargetSubtarget; class formatted_raw_ostream; class raw_ostream; diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp index d8355ab86cf..c918bf63120 100644 --- a/lib/CodeGen/IfConversion.cpp +++ b/lib/CodeGen/IfConversion.cpp @@ -18,8 +18,8 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index 28a81e18819..722ceb20243 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -28,10 +28,10 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/ADT/DenseMap.h" diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp index 94941ecf23b..9cceb4e8d74 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/lib/CodeGen/ScoreboardHazardRecognizer.cpp index 35e48cd8a13..0e005d35189 100644 --- a/lib/CodeGen/ScoreboardHazardRecognizer.cpp +++ b/lib/CodeGen/ScoreboardHazardRecognizer.cpp @@ -16,11 +16,11 @@ #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType #include "llvm/CodeGen/ScoreboardHazardRecognizer.h" #include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" using namespace llvm; diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index ca70adafc08..63ca3264171 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -17,6 +17,7 @@ #include "ScheduleDAGSDNodes.h" #include "InstrEmitter.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" diff --git a/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index a8822e58d40..83b1f0542c3 100644 --- a/lib/ExecutionEngine/TargetSelect.cpp +++ b/lib/ExecutionEngine/TargetSelect.cpp @@ -16,10 +16,10 @@ #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Module.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" using namespace llvm; diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp new file mode 100644 index 00000000000..3ed122aad86 --- /dev/null +++ b/lib/MC/SubtargetFeature.cpp @@ -0,0 +1,384 @@ +//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// +// +// 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 SubtargetFeature interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Static Helper Functions +//===----------------------------------------------------------------------===// + +/// hasFlag - Determine if a feature has a flag; '+' or '-' +/// +static inline bool hasFlag(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' or '-' flag + return Ch == '+' || Ch =='-'; +} + +/// StripFlag - Return string stripped of flag. +/// +static inline std::string StripFlag(const std::string &Feature) { + return hasFlag(Feature) ? Feature.substr(1) : Feature; +} + +/// isEnabled - Return true if enable flag; '+'. +/// +static inline bool isEnabled(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' for enabled + return Ch == '+'; +} + +/// PrependFlag - Return a string with a prepended flag; '+' or '-'. +/// +static inline std::string PrependFlag(const std::string &Feature, + bool IsEnabled) { + assert(!Feature.empty() && "Empty string"); + if (hasFlag(Feature)) return Feature; + return std::string(IsEnabled ? "+" : "-") + Feature; +} + +/// Split - Splits a string of comma separated items in to a vector of strings. +/// +static void Split(std::vector &V, const std::string &S) { + // Start at beginning of string. + size_t Pos = 0; + while (true) { + // Find the next comma + size_t Comma = S.find(',', Pos); + // If no comma found then the rest of the string is used + if (Comma == std::string::npos) { + // Add string to vector + V.push_back(S.substr(Pos)); + break; + } + // Otherwise add substring to vector + V.push_back(S.substr(Pos, Comma - Pos)); + // Advance to next item + Pos = Comma + 1; + } +} + +/// Join a vector of strings to a string with a comma separating each element. +/// +static std::string Join(const std::vector &V) { + // Start with empty string. + std::string Result; + // If the vector is not empty + if (!V.empty()) { + // Start with the CPU feature + Result = V[0]; + // For each successive feature + for (size_t i = 1; i < V.size(); i++) { + // Add a comma + Result += ","; + // Add the feature + Result += V[i]; + } + } + // Return the features string + return Result; +} + +/// Adding features. +void SubtargetFeatures::AddFeature(const std::string &String, + bool IsEnabled) { + // Don't add empty features + if (!String.empty()) { + // Convert to lowercase, prepend flag and add to vector + Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); + } +} + +/// Find KV in array using binary search. +template const T *Find(const std::string &S, const T *A, size_t L) { + // Make the lower bound element we're looking for + T KV; + KV.Key = S.c_str(); + // Determine the end of the array + const T *Hi = A + L; + // Binary search the array + const T *F = std::lower_bound(A, Hi, KV); + // If not found then return NULL + if (F == Hi || std::string(F->Key) != S) return NULL; + // Return the found array item + return F; +} + +/// getLongestEntryLength - Return the length of the longest entry in the table. +/// +static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, + size_t Size) { + size_t MaxLen = 0; + for (size_t i = 0; i < Size; i++) + MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); + return MaxLen; +} + +/// Display help for feature choices. +/// +static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, + const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { + // Determine the length of the longest CPU and Feature entries. + unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); + unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); + + // Print the CPU table. + errs() << "Available CPUs for this target:\n\n"; + for (size_t i = 0; i != CPUTableSize; i++) + errs() << " " << CPUTable[i].Key + << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') + << " - " << CPUTable[i].Desc << ".\n"; + errs() << "\n"; + + // Print the Feature table. + errs() << "Available features for this target:\n\n"; + for (size_t i = 0; i != FeatTableSize; i++) + errs() << " " << FeatTable[i].Key + << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') + << " - " << FeatTable[i].Desc << ".\n"; + errs() << "\n"; + + errs() << "Use +feature to enable a feature, or -feature to disable it.\n" + << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; + std::exit(1); +} + +//===----------------------------------------------------------------------===// +// SubtargetFeatures Implementation +//===----------------------------------------------------------------------===// + +SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { + // Break up string into separate features + Split(Features, Initial); +} + + +std::string SubtargetFeatures::getString() const { + return Join(Features); +} +void SubtargetFeatures::setString(const std::string &Initial) { + // Throw out old features + Features.clear(); + // Break up string into separate features + Split(Features, LowercaseString(Initial)); +} + + +/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" +/// clears CPU. +void SubtargetFeatures::setCPU(const std::string &String) { + Features[0] = LowercaseString(String); +} + + +/// setCPUIfNone - Setting CPU string only if no string is set. +/// +void SubtargetFeatures::setCPUIfNone(const std::string &String) { + if (Features[0].empty()) setCPU(String); +} + +/// getCPU - Returns current CPU. +/// +const std::string & SubtargetFeatures::getCPU() const { + return Features[0]; +} + + +/// SetImpliedBits - For each feature that is (transitively) implied by this +/// feature, set it. +/// +static +void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FeatureEntry->Implies & FE.Value) { + Bits |= FE.Value; + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// ClearImpliedBits - For each feature that (transitively) implies this +/// feature, clear it. +/// +static +void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FE.Implies & FeatureEntry->Value) { + Bits &= ~FE.Value; + ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// getBits - Get feature bits. +/// +uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + assert(CPUTable && "missing CPU table"); + assert(FeatureTable && "missing features table"); +#ifndef NDEBUG + for (size_t i = 1; i < CPUTableSize; i++) { + assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && + "CPU table is not sorted"); + } + for (size_t i = 1; i < FeatureTableSize; i++) { + assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && + "CPU features table is not sorted"); + } +#endif + uint64_t Bits = 0; // Resulting bits + + // Check if help is needed + if (Features[0] == "help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + + // Find CPU entry + const SubtargetFeatureKV *CPUEntry = + Find(Features[0], CPUTable, CPUTableSize); + // If there is a match + if (CPUEntry) { + // Set base feature bits + Bits = CPUEntry->Value; + + // Set the feature implied by this CPU feature, if any. + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + if (CPUEntry->Value & FE.Value) + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } else { + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; + } + // Iterate through each feature + for (size_t i = 1; i < Features.size(); i++) { + const std::string &Feature = Features[i]; + + // Check for help + if (Feature == "+help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + + // Find feature in table. + const SubtargetFeatureKV *FeatureEntry = + Find(StripFlag(Feature), FeatureTable, FeatureTableSize); + // If there is a match + if (FeatureEntry) { + // Enable/disable feature in bits + if (isEnabled(Feature)) { + Bits |= FeatureEntry->Value; + + // For each feature that this implies, set it. + SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } else { + Bits &= ~FeatureEntry->Value; + + // For each feature that implies this, clear it. + ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } + } else { + errs() << "'" << Feature + << "' is not a recognized feature for this target" + << " (ignoring feature)\n"; + } + } + + return Bits; +} + +/// Get info pointer +void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, + size_t TableSize) { + assert(Table && "missing table"); +#ifndef NDEBUG + for (size_t i = 1; i < TableSize; i++) { + assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); + } +#endif + + // Find entry + const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); + + if (Entry) { + return Entry->Value; + } else { + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; + return NULL; + } +} + +/// print - Print feature string. +/// +void SubtargetFeatures::print(raw_ostream &OS) const { + for (size_t i = 0, e = Features.size(); i != e; ++i) + OS << Features[i] << " "; + OS << "\n"; +} + +/// dump - Dump feature info. +/// +void SubtargetFeatures::dump() const { + print(dbgs()); +} + +/// getDefaultSubtargetFeatures - Return a string listing the features +/// associated with the target triple. +/// +/// FIXME: This is an inelegant way of specifying the features of a +/// subtarget. It would be better if we could encode this information +/// into the IR. See . +/// +void SubtargetFeatures::getDefaultSubtargetFeatures(const std::string &CPU, + const Triple& Triple) { + setCPU(CPU); + + if (Triple.getVendor() == Triple::Apple) { + if (Triple.getArch() == Triple::ppc) { + // powerpc-apple-* + AddFeature("altivec"); + } else if (Triple.getArch() == Triple::ppc64) { + // powerpc64-apple-* + AddFeature("64bit"); + AddFeature("altivec"); + } + } +} diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 0271c873f19..e4bcf3e3641 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -14,9 +14,8 @@ #ifndef ARMSUBTARGET_H #define ARMSUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetSubtarget.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/ADT/Triple.h" #include diff --git a/lib/Target/Alpha/AlphaSubtarget.h b/lib/Target/Alpha/AlphaSubtarget.h index f0eb93c6cba..ab7d1e05620 100644 --- a/lib/Target/Alpha/AlphaSubtarget.h +++ b/lib/Target/Alpha/AlphaSubtarget.h @@ -14,9 +14,8 @@ #ifndef ALPHASUBTARGET_H #define ALPHASUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetSubtarget.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/CellSPU/SPUSubtarget.h b/lib/Target/CellSPU/SPUSubtarget.h index d7929302f08..39b2d86196c 100644 --- a/lib/Target/CellSPU/SPUSubtarget.h +++ b/lib/Target/CellSPU/SPUSubtarget.h @@ -14,9 +14,8 @@ #ifndef CELLSUBTARGET_H #define CELLSUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetSubtarget.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/MBlaze/MBlazeSubtarget.h b/lib/Target/MBlaze/MBlazeSubtarget.h index 2255b2809be..342b2fb65d7 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.h +++ b/lib/Target/MBlaze/MBlazeSubtarget.h @@ -15,8 +15,7 @@ #define MBLAZESUBTARGET_H #include "llvm/Target/TargetSubtarget.h" -#include "llvm/Target/TargetMachine.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 096bbed7b04..f09df6b9a11 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -15,8 +15,7 @@ #define MIPSSUBTARGET_H #include "llvm/Target/TargetSubtarget.h" -#include "llvm/Target/TargetMachine.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 8fd1a447692..799bb3dd81f 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -14,10 +14,9 @@ #ifndef POWERPCSUBTARGET_H #define POWERPCSUBTARGET_H -#include "llvm/ADT/Triple.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetSubtarget.h" - +#include "llvm/MC/MCInstrItineraries.h" +#include "llvm/ADT/Triple.h" #include // GCC #defines PPC on Linux but we use it as our namespace name diff --git a/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp deleted file mode 100644 index e0a9de82983..00000000000 --- a/lib/Target/SubtargetFeature.cpp +++ /dev/null @@ -1,384 +0,0 @@ -//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// -// -// 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 SubtargetFeature interface. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/StringExtras.h" -#include -#include -#include -#include -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Static Helper Functions -//===----------------------------------------------------------------------===// - -/// hasFlag - Determine if a feature has a flag; '+' or '-' -/// -static inline bool hasFlag(const std::string &Feature) { - assert(!Feature.empty() && "Empty string"); - // Get first character - char Ch = Feature[0]; - // Check if first character is '+' or '-' flag - return Ch == '+' || Ch =='-'; -} - -/// StripFlag - Return string stripped of flag. -/// -static inline std::string StripFlag(const std::string &Feature) { - return hasFlag(Feature) ? Feature.substr(1) : Feature; -} - -/// isEnabled - Return true if enable flag; '+'. -/// -static inline bool isEnabled(const std::string &Feature) { - assert(!Feature.empty() && "Empty string"); - // Get first character - char Ch = Feature[0]; - // Check if first character is '+' for enabled - return Ch == '+'; -} - -/// PrependFlag - Return a string with a prepended flag; '+' or '-'. -/// -static inline std::string PrependFlag(const std::string &Feature, - bool IsEnabled) { - assert(!Feature.empty() && "Empty string"); - if (hasFlag(Feature)) return Feature; - return std::string(IsEnabled ? "+" : "-") + Feature; -} - -/// Split - Splits a string of comma separated items in to a vector of strings. -/// -static void Split(std::vector &V, const std::string &S) { - // Start at beginning of string. - size_t Pos = 0; - while (true) { - // Find the next comma - size_t Comma = S.find(',', Pos); - // If no comma found then the rest of the string is used - if (Comma == std::string::npos) { - // Add string to vector - V.push_back(S.substr(Pos)); - break; - } - // Otherwise add substring to vector - V.push_back(S.substr(Pos, Comma - Pos)); - // Advance to next item - Pos = Comma + 1; - } -} - -/// Join a vector of strings to a string with a comma separating each element. -/// -static std::string Join(const std::vector &V) { - // Start with empty string. - std::string Result; - // If the vector is not empty - if (!V.empty()) { - // Start with the CPU feature - Result = V[0]; - // For each successive feature - for (size_t i = 1; i < V.size(); i++) { - // Add a comma - Result += ","; - // Add the feature - Result += V[i]; - } - } - // Return the features string - return Result; -} - -/// Adding features. -void SubtargetFeatures::AddFeature(const std::string &String, - bool IsEnabled) { - // Don't add empty features - if (!String.empty()) { - // Convert to lowercase, prepend flag and add to vector - Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); - } -} - -/// Find KV in array using binary search. -template const T *Find(const std::string &S, const T *A, size_t L) { - // Make the lower bound element we're looking for - T KV; - KV.Key = S.c_str(); - // Determine the end of the array - const T *Hi = A + L; - // Binary search the array - const T *F = std::lower_bound(A, Hi, KV); - // If not found then return NULL - if (F == Hi || std::string(F->Key) != S) return NULL; - // Return the found array item - return F; -} - -/// getLongestEntryLength - Return the length of the longest entry in the table. -/// -static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, - size_t Size) { - size_t MaxLen = 0; - for (size_t i = 0; i < Size; i++) - MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); - return MaxLen; -} - -/// Display help for feature choices. -/// -static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, - const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { - // Determine the length of the longest CPU and Feature entries. - unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); - - // Print the CPU table. - errs() << "Available CPUs for this target:\n\n"; - for (size_t i = 0; i != CPUTableSize; i++) - errs() << " " << CPUTable[i].Key - << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') - << " - " << CPUTable[i].Desc << ".\n"; - errs() << "\n"; - - // Print the Feature table. - errs() << "Available features for this target:\n\n"; - for (size_t i = 0; i != FeatTableSize; i++) - errs() << " " << FeatTable[i].Key - << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') - << " - " << FeatTable[i].Desc << ".\n"; - errs() << "\n"; - - errs() << "Use +feature to enable a feature, or -feature to disable it.\n" - << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; - std::exit(1); -} - -//===----------------------------------------------------------------------===// -// SubtargetFeatures Implementation -//===----------------------------------------------------------------------===// - -SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { - // Break up string into separate features - Split(Features, Initial); -} - - -std::string SubtargetFeatures::getString() const { - return Join(Features); -} -void SubtargetFeatures::setString(const std::string &Initial) { - // Throw out old features - Features.clear(); - // Break up string into separate features - Split(Features, LowercaseString(Initial)); -} - - -/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" -/// clears CPU. -void SubtargetFeatures::setCPU(const std::string &String) { - Features[0] = LowercaseString(String); -} - - -/// setCPUIfNone - Setting CPU string only if no string is set. -/// -void SubtargetFeatures::setCPUIfNone(const std::string &String) { - if (Features[0].empty()) setCPU(String); -} - -/// getCPU - Returns current CPU. -/// -const std::string & SubtargetFeatures::getCPU() const { - return Features[0]; -} - - -/// SetImpliedBits - For each feature that is (transitively) implied by this -/// feature, set it. -/// -static -void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - - if (FeatureEntry->Value == FE.Value) continue; - - if (FeatureEntry->Implies & FE.Value) { - Bits |= FE.Value; - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } -} - -/// ClearImpliedBits - For each feature that (transitively) implies this -/// feature, clear it. -/// -static -void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - - if (FeatureEntry->Value == FE.Value) continue; - - if (FE.Implies & FeatureEntry->Value) { - Bits &= ~FE.Value; - ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } -} - -/// getBits - Get feature bits. -/// -uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - assert(CPUTable && "missing CPU table"); - assert(FeatureTable && "missing features table"); -#ifndef NDEBUG - for (size_t i = 1; i < CPUTableSize; i++) { - assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && - "CPU table is not sorted"); - } - for (size_t i = 1; i < FeatureTableSize; i++) { - assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && - "CPU features table is not sorted"); - } -#endif - uint64_t Bits = 0; // Resulting bits - - // Check if help is needed - if (Features[0] == "help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); - - // Find CPU entry - const SubtargetFeatureKV *CPUEntry = - Find(Features[0], CPUTable, CPUTableSize); - // If there is a match - if (CPUEntry) { - // Set base feature bits - Bits = CPUEntry->Value; - - // Set the feature implied by this CPU feature, if any. - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - if (CPUEntry->Value & FE.Value) - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } else { - errs() << "'" << Features[0] - << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - } - // Iterate through each feature - for (size_t i = 1; i < Features.size(); i++) { - const std::string &Feature = Features[i]; - - // Check for help - if (Feature == "+help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); - - // Find feature in table. - const SubtargetFeatureKV *FeatureEntry = - Find(StripFlag(Feature), FeatureTable, FeatureTableSize); - // If there is a match - if (FeatureEntry) { - // Enable/disable feature in bits - if (isEnabled(Feature)) { - Bits |= FeatureEntry->Value; - - // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); - } else { - Bits &= ~FeatureEntry->Value; - - // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); - } - } else { - errs() << "'" << Feature - << "' is not a recognized feature for this target" - << " (ignoring feature)\n"; - } - } - - return Bits; -} - -/// Get info pointer -void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, - size_t TableSize) { - assert(Table && "missing table"); -#ifndef NDEBUG - for (size_t i = 1; i < TableSize; i++) { - assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); - } -#endif - - // Find entry - const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); - - if (Entry) { - return Entry->Value; - } else { - errs() << "'" << Features[0] - << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - return NULL; - } -} - -/// print - Print feature string. -/// -void SubtargetFeatures::print(raw_ostream &OS) const { - for (size_t i = 0, e = Features.size(); i != e; ++i) - OS << Features[i] << " "; - OS << "\n"; -} - -/// dump - Dump feature info. -/// -void SubtargetFeatures::dump() const { - print(dbgs()); -} - -/// getDefaultSubtargetFeatures - Return a string listing the features -/// associated with the target triple. -/// -/// FIXME: This is an inelegant way of specifying the features of a -/// subtarget. It would be better if we could encode this information -/// into the IR. See . -/// -void SubtargetFeatures::getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple) { - setCPU(CPU); - - if (Triple.getVendor() == Triple::Apple) { - if (Triple.getArch() == Triple::ppc) { - // powerpc-apple-* - AddFeature("altivec"); - } else if (Triple.getArch() == Triple::ppc64) { - // powerpc64-apple-* - AddFeature("64bit"); - AddFeature("altivec"); - } - } -} diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index d30bb6c379c..2931416febb 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.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 using namespace llvm; diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 162d6c8ad9c..e89b4d8318b 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -22,6 +22,7 @@ #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" #include "llvm/Config/config.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" @@ -31,7 +32,6 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Host.h" #include "llvm/Support/Signals.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 077f0e6700b..e2244597af9 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -19,11 +19,11 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Target/TargetAsmBackend.h" #include "llvm/Target/TargetAsmParser.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/SubtargetFeature.h" // FIXME. #include "llvm/Target/TargetAsmInfo.h" // FIXME. #include "llvm/Target/TargetLowering.h" // FIXME. #include "llvm/Target/TargetLoweringObjectFile.h" // FIXME. diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 3abd6413657..f175255c515 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -26,8 +26,8 @@ #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 4e754f6dce9..814d80bda07 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -29,7 +29,6 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/system_error.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -37,6 +36,7 @@ #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Target/TargetAsmParser.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 928fa4bee90..6899cb194a4 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -654,8 +654,8 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#include \"llvm/Support/Debug.h\"\n"; OS << "#include \"llvm/Support/raw_ostream.h\"\n"; - OS << "#include \"llvm/Target/SubtargetFeature.h\"\n"; - OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n"; + OS << "#include \"llvm/MC/SubtargetFeature.h\"\n"; + OS << "#include \"llvm/MC/MCInstrItineraries.h\"\n\n"; // Enumeration(OS, "FuncUnit", true); // OS<<"\n"; diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h index 93055b7fec1..cf793c880bc 100644 --- a/utils/TableGen/SubtargetEmitter.h +++ b/utils/TableGen/SubtargetEmitter.h @@ -15,7 +15,7 @@ #define SUBTARGET_EMITTER_H #include "TableGenBackend.h" -#include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/MC/MCInstrItineraries.h" #include #include #include