diff options
Diffstat (limited to 'include/llvm/CodeGen')
45 files changed, 2306 insertions, 1511 deletions
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index ef609e4..62d0679 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -16,30 +16,43 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_H #define LLVM_CODEGEN_ASMPRINTER_H -#include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/Support/DebugLoc.h" #include "llvm/Target/TargetMachine.h" -#include <set> +#include "llvm/ADT/DenseMap.h" namespace llvm { class GCStrategy; class Constant; class ConstantArray; + class ConstantFP; class ConstantInt; class ConstantStruct; class ConstantVector; class GCMetadataPrinter; + class GlobalValue; class GlobalVariable; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class MachineLoopInfo; + class MachineLoop; + class MachineConstantPool; class MachineConstantPoolEntry; class MachineConstantPoolValue; + class MachineJumpTableInfo; class MachineModuleInfo; + class MCInst; + class MCContext; + class MCSection; + class MCStreamer; + class MCSymbol; class DwarfWriter; class Mangler; - class Section; - class TargetAsmInfo; + class MCAsmInfo; + class TargetLoweringObjectFile; class Type; - class raw_ostream; + class formatted_raw_ostream; /// AsmPrinter - This class is intended to be used as a driving class for all /// asm writers. @@ -57,31 +70,51 @@ namespace llvm { typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type; typedef gcp_map_type::iterator gcp_iterator; gcp_map_type GCMetadataPrinters; - - protected: + + /// If VerboseAsm is set, a pointer to the loop info for this + /// function. + /// + MachineLoopInfo *LI; + + public: /// MMI - If available, this is a pointer to the current MachineModuleInfo. MachineModuleInfo *MMI; + protected: /// DW - If available, this is a pointer to the current dwarf writer. DwarfWriter *DW; - + public: /// Output stream on which we're printing assembly code. /// - raw_ostream &O; + formatted_raw_ostream &O; /// Target machine description. /// TargetMachine &TM; + /// getObjFileLowering - Return information about object file lowering. + TargetLoweringObjectFile &getObjFileLowering() const; + /// Target Asm Printer information. /// - const TargetAsmInfo *TAI; + const MCAsmInfo *MAI; /// Target Register Information. /// const TargetRegisterInfo *TRI; + /// OutContext - This is the context for the output file that we are + /// streaming. This owns all of the global MC-related objects for the + /// generated translation unit. + MCContext &OutContext; + + /// OutStreamer - This is the MCStreamer object for the file we are + /// generating. This contains the transient state for the current + /// translation unit that we are generating (such as the current section + /// etc). + MCStreamer &OutStreamer; + /// The current machine function. const MachineFunction *MF; @@ -94,14 +127,9 @@ namespace llvm { /// std::string CurrentFnName; - /// CurrentSection - The current section we are emitting to. This is - /// controlled and used by the SwitchSection method. - std::string CurrentSection; - const Section* CurrentSection_; - - /// IsInTextSection - True if the current section we are emitting to is a - /// text section. - bool IsInTextSection; + /// getCurrentSection() - Return the current section we are emitting to. + const MCSection *getCurrentSection() const; + /// VerboseAsm - Emit comments in assembly output if this is true. /// @@ -113,12 +141,12 @@ namespace llvm { mutable const Function *LastFn; mutable unsigned Counter; - // Private state for processDebugLock() + // Private state for processDebugLoc() mutable DebugLocTuple PrevDLT; protected: - explicit AsmPrinter(raw_ostream &o, TargetMachine &TM, - const TargetAsmInfo *T, bool V); + explicit AsmPrinter(formatted_raw_ostream &o, TargetMachine &TM, + const MCAsmInfo *T, bool V); public: virtual ~AsmPrinter(); @@ -127,54 +155,10 @@ namespace llvm { /// bool isVerbose() const { return VerboseAsm; } - /// SwitchToTextSection - Switch to the specified section of the executable - /// if we are not already in it! If GV is non-null and if the global has an - /// explicitly requested section, we switch to the section indicated for the - /// global instead of NewSection. - /// - /// If the new section is an empty string, this method forgets what the - /// current section is, but does not emit a .section directive. - /// - /// This method is used when about to emit executable code. - /// - void SwitchToTextSection(const char *NewSection, - const GlobalValue *GV = NULL); - - /// SwitchToDataSection - Switch to the specified section of the executable - /// if we are not already in it! If GV is non-null and if the global has an - /// explicitly requested section, we switch to the section indicated for the - /// global instead of NewSection. - /// - /// If the new section is an empty string, this method forgets what the - /// current section is, but does not emit a .section directive. - /// - /// This method is used when about to emit data. For most assemblers, this - /// is the same as the SwitchToTextSection method, but not all assemblers - /// are the same. + /// getFunctionNumber - Return a unique ID for the current function. /// - void SwitchToDataSection(const char *NewSection, - const GlobalValue *GV = NULL); - - /// SwitchToSection - Switch to the specified section of the executable if - /// we are not already in it! - void SwitchToSection(const Section* NS); - - /// getGlobalLinkName - Returns the asm/link name of of the specified - /// global variable. Should be overridden by each target asm printer to - /// generate the appropriate value. - virtual const std::string &getGlobalLinkName(const GlobalVariable *GV, - std::string &LinkName) const; - - /// EmitExternalGlobal - Emit the external reference to a global variable. - /// Should be overridden if an indirect reference should be used. - virtual void EmitExternalGlobal(const GlobalVariable *GV); - - /// getCurrentFunctionEHName - Called to return (and cache) the - /// CurrentFnEHName. - /// - const std::string &getCurrentFunctionEHName(const MachineFunction *MF, - std::string &FuncEHName) const; - + unsigned getFunctionNumber() const { return FunctionNumber; } + protected: /// getAnalysisUsage - Record analysis usage. /// @@ -185,6 +169,14 @@ namespace llvm { /// call this implementation. bool doInitialization(Module &M); + /// EmitStartOfAsmFile - This virtual method can be overridden by targets + /// that want to emit something at the start of their file. + virtual void EmitStartOfAsmFile(Module &M) {} + + /// EmitEndOfAsmFile - This virtual method can be overridden by targets that + /// want to emit something at the end of their file. + virtual void EmitEndOfAsmFile(Module &M) {} + /// doFinalization - Shut down the asmprinter. If you override this in your /// pass, you must make sure to call it explicitly. bool doFinalization(Module &M); @@ -212,14 +204,14 @@ namespace llvm { unsigned AsmVariant, const char *ExtraCode); + /// PrintGlobalVariable - Emit the specified global variable and its + /// initializer to the output stream. + virtual void PrintGlobalVariable(const GlobalVariable *GV) = 0; + /// SetupMachineFunction - This should be called when a new MachineFunction /// is being processed from runOnMachineFunction. void SetupMachineFunction(MachineFunction &MF); - /// getFunctionNumber - Return a unique ID for the current function. - /// - unsigned getFunctionNumber() const { return FunctionNumber; } - /// IncrementFunctionNumber - Increase Function Number. AsmPrinters should /// not normally call this, as the counter is automatically bumped by /// SetupMachineFunction. @@ -241,7 +233,7 @@ namespace llvm { /// special global used by LLVM. If so, emit it and return true, otherwise /// do nothing and return false. bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); - + public: //===------------------------------------------------------------------===// /// LEB 128 number encoding. @@ -267,7 +259,8 @@ namespace llvm { void EOL() const; void EOL(const std::string &Comment) const; void EOL(const char* Comment) const; - + void EOL(const char *Comment, unsigned Encoding) const; + /// EmitULEB128Bytes - Emit an assembler byte data directive to compose an /// unsigned leb128 value. void EmitULEB128Bytes(unsigned Value) const; @@ -332,6 +325,19 @@ namespace llvm { /// debug tables. void printDeclare(const MachineInstr *MI) const; + /// EmitComments - Pretty-print comments for instructions + void EmitComments(const MachineInstr &MI) const; + /// EmitComments - Pretty-print comments for basic blocks + void EmitComments(const MachineBasicBlock &MBB) const; + + /// GetMBBSymbol - Return the MCSymbol corresponding to the specified basic + /// block label. + MCSymbol *GetMBBSymbol(unsigned MBBID) const; + + /// EmitBasicBlockStart - This method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing + /// it if appropriate. + void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; protected: /// EmitZeros - Emit a block of zeros. /// @@ -351,8 +357,8 @@ namespace llvm { virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); /// processDebugLoc - Processes the debug information of each machine - /// instruction's DebugLoc. - void processDebugLoc(DebugLoc DL); + /// instruction's DebugLoc. + void processDebugLoc(const MachineInstr *MI, bool BeforePrintingInsn); /// printInlineAsm - This method formats and prints the specified machine /// instruction that is an inline asm. @@ -362,13 +368,7 @@ namespace llvm { /// that is an implicit def. virtual void printImplicitDef(const MachineInstr *MI) const; - /// printBasicBlockLabel - This method prints the label for the specified - /// MachineBasicBlock - virtual void printBasicBlockLabel(const MachineBasicBlock *MBB, - bool printAlign = false, - bool printColon = false, - bool printComment = true) const; - + /// printPICJumpTableSetLabel - This method prints a set label for the /// specified MachineBasicBlock for a jumptable entry. virtual void printPICJumpTableSetLabel(unsigned uid, @@ -383,22 +383,14 @@ namespace llvm { /// specified type. void printDataDirective(const Type *type, unsigned AddrSpace = 0); - /// printSuffixedName - This prints a name with preceding - /// getPrivateGlobalPrefix and the specified suffix, handling quoted names - /// correctly. - void printSuffixedName(const char *Name, const char *Suffix, - const char *Prefix = 0); - void printSuffixedName(const std::string &Name, const char* Suffix); - /// printVisibility - This prints visibility information about symbol, if /// this is suported by the target. void printVisibility(const std::string& Name, unsigned Visibility) const; /// printOffset - This is just convenient handler for printing offsets. void printOffset(int64_t Offset) const; - + private: - const GlobalValue *findGlobalValue(const Constant* CV); void EmitLLVMUsedList(Constant *List); void EmitXXStructorList(Constant *List); void EmitGlobalConstantStruct(const ConstantStruct* CVS, diff --git a/include/llvm/CodeGen/BinaryObject.h b/include/llvm/CodeGen/BinaryObject.h index ce0c07a..2d4bd73 100644 --- a/include/llvm/CodeGen/BinaryObject.h +++ b/include/llvm/CodeGen/BinaryObject.h @@ -68,6 +68,13 @@ public: return !Relocations.empty(); } + /// emitZeros - This callback is invoked to emit a arbitrary number + /// of zero bytes to the data stream. + inline void emitZeros(unsigned Size) { + for (unsigned i=0; i < Size; ++i) + emitByte(0); + } + /// emitByte - This callback is invoked when a byte needs to be /// written to the data stream. inline void emitByte(uint8_t B) { @@ -86,15 +93,15 @@ public: /// emitWord16LE - This callback is invoked when a 16-bit word needs to be /// written to the data stream in correct endian format and correct size. inline void emitWord16LE(uint16_t W) { - Data.push_back((W >> 0) & 255); - Data.push_back((W >> 8) & 255); + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); } /// emitWord16BE - This callback is invoked when a 16-bit word needs to be /// written to the data stream in correct endian format and correct size. inline void emitWord16BE(uint16_t W) { - Data.push_back((W >> 8) & 255); - Data.push_back((W >> 0) & 255); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); } /// emitWord - This callback is invoked when a word needs to be @@ -124,49 +131,62 @@ public: emitDWordBE(W); } + /// emitWord64 - This callback is invoked when a x86_fp80 needs to be + /// written to the data stream in correct endian format. + inline void emitWordFP80(const uint64_t *W, unsigned PadSize) { + if (IsLittleEndian) { + emitWord64(W[0]); + emitWord16(W[1]); + } else { + emitWord16(W[1]); + emitWord64(W[0]); + } + emitZeros(PadSize); + } + /// emitWordLE - This callback is invoked when a 32-bit word needs to be /// written to the data stream in little-endian format. inline void emitWordLE(uint32_t W) { - Data.push_back((W >> 0) & 255); - Data.push_back((W >> 8) & 255); - Data.push_back((W >> 16) & 255); - Data.push_back((W >> 24) & 255); + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 24)); } /// emitWordBE - This callback is invoked when a 32-bit word needs to be /// written to the data stream in big-endian format. /// inline void emitWordBE(uint32_t W) { - Data.push_back((W >> 24) & 255); - Data.push_back((W >> 16) & 255); - Data.push_back((W >> 8) & 255); - Data.push_back((W >> 0) & 255); + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); } /// emitDWordLE - This callback is invoked when a 64-bit word needs to be /// written to the data stream in little-endian format. inline void emitDWordLE(uint64_t W) { - Data.push_back(unsigned(W >> 0) & 255); - Data.push_back(unsigned(W >> 8) & 255); - Data.push_back(unsigned(W >> 16) & 255); - Data.push_back(unsigned(W >> 24) & 255); - Data.push_back(unsigned(W >> 32) & 255); - Data.push_back(unsigned(W >> 40) & 255); - Data.push_back(unsigned(W >> 48) & 255); - Data.push_back(unsigned(W >> 56) & 255); + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 32)); + Data.push_back((uint8_t)(W >> 40)); + Data.push_back((uint8_t)(W >> 48)); + Data.push_back((uint8_t)(W >> 56)); } /// emitDWordBE - This callback is invoked when a 64-bit word needs to be /// written to the data stream in big-endian format. inline void emitDWordBE(uint64_t W) { - Data.push_back(unsigned(W >> 56) & 255); - Data.push_back(unsigned(W >> 48) & 255); - Data.push_back(unsigned(W >> 40) & 255); - Data.push_back(unsigned(W >> 32) & 255); - Data.push_back(unsigned(W >> 24) & 255); - Data.push_back(unsigned(W >> 16) & 255); - Data.push_back(unsigned(W >> 8) & 255); - Data.push_back(unsigned(W >> 0) & 255); + Data.push_back((uint8_t)(W >> 56)); + Data.push_back((uint8_t)(W >> 48)); + Data.push_back((uint8_t)(W >> 40)); + Data.push_back((uint8_t)(W >> 32)); + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); } /// fixByte - This callback is invoked when a byte needs to be @@ -187,15 +207,15 @@ public: /// emitWord16LE - This callback is invoked when a 16-bit word needs to /// fixup the data stream in little endian format. inline void fixWord16LE(uint16_t W, uint32_t offset) { - Data[offset++] = W & 255; - Data[offset] = (W >> 8) & 255; + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); } /// fixWord16BE - This callback is invoked when a 16-bit word needs to /// fixup data stream in big endian format. inline void fixWord16BE(uint16_t W, uint32_t offset) { - Data[offset++] = (W >> 8) & 255; - Data[offset] = W & 255; + Data[offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); } /// emitWord - This callback is invoked when a word needs to @@ -219,19 +239,19 @@ public: /// fixWord32LE - This callback is invoked when a 32-bit word needs to /// fixup the data in little endian format. inline void fixWord32LE(uint32_t W, uint32_t offset) { - Data[offset++] = W & 255; - Data[offset++] = (W >> 8) & 255; - Data[offset++] = (W >> 16) & 255; - Data[offset] = (W >> 24) & 255; + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 24); } /// fixWord32BE - This callback is invoked when a 32-bit word needs to /// fixup the data in big endian format. inline void fixWord32BE(uint32_t W, uint32_t offset) { - Data[offset++] = (W >> 24) & 255; - Data[offset++] = (W >> 16) & 255; - Data[offset++] = (W >> 8) & 255; - Data[offset] = W & 255; + Data[offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); } /// fixWord64 - This callback is invoked when a 64-bit word needs to @@ -246,42 +266,42 @@ public: /// fixWord64BE - This callback is invoked when a 64-bit word needs to /// fixup the data in little endian format. inline void fixWord64LE(uint64_t W, uint32_t offset) { - Data[offset++] = W & 255; - Data[offset++] = (W >> 8) & 255; - Data[offset++] = (W >> 16) & 255; - Data[offset++] = (W >> 24) & 255; - Data[offset++] = (W >> 32) & 255; - Data[offset++] = (W >> 40) & 255; - Data[offset++] = (W >> 48) & 255; - Data[offset] = (W >> 56) & 255; + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 32); + Data[++offset] = (uint8_t)(W >> 40); + Data[++offset] = (uint8_t)(W >> 48); + Data[++offset] = (uint8_t)(W >> 56); } /// fixWord64BE - This callback is invoked when a 64-bit word needs to /// fixup the data in big endian format. inline void fixWord64BE(uint64_t W, uint32_t offset) { - Data[offset++] = (W >> 56) & 255; - Data[offset++] = (W >> 48) & 255; - Data[offset++] = (W >> 40) & 255; - Data[offset++] = (W >> 32) & 255; - Data[offset++] = (W >> 24) & 255; - Data[offset++] = (W >> 16) & 255; - Data[offset++] = (W >> 8) & 255; - Data[offset] = W & 255; + Data[offset] = (uint8_t)(W >> 56); + Data[++offset] = (uint8_t)(W >> 48); + Data[++offset] = (uint8_t)(W >> 40); + Data[++offset] = (uint8_t)(W >> 32); + Data[++offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); } /// emitAlignment - Pad the data to the specified alignment. - void emitAlignment(unsigned Alignment) { + void emitAlignment(unsigned Alignment, uint8_t fill = 0) { if (Alignment <= 1) return; unsigned PadSize = -Data.size() & (Alignment-1); for (unsigned i = 0; i<PadSize; ++i) - Data.push_back(0); + Data.push_back(fill); } /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be /// written to the data stream. void emitULEB128Bytes(uint64_t Value) { do { - unsigned char Byte = Value & 0x7f; + uint8_t Byte = (uint8_t)(Value & 0x7f); Value >>= 7; if (Value) Byte |= 0x80; emitByte(Byte); @@ -295,7 +315,7 @@ public: bool IsMore; do { - unsigned char Byte = Value & 0x7f; + uint8_t Byte = (uint8_t)(Value & 0x7f); Value >>= 7; IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; if (IsMore) Byte |= 0x80; diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 7c83e24..5e730fc 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CallingConv.h" namespace llvm { class TargetRegisterInfo; @@ -33,34 +34,35 @@ public: SExt, // The value is sign extended in the location. ZExt, // The value is zero extended in the location. AExt, // The value is extended with undefined upper bits. - BCvt // The value is bit-converted in the location. + BCvt, // The value is bit-converted in the location. + Indirect // The location contains pointer to the value. // TODO: a subset of the value is in the location. }; private: /// ValNo - This is the value number begin assigned (e.g. an argument number). unsigned ValNo; - + /// Loc is either a stack offset or a register number. unsigned Loc; - + /// isMem - True if this is a memory loc, false if it is a register loc. bool isMem : 1; - + /// isCustom - True if this arg/retval requires special handling. bool isCustom : 1; /// Information about how the value is assigned. LocInfo HTP : 6; - + /// ValVT - The type of the value being assigned. - MVT ValVT; + EVT ValVT; /// LocVT - The type of the location being assigned to. - MVT LocVT; + EVT LocVT; public: - - static CCValAssign getReg(unsigned ValNo, MVT ValVT, - unsigned RegNo, MVT LocVT, + + static CCValAssign getReg(unsigned ValNo, EVT ValVT, + unsigned RegNo, EVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret.ValNo = ValNo; @@ -73,8 +75,8 @@ public: return Ret; } - static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, - unsigned RegNo, MVT LocVT, + static CCValAssign getCustomReg(unsigned ValNo, EVT ValVT, + unsigned RegNo, EVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP); @@ -82,8 +84,8 @@ public: return Ret; } - static CCValAssign getMem(unsigned ValNo, MVT ValVT, - unsigned Offset, MVT LocVT, + static CCValAssign getMem(unsigned ValNo, EVT ValVT, + unsigned Offset, EVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret.ValNo = ValNo; @@ -95,9 +97,9 @@ public: Ret.LocVT = LocVT; return Ret; } - - static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, - unsigned Offset, MVT LocVT, + + static CCValAssign getCustomMem(unsigned ValNo, EVT ValVT, + unsigned Offset, EVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP); @@ -106,57 +108,63 @@ public: } unsigned getValNo() const { return ValNo; } - MVT getValVT() const { return ValVT; } + EVT getValVT() const { return ValVT; } bool isRegLoc() const { return !isMem; } bool isMemLoc() const { return isMem; } - + bool needsCustom() const { return isCustom; } unsigned getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } - MVT getLocVT() const { return LocVT; } - + EVT getLocVT() const { return LocVT; } + LocInfo getLocInfo() const { return HTP; } + bool isExtInLoc() const { + return (HTP == AExt || HTP == SExt || HTP == ZExt); + } + }; /// CCAssignFn - This function assigns a location for Val, updating State to /// reflect the change. -typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, - MVT LocVT, CCValAssign::LocInfo LocInfo, +typedef bool CCAssignFn(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State); /// CCCustomFn - This function assigns a location for Val, possibly updating /// all args to reflect changes and indicates if it handled it. It must set /// isCustom if it handles the arg and returns true. -typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, +typedef bool CCCustomFn(unsigned &ValNo, EVT &ValVT, + EVT &LocVT, CCValAssign::LocInfo &LocInfo, ISD::ArgFlagsTy &ArgFlags, CCState &State); /// CCState - This class holds information needed while lowering arguments and /// return values. It captures which registers are already assigned and which /// stack slots are used. It provides accessors to allocate these values. class CCState { - unsigned CallingConv; + CallingConv::ID CallingConv; bool IsVarArg; const TargetMachine &TM; const TargetRegisterInfo &TRI; SmallVector<CCValAssign, 16> &Locs; - + LLVMContext &Context; + unsigned StackOffset; SmallVector<uint32_t, 16> UsedRegs; public: - CCState(unsigned CC, bool isVarArg, const TargetMachine &TM, - SmallVector<CCValAssign, 16> &locs); - + CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM, + SmallVector<CCValAssign, 16> &locs, LLVMContext &C); + void addLoc(const CCValAssign &V) { Locs.push_back(V); } - + + LLVMContext &getContext() const { return Context; } const TargetMachine &getTarget() const { return TM; } - unsigned getCallingConv() const { return CallingConv; } + CallingConv::ID getCallingConv() const { return CallingConv; } bool isVarArg() const { return IsVarArg; } - + unsigned getNextStackOffset() const { return StackOffset; } /// isAllocated - Return true if the specified register (or an alias) is @@ -164,32 +172,36 @@ public: bool isAllocated(unsigned Reg) const { return UsedRegs[Reg/32] & (1 << (Reg&31)); } - - /// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, + + /// AnalyzeFormalArguments - Analyze an array of argument values, /// incorporating info about the formals into this state. - void AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn); - - /// AnalyzeReturn - Analyze the returned values of an ISD::RET node, + void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, + CCAssignFn Fn); + + /// AnalyzeReturn - Analyze the returned values of a return, /// incorporating info about the result values into this state. - void AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn); - - /// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info - /// about the passed values into this state. - void AnalyzeCallOperands(CallSDNode *TheCall, CCAssignFn Fn); + void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, + CCAssignFn Fn); + + /// AnalyzeCallOperands - Analyze the outgoing arguments to a call, + /// incorporating info about the passed values into this state. + void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, + CCAssignFn Fn); /// AnalyzeCallOperands - Same as above except it takes vectors of types /// and argument flags. - void AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs, + void AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs, SmallVectorImpl<ISD::ArgFlagsTy> &Flags, CCAssignFn Fn); - /// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, + /// AnalyzeCallResult - Analyze the return values of a call, /// incorporating info about the passed values into this state. - void AnalyzeCallResult(CallSDNode *TheCall, CCAssignFn Fn); - + void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, + CCAssignFn Fn); + /// AnalyzeCallResult - Same as above except it's specialized for calls which /// produce a single value. - void AnalyzeCallResult(MVT VT, CCAssignFn Fn); + void AnalyzeCallResult(EVT VT, CCAssignFn Fn); /// getFirstUnallocated - Return the first unallocated register in the set, or /// NumRegs if they are all allocated. @@ -199,7 +211,7 @@ public: return i; return NumRegs; } - + /// AllocateReg - Attempt to allocate one register. If it is not available, /// return zero. Otherwise, return the register, marking it and any aliases /// as allocated. @@ -258,8 +270,8 @@ public: // HandleByVal - Allocate a stack slot large enough to pass an argument by // value. The size and alignment information of the argument is encoded in its // parameter attribute. - void HandleByVal(unsigned ValNo, MVT ValVT, - MVT LocVT, CCValAssign::LocInfo LocInfo, + void HandleByVal(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); private: diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h index facd5f6..e7a2f66 100644 --- a/include/llvm/CodeGen/DwarfWriter.h +++ b/include/llvm/CodeGen/DwarfWriter.h @@ -33,8 +33,8 @@ class MachineFunction; class MachineInstr; class Value; class Module; -class GlobalVariable; -class TargetAsmInfo; +class MDNode; +class MCAsmInfo; class raw_ostream; class Instruction; class DICompileUnit; @@ -68,7 +68,7 @@ public: /// BeginModule - Emit all Dwarf sections that should come prior to the /// content. void BeginModule(Module *M, MachineModuleInfo *MMI, raw_ostream &OS, - AsmPrinter *A, const TargetAsmInfo *T); + AsmPrinter *A, const MCAsmInfo *T); /// EndModule - Emit all Dwarf sections that should come after the content. /// @@ -85,21 +85,20 @@ public: /// RecordSourceLine - Register a source line with debug info. Returns a /// unique label ID used to generate a label and provide correspondence to /// the source line list. - unsigned RecordSourceLine(unsigned Line, unsigned Col, DICompileUnit CU); + unsigned RecordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); /// RecordRegionStart - Indicate the start of a region. - unsigned RecordRegionStart(GlobalVariable *V); + unsigned RecordRegionStart(MDNode *N); /// RecordRegionEnd - Indicate the end of a region. - unsigned RecordRegionEnd(GlobalVariable *V); + unsigned RecordRegionEnd(MDNode *N); /// getRecordSourceLineCount - Count source lines. unsigned getRecordSourceLineCount(); /// RecordVariable - Indicate the declaration of a local variable. /// - void RecordVariable(GlobalVariable *GV, unsigned FrameIndex, - const MachineInstr *MI); + void RecordVariable(MDNode *N, unsigned FrameIndex); /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should /// be emitted. @@ -111,13 +110,10 @@ public: /// RecordInlinedFnEnd - Indicate the end of inlined subroutine. unsigned RecordInlinedFnEnd(DISubprogram SP); - - /// RecordVariableScope - Record scope for the variable declared by - /// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. - void RecordVariableScope(DIVariable &DV, const MachineInstr *DeclareMI); + void SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned L); + void SetDbgScopeEndLabels(const MachineInstr *MI, unsigned L); }; - } // end llvm namespace #endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index c7b1a42..1efd1e0 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -91,7 +91,7 @@ public: /// bool SelectInstruction(Instruction *I); - /// SelectInstruction - Do "fast" instruction selection for the given + /// SelectOperator - Do "fast" instruction selection for the given /// LLVM IR operator (Instruction or ConstantExpr), and append /// generated machine instructions to the current block. Return true /// if selection was successful. @@ -137,24 +137,24 @@ protected: /// FastEmit_r - This method is called by target-independent code /// to request that an instruction with the given type and opcode /// be emitted. - virtual unsigned FastEmit_(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_(MVT VT, + MVT RetVT, ISD::NodeType Opcode); /// FastEmit_r - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and /// register operand be emitted. /// - virtual unsigned FastEmit_r(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_r(MVT VT, + MVT RetVT, ISD::NodeType Opcode, unsigned Op0); /// FastEmit_rr - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and /// register operands be emitted. /// - virtual unsigned FastEmit_rr(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_rr(MVT VT, + MVT RetVT, ISD::NodeType Opcode, unsigned Op0, unsigned Op1); @@ -162,8 +162,8 @@ protected: /// to request that an instruction with the given type, opcode, and /// register and immediate operands be emitted. /// - virtual unsigned FastEmit_ri(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_ri(MVT VT, + MVT RetVT, ISD::NodeType Opcode, unsigned Op0, uint64_t Imm); @@ -171,8 +171,8 @@ protected: /// to request that an instruction with the given type, opcode, and /// register and floating-point immediate operands be emitted. /// - virtual unsigned FastEmit_rf(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_rf(MVT VT, + MVT RetVT, ISD::NodeType Opcode, unsigned Op0, ConstantFP *FPImm); @@ -180,8 +180,8 @@ protected: /// to request that an instruction with the given type, opcode, and /// register and immediate operands be emitted. /// - virtual unsigned FastEmit_rri(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_rri(MVT VT, + MVT RetVT, ISD::NodeType Opcode, unsigned Op0, unsigned Op1, uint64_t Imm); @@ -189,33 +189,33 @@ protected: /// to emit an instruction with an immediate operand using FastEmit_ri. /// If that fails, it materializes the immediate into a register and try /// FastEmit_rr instead. - unsigned FastEmit_ri_(MVT::SimpleValueType VT, + unsigned FastEmit_ri_(MVT VT, ISD::NodeType Opcode, unsigned Op0, uint64_t Imm, - MVT::SimpleValueType ImmType); + MVT ImmType); /// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries /// to emit an instruction with an immediate operand using FastEmit_rf. /// If that fails, it materializes the immediate into a register and try /// FastEmit_rr instead. - unsigned FastEmit_rf_(MVT::SimpleValueType VT, + unsigned FastEmit_rf_(MVT VT, ISD::NodeType Opcode, unsigned Op0, ConstantFP *FPImm, - MVT::SimpleValueType ImmType); + MVT ImmType); /// FastEmit_i - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and /// immediate operand be emitted. - virtual unsigned FastEmit_i(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_i(MVT VT, + MVT RetVT, ISD::NodeType Opcode, uint64_t Imm); /// FastEmit_f - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and /// floating-point immediate operand be emitted. - virtual unsigned FastEmit_f(MVT::SimpleValueType VT, - MVT::SimpleValueType RetVT, + virtual unsigned FastEmit_f(MVT VT, + MVT RetVT, ISD::NodeType Opcode, ConstantFP *FPImm); @@ -268,12 +268,12 @@ protected: /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg /// from a specified index of a superregister to a specified type. - unsigned FastEmitInst_extractsubreg(MVT::SimpleValueType RetVT, + unsigned FastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, uint32_t Idx); /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op /// with all but the least significant bit set to zero. - unsigned FastEmitZExtFromI1(MVT::SimpleValueType VT, + unsigned FastEmitZExtFromI1(MVT VT, unsigned Op); /// FastEmitBranch - Emit an unconditional branch to the given block, @@ -300,6 +300,8 @@ protected: private: bool SelectBinaryOp(User *I, ISD::NodeType ISDOpcode); + bool SelectFNeg(User *I); + bool SelectGetElementPtr(User *I); bool SelectCall(User *I); diff --git a/include/llvm/CodeGen/FileWriters.h b/include/llvm/CodeGen/FileWriters.h index b3781e0..a913d21 100644 --- a/include/llvm/CodeGen/FileWriters.h +++ b/include/llvm/CodeGen/FileWriters.h @@ -17,14 +17,14 @@ namespace llvm { class PassManagerBase; - class MachineCodeEmitter; + class ObjectCodeEmitter; class TargetMachine; class raw_ostream; - MachineCodeEmitter *AddELFWriter(PassManagerBase &FPM, raw_ostream &O, - TargetMachine &TM); - MachineCodeEmitter *AddMachOWriter(PassManagerBase &FPM, raw_ostream &O, - TargetMachine &TM); + ObjectCodeEmitter *AddELFWriter(PassManagerBase &FPM, raw_ostream &O, + TargetMachine &TM); + ObjectCodeEmitter *AddMachOWriter(PassManagerBase &FPM, raw_ostream &O, + TargetMachine &TM); } // end llvm namespace diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index e94aba3..04fd8be 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -42,7 +42,7 @@ namespace llvm { class AsmPrinter; class GCStrategy; class Constant; - class TargetAsmInfo; + class MCAsmInfo; namespace GC { diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index b693b1b..ff1a205 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -63,10 +63,10 @@ namespace llvm { /// beginAssembly/finishAssembly - Emit module metadata as assembly code. virtual void beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + const MCAsmInfo &MAI); virtual void finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + const MCAsmInfo &MAI); virtual ~GCMetadataPrinter(); }; diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h index 73197af..180783a 100644 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ b/include/llvm/CodeGen/JITCodeEmitter.h @@ -19,7 +19,7 @@ #include <string> #include "llvm/Support/DataTypes.h" -#include "llvm/Support/Streams.h" +#include "llvm/Support/MathExtras.h" #include "llvm/CodeGen/MachineCodeEmitter.h" using namespace std; @@ -162,17 +162,26 @@ public: /// alignment (saturated to BufferEnd of course). void emitAlignment(unsigned Alignment) { if (Alignment == 0) Alignment = 1; + uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, + Alignment); + CurBufferPtr = std::min(NewPtr, BufferEnd); + } - if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) { - // Move the current buffer ptr up to the specified alignment. - CurBufferPtr = - (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) & - ~(uintptr_t)(Alignment-1)); - } else { + /// emitAlignmentWithFill - Similar to emitAlignment, except that the + /// extra bytes are filled with the provided byte. + void emitAlignmentWithFill(unsigned Alignment, uint8_t Fill) { + if (Alignment == 0) Alignment = 1; + uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, + Alignment); + // Fail if we don't have room. + if (NewPtr > BufferEnd) { CurBufferPtr = BufferEnd; + return; + } + while (CurBufferPtr < NewPtr) { + *CurBufferPtr++ = Fill; } } - /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be /// written to the output stream. @@ -267,6 +276,11 @@ public: return Result; } + /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, + /// this method does not allocate memory in the current output buffer, + /// because a global may live longer than the current function. + virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; + /// StartMachineBasicBlock - This should be called by the target when a new /// basic block is about to be emitted. This way the MCE knows where the /// start of the block is, and can implement getMachineBasicBlockAddress. @@ -285,6 +299,13 @@ public: return CurBufferPtr-BufferBegin; } + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + bool earlyResolveAddresses() const { return true; } + /// addRelocation - Whenever a relocatable address is needed, it should be /// noted with this interface. virtual void addRelocation(const MachineRelocation &MR) = 0; diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index a231f49..4d2d0ee 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -32,9 +32,7 @@ namespace { (void) llvm::createDeadMachineInstructionElimPass(); - (void) llvm::createSimpleRegisterAllocator(); (void) llvm::createLocalRegisterAllocator(); - (void) llvm::createBigBlockRegisterAllocator(); (void) llvm::createLinearScanRegisterAllocator(); (void) llvm::createPBQPRegisterAllocator(); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 0cb7e90..05bd173 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -21,9 +21,10 @@ #ifndef LLVM_CODEGEN_LIVEINTERVAL_H #define LLVM_CODEGEN_LIVEINTERVAL_H +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" -#include <iosfwd> +#include "llvm/Support/AlignOf.h" #include <cassert> #include <climits> @@ -31,7 +32,210 @@ namespace llvm { class MachineInstr; class MachineRegisterInfo; class TargetRegisterInfo; - struct LiveInterval; + class raw_ostream; + + /// LiveIndex - An opaque wrapper around machine indexes. + class LiveIndex { + friend class VNInfo; + friend class LiveInterval; + friend class LiveIntervals; + friend struct DenseMapInfo<LiveIndex>; + + public: + + enum Slot { LOAD, USE, DEF, STORE, NUM }; + + private: + + unsigned index; + + static const unsigned PHI_BIT = 1 << 31; + + public: + + /// Construct a default LiveIndex pointing to a reserved index. + LiveIndex() : index(0) {} + + /// Construct an index from the given index, pointing to the given slot. + LiveIndex(LiveIndex m, Slot s) + : index((m.index / NUM) * NUM + s) {} + + /// Print this index to the given raw_ostream. + void print(raw_ostream &os) const; + + /// Compare two LiveIndex objects for equality. + bool operator==(LiveIndex other) const { + return ((index & ~PHI_BIT) == (other.index & ~PHI_BIT)); + } + /// Compare two LiveIndex objects for inequality. + bool operator!=(LiveIndex other) const { + return ((index & ~PHI_BIT) != (other.index & ~PHI_BIT)); + } + + /// Compare two LiveIndex objects. Return true if the first index + /// is strictly lower than the second. + bool operator<(LiveIndex other) const { + return ((index & ~PHI_BIT) < (other.index & ~PHI_BIT)); + } + /// Compare two LiveIndex objects. Return true if the first index + /// is lower than, or equal to, the second. + bool operator<=(LiveIndex other) const { + return ((index & ~PHI_BIT) <= (other.index & ~PHI_BIT)); + } + + /// Compare two LiveIndex objects. Return true if the first index + /// is greater than the second. + bool operator>(LiveIndex other) const { + return ((index & ~PHI_BIT) > (other.index & ~PHI_BIT)); + } + + /// Compare two LiveIndex objects. Return true if the first index + /// is greater than, or equal to, the second. + bool operator>=(LiveIndex other) const { + return ((index & ~PHI_BIT) >= (other.index & ~PHI_BIT)); + } + + /// Returns true if this index represents a load. + bool isLoad() const { + return ((index % NUM) == LOAD); + } + + /// Returns true if this index represents a use. + bool isUse() const { + return ((index % NUM) == USE); + } + + /// Returns true if this index represents a def. + bool isDef() const { + return ((index % NUM) == DEF); + } + + /// Returns true if this index represents a store. + bool isStore() const { + return ((index % NUM) == STORE); + } + + /// Returns the slot for this LiveIndex. + Slot getSlot() const { + return static_cast<Slot>(index % NUM); + } + + /// Returns true if this index represents a non-PHI use/def. + bool isNonPHIIndex() const { + return ((index & PHI_BIT) == 0); + } + + /// Returns true if this index represents a PHI use/def. + bool isPHIIndex() const { + return ((index & PHI_BIT) == PHI_BIT); + } + + private: + + /// Construct an index from the given index, with its PHI kill marker set. + LiveIndex(bool phi, LiveIndex o) : index(o.index) { + if (phi) + index |= PHI_BIT; + else + index &= ~PHI_BIT; + } + + explicit LiveIndex(unsigned idx) + : index(idx & ~PHI_BIT) {} + + LiveIndex(bool phi, unsigned idx) + : index(idx & ~PHI_BIT) { + if (phi) + index |= PHI_BIT; + } + + LiveIndex(bool phi, unsigned idx, Slot slot) + : index(((idx / NUM) * NUM + slot) & ~PHI_BIT) { + if (phi) + index |= PHI_BIT; + } + + LiveIndex nextSlot_() const { + assert((index & PHI_BIT) == ((index + 1) & PHI_BIT) && + "Index out of bounds."); + return LiveIndex(index + 1); + } + + LiveIndex nextIndex_() const { + assert((index & PHI_BIT) == ((index + NUM) & PHI_BIT) && + "Index out of bounds."); + return LiveIndex(index + NUM); + } + + LiveIndex prevSlot_() const { + assert((index & PHI_BIT) == ((index - 1) & PHI_BIT) && + "Index out of bounds."); + return LiveIndex(index - 1); + } + + LiveIndex prevIndex_() const { + assert((index & PHI_BIT) == ((index - NUM) & PHI_BIT) && + "Index out of bounds."); + return LiveIndex(index - NUM); + } + + int distance(LiveIndex other) const { + return (other.index & ~PHI_BIT) - (index & ~PHI_BIT); + } + + /// Returns an unsigned number suitable as an index into a + /// vector over all instructions. + unsigned getVecIndex() const { + return (index & ~PHI_BIT) / NUM; + } + + /// Scale this index by the given factor. + LiveIndex scale(unsigned factor) const { + unsigned i = (index & ~PHI_BIT) / NUM, + o = (index % ~PHI_BIT) % NUM; + assert(index <= (~0U & ~PHI_BIT) / (factor * NUM) && + "Rescaled interval would overflow"); + return LiveIndex(i * NUM * factor, o); + } + + static LiveIndex emptyKey() { + return LiveIndex(true, 0x7fffffff); + } + + static LiveIndex tombstoneKey() { + return LiveIndex(true, 0x7ffffffe); + } + + static unsigned getHashValue(const LiveIndex &v) { + return v.index * 37; + } + + }; + + inline raw_ostream& operator<<(raw_ostream &os, LiveIndex mi) { + mi.print(os); + return os; + } + + /// Densemap specialization for LiveIndex. + template <> + struct DenseMapInfo<LiveIndex> { + static inline LiveIndex getEmptyKey() { + return LiveIndex::emptyKey(); + } + static inline LiveIndex getTombstoneKey() { + return LiveIndex::tombstoneKey(); + } + static inline unsigned getHashValue(const LiveIndex &v) { + return LiveIndex::getHashValue(v); + } + static inline bool isEqual(const LiveIndex &LHS, + const LiveIndex &RHS) { + return (LHS == RHS); + } + static inline bool isPod() { return true; } + }; + /// VNInfo - Value Number Information. /// This class holds information about a machine level values, including @@ -48,7 +252,6 @@ namespace llvm { /// index of the MBB in which the PHI originally existed. This can be used /// to insert code (spills or copies) which deals with the value, which will /// be live in to the block. - class VNInfo { private: enum { @@ -60,36 +263,70 @@ namespace llvm { }; unsigned char flags; + union { + MachineInstr *copy; + unsigned reg; + } cr; public: + + typedef SmallVector<LiveIndex, 4> KillSet; + /// The ID number of this value. unsigned id; /// The index of the defining instruction (if isDefAccurate() returns true). - unsigned def; - MachineInstr *copy; - SmallVector<unsigned, 4> kills; + LiveIndex def; + + KillSet kills; VNInfo() - : flags(IS_UNUSED), id(~1U), def(0), copy(0) {} + : flags(IS_UNUSED), id(~1U) { cr.copy = 0; } /// VNInfo constructor. /// d is presumed to point to the actual defining instr. If it doesn't /// setIsDefAccurate(false) should be called after construction. - VNInfo(unsigned i, unsigned d, MachineInstr *c) - : flags(IS_DEF_ACCURATE), id(i), def(d), copy(c) {} + VNInfo(unsigned i, LiveIndex d, MachineInstr *c) + : flags(IS_DEF_ACCURATE), id(i), def(d) { cr.copy = c; } /// VNInfo construtor, copies values from orig, except for the value number. VNInfo(unsigned i, const VNInfo &orig) - : flags(orig.flags), id(i), def(orig.def), copy(orig.copy), - kills(orig.kills) {} + : flags(orig.flags), cr(orig.cr), id(i), def(orig.def), kills(orig.kills) + { } + + /// Copy from the parameter into this VNInfo. + void copyFrom(VNInfo &src) { + flags = src.flags; + cr = src.cr; + def = src.def; + kills = src.kills; + } /// Used for copying value number info. unsigned getFlags() const { return flags; } void setFlags(unsigned flags) { this->flags = flags; } + /// For a register interval, if this VN was definied by a copy instr + /// getCopy() returns a pointer to it, otherwise returns 0. + /// For a stack interval the behaviour of this method is undefined. + MachineInstr* getCopy() const { return cr.copy; } + /// For a register interval, set the copy member. + /// This method should not be called on stack intervals as it may lead to + /// undefined behavior. + void setCopy(MachineInstr *c) { cr.copy = c; } + + /// For a stack interval, returns the reg which this stack interval was + /// defined from. + /// For a register interval the behaviour of this method is undefined. + unsigned getReg() const { return cr.reg; } + /// For a stack interval, set the defining register. + /// This method should not be called on register intervals as it may lead + /// to undefined behaviour. + void setReg(unsigned reg) { cr.reg = reg; } + /// Returns true if one or more kills are PHI nodes. bool hasPHIKill() const { return flags & HAS_PHI_KILL; } + /// Set the PHI kill flag on this value. void setHasPHIKill(bool hasKill) { if (hasKill) flags |= HAS_PHI_KILL; @@ -100,16 +337,18 @@ namespace llvm { /// Returns true if this value is re-defined by an early clobber somewhere /// during the live range. bool hasRedefByEC() const { return flags & REDEF_BY_EC; } + /// Set the "redef by early clobber" flag on this value. void setHasRedefByEC(bool hasRedef) { if (hasRedef) flags |= REDEF_BY_EC; else flags &= ~REDEF_BY_EC; } - + /// Returns true if this value is defined by a PHI instruction (or was, /// PHI instrucions may have been eliminated). bool isPHIDef() const { return flags & IS_PHI_DEF; } + /// Set the "phi def" flag on this value. void setIsPHIDef(bool phiDef) { if (phiDef) flags |= IS_PHI_DEF; @@ -119,6 +358,7 @@ namespace llvm { /// Returns true if this value is unused. bool isUnused() const { return flags & IS_UNUSED; } + /// Set the "is unused" flag on this value. void setIsUnused(bool unused) { if (unused) flags |= IS_UNUSED; @@ -128,6 +368,7 @@ namespace llvm { /// Returns true if the def is accurate. bool isDefAccurate() const { return flags & IS_DEF_ACCURATE; } + /// Set the "is def accurate" flag on this value. void setIsDefAccurate(bool defAccurate) { if (defAccurate) flags |= IS_DEF_ACCURATE; @@ -135,26 +376,74 @@ namespace llvm { flags &= ~IS_DEF_ACCURATE; } + /// Returns true if the given index is a kill of this value. + bool isKill(LiveIndex k) const { + KillSet::const_iterator + i = std::lower_bound(kills.begin(), kills.end(), k); + return (i != kills.end() && *i == k); + } + + /// addKill - Add a kill instruction index to the specified value + /// number. + void addKill(LiveIndex k) { + if (kills.empty()) { + kills.push_back(k); + } else { + KillSet::iterator + i = std::lower_bound(kills.begin(), kills.end(), k); + kills.insert(i, k); + } + } + + /// Remove the specified kill index from this value's kills list. + /// Returns true if the value was present, otherwise returns false. + bool removeKill(LiveIndex k) { + KillSet::iterator i = std::lower_bound(kills.begin(), kills.end(), k); + if (i != kills.end() && *i == k) { + kills.erase(i); + return true; + } + return false; + } + + /// Remove all kills in the range [s, e). + void removeKills(LiveIndex s, LiveIndex e) { + KillSet::iterator + si = std::lower_bound(kills.begin(), kills.end(), s), + se = std::upper_bound(kills.begin(), kills.end(), e); + + kills.erase(si, se); + } + }; /// LiveRange structure - This represents a simple register range in the /// program, with an inclusive start point and an exclusive end point. /// These ranges are rendered as [start,end). struct LiveRange { - unsigned start; // Start point of the interval (inclusive) - unsigned end; // End point of the interval (exclusive) + LiveIndex start; // Start point of the interval (inclusive) + LiveIndex end; // End point of the interval (exclusive) VNInfo *valno; // identifier for the value contained in this interval. - LiveRange(unsigned S, unsigned E, VNInfo *V) : start(S), end(E), valno(V) { + LiveRange(LiveIndex S, LiveIndex E, VNInfo *V) + : start(S), end(E), valno(V) { + assert(S < E && "Cannot create empty or backwards range"); } /// contains - Return true if the index is covered by this range. /// - bool contains(unsigned I) const { + bool contains(LiveIndex I) const { return start <= I && I < end; } + /// containsRange - Return true if the given range, [S, E), is covered by + /// this range. + bool containsRange(LiveIndex S, LiveIndex E) const { + assert((S < E) && "Backwards interval?"); + return (start <= S && S < end) && (start < E && E <= end); + } + bool operator<(const LiveRange &LR) const { return start < LR.start || (start == LR.start && end < LR.end); } @@ -163,28 +452,29 @@ namespace llvm { } void dump() const; - void print(std::ostream &os) const; - void print(std::ostream *os) const { if (os) print(*os); } + void print(raw_ostream &os) const; private: LiveRange(); // DO NOT IMPLEMENT }; - std::ostream& operator<<(std::ostream& os, const LiveRange &LR); + raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR); - inline bool operator<(unsigned V, const LiveRange &LR) { + inline bool operator<(LiveIndex V, const LiveRange &LR) { return V < LR.start; } - inline bool operator<(const LiveRange &LR, unsigned V) { + inline bool operator<(const LiveRange &LR, LiveIndex V) { return LR.start < V; } /// LiveInterval - This class represents some number of live ranges for a /// register or value. This class also contains a bit of register allocator /// state. - struct LiveInterval { + class LiveInterval { + public: + typedef SmallVector<LiveRange,4> Ranges; typedef SmallVector<VNInfo*,4> VNInfoList; @@ -193,8 +483,6 @@ namespace llvm { float weight; // weight of this interval Ranges ranges; // the ranges in which this register is live VNInfoList valnos; // value#'s - - public: struct InstrSlots { enum { @@ -205,14 +493,6 @@ namespace llvm { NUM = 4 }; - static unsigned scale(unsigned slot, unsigned factor) { - unsigned index = slot / NUM, - offset = slot % NUM; - assert(index <= ~0U / (factor * NUM) && - "Rescaled interval would overflow"); - return index * NUM * factor + offset; - } - }; LiveInterval(unsigned Reg, float Weight, bool IsSS = false) @@ -242,8 +522,8 @@ namespace llvm { /// end of the interval. If no LiveRange contains this position, but the /// position is in a hole, this method returns an iterator pointing the the /// LiveRange immediately after the hole. - iterator advanceTo(iterator I, unsigned Pos) { - if (Pos >= endNumber()) + iterator advanceTo(iterator I, LiveIndex Pos) { + if (Pos >= endIndex()) return end(); while (I->end <= Pos) ++I; return I; @@ -286,33 +566,15 @@ namespace llvm { inline const VNInfo *getValNumInfo(unsigned ValNo) const { return valnos[ValNo]; } - - /// copyValNumInfo - Copy the value number info for one value number to - /// another. - void copyValNumInfo(VNInfo *DstValNo, const VNInfo *SrcValNo) { - DstValNo->def = SrcValNo->def; - DstValNo->copy = SrcValNo->copy; - DstValNo->setFlags(SrcValNo->getFlags()); - DstValNo->kills = SrcValNo->kills; - } /// getNextValue - Create a new value number and return it. MIIdx specifies /// the instruction that defines the value number. - VNInfo *getNextValue(unsigned MIIdx, MachineInstr *CopyMI, - bool isDefAccurate, BumpPtrAllocator &VNInfoAllocator) { - - assert(MIIdx != ~0u && MIIdx != ~1u && - "PHI def / unused flags should now be passed explicitly."); -#ifdef __GNUC__ - unsigned Alignment = (unsigned)__alignof__(VNInfo); -#else - // FIXME: ugly. - unsigned Alignment = 8; -#endif + VNInfo *getNextValue(LiveIndex def, MachineInstr *CopyMI, + bool isDefAccurate, BumpPtrAllocator &VNInfoAllocator){ VNInfo *VNI = static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo), - Alignment)); - new (VNI) VNInfo((unsigned)valnos.size(), MIIdx, CopyMI); + alignof<VNInfo>())); + new (VNI) VNInfo((unsigned)valnos.size(), def, CopyMI); VNI->setIsDefAccurate(isDefAccurate); valnos.push_back(VNI); return VNI; @@ -320,86 +582,31 @@ namespace llvm { /// Create a copy of the given value. The new value will be identical except /// for the Value number. - VNInfo *createValueCopy(const VNInfo *orig, BumpPtrAllocator &VNInfoAllocator) { - -#ifdef __GNUC__ - unsigned Alignment = (unsigned)__alignof__(VNInfo); -#else - // FIXME: ugly. - unsigned Alignment = 8; -#endif + VNInfo *createValueCopy(const VNInfo *orig, + BumpPtrAllocator &VNInfoAllocator) { VNInfo *VNI = static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo), - Alignment)); + alignof<VNInfo>())); new (VNI) VNInfo((unsigned)valnos.size(), *orig); valnos.push_back(VNI); return VNI; } - /// addKill - Add a kill instruction index to the specified value - /// number. - static void addKill(VNInfo *VNI, unsigned KillIdx) { - SmallVector<unsigned, 4> &kills = VNI->kills; - if (kills.empty()) { - kills.push_back(KillIdx); - } else { - SmallVector<unsigned, 4>::iterator - I = std::lower_bound(kills.begin(), kills.end(), KillIdx); - kills.insert(I, KillIdx); - } - } - /// addKills - Add a number of kills into the VNInfo kill vector. If this /// interval is live at a kill point, then the kill is not added. - void addKills(VNInfo *VNI, const SmallVector<unsigned, 4> &kills) { + void addKills(VNInfo *VNI, const VNInfo::KillSet &kills) { for (unsigned i = 0, e = static_cast<unsigned>(kills.size()); i != e; ++i) { - unsigned KillIdx = kills[i]; - if (!liveBeforeAndAt(KillIdx)) { - SmallVector<unsigned, 4>::iterator - I = std::lower_bound(VNI->kills.begin(), VNI->kills.end(), KillIdx); - VNI->kills.insert(I, KillIdx); + if (!liveBeforeAndAt(kills[i])) { + VNI->addKill(kills[i]); } } } - /// removeKill - Remove the specified kill from the list of kills of - /// the specified val#. - static bool removeKill(VNInfo *VNI, unsigned KillIdx) { - SmallVector<unsigned, 4> &kills = VNI->kills; - SmallVector<unsigned, 4>::iterator - I = std::lower_bound(kills.begin(), kills.end(), KillIdx); - if (I != kills.end() && *I == KillIdx) { - kills.erase(I); - return true; - } - return false; - } - - /// removeKills - Remove all the kills in specified range - /// [Start, End] of the specified val#. - static void removeKills(VNInfo *VNI, unsigned Start, unsigned End) { - SmallVector<unsigned, 4> &kills = VNI->kills; - SmallVector<unsigned, 4>::iterator - I = std::lower_bound(kills.begin(), kills.end(), Start); - SmallVector<unsigned, 4>::iterator - E = std::upper_bound(kills.begin(), kills.end(), End); - kills.erase(I, E); - } - - /// isKill - Return true if the specified index is a kill of the - /// specified val#. - static bool isKill(const VNInfo *VNI, unsigned KillIdx) { - const SmallVector<unsigned, 4> &kills = VNI->kills; - SmallVector<unsigned, 4>::const_iterator - I = std::lower_bound(kills.begin(), kills.end(), KillIdx); - return I != kills.end() && *I == KillIdx; - } - /// isOnlyLROfValNo - Return true if the specified live range is the only /// one defined by the its val#. - bool isOnlyLROfValNo( const LiveRange *LR) { + bool isOnlyLROfValNo(const LiveRange *LR) { for (const_iterator I = begin(), E = end(); I != E; ++I) { const LiveRange *Tmp = I; if (Tmp != LR && Tmp->valno == LR->valno) @@ -423,7 +630,8 @@ namespace llvm { /// MergeInClobberRange - Same as MergeInClobberRanges except it merge in a /// single LiveRange only. - void MergeInClobberRange(unsigned Start, unsigned End, + void MergeInClobberRange(LiveIndex Start, + LiveIndex End, BumpPtrAllocator &VNInfoAllocator); /// MergeValueInAsValue - Merge all of the live ranges of a specific val# @@ -448,51 +656,62 @@ namespace llvm { bool empty() const { return ranges.empty(); } - /// beginNumber - Return the lowest numbered slot covered by interval. - unsigned beginNumber() const { + /// beginIndex - Return the lowest numbered slot covered by interval. + LiveIndex beginIndex() const { if (empty()) - return 0; + return LiveIndex(); return ranges.front().start; } /// endNumber - return the maximum point of the interval of the whole, /// exclusive. - unsigned endNumber() const { + LiveIndex endIndex() const { if (empty()) - return 0; + return LiveIndex(); return ranges.back().end; } - bool expiredAt(unsigned index) const { - return index >= endNumber(); + bool expiredAt(LiveIndex index) const { + return index >= endIndex(); } - bool liveAt(unsigned index) const; + bool liveAt(LiveIndex index) const; // liveBeforeAndAt - Check if the interval is live at the index and the // index just before it. If index is liveAt, check if it starts a new live // range.If it does, then check if the previous live range ends at index-1. - bool liveBeforeAndAt(unsigned index) const; + bool liveBeforeAndAt(LiveIndex index) const; /// getLiveRangeContaining - Return the live range that contains the /// specified index, or null if there is none. - const LiveRange *getLiveRangeContaining(unsigned Idx) const { + const LiveRange *getLiveRangeContaining(LiveIndex Idx) const { const_iterator I = FindLiveRangeContaining(Idx); return I == end() ? 0 : &*I; } + /// getLiveRangeContaining - Return the live range that contains the + /// specified index, or null if there is none. + LiveRange *getLiveRangeContaining(LiveIndex Idx) { + iterator I = FindLiveRangeContaining(Idx); + return I == end() ? 0 : &*I; + } + /// FindLiveRangeContaining - Return an iterator to the live range that /// contains the specified index, or end() if there is none. - const_iterator FindLiveRangeContaining(unsigned Idx) const; + const_iterator FindLiveRangeContaining(LiveIndex Idx) const; /// FindLiveRangeContaining - Return an iterator to the live range that /// contains the specified index, or end() if there is none. - iterator FindLiveRangeContaining(unsigned Idx); + iterator FindLiveRangeContaining(LiveIndex Idx); + + /// findDefinedVNInfo - Find the by the specified + /// index (register interval) or defined + VNInfo *findDefinedVNInfoForRegInt(LiveIndex Idx) const; + + /// findDefinedVNInfo - Find the VNInfo that's defined by the specified + /// register (stack inteval only). + VNInfo *findDefinedVNInfoForStackInt(unsigned Reg) const; - /// findDefinedVNInfo - Find the VNInfo that's defined at the specified - /// index (register interval) or defined by the specified register (stack - /// inteval). - VNInfo *findDefinedVNInfo(unsigned DefIdxOrReg) const; /// overlaps - Return true if the intersection of the two live intervals is /// not empty. @@ -502,7 +721,7 @@ namespace llvm { /// overlaps - Return true if the live interval overlaps a range specified /// by [Start, End). - bool overlaps(unsigned Start, unsigned End) const; + bool overlaps(LiveIndex Start, LiveIndex End) const; /// overlapsFrom - Return true if the intersection of the two live intervals /// is not empty. The specified iterator is a hint that we can begin @@ -526,11 +745,12 @@ namespace llvm { /// isInOneLiveRange - Return true if the range specified is entirely in the /// a single LiveRange of the live interval. - bool isInOneLiveRange(unsigned Start, unsigned End); + bool isInOneLiveRange(LiveIndex Start, LiveIndex End); /// removeRange - Remove the specified range from this interval. Note that /// the range must be a single LiveRange in its entirety. - void removeRange(unsigned Start, unsigned End, bool RemoveDeadValNo = false); + void removeRange(LiveIndex Start, LiveIndex End, + bool RemoveDeadValNo = false); void removeRange(LiveRange LR, bool RemoveDeadValNo = false) { removeRange(LR.start, LR.end, RemoveDeadValNo); @@ -548,24 +768,30 @@ namespace llvm { /// unsigned getSize() const; + /// ComputeJoinedWeight - Set the weight of a live interval after + /// Other has been merged into it. + void ComputeJoinedWeight(const LiveInterval &Other); + bool operator<(const LiveInterval& other) const { - return beginNumber() < other.beginNumber(); + const LiveIndex &thisIndex = beginIndex(); + const LiveIndex &otherIndex = other.beginIndex(); + return (thisIndex < otherIndex || + (thisIndex == otherIndex && reg < other.reg)); } - void print(std::ostream &OS, const TargetRegisterInfo *TRI = 0) const; - void print(std::ostream *OS, const TargetRegisterInfo *TRI = 0) const { - if (OS) print(*OS, TRI); - } + void print(raw_ostream &OS, const TargetRegisterInfo *TRI = 0) const; void dump() const; private: + Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); - void extendIntervalEndTo(Ranges::iterator I, unsigned NewEnd); - Ranges::iterator extendIntervalStartTo(Ranges::iterator I, unsigned NewStr); + void extendIntervalEndTo(Ranges::iterator I, LiveIndex NewEnd); + Ranges::iterator extendIntervalStartTo(Ranges::iterator I, LiveIndex NewStr); LiveInterval& operator=(const LiveInterval& rhs); // DO NOT IMPLEMENT + }; - inline std::ostream &operator<<(std::ostream &OS, const LiveInterval &LI) { + inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { LI.print(OS); return OS; } diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 7ae98bb..511db6d 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -20,6 +20,7 @@ #ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H #define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/ADT/BitVector.h" @@ -39,13 +40,13 @@ namespace llvm { class TargetInstrInfo; class TargetRegisterClass; class VirtRegMap; - typedef std::pair<unsigned, MachineBasicBlock*> IdxMBBPair; + typedef std::pair<LiveIndex, MachineBasicBlock*> IdxMBBPair; - inline bool operator<(unsigned V, const IdxMBBPair &IM) { + inline bool operator<(LiveIndex V, const IdxMBBPair &IM) { return V < IM.first; } - inline bool operator<(const IdxMBBPair &IM, unsigned V) { + inline bool operator<(const IdxMBBPair &IM, LiveIndex V) { return IM.first < V; } @@ -70,7 +71,7 @@ namespace llvm { /// MBB2IdxMap - The indexes of the first and last instructions in the /// specified basic block. - std::vector<std::pair<unsigned, unsigned> > MBB2IdxMap; + std::vector<std::pair<LiveIndex, LiveIndex> > MBB2IdxMap; /// Idx2MBBMap - Sorted list of pairs of index of first instruction /// and MBB id. @@ -79,7 +80,7 @@ namespace llvm { /// FunctionSize - The number of instructions present in the function uint64_t FunctionSize; - typedef DenseMap<MachineInstr*, unsigned> Mi2IndexMap; + typedef DenseMap<const MachineInstr*, LiveIndex> Mi2IndexMap; Mi2IndexMap mi2iMap_; typedef std::vector<MachineInstr*> Index2MiMap; @@ -88,9 +89,16 @@ namespace llvm { typedef DenseMap<unsigned, LiveInterval*> Reg2IntervalMap; Reg2IntervalMap r2iMap_; + DenseMap<MachineBasicBlock*, LiveIndex> terminatorGaps; + + /// phiJoinCopies - Copy instructions which are PHI joins. + SmallVector<MachineInstr*, 16> phiJoinCopies; + + /// allocatableRegs_ - A bit vector of allocatable registers. BitVector allocatableRegs_; - std::vector<MachineInstr*> ClonedMIs; + /// CloneMIs - A list of clones as result of re-materialization. + std::vector<MachineInstr*> CloneMIs; typedef LiveInterval::InstrSlots InstrSlots; @@ -98,23 +106,40 @@ namespace llvm { static char ID; // Pass identification, replacement for typeid LiveIntervals() : MachineFunctionPass(&ID) {} - static unsigned getBaseIndex(unsigned index) { - return index - (index % InstrSlots::NUM); + LiveIndex getBaseIndex(LiveIndex index) { + return LiveIndex(index, LiveIndex::LOAD); + } + LiveIndex getBoundaryIndex(LiveIndex index) { + return LiveIndex(index, + (LiveIndex::Slot)(LiveIndex::NUM - 1)); + } + LiveIndex getLoadIndex(LiveIndex index) { + return LiveIndex(index, LiveIndex::LOAD); } - static unsigned getBoundaryIndex(unsigned index) { - return getBaseIndex(index + InstrSlots::NUM - 1); + LiveIndex getUseIndex(LiveIndex index) { + return LiveIndex(index, LiveIndex::USE); } - static unsigned getLoadIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::LOAD; + LiveIndex getDefIndex(LiveIndex index) { + return LiveIndex(index, LiveIndex::DEF); } - static unsigned getUseIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::USE; + LiveIndex getStoreIndex(LiveIndex index) { + return LiveIndex(index, LiveIndex::STORE); + } + + LiveIndex getNextSlot(LiveIndex m) const { + return m.nextSlot_(); + } + + LiveIndex getNextIndex(LiveIndex m) const { + return m.nextIndex_(); } - static unsigned getDefIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::DEF; + + LiveIndex getPrevSlot(LiveIndex m) const { + return m.prevSlot_(); } - static unsigned getStoreIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::STORE; + + LiveIndex getPrevIndex(LiveIndex m) const { + return m.prevIndex_(); } static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) { @@ -147,20 +172,20 @@ namespace llvm { /// getMBBStartIdx - Return the base index of the first instruction in the /// specified MachineBasicBlock. - unsigned getMBBStartIdx(MachineBasicBlock *MBB) const { + LiveIndex getMBBStartIdx(MachineBasicBlock *MBB) const { return getMBBStartIdx(MBB->getNumber()); } - unsigned getMBBStartIdx(unsigned MBBNo) const { + LiveIndex getMBBStartIdx(unsigned MBBNo) const { assert(MBBNo < MBB2IdxMap.size() && "Invalid MBB number!"); return MBB2IdxMap[MBBNo].first; } /// getMBBEndIdx - Return the store index of the last instruction in the /// specified MachineBasicBlock. - unsigned getMBBEndIdx(MachineBasicBlock *MBB) const { + LiveIndex getMBBEndIdx(MachineBasicBlock *MBB) const { return getMBBEndIdx(MBB->getNumber()); } - unsigned getMBBEndIdx(unsigned MBBNo) const { + LiveIndex getMBBEndIdx(unsigned MBBNo) const { assert(MBBNo < MBB2IdxMap.size() && "Invalid MBB number!"); return MBB2IdxMap[MBBNo].second; } @@ -181,7 +206,7 @@ namespace llvm { /// getMBBFromIndex - given an index in any instruction of an /// MBB return a pointer the MBB - MachineBasicBlock* getMBBFromIndex(unsigned index) const { + MachineBasicBlock* getMBBFromIndex(LiveIndex index) const { std::vector<IdxMBBPair>::const_iterator I = std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), index); // Take the pair containing the index @@ -189,14 +214,14 @@ namespace llvm { ((I != Idx2MBBMap.end() && I->first > index) || (I == Idx2MBBMap.end() && Idx2MBBMap.size()>0)) ? (I-1): I; - assert(J != Idx2MBBMap.end() && J->first < index+1 && + assert(J != Idx2MBBMap.end() && J->first <= index && index <= getMBBEndIdx(J->second) && "index does not correspond to an MBB"); return J->second; } /// getInstructionIndex - returns the base index of instr - unsigned getInstructionIndex(MachineInstr* instr) const { + LiveIndex getInstructionIndex(const MachineInstr* instr) const { Mi2IndexMap::const_iterator it = mi2iMap_.find(instr); assert(it != mi2iMap_.end() && "Invalid instruction!"); return it->second; @@ -204,48 +229,49 @@ namespace llvm { /// getInstructionFromIndex - given an index in any slot of an /// instruction return a pointer the instruction - MachineInstr* getInstructionFromIndex(unsigned index) const { - index /= InstrSlots::NUM; // convert index to vector index - assert(index < i2miMap_.size() && + MachineInstr* getInstructionFromIndex(LiveIndex index) const { + // convert index to vector index + unsigned i = index.getVecIndex(); + assert(i < i2miMap_.size() && "index does not correspond to an instruction"); - return i2miMap_[index]; + return i2miMap_[i]; } /// hasGapBeforeInstr - Return true if the previous instruction slot, /// i.e. Index - InstrSlots::NUM, is not occupied. - bool hasGapBeforeInstr(unsigned Index) { - Index = getBaseIndex(Index - InstrSlots::NUM); + bool hasGapBeforeInstr(LiveIndex Index) { + Index = getBaseIndex(getPrevIndex(Index)); return getInstructionFromIndex(Index) == 0; } /// hasGapAfterInstr - Return true if the successive instruction slot, /// i.e. Index + InstrSlots::Num, is not occupied. - bool hasGapAfterInstr(unsigned Index) { - Index = getBaseIndex(Index + InstrSlots::NUM); + bool hasGapAfterInstr(LiveIndex Index) { + Index = getBaseIndex(getNextIndex(Index)); return getInstructionFromIndex(Index) == 0; } /// findGapBeforeInstr - Find an empty instruction slot before the /// specified index. If "Furthest" is true, find one that's furthest /// away from the index (but before any index that's occupied). - unsigned findGapBeforeInstr(unsigned Index, bool Furthest = false) { - Index = getBaseIndex(Index - InstrSlots::NUM); + LiveIndex findGapBeforeInstr(LiveIndex Index, bool Furthest = false) { + Index = getBaseIndex(getPrevIndex(Index)); if (getInstructionFromIndex(Index)) - return 0; // No gap! + return LiveIndex(); // No gap! if (!Furthest) return Index; - unsigned PrevIndex = getBaseIndex(Index - InstrSlots::NUM); + LiveIndex PrevIndex = getBaseIndex(getPrevIndex(Index)); while (getInstructionFromIndex(Index)) { Index = PrevIndex; - PrevIndex = getBaseIndex(Index - InstrSlots::NUM); + PrevIndex = getBaseIndex(getPrevIndex(Index)); } return Index; } /// InsertMachineInstrInMaps - Insert the specified machine instruction /// into the instruction index map at the given index. - void InsertMachineInstrInMaps(MachineInstr *MI, unsigned Index) { - i2miMap_[Index / InstrSlots::NUM] = MI; + void InsertMachineInstrInMaps(MachineInstr *MI, LiveIndex Index) { + i2miMap_[Index.getVecIndex()] = MI; Mi2IndexMap::iterator it = mi2iMap_.find(MI); assert(it == mi2iMap_.end() && "Already in map!"); mi2iMap_[MI] = Index; @@ -265,12 +291,12 @@ namespace llvm { /// findLiveInMBBs - Given a live range, if the value of the range /// is live in any MBB returns true as well as the list of basic blocks /// in which the value is live. - bool findLiveInMBBs(unsigned Start, unsigned End, + bool findLiveInMBBs(LiveIndex Start, LiveIndex End, SmallVectorImpl<MachineBasicBlock*> &MBBs) const; /// findReachableMBBs - Return a list MBB that can be reached via any /// branch or fallthroughs. Return true if the list is not empty. - bool findReachableMBBs(unsigned Start, unsigned End, + bool findReachableMBBs(LiveIndex Start, LiveIndex End, SmallVectorImpl<MachineBasicBlock*> &MBBs) const; // Interval creation @@ -289,7 +315,7 @@ namespace llvm { /// addLiveRangeToEndOfBlock - Given a register and an instruction, /// adds a live range from that instruction to the end of its MBB. LiveRange addLiveRangeToEndOfBlock(unsigned reg, - MachineInstr* startInst); + MachineInstr* startInst); // Interval removal @@ -312,7 +338,7 @@ namespace llvm { // MachineInstr -> index mappings Mi2IndexMap::iterator mi2i = mi2iMap_.find(MI); if (mi2i != mi2iMap_.end()) { - i2miMap_[mi2i->second/InstrSlots::NUM] = 0; + i2miMap_[mi2i->second.index/InstrSlots::NUM] = 0; mi2iMap_.erase(mi2i); } } @@ -323,10 +349,10 @@ namespace llvm { Mi2IndexMap::iterator mi2i = mi2iMap_.find(MI); if (mi2i == mi2iMap_.end()) return; - i2miMap_[mi2i->second/InstrSlots::NUM] = NewMI; + i2miMap_[mi2i->second.index/InstrSlots::NUM] = NewMI; Mi2IndexMap::iterator it = mi2iMap_.find(MI); assert(it != mi2iMap_.end() && "Invalid instruction!"); - unsigned Index = it->second; + LiveIndex Index = it->second; mi2iMap_.erase(it); mi2iMap_[NewMI] = Index; } @@ -344,10 +370,7 @@ namespace llvm { virtual bool runOnMachineFunction(MachineFunction&); /// print - Implement the dump method. - virtual void print(std::ostream &O, const Module* = 0) const; - void print(std::ostream *O, const Module* M = 0) const { - if (O) print(*O, M); - } + virtual void print(raw_ostream &O, const Module* = 0) const; /// addIntervalsForSpills - Create new intervals for spilled defs / uses of /// the given interval. FIXME: It also returns the weight of the spill slot @@ -408,32 +431,40 @@ namespace llvm { private: /// computeIntervals - Compute live intervals. void computeIntervals(); - + + bool isProfitableToCoalesce(LiveInterval &DstInt, LiveInterval &SrcInt, + SmallVector<MachineInstr*,16> &IdentCopies, + SmallVector<MachineInstr*,16> &OtherCopies); + + void performEarlyCoalescing(); + /// handleRegisterDef - update intervals for a register def /// (calls handlePhysicalRegisterDef and /// handleVirtualRegisterDef) void handleRegisterDef(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MI, unsigned MIIdx, + MachineBasicBlock::iterator MI, + LiveIndex MIIdx, MachineOperand& MO, unsigned MOIdx); /// handleVirtualRegisterDef - update intervals for a virtual /// register def void handleVirtualRegisterDef(MachineBasicBlock *MBB, MachineBasicBlock::iterator MI, - unsigned MIIdx, MachineOperand& MO, - unsigned MOIdx, LiveInterval& interval); + LiveIndex MIIdx, MachineOperand& MO, + unsigned MOIdx, + LiveInterval& interval); /// handlePhysicalRegisterDef - update intervals for a physical register /// def. void handlePhysicalRegisterDef(MachineBasicBlock* mbb, MachineBasicBlock::iterator mi, - unsigned MIIdx, MachineOperand& MO, + LiveIndex MIIdx, MachineOperand& MO, LiveInterval &interval, MachineInstr *CopyMI); /// handleLiveInRegister - Create interval for a livein register. void handleLiveInRegister(MachineBasicBlock* mbb, - unsigned MIIdx, + LiveIndex MIIdx, LiveInterval &interval, bool isAlias = false); /// getReMatImplicitUse - If the remat definition MI has one (for now, we @@ -446,7 +477,7 @@ namespace llvm { /// which reaches the given instruction also reaches the specified use /// index. bool isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI, - unsigned UseIdx) const; + LiveIndex UseIdx) const; /// isReMaterializable - Returns true if the definition MI of the specified /// val# of the specified interval is re-materializable. Also returns true @@ -461,9 +492,9 @@ namespace llvm { /// MI. If it is successul, MI is updated with the newly created MI and /// returns true. bool tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm, - MachineInstr *DefMI, unsigned InstrIdx, + MachineInstr *DefMI, LiveIndex InstrIdx, SmallVector<unsigned, 2> &Ops, - bool isSS, int Slot, unsigned Reg); + bool isSS, int FrameIndex, unsigned Reg); /// canFoldMemoryOperand - Return true if the specified load / store /// folding is possible. @@ -474,7 +505,8 @@ namespace llvm { /// anyKillInMBBAfterIdx - Returns true if there is a kill of the specified /// VNInfo that's after the specified index but is within the basic block. bool anyKillInMBBAfterIdx(const LiveInterval &li, const VNInfo *VNI, - MachineBasicBlock *MBB, unsigned Idx) const; + MachineBasicBlock *MBB, + LiveIndex Idx) const; /// hasAllocatableSuperReg - Return true if the specified physical register /// has any super register that's allocatable. @@ -482,16 +514,17 @@ namespace llvm { /// SRInfo - Spill / restore info. struct SRInfo { - int index; + LiveIndex index; unsigned vreg; bool canFold; - SRInfo(int i, unsigned vr, bool f) : index(i), vreg(vr), canFold(f) {}; + SRInfo(LiveIndex i, unsigned vr, bool f) + : index(i), vreg(vr), canFold(f) {} }; - bool alsoFoldARestore(int Id, int index, unsigned vr, + bool alsoFoldARestore(int Id, LiveIndex index, unsigned vr, BitVector &RestoreMBBs, DenseMap<unsigned,std::vector<SRInfo> >&RestoreIdxes); - void eraseRestoreInfo(int Id, int index, unsigned vr, + void eraseRestoreInfo(int Id, LiveIndex index, unsigned vr, BitVector &RestoreMBBs, DenseMap<unsigned,std::vector<SRInfo> >&RestoreIdxes); @@ -510,8 +543,9 @@ namespace llvm { /// functions for addIntervalsForSpills to rewrite uses / defs for the given /// live range. bool rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI, - bool TrySplit, unsigned index, unsigned end, MachineInstr *MI, - MachineInstr *OrigDefMI, MachineInstr *DefMI, unsigned Slot, int LdSlot, + bool TrySplit, LiveIndex index, LiveIndex end, + MachineInstr *MI, MachineInstr *OrigDefMI, MachineInstr *DefMI, + unsigned Slot, int LdSlot, bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, VirtRegMap &vrm, const TargetRegisterClass* rc, SmallVector<int, 4> &ReMatIds, const MachineLoopInfo *loopInfo, @@ -533,9 +567,9 @@ namespace llvm { static LiveInterval* createInterval(unsigned Reg); - void printRegName(unsigned reg) const; + void printInstrs(raw_ostream &O) const; + void dumpInstrs() const; }; - } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h index 27ae1be..d63a222 100644 --- a/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/include/llvm/CodeGen/LiveStackAnalysis.h @@ -102,10 +102,7 @@ namespace llvm { virtual bool runOnMachineFunction(MachineFunction&); /// print - Implement the dump method. - virtual void print(std::ostream &O, const Module* = 0) const; - void print(std::ostream *O, const Module* M = 0) const { - if (O) print(*O, M); - } + virtual void print(raw_ostream &O, const Module* = 0) const; }; } diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index 26c0362..172fb75 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -29,9 +29,12 @@ #ifndef LLVM_CODEGEN_LIVEVARIABLES_H #define LLVM_CODEGEN_LIVEVARIABLES_H +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseBitVector.h" @@ -146,16 +149,14 @@ private: // Intermediate data structures bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); - void HandlePhysRegDef(unsigned Reg, MachineInstr *MI); + void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + SmallVector<unsigned, 4> &Defs); + void UpdatePhysRegDefs(MachineInstr *MI, SmallVector<unsigned, 4> &Defs); /// FindLastPartialDef - Return the last partial def of the specified register. - /// Also returns the sub-register that's defined. - MachineInstr *FindLastPartialDef(unsigned Reg, unsigned &PartDefReg); - - /// hasRegisterUseBelow - Return true if the specified register is used after - /// the current instruction and before it's next definition. - bool hasRegisterUseBelow(unsigned Reg, MachineBasicBlock::iterator I, - MachineBasicBlock *MBB); + /// Also returns the sub-registers that're defined by the instruction. + MachineInstr *FindLastPartialDef(unsigned Reg, + SmallSet<unsigned,4> &PartDefRegs); /// analyzePHINodes - Gather information about the PHI nodes in here. In /// particular, we want to map the variable information of a virtual diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 134d226..2a9e86a 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -16,17 +16,17 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/Support/Streams.h" namespace llvm { class BasicBlock; class MachineFunction; +class raw_ostream; template <> struct ilist_traits<MachineInstr> : public ilist_default_traits<MachineInstr> { private: - mutable ilist_node<MachineInstr> Sentinel; + mutable ilist_half_node<MachineInstr> Sentinel; // this is only set by the MachineBasicBlock owning the LiveList friend class MachineBasicBlock; @@ -310,8 +310,7 @@ public: // Debugging methods. void dump() const; - void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + void print(raw_ostream &OS) const; /// getNumber - MachineBasicBlocks are uniquely numbered at the function /// level, unless they're not in a MachineFunction yet, in which case this @@ -339,7 +338,7 @@ private: // Methods used to maintain doubly linked list of blocks... void removePredecessor(MachineBasicBlock *pred); }; -std::ostream& operator<<(std::ostream &OS, const MachineBasicBlock &MBB); +raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB); //===--------------------------------------------------------------------===// // GraphTraits specializations for machine basic block graphs (machine-CFGs) diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h index eb1ea2d..abb6dd9 100644 --- a/include/llvm/CodeGen/MachineCodeEmitter.h +++ b/include/llvm/CodeGen/MachineCodeEmitter.h @@ -18,6 +18,7 @@ #define LLVM_CODEGEN_MACHINECODEEMITTER_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/DebugLoc.h" namespace llvm { @@ -74,24 +75,6 @@ public: /// false. /// virtual bool finishFunction(MachineFunction &F) = 0; - - /// startGVStub - This callback is invoked when the JIT needs the - /// address of a GV (e.g. function) that has not been code generated yet. - /// The StubSize specifies the total size required by the stub. - /// - virtual void startGVStub(const GlobalValue* GV, unsigned StubSize, - unsigned Alignment = 1) = 0; - - /// startGVStub - This callback is invoked when the JIT needs the address of a - /// GV (e.g. function) that has not been code generated yet. Buffer points to - /// memory already allocated for this stub. - /// - virtual void startGVStub(const GlobalValue* GV, void *Buffer, - unsigned StubSize) = 0; - - /// finishGVStub - This callback is invoked to terminate a GV stub. - /// - virtual void *finishGVStub(const GlobalValue* F) = 0; /// emitByte - This callback is invoked when a byte needs to be written to the /// output stream. @@ -250,7 +233,12 @@ public: (*(uint64_t*)Addr) = (uint64_t)Value; } - + /// processDebugLoc - Records debug location information about a + /// MachineInstruction. This is called before emitting any bytes associated + /// with the instruction. Even if successive instructions have the same debug + /// location, this method will be called for each one. + virtual void processDebugLoc(DebugLoc DL, bool BeforePrintintInsn) {} + /// emitLabel - Emits a label virtual void emitLabel(uint64_t LabelID) = 0; @@ -288,14 +276,20 @@ public: /// getCurrentPCOffset - Return the offset from the start of the emitted /// buffer that we are currently writing to. - uintptr_t getCurrentPCOffset() const { + virtual uintptr_t getCurrentPCOffset() const { return CurBufferPtr-BufferBegin; } + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + virtual bool earlyResolveAddresses() const = 0; + /// addRelocation - Whenever a relocatable address is needed, it should be /// noted with this interface. virtual void addRelocation(const MachineRelocation &MR) = 0; - /// FIXME: These should all be handled with relocations! diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index 99996cf..8d6c1d1 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -41,8 +41,15 @@ public: /// getType - get type of this MachineConstantPoolValue. /// - inline const Type *getType() const { return Ty; } + const Type *getType() const { return Ty; } + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are the same as Constant::getRelocationInfo(). + virtual unsigned getRelocationInfo() const = 0; + virtual int getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment) = 0; @@ -82,7 +89,7 @@ public: MachineConstantPoolEntry(MachineConstantPoolValue *V, unsigned A) : Alignment(A) { Val.MachineCPVal = V; - Alignment |= 1 << (sizeof(unsigned)*CHAR_BIT-1); + Alignment |= 1U << (sizeof(unsigned)*CHAR_BIT-1); } bool isMachineConstantPoolEntry() const { @@ -94,6 +101,19 @@ public: } const Type *getType() const; + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are: + /// + /// 0: This constant pool entry is guaranteed to never have a relocation + /// applied to it (because it holds a simple constant like '4'). + /// 1: This entry has relocations, but the entries are guaranteed to be + /// resolvable by the static linker, so the dynamic linker will never see + /// them. + /// 2: This entry may have arbitrary relocations. + unsigned getRelocationInfo() const; }; /// The MachineConstantPool class keeps track of constants referenced by a diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 5981e5a..e56776b 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -15,13 +15,15 @@ #ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H #define LLVM_CODEGEN_MACHINEDOMINATORS_H +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/DominatorInternals.h" namespace llvm { -inline void WriteAsOperand(std::ostream &, const MachineBasicBlock*, bool t) { } +inline void WriteAsOperand(raw_ostream &, const MachineBasicBlock*, bool t) { } template<> inline void DominatorTreeBase<MachineBasicBlock>::addRoot(MachineBasicBlock* MBB) { @@ -160,9 +162,7 @@ public: virtual void releaseMemory(); - virtual void print(std::ostream &OS, const Module* M= 0) const { - DT->print(OS, M); - } + virtual void print(raw_ostream &OS, const Module*) const; }; //===------------------------------------- diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 4c981f7..b5479ba 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -14,17 +14,20 @@ #ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H #define LLVM_CODEGEN_MACHINEFRAMEINFO_H +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Support/DataTypes.h" #include <cassert> -#include <iosfwd> #include <vector> namespace llvm { +class raw_ostream; class TargetData; class TargetRegisterClass; class Type; class MachineModuleInfo; class MachineFunction; +class MachineBasicBlock; class TargetFrameInfo; /// The CalleeSavedInfo class tracks the information need to locate where a @@ -130,11 +133,14 @@ class MachineFrameInfo { uint64_t StackSize; /// OffsetAdjustment - The amount that a frame offset needs to be adjusted to - /// have the actual offset from the stack/frame pointer. The calculation is - /// MFI->getObjectOffset(Index) + StackSize - TFI.getOffsetOfLocalArea() + - /// OffsetAdjustment. If OffsetAdjustment is zero (default) then offsets are - /// away from TOS. If OffsetAdjustment == StackSize then offsets are toward - /// TOS. + /// have the actual offset from the stack/frame pointer. The exact usage of + /// this is target-dependent, but it is typically used to adjust between + /// SP-relative and FP-relative offsets. E.G., if objects are accessed via + /// SP then OffsetAdjustment is zero; if FP is used, OffsetAdjustment is set + /// to the distance between the initial SP and the value in FP. For many + /// targets, this value is only used when generating debug info (via + /// TargetRegisterInfo::getFrameIndexOffset); when generating code, the + /// corresponding adjustments are performed directly. int OffsetAdjustment; /// MaxAlignment - The prolog/epilog code inserter may process objects @@ -166,7 +172,10 @@ class MachineFrameInfo { /// epilog code inserter, this data used for debug info and exception /// handling. std::vector<CalleeSavedInfo> CSInfo; - + + /// CSIValid - Has CSInfo been set yet? + bool CSIValid; + /// MMI - This field is set (via setMachineModuleInfo) by a module info /// consumer (ex. DwarfWriter) to indicate that frame layout information /// should be acquired. Typically, it's the responsibility of the target's @@ -185,6 +194,7 @@ public: HasCalls = false; StackProtectorIdx = -1; MaxCallFrameSize = 0; + CSIValid = false; MMI = 0; } @@ -389,6 +399,22 @@ public: CSInfo = CSI; } + /// isCalleeSavedInfoValid - Has the callee saved info been calculated yet? + bool isCalleeSavedInfoValid() const { return CSIValid; } + + void setCalleeSavedInfoValid(bool v) { CSIValid = v; } + + /// getPristineRegs - Return a set of physical registers that are pristine on + /// entry to the MBB. + /// + /// Pristine registers hold a value that is useless to the current function, + /// but that must be preserved - they are callee saved registers that have not + /// been saved yet. + /// + /// Before the PrologueEpilogueInserter has placed the CSR spill code, this + /// method always returns an empty set. + BitVector getPristineRegs(const MachineBasicBlock *MBB) const; + /// getMachineModuleInfo - Used by a prologue/epilogue /// emitter (TargetRegisterInfo) to provide frame layout information. MachineModuleInfo *getMachineModuleInfo() const { return MMI; } @@ -400,9 +426,9 @@ public: /// print - Used by the MachineFunction printer to print information about /// stack objects. Implemented in MachineFunction.cpp /// - void print(const MachineFunction &MF, std::ostream &OS) const; + void print(const MachineFunction &MF, raw_ostream &OS) const; - /// dump - Call print(MF, std::cerr) to be called from the debugger. + /// dump - Print the function to stderr. void dump(const MachineFunction &MF) const; }; diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index ea6a384..ba831ca 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -18,15 +18,16 @@ #ifndef LLVM_CODEGEN_MACHINEFUNCTION_H #define LLVM_CODEGEN_MACHINEFUNCTION_H +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/ilist.h" #include "llvm/Support/DebugLoc.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Support/Annotation.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Recycler.h" +#include <map> namespace llvm { +class Value; class Function; class MachineRegisterInfo; class MachineFrameInfo; @@ -38,7 +39,7 @@ class TargetRegisterClass; template <> struct ilist_traits<MachineBasicBlock> : public ilist_default_traits<MachineBasicBlock> { - mutable ilist_node<MachineBasicBlock> Sentinel; + mutable ilist_half_node<MachineBasicBlock> Sentinel; public: MachineBasicBlock *createSentinel() const { return static_cast<MachineBasicBlock*>(&Sentinel); @@ -63,11 +64,11 @@ private: /// of type are accessed/created with MF::getInfo and destroyed when the /// MachineFunction is destroyed. struct MachineFunctionInfo { - virtual ~MachineFunctionInfo() {} + virtual ~MachineFunctionInfo(); }; -class MachineFunction : private Annotation { - const Function *Fn; +class MachineFunction { + Function *Fn; const TargetMachine &Target; // RegInfo - Information about each register in use in the function. @@ -115,12 +116,12 @@ class MachineFunction : private Annotation { unsigned Alignment; public: - MachineFunction(const Function *Fn, const TargetMachine &TM); + MachineFunction(Function *Fn, const TargetMachine &TM); ~MachineFunction(); /// getFunction - Return the LLVM function that this machine code represents /// - const Function *getFunction() const { return Fn; } + Function *getFunction() const { return Fn; } /// getTarget - Return the target machine this machine code is compiled with /// @@ -159,8 +160,8 @@ public: /// void setAlignment(unsigned A) { Alignment = A; } - /// MachineFunctionInfo - Keep track of various per-function pieces of - /// information for backends that would like to do so. + /// getInfo - Keep track of various per-function pieces of information for + /// backends that would like to do so. /// template<typename Ty> Ty *getInfo() { @@ -207,8 +208,7 @@ public: /// print - Print out the MachineFunction in a format suitable for debugging /// to the specified stream. /// - void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + void print(raw_ostream &OS) const; /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the @@ -229,21 +229,6 @@ public: /// void dump() const; - /// construct - Allocate and initialize a MachineFunction for a given Function - /// and Target - /// - static MachineFunction& construct(const Function *F, const TargetMachine &TM); - - /// destruct - Destroy the MachineFunction corresponding to a given Function - /// - static void destruct(const Function *F); - - /// get - Return a handle to a MachineFunction corresponding to the given - /// Function. This should not be called before "construct()" for a given - /// Function. - /// - static MachineFunction& get(const Function *F); - // Provide accessors for the MachineBasicBlock list... typedef BasicBlockListType::iterator iterator; typedef BasicBlockListType::const_iterator const_iterator; @@ -336,16 +321,42 @@ public: /// void DeleteMachineBasicBlock(MachineBasicBlock *MBB); + /// getMachineMemOperand - Allocate a new MachineMemOperand. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const Value *v, unsigned f, + int64_t o, uint64_t s, + unsigned base_alignment); + + /// getMachineMemOperand - Allocate a new MachineMemOperand by copying + /// an existing one, adjusting by an offset and using the given size. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + int64_t Offset, uint64_t Size); + + /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand + /// pointers. This array is owned by the MachineFunction. + MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num); + + /// extractLoadMemRefs - Allocate an array and populate it with just the + /// load information from the given MachineMemOperand sequence. + std::pair<MachineInstr::mmo_iterator, + MachineInstr::mmo_iterator> + extractLoadMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End); + + /// extractStoreMemRefs - Allocate an array and populate it with just the + /// store information from the given MachineMemOperand sequence. + std::pair<MachineInstr::mmo_iterator, + MachineInstr::mmo_iterator> + extractStoreMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End); + //===--------------------------------------------------------------------===// // Debug location. // - /// getOrCreateDebugLocID - Look up the DebugLocTuple index with the given - /// source file, line, and column. If none currently exists, create a new - /// DebugLocTuple, and insert it into the DebugIdMap. - unsigned getOrCreateDebugLocID(GlobalVariable *CompileUnit, - unsigned Line, unsigned Col); - /// getDebugLocTuple - Get the DebugLocTuple for a given DebugLoc object. DebugLocTuple getDebugLocTuple(DebugLoc DL) const; diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h new file mode 100644 index 0000000..d020a7b --- /dev/null +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -0,0 +1,49 @@ +//===-- MachineFunctionAnalysis.h - Owner of MachineFunctions ----*-C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MachineFunctionAnalysis class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H +#define LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H + +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class MachineFunction; + +/// MachineFunctionAnalysis - This class is a Pass that manages a +/// MachineFunction object. +struct MachineFunctionAnalysis : public FunctionPass { +private: + const TargetMachine &TM; + CodeGenOpt::Level OptLevel; + MachineFunction *MF; + +public: + static char ID; + explicit MachineFunctionAnalysis(TargetMachine &tm, + CodeGenOpt::Level OL = CodeGenOpt::Default); + ~MachineFunctionAnalysis(); + + MachineFunction &getMF() const { return *MF; } + CodeGenOpt::Level getOptLevel() const { return OptLevel; } + +private: + virtual bool runOnFunction(Function &F); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h index 6b5e64a..bac1103 100644 --- a/include/llvm/CodeGen/MachineFunctionPass.h +++ b/include/llvm/CodeGen/MachineFunctionPass.h @@ -20,23 +20,34 @@ #define LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H #include "llvm/Pass.h" -#include "llvm/CodeGen/MachineFunction.h" namespace llvm { - // FIXME: This pass should declare that the pass does not invalidate any LLVM - // passes. -struct MachineFunctionPass : public FunctionPass { +class MachineFunction; + +/// MachineFunctionPass - This class adapts the FunctionPass interface to +/// allow convenient creation of passes that operate on the MachineFunction +/// representation. Instead of overriding runOnFunction, subclasses +/// override runOnMachineFunction. +class MachineFunctionPass : public FunctionPass { +protected: explicit MachineFunctionPass(intptr_t ID) : FunctionPass(ID) {} explicit MachineFunctionPass(void *ID) : FunctionPass(ID) {} -protected: /// runOnMachineFunction - This method must be overloaded to perform the /// desired machine code transformation or analysis. /// virtual bool runOnMachineFunction(MachineFunction &MF) = 0; -public: + /// getAnalysisUsage - Subclasses that override getAnalysisUsage + /// must call this. + /// + /// For MachineFunctionPasses, calling AU.preservesCFG() indicates that + /// the pass does not modify the MachineBasicBlock CFG. + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +private: bool runOnFunction(Function &F); }; diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 2b2f24a..de22710 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -20,29 +20,34 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/Target/TargetInstrDesc.h" #include "llvm/Support/DebugLoc.h" -#include <list> #include <vector> namespace llvm { +class AliasAnalysis; class TargetInstrDesc; class TargetInstrInfo; class TargetRegisterInfo; class MachineFunction; +class MachineMemOperand; //===----------------------------------------------------------------------===// /// MachineInstr - Representation of each machine instruction. /// class MachineInstr : public ilist_node<MachineInstr> { +public: + typedef MachineMemOperand **mmo_iterator; + +private: const TargetInstrDesc *TID; // Instruction descriptor. unsigned short NumImplicitOps; // Number of implicit operands (which // are determined at construction time). std::vector<MachineOperand> Operands; // the operands - std::list<MachineMemOperand> MemOperands; // information on memory references + mmo_iterator MemRefs; // information on memory references + mmo_iterator MemRefsEnd; MachineBasicBlock *Parent; // Pointer to the owning basic block. DebugLoc debugLoc; // Source line information. @@ -132,21 +137,14 @@ public: unsigned getNumExplicitOperands() const; /// Access to memory operands of the instruction - std::list<MachineMemOperand>::iterator memoperands_begin() - { return MemOperands.begin(); } - std::list<MachineMemOperand>::iterator memoperands_end() - { return MemOperands.end(); } - std::list<MachineMemOperand>::const_iterator memoperands_begin() const - { return MemOperands.begin(); } - std::list<MachineMemOperand>::const_iterator memoperands_end() const - { return MemOperands.end(); } - bool memoperands_empty() const { return MemOperands.empty(); } + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } /// hasOneMemOperand - Return true if this instruction has exactly one /// MachineMemOperand. bool hasOneMemOperand() const { - return !memoperands_empty() && - next(memoperands_begin()) == memoperands_end(); + return MemRefsEnd - MemRefs == 1; } /// isIdenticalTo - Return true if this instruction is identical to (same @@ -208,7 +206,7 @@ public: } /// findRegisterUseOperandIdx() - Returns the operand index that is a use of - /// the specific register or -1 if it is not found. It further tightening + /// the specific register or -1 if it is not found. It further tightens /// the search criteria to a use that kills the register if isKill is true. int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false, const TargetRegisterInfo *TRI = NULL) const; @@ -277,11 +275,13 @@ public: /// isSafeToMove - Return true if it is safe to move this instruction. If /// SawStore is set to true, it means that there is a store (or call) between /// the instruction's location and its intended destination. - bool isSafeToMove(const TargetInstrInfo *TII, bool &SawStore) const; + bool isSafeToMove(const TargetInstrInfo *TII, bool &SawStore, + AliasAnalysis *AA) const; /// isSafeToReMat - Return true if it's safe to rematerialize the specified /// instruction which defined the specified register instead of copying it. - bool isSafeToReMat(const TargetInstrInfo *TII, unsigned DstReg) const; + bool isSafeToReMat(const TargetInstrInfo *TII, unsigned DstReg, + AliasAnalysis *AA) const; /// hasVolatileMemoryRef - Return true if this instruction may have a /// volatile memory reference, or if the information describing the @@ -289,19 +289,17 @@ public: /// have no volatile memory references. bool hasVolatileMemoryRef() const; + /// isInvariantLoad - Return true if this instruction is loading from a + /// location whose value is invariant across the function. For example, + /// loading a value from the constant pool or from from the argument area of + /// a function if it does not change. This should only return true of *all* + /// loads the instruction does are invariant (if it does multiple loads). + bool isInvariantLoad(AliasAnalysis *AA) const; + // // Debugging support // - void print(std::ostream *OS, const TargetMachine *TM) const { - if (OS) print(*OS, TM); - } - void print(std::ostream &OS, const TargetMachine *TM = 0) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } - void print(raw_ostream *OS, const TargetMachine *TM) const { - if (OS) print(*OS, TM); - } void print(raw_ostream &OS, const TargetMachine *TM = 0) const; - void print(raw_ostream *OS) const { if (OS) print(*OS); } void dump() const; //===--------------------------------------------------------------------===// @@ -328,13 +326,17 @@ public: /// void RemoveOperand(unsigned i); - /// addMemOperand - Add a MachineMemOperand to the machine instruction, - /// referencing arbitrary storage. - void addMemOperand(MachineFunction &MF, - const MachineMemOperand &MO); + /// addMemOperand - Add a MachineMemOperand to the machine instruction. + /// This function should be used only occasionally. The setMemRefs function + /// is the primary method for setting up a MachineInstr's MemRefs list. + void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); - /// clearMemOperands - Erase all of this MachineInstr's MachineMemOperands. - void clearMemOperands(MachineFunction &MF); + /// setMemRefs - Assign this MachineInstr's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } private: /// getRegInfo - If this instruction is embedded into a MachineFunction, @@ -360,11 +362,6 @@ private: //===----------------------------------------------------------------------===// // Debugging Support -inline std::ostream& operator<<(std::ostream &OS, const MachineInstr &MI) { - MI.print(OS); - return OS; -} - inline raw_ostream& operator<<(raw_ostream &OS, const MachineInstr &MI) { MI.print(OS); return OS; diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index c6a6679..7f681d7 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -39,6 +39,7 @@ namespace RegState { class MachineInstrBuilder { MachineInstr *MI; public: + MachineInstrBuilder() : MI(0) {} explicit MachineInstrBuilder(MachineInstr *mi) : MI(mi) {} /// Allow automatic conversion to the machine instruction we are working on. @@ -108,20 +109,19 @@ public: } const MachineInstrBuilder &addMetadata(MDNode *N, - int64_t Offset = 0, - unsigned char TargetFlags = 0) const { + int64_t Offset = 0, + unsigned char TargetFlags = 0) const { MI->addOperand(MachineOperand::CreateMDNode(N, Offset, TargetFlags)); return *this; } const MachineInstrBuilder &addExternalSymbol(const char *FnName, - int64_t Offset = 0, unsigned char TargetFlags = 0) const { - MI->addOperand(MachineOperand::CreateES(FnName, Offset, TargetFlags)); + MI->addOperand(MachineOperand::CreateES(FnName, TargetFlags)); return *this; } - const MachineInstrBuilder &addMemOperand(const MachineMemOperand &MMO) const { + const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { MI->addMemOperand(*MI->getParent()->getParent(), MMO); return *this; } @@ -191,7 +191,7 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, /// BuildMI - This version of the builder inserts the newly-built /// instruction at the end of the given MachineBasicBlock, and sets up the first -/// operand as a destination virtual register. +/// operand as a destination virtual register. /// inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, DebugLoc DL, diff --git a/include/llvm/CodeGen/MachineJumpTableInfo.h b/include/llvm/CodeGen/MachineJumpTableInfo.h index 56e2e54..3ff2f2e 100644 --- a/include/llvm/CodeGen/MachineJumpTableInfo.h +++ b/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -21,13 +21,13 @@ #define LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H #include <vector> -#include <iosfwd> #include <cassert> namespace llvm { class MachineBasicBlock; class TargetData; +class raw_ostream; /// MachineJumpTableEntry - One jump table in the jump table info. /// @@ -79,10 +79,9 @@ public: /// print - Used by the MachineFunction printer to print information about /// jump tables. Implemented in MachineFunction.cpp /// - void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + void print(raw_ostream &OS) const; - /// dump - Call print(std::cerr) to be called from the debugger. + /// dump - Call to stderr. /// void dump() const; }; diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 2d19d7a..65ad4e4 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -35,48 +35,23 @@ namespace llvm { -// Provide overrides for Loop methods that don't make sense for machine loops. -template<> inline -PHINode *LoopBase<MachineBasicBlock>::getCanonicalInductionVariable() const { - assert(0 && "getCanonicalInductionVariable not supported for machine loops!"); - return 0; -} - -template<> inline Instruction* -LoopBase<MachineBasicBlock>::getCanonicalInductionVariableIncrement() const { - assert(0 && - "getCanonicalInductionVariableIncrement not supported for machine loops!"); - return 0; -} - -template<> -inline bool LoopBase<MachineBasicBlock>::isLoopInvariant(Value *V) const { - assert(0 && "isLoopInvariant not supported for machine loops!"); - return false; -} - -template<> -inline Value *LoopBase<MachineBasicBlock>::getTripCount() const { - assert(0 && "getTripCount not supported for machine loops!"); - return 0; -} - -template<> -inline bool LoopBase<MachineBasicBlock>::isLCSSAForm() const { - assert(0 && "isLCSSAForm not supported for machine loops"); - return false; -} - -typedef LoopBase<MachineBasicBlock> MachineLoop; +class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> { +public: + MachineLoop(); +private: + friend class LoopInfoBase<MachineBasicBlock, MachineLoop>; + explicit MachineLoop(MachineBasicBlock *MBB) + : LoopBase<MachineBasicBlock, MachineLoop>(MBB) {} +}; class MachineLoopInfo : public MachineFunctionPass { - LoopInfoBase<MachineBasicBlock> LI; - friend class LoopBase<MachineBasicBlock>; + LoopInfoBase<MachineBasicBlock, MachineLoop> LI; + friend class LoopBase<MachineBasicBlock, MachineLoop>; void operator=(const MachineLoopInfo &); // do not implement MachineLoopInfo(const MachineLoopInfo &); // do not implement - LoopInfoBase<MachineBasicBlock>& getBase() { return LI; } + LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; } public: static char ID; // Pass identification, replacement for typeid @@ -86,7 +61,7 @@ public: /// iterator/begin/end - The interface to the top-level loops in the current /// function. /// - typedef LoopInfoBase<MachineBasicBlock>::iterator iterator; + typedef LoopInfoBase<MachineBasicBlock, MachineLoop>::iterator iterator; inline iterator begin() const { return LI.begin(); } inline iterator end() const { return LI.end(); } bool empty() const { return LI.empty(); } diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index 4388c0a..b7e267d 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -20,6 +20,7 @@ namespace llvm { class Value; class FoldingSetNodeID; +class raw_ostream; //===----------------------------------------------------------------------===// /// MachineMemOperand - A description of a memory reference used in the backend. @@ -47,14 +48,17 @@ public: }; /// MachineMemOperand - Construct an MachineMemOperand object with the - /// specified address Value, flags, offset, size, and alignment. + /// specified address Value, flags, offset, size, and base alignment. MachineMemOperand(const Value *v, unsigned int f, int64_t o, uint64_t s, - unsigned int a); + unsigned int base_alignment); - /// getValue - Return the base address of the memory access. - /// Special values are PseudoSourceValue::FPRel, PseudoSourceValue::SPRel, - /// and the other PseudoSourceValue members which indicate references to - /// frame/stack pointer relative references and other special references. + /// getValue - Return the base address of the memory access. This may either + /// be a normal LLVM IR Value, or one of the special values used in CodeGen. + /// Special values are those obtained via + /// PseudoSourceValue::getFixedStack(int), PseudoSourceValue::getStack, and + /// other PseudoSourceValue member functions which return objects which stand + /// for frame/stack pointer relative references and other special references + /// which are not representable in the high-level IR. const Value *getValue() const { return V; } /// getFlags - Return the raw flags of the source value, \see MemOperandFlags. @@ -69,18 +73,34 @@ public: uint64_t getSize() const { return Size; } /// getAlignment - Return the minimum known alignment in bytes of the - /// memory reference. - unsigned int getAlignment() const { return (1u << (Flags >> 3)) >> 1; } + /// actual memory reference. + uint64_t getAlignment() const; + + /// getBaseAlignment - Return the minimum known alignment in bytes of the + /// base address, without the offset. + uint64_t getBaseAlignment() const { return (1u << (Flags >> 3)) >> 1; } bool isLoad() const { return Flags & MOLoad; } bool isStore() const { return Flags & MOStore; } bool isVolatile() const { return Flags & MOVolatile; } + /// refineAlignment - Update this MachineMemOperand to reflect the alignment + /// of MMO, if it has a greater alignment. This must only be used when the + /// new alignment applies to all users of this MachineMemOperand. + void refineAlignment(const MachineMemOperand *MMO); + + /// setValue - Change the SourceValue for this MachineMemOperand. This + /// should only be used when an object is being relocated and all references + /// to it are being updated. + void setValue(const Value *NewSV) { V = NewSV; } + /// Profile - Gather unique data for the object. /// void Profile(FoldingSetNodeID &ID) const; }; +raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MRO); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 1872bd2..5878d67 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -42,18 +42,34 @@ #include "llvm/CodeGen/MachineLocation.h" #include "llvm/GlobalValue.h" #include "llvm/Pass.h" +#include "llvm/Metadata.h" + +#define ATTACH_DEBUG_INFO_TO_AN_INSN 1 namespace llvm { //===----------------------------------------------------------------------===// // Forward declarations. class Constant; +class MDNode; class GlobalVariable; class MachineBasicBlock; class MachineFunction; class Module; class PointerType; class StructType; + + +/// MachineModuleInfoImpl - This class can be derived from and used by targets +/// to hold private target-specific information for each Module. Objects of +/// type are accessed/created with MMI::getInfo and destroyed when the +/// MachineModuleInfo is destroyed. +class MachineModuleInfoImpl { +public: + virtual ~MachineModuleInfoImpl(); +}; + + //===----------------------------------------------------------------------===// /// LandingPadInfo - This structure is used to retain landing pad info for @@ -80,7 +96,11 @@ struct LandingPadInfo { /// schemes and reformated for specific use. /// class MachineModuleInfo : public ImmutablePass { -private: + /// ObjFileMMI - This is the object-file-format-specific implementation of + /// MachineModuleInfoImpl, which lets targets accumulate whatever info they + /// want. + MachineModuleInfoImpl *ObjFileMMI; + // LabelIDList - One entry per assigned label. Normally the entry is equal to // the list index(+1). If the entry is zero then the label has been deleted. // Any other value indicates the label has been deleted by is mapped to @@ -112,8 +132,9 @@ private: // common EH frames. std::vector<Function *> Personalities; - // UsedFunctions - the functions in the llvm.used list in a more easily - // searchable format. + /// UsedFunctions - The functions in the @llvm.used list in a more easily + /// searchable format. This does not include the functions in + /// llvm.compiler.used. SmallPtrSet<const Function *, 32> UsedFunctions; /// UsedDbgLabels - labels are used by debug info entries. @@ -125,28 +146,45 @@ private: /// DbgInfoAvailable - True if debugging information is available /// in this module. bool DbgInfoAvailable; + public: static char ID; // Pass identification, replacement for typeid + typedef SmallVector< std::pair< WeakMetadataVH, unsigned>, 4 > VariableDbgInfoMapTy; + VariableDbgInfoMapTy VariableDbgInfo; + MachineModuleInfo(); ~MachineModuleInfo(); - /// doInitialization - Initialize the state for a new module. - /// bool doInitialization(); - - /// doFinalization - Tear down the state after completion of a module. - /// bool doFinalization(); - + /// BeginFunction - Begin gathering function meta information. /// - void BeginFunction(MachineFunction *MF); + void BeginFunction(MachineFunction *) {} /// EndFunction - Discard function meta information. /// void EndFunction(); + /// getInfo - Keep track of various per-function pieces of information for + /// backends that would like to do so. + /// + template<typename Ty> + Ty &getObjFileInfo() { + if (ObjFileMMI == 0) + ObjFileMMI = new Ty(*this); + + assert((void*)dynamic_cast<Ty*>(ObjFileMMI) == (void*)ObjFileMMI && + "Invalid concrete type or multiple inheritence for getInfo"); + return *static_cast<Ty*>(ObjFileMMI); + } + + template<typename Ty> + const Ty &getObjFileInfo() const { + return const_cast<MachineModuleInfo*>(this)->getObjFileInfo<Ty>(); + } + /// AnalyzeModule - Scan the module for global debug information. /// void AnalyzeModule(Module &M); @@ -240,9 +278,11 @@ public: return Personalities; } - // UsedFunctions - Return set of the functions in the llvm.used list. - const SmallPtrSet<const Function *, 32>& getUsedFunctions() const { - return UsedFunctions; + /// isUsedFunction - Return true if the functions in the llvm.used list. This + /// does not return true for things in llvm.compiler.used unless they are also + /// in llvm.used. + bool isUsedFunction(const Function *F) { + return UsedFunctions.count(F); } /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. @@ -293,6 +333,14 @@ public: /// of one is required to emit exception handling info. Function *getPersonality() const; + /// setVariableDbgInfo - Collect information used to emit debugging information + /// of a variable. + void setVariableDbgInfo(MDNode *N, unsigned S) { + VariableDbgInfo.push_back(std::make_pair(N, S)); + } + + VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; } + }; // End class MachineModuleInfo } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h new file mode 100644 index 0000000..44813cb --- /dev/null +++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -0,0 +1,79 @@ +//===-- llvm/CodeGen/MachineModuleInfoImpls.h -------------------*- 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 object-file format specific implementations of +// MachineModuleInfoImpl. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H +#define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H + +#include "llvm/CodeGen/MachineModuleInfo.h" + +namespace llvm { + class MCSymbol; + + /// MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation + /// for MachO targets. + class MachineModuleInfoMachO : public MachineModuleInfoImpl { + /// FnStubs - Darwin '$stub' stubs. The key is something like "Lfoo$stub", + /// the value is something like "_foo". + DenseMap<const MCSymbol*, const MCSymbol*> FnStubs; + + /// GVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like + /// "Lfoo$non_lazy_ptr", the value is something like "_foo". + DenseMap<const MCSymbol*, const MCSymbol*> GVStubs; + + /// HiddenGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like + /// "Lfoo$non_lazy_ptr", the value is something like "_foo". Unlike GVStubs + /// these are for things with hidden visibility. + DenseMap<const MCSymbol*, const MCSymbol*> HiddenGVStubs; + + virtual void Anchor(); // Out of line virtual method. + public: + MachineModuleInfoMachO(const MachineModuleInfo &) {} + + const MCSymbol *&getFnStubEntry(const MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return FnStubs[Sym]; + } + + const MCSymbol *&getGVStubEntry(const MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return GVStubs[Sym]; + } + + const MCSymbol *&getHiddenGVStubEntry(const MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return HiddenGVStubs[Sym]; + } + + /// Accessor methods to return the set of stubs in sorted order. + typedef std::vector<std::pair<const MCSymbol*, const MCSymbol*> > + SymbolListTy; + + SymbolListTy GetFnStubList() const { + return GetSortedStubs(FnStubs); + } + SymbolListTy GetGVStubList() const { + return GetSortedStubs(GVStubs); + } + SymbolListTy GetHiddenGVStubList() const { + return GetSortedStubs(HiddenGVStubs); + } + + private: + static SymbolListTy + GetSortedStubs(const DenseMap<const MCSymbol*, const MCSymbol*> &Map); + }; + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 26ec239..f715c44 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -16,7 +16,6 @@ #include "llvm/Support/DataTypes.h" #include <cassert> -#include <iosfwd> namespace llvm { @@ -111,7 +110,7 @@ private: GlobalValue *GV; // For MO_GlobalAddress. MDNode *Node; // For MO_Metadata. } Val; - int64_t Offset; // An offset from the object. + int64_t Offset; // An offset from the object. } OffsetedInfo; } Contents; @@ -119,12 +118,6 @@ private: TargetFlags = 0; } public: - MachineOperand(const MachineOperand &M) { - *this = M; - } - - ~MachineOperand() {} - /// getType - Returns the MachineOperandType for this operand. /// MachineOperandType getType() const { return (MachineOperandType)OpKind; } @@ -139,7 +132,6 @@ public: MachineInstr *getParent() { return ParentMI; } const MachineInstr *getParent() const { return ParentMI; } - void print(std::ostream &os, const TargetMachine *TM = 0) const; void print(raw_ostream &os, const TargetMachine *TM = 0) const; //===--------------------------------------------------------------------===// @@ -164,6 +156,8 @@ public: bool isGlobal() const { return OpKind == MO_GlobalAddress; } /// isSymbol - Tests if this is a MO_ExternalSymbol operand. bool isSymbol() const { return OpKind == MO_ExternalSymbol; } + /// isMetadata - Tests if this is a MO_Metadata operand. + bool isMetadata() const { return OpKind == MO_Metadata; } //===--------------------------------------------------------------------===// // Accessors for Register Operands @@ -304,6 +298,8 @@ public: return Contents.OffsetedInfo.Val.Node; } + /// getOffset - Return the offset from the symbol in this operand. This always + /// returns 0 for ExternalSymbol operands. int64_t getOffset() const { assert((isGlobal() || isSymbol() || isCPI()) && "Wrong MachineOperand accessor"); @@ -325,7 +321,7 @@ public: } void setOffset(int64_t Offset) { - assert((isGlobal() || isSymbol() || isCPI()) && + assert((isGlobal() || isSymbol() || isCPI() || isMetadata()) && "Wrong MachineOperand accessor"); Contents.OffsetedInfo.Offset = Offset; } @@ -438,28 +434,14 @@ public: Op.setTargetFlags(TargetFlags); return Op; } - static MachineOperand CreateES(const char *SymName, int64_t Offset = 0, + static MachineOperand CreateES(const char *SymName, unsigned char TargetFlags = 0) { MachineOperand Op(MachineOperand::MO_ExternalSymbol); Op.Contents.OffsetedInfo.Val.SymbolName = SymName; - Op.setOffset(Offset); + Op.setOffset(0); // Offset is always 0. Op.setTargetFlags(TargetFlags); return Op; } - const MachineOperand &operator=(const MachineOperand &MO) { - OpKind = MO.OpKind; - IsDef = MO.IsDef; - IsImp = MO.IsImp; - IsKill = MO.IsKill; - IsDead = MO.IsDead; - IsUndef = MO.IsUndef; - IsEarlyClobber = MO.IsEarlyClobber; - SubReg = MO.SubReg; - ParentMI = MO.ParentMI; - Contents = MO.Contents; - TargetFlags = MO.TargetFlags; - return *this; - } friend class MachineInstr; friend class MachineRegisterInfo; @@ -486,11 +468,6 @@ private: void RemoveRegOperandFromRegInfo(); }; -inline std::ostream &operator<<(std::ostream &OS, const MachineOperand &MO) { - MO.print(OS, 0); - return OS; -} - inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand& MO) { MO.print(OS, 0); return OS; diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 80c37b3..18e6020 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -16,7 +16,6 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/iterator.h" #include <vector> namespace llvm { @@ -256,7 +255,7 @@ public: /// returns end(). template<bool ReturnUses, bool ReturnDefs> class defusechain_iterator - : public forward_iterator<MachineInstr, ptrdiff_t> { + : public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> { MachineOperand *Op; explicit defusechain_iterator(MachineOperand *op) : Op(op) { // If the first node isn't one we're interested in, advance to one that @@ -269,8 +268,10 @@ public: } friend class MachineRegisterInfo; public: - typedef forward_iterator<MachineInstr, ptrdiff_t>::reference reference; - typedef forward_iterator<MachineInstr, ptrdiff_t>::pointer pointer; + typedef std::iterator<std::forward_iterator_tag, + MachineInstr, ptrdiff_t>::reference reference; + typedef std::iterator<std::forward_iterator_tag, + MachineInstr, ptrdiff_t>::pointer pointer; defusechain_iterator(const defusechain_iterator &I) : Op(I.Op) {} defusechain_iterator() : Op(0) {} diff --git a/include/llvm/CodeGen/ObjectCodeEmitter.h b/include/llvm/CodeGen/ObjectCodeEmitter.h new file mode 100644 index 0000000..8252e07 --- /dev/null +++ b/include/llvm/CodeGen/ObjectCodeEmitter.h @@ -0,0 +1,178 @@ +//===-- llvm/CodeGen/ObjectCodeEmitter.h - Object Code Emitter -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generalized Object Code Emitter, works with ObjectModule and BinaryObject. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_OBJECTCODEEMITTER_H +#define LLVM_CODEGEN_OBJECTCODEEMITTER_H + +#include "llvm/CodeGen/MachineCodeEmitter.h" + +namespace llvm { + +class BinaryObject; +class MachineBasicBlock; +class MachineCodeEmitter; +class MachineFunction; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineModuleInfo; + +class ObjectCodeEmitter : public MachineCodeEmitter { +protected: + + /// Binary Object (Section or Segment) we are emitting to. + BinaryObject *BO; + + /// MBBLocations - This vector is a mapping from MBB ID's to their address. + /// It is filled in by the StartMachineBasicBlock callback and queried by + /// the getMachineBasicBlockAddress callback. + std::vector<uintptr_t> MBBLocations; + + /// LabelLocations - This vector is a mapping from Label ID's to their + /// address. + std::vector<uintptr_t> LabelLocations; + + /// CPLocations - This is a map of constant pool indices to offsets from the + /// start of the section for that constant pool index. + std::vector<uintptr_t> CPLocations; + + /// CPSections - This is a map of constant pool indices to the Section + /// containing the constant pool entry for that index. + std::vector<uintptr_t> CPSections; + + /// JTLocations - This is a map of jump table indices to offsets from the + /// start of the section for that jump table index. + std::vector<uintptr_t> JTLocations; + +public: + ObjectCodeEmitter(); + ObjectCodeEmitter(BinaryObject *bo); + virtual ~ObjectCodeEmitter(); + + /// setBinaryObject - set the BinaryObject we are writting to + void setBinaryObject(BinaryObject *bo); + + /// emitByte - This callback is invoked when a byte needs to be + /// written to the data stream, without buffer overflow testing. + void emitByte(uint8_t B); + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in little-endian format. + void emitWordLE(uint32_t W); + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in big-endian format. + void emitWordBE(uint32_t W); + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in little-endian format. + void emitDWordLE(uint64_t W); + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in big-endian format. + void emitDWordBE(uint64_t W); + + /// emitAlignment - Move the CurBufferPtr pointer up the the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment = 0, uint8_t fill = 0); + + /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be + /// written to the data stream. + void emitULEB128Bytes(uint64_t Value); + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the data stream. + void emitSLEB128Bytes(uint64_t Value); + + /// emitString - This callback is invoked when a String needs to be + /// written to the data stream. + void emitString(const std::string &String); + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + uintptr_t getCurrentPCValue() const; + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + uintptr_t getCurrentPCOffset() const; + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + void addRelocation(const MachineRelocation& relocation); + + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + bool earlyResolveAddresses() const { return false; } + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + virtual bool finishFunction(MachineFunction &F) = 0; + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB); + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const; + + /// emitLabel - Emits a label + virtual void emitLabel(uint64_t LabelID) = 0; + + /// getLabelAddress - Return the address of the specified LabelID, only usable + /// after the LabelID has been emitted. + virtual uintptr_t getLabelAddress(uint64_t LabelID) const = 0; + + /// emitJumpTables - Emit all the jump tables for a given jump table info + /// record to the appropriate section. + virtual void emitJumpTables(MachineJumpTableInfo *MJTI) = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const; + + /// emitConstantPool - For each constant pool entry, figure out which section + /// the constant should live in, allocate space for it, and emit it to the + /// Section data buffer. + virtual void emitConstantPool(MachineConstantPool *MCP) = 0; + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const; + + /// getConstantPoolEntrySection - Return the section of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + virtual uintptr_t getConstantPoolEntrySection(unsigned Index) const; + + /// Specifies the MachineModuleInfo object. This is used for exception handling + /// purposes. + virtual void setModuleInfo(MachineModuleInfo* Info) = 0; + // to be implemented or depreciated with MachineModuleInfo + +}; // end class ObjectCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 7f1c16f..1e7115e 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -15,7 +15,6 @@ #ifndef LLVM_CODEGEN_PASSES_H #define LLVM_CODEGEN_PASSES_H -#include <iosfwd> #include <string> namespace llvm { @@ -25,6 +24,7 @@ namespace llvm { class TargetMachine; class TargetLowering; class RegisterCoalescer; + class raw_ostream; /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a @@ -35,8 +35,8 @@ namespace llvm { FunctionPass *createUnreachableBlockEliminationPass(); /// MachineFunctionPrinter pass - This pass prints out the machine function to - /// standard error, as a debugging tool. - FunctionPass *createMachineFunctionPrinterPass(std::ostream *OS, + /// the given stream, as a debugging tool. + FunctionPass *createMachineFunctionPrinterPass(raw_ostream &OS, const std::string &Banner =""); /// MachineLoopInfo pass - This pass is a loop analysis pass. @@ -87,27 +87,12 @@ namespace llvm { /// FunctionPass *createRegisterAllocator(); - /// SimpleRegisterAllocation Pass - This pass converts the input machine code - /// from SSA form to use explicit registers by spilling every register. Wow, - /// great policy huh? - /// - FunctionPass *createSimpleRegisterAllocator(); - /// LocalRegisterAllocation Pass - This pass register allocates the input code /// a basic block at a time, yielding code better than the simple register /// allocator, but not as good as a global allocator. /// FunctionPass *createLocalRegisterAllocator(); - /// BigBlockRegisterAllocation Pass - The BigBlock register allocator - /// munches single basic blocks at a time, like the local register - /// allocator. While the BigBlock allocator is a little slower, and uses - /// somewhat more memory than the local register allocator, it tends to - /// yield the best allocations (of any of the allocators) for blocks that - /// have hundreds or thousands of instructions in sequence. - /// - FunctionPass *createBigBlockRegisterAllocator(); - /// LinearScanRegisterAllocation Pass - This pass implements the linear scan /// register allocation algorithm, a global register allocator. /// @@ -155,11 +140,6 @@ namespace llvm { /// by seeing if the labels map to the same reduced label. FunctionPass *createDebugLabelFoldingPass(); - /// MachineCodeDeletion Pass - This pass deletes all of the machine code for - /// the current function, which should happen after the function has been - /// emitted to a .s file or to memory. - FunctionPass *createMachineCodeDeleter(); - /// getRegisterAllocator - This creates an instance of the register allocator /// for the Sparc. FunctionPass *getRegisterAllocator(TargetMachine &T); @@ -180,7 +160,7 @@ namespace llvm { /// Creates a pass to print GC metadata. /// - FunctionPass *createGCInfoPrinter(std::ostream &OS); + FunctionPass *createGCInfoPrinter(raw_ostream &OS); /// createMachineLICMPass - This pass performs LICM on machine instructions. /// @@ -207,6 +187,10 @@ namespace llvm { /// adapted to code generation. Required if using dwarf exception handling. FunctionPass *createDwarfEHPass(const TargetLowering *tli, bool fast); + /// createSjLjEHPass - This pass adapts exception handling code to use + /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. + FunctionPass *createSjLjEHPass(const TargetLowering *tli); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index 3ad2502..c6be645 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -25,18 +25,17 @@ namespace llvm { /// stack frame (e.g., a spill slot), below the stack frame (e.g., argument /// space), or constant pool. class PseudoSourceValue : public Value { + private: + /// printCustom - Implement printing for PseudoSourceValue. This is called + /// from Value::print or Value's operator<<. + /// + virtual void printCustom(raw_ostream &O) const; + public: PseudoSourceValue(); - /// dump - Support for debugging, callable in GDB: V->dump() - // - virtual void dump() const; - - /// print - Implement operator<< on PseudoSourceValue. - /// - virtual void print(raw_ostream &OS) const; - - /// isConstant - Test whether this PseudoSourceValue has a constant value. + /// isConstant - Test whether the memory pointed to by this + /// PseudoSourceValue has a constant value. /// virtual bool isConstant(const MachineFrameInfo *) const; @@ -52,18 +51,21 @@ namespace llvm { /// e.g., a spill slot. static const PseudoSourceValue *getFixedStack(int FI); - /// A source value referencing the area below the stack frame of a function, - /// e.g., the argument space. + /// A pseudo source value referencing the area below the stack frame of + /// a function, e.g., the argument space. static const PseudoSourceValue *getStack(); - /// A source value referencing the global offset table (or something the - /// like). + /// A pseudo source value referencing the global offset table + /// (or something the like). static const PseudoSourceValue *getGOT(); - /// A SV referencing the constant pool + /// A pseudo source value referencing the constant pool. Since constant + /// pools are constant, this doesn't need to identify a specific constant + /// pool entry. static const PseudoSourceValue *getConstantPool(); - /// A SV referencing the jump table + /// A pseudo source value referencing a jump table. Since jump tables are + /// constant, this doesn't need to identify a specific jump table. static const PseudoSourceValue *getJumpTable(); }; } // End llvm namespace diff --git a/include/llvm/CodeGen/RegAllocRegistry.h b/include/llvm/CodeGen/RegAllocRegistry.h index a08e42a..100e357 100644 --- a/include/llvm/CodeGen/RegAllocRegistry.h +++ b/include/llvm/CodeGen/RegAllocRegistry.h @@ -34,7 +34,9 @@ public: RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) : MachinePassRegistryNode(N, D, (MachinePassCtor)C) - { Registry.Add(this); } + { + Registry.Add(this); + } ~RegisterRegAlloc() { Registry.Remove(this); } diff --git a/include/llvm/CodeGen/RegisterCoalescer.h b/include/llvm/CodeGen/RegisterCoalescer.h index 79dd9db..1490aa0 100644 --- a/include/llvm/CodeGen/RegisterCoalescer.h +++ b/include/llvm/CodeGen/RegisterCoalescer.h @@ -42,7 +42,7 @@ namespace llvm { /// Reset state. Can be used to allow a coalescer run by /// PassManager to be run again by the register allocator. - virtual void reset(MachineFunction &mf) {}; + virtual void reset(MachineFunction &mf) {} /// Register allocators must call this from their own /// getAnalysisUsage to cover the case where the coalescer is not @@ -51,7 +51,7 @@ namespace llvm { /// which to invalidate when running the register allocator or any /// pass that might call coalescing. The long-term solution is to /// allow hierarchies of PassManagers. - virtual void getAnalysisUsage(AnalysisUsage &AU) const {}; + virtual void getAnalysisUsage(AnalysisUsage &AU) const {} }; /// An abstract interface for register allocators to interact with @@ -68,7 +68,7 @@ namespace llvm { /// /// public: /// LinearScanRegallocQuery(LiveIntervals &intervals) - /// : li(intervals) {}; + /// : li(intervals) {} /// /// /// This is pretty slow and conservative, but since linear scan /// /// allocation doesn't pre-compute interference information it's @@ -85,14 +85,14 @@ namespace llvm { /// interferences.insert(&iv->second); /// } /// } - /// }; + /// } /// /// /// This is *really* slow and stupid. See above. /// int getNumberOfInterferences(const LiveInterval &a) const { /// IntervalSet intervals; /// getInterferences(intervals, a); /// return intervals.size(); - /// }; + /// } /// }; /// /// In the allocator: @@ -108,14 +108,14 @@ namespace llvm { public: typedef SmallPtrSet<const LiveInterval *, 8> IntervalSet; - virtual ~RegallocQuery() {}; + virtual ~RegallocQuery() {} /// Return whether two live ranges interfere. virtual bool interfere(const LiveInterval &a, const LiveInterval &b) const { // A naive test return a.overlaps(b); - }; + } /// Return the set of intervals that interfere with this one. virtual void getInterferences(IntervalSet &interferences, @@ -129,7 +129,7 @@ namespace llvm { /// coalescing or other modifications. virtual void updateDataForMerge(const LiveInterval &a, const LiveInterval &b, - const MachineInstr ©) {}; + const MachineInstr ©) {} /// Allow the register allocator to communicate when it doesn't /// want a copy coalesced. This may be due to assumptions made by diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 458c2e4..84b726d 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -19,7 +19,6 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" namespace llvm { @@ -69,14 +68,6 @@ class RegScavenger { /// available, unset means the register is currently being used. BitVector RegsAvailable; - /// CurrDist - Distance from MBB entry to the current instruction MBBI. - /// - unsigned CurrDist; - - /// DistanceMap - Keep track the distance of a MI from the start of the - /// current basic block. - DenseMap<MachineInstr*, unsigned> DistanceMap; - public: RegScavenger() : MBB(NULL), NumPhysRegs(0), Tracking(false), @@ -86,56 +77,30 @@ public: /// basic block. void enterBasicBlock(MachineBasicBlock *mbb); - /// forward / backward - Move the internal MBB iterator and update register - /// states. + /// initRegState - allow resetting register state info for multiple + /// passes over/within the same function. + void initRegState(); + + /// forward - Move the internal MBB iterator and update register states. void forward(); - void backward(); - /// forward / backward - Move the internal MBB iterator and update register - /// states until it has processed the specific iterator. + /// forward - Move the internal MBB iterator and update register states until + /// it has processed the specific iterator. void forward(MachineBasicBlock::iterator I) { if (!Tracking && MBB->begin() != I) forward(); while (MBBI != I) forward(); } - void backward(MachineBasicBlock::iterator I) { - while (MBBI != I) backward(); - } /// skipTo - Move the internal MBB iterator but do not update register states. /// void skipTo(MachineBasicBlock::iterator I) { MBBI = I; } - /// isReserved - Returns true if a register is reserved. It is never "unused". - bool isReserved(unsigned Reg) const { return ReservedRegs[Reg]; } - - /// isUsed / isUsed - Test if a register is currently being used. - /// - bool isUsed(unsigned Reg) const { return !RegsAvailable[Reg]; } - bool isUnused(unsigned Reg) const { return RegsAvailable[Reg]; } - /// getRegsUsed - return all registers currently in use in used. void getRegsUsed(BitVector &used, bool includeReserved); - /// setUsed / setUnused - Mark the state of one or a number of registers. - /// - void setUsed(unsigned Reg); - void setUsed(BitVector &Regs) { - RegsAvailable &= ~Regs; - } - void setUnused(unsigned Reg, const MachineInstr *MI); - void setUnused(BitVector &Regs) { - RegsAvailable |= Regs; - } - - /// FindUnusedReg - Find a unused register of the specified register class - /// from the specified set of registers. It return 0 is none is found. - unsigned FindUnusedReg(const TargetRegisterClass *RegClass, - const BitVector &Candidates) const; - /// FindUnusedReg - Find a unused register of the specified register class. - /// Exclude callee saved registers if directed. It return 0 is none is found. - unsigned FindUnusedReg(const TargetRegisterClass *RegClass, - bool ExCalleeSaved = false) const; + /// Return 0 if none is found. + unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const; /// setScavengingFrameIndex / getScavengingFrameIndex - accessor and setter of /// ScavengingFrameIndex. @@ -152,16 +117,43 @@ public: return scavengeRegister(RegClass, MBBI, SPAdj); } + /// setUsed - Tell the scavenger a register is used. + /// + void setUsed(unsigned Reg); private: - /// restoreScavengedReg - Restore scavenged by loading it back from the - /// emergency spill slot. Mark it used. - void restoreScavengedReg(); + /// isReserved - Returns true if a register is reserved. It is never "unused". + bool isReserved(unsigned Reg) const { return ReservedRegs.test(Reg); } + + /// isUsed / isUnused - Test if a register is currently being used. + /// + bool isUsed(unsigned Reg) const { return !RegsAvailable.test(Reg); } + bool isUnused(unsigned Reg) const { return RegsAvailable.test(Reg); } + + /// isAliasUsed - Is Reg or an alias currently in use? + bool isAliasUsed(unsigned Reg) const; + + /// setUsed / setUnused - Mark the state of one or a number of registers. + /// + void setUsed(BitVector &Regs) { + RegsAvailable &= ~Regs; + } + void setUnused(BitVector &Regs) { + RegsAvailable |= Regs; + } + + /// Add Reg and all its sub-registers to BV. + void addRegWithSubRegs(BitVector &BV, unsigned Reg); + + /// Add Reg and its aliases to BV. + void addRegWithAliases(BitVector &BV, unsigned Reg); + + unsigned findSurvivorReg(MachineBasicBlock::iterator MI, + BitVector &Candidates, + unsigned InstrLimit, + MachineBasicBlock::iterator &UseMI); - MachineInstr *findFirstUse(MachineBasicBlock *MBB, - MachineBasicBlock::iterator I, unsigned Reg, - unsigned &Dist); }; - + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 7f2c8bc..7a40f02 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -224,6 +224,11 @@ namespace RTLIB { O_F32, O_F64, + // MEMORY + MEMCPY, + MEMSET, + MEMMOVE, + // EXCEPTION HANDLING UNWIND_RESUME, @@ -232,27 +237,27 @@ namespace RTLIB { /// getFPEXT - Return the FPEXT_*_* value for the given types, or /// UNKNOWN_LIBCALL if there is none. - Libcall getFPEXT(MVT OpVT, MVT RetVT); + Libcall getFPEXT(EVT OpVT, EVT RetVT); /// getFPROUND - Return the FPROUND_*_* value for the given types, or /// UNKNOWN_LIBCALL if there is none. - Libcall getFPROUND(MVT OpVT, MVT RetVT); + Libcall getFPROUND(EVT OpVT, EVT RetVT); /// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or /// UNKNOWN_LIBCALL if there is none. - Libcall getFPTOSINT(MVT OpVT, MVT RetVT); + Libcall getFPTOSINT(EVT OpVT, EVT RetVT); /// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or /// UNKNOWN_LIBCALL if there is none. - Libcall getFPTOUINT(MVT OpVT, MVT RetVT); + Libcall getFPTOUINT(EVT OpVT, EVT RetVT); /// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or /// UNKNOWN_LIBCALL if there is none. - Libcall getSINTTOFP(MVT OpVT, MVT RetVT); + Libcall getSINTTOFP(EVT OpVT, EVT RetVT); /// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or /// UNKNOWN_LIBCALL if there is none. - Libcall getUINTTOFP(MVT OpVT, MVT RetVT); + Libcall getUINTTOFP(EVT OpVT, EVT RetVT); } } diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 237d491..39563f7 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -23,6 +23,7 @@ #include "llvm/ADT/PointerIntPair.h" namespace llvm { + class AliasAnalysis; class SUnit; class MachineConstantPool; class MachineFunction; @@ -145,6 +146,11 @@ namespace llvm { return Latency; } + /// setLatency - Set the latency for this edge. + void setLatency(unsigned Lat) { + Latency = Lat; + } + //// getSUnit - Return the SUnit to which this edge points. SUnit *getSUnit() const { return Dep.getPointer(); @@ -238,10 +244,10 @@ namespace llvm { unsigned NodeNum; // Entry # of node in the node vector. unsigned NodeQueueId; // Queue id of node. unsigned short Latency; // Node latency. - short NumPreds; // # of SDep::Data preds. - short NumSuccs; // # of SDep::Data sucss. - short NumPredsLeft; // # of preds not scheduled. - short NumSuccsLeft; // # of succs not scheduled. + unsigned NumPreds; // # of SDep::Data preds. + unsigned NumSuccs; // # of SDep::Data sucss. + unsigned NumPredsLeft; // # of preds not scheduled. + unsigned NumSuccsLeft; // # of succs not scheduled. bool isTwoAddress : 1; // Is a two-address instruction. bool isCommutable : 1; // Is a commutable instruction. bool hasPhysRegDefs : 1; // Has physreg defs that are being used. @@ -429,8 +435,8 @@ namespace llvm { class ScheduleDAG { public: - MachineBasicBlock *BB; // The block in which to insert instructions. - MachineBasicBlock::iterator InsertPos;// The position to insert instructions. + MachineBasicBlock *BB; // The block in which to insert instructions + MachineBasicBlock::iterator InsertPos;// The position to insert instructions const TargetMachine &TM; // Target processor const TargetInstrInfo *TII; // Target instruction information const TargetRegisterInfo *TRI; // Target processor register info @@ -456,7 +462,8 @@ namespace llvm { /// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock /// according to the order specified in Sequence. /// - virtual MachineBasicBlock *EmitSchedule() = 0; + virtual MachineBasicBlock* + EmitSchedule(DenseMap<MachineBasicBlock*, MachineBasicBlock*>*) = 0; void dumpSchedule() const; @@ -484,19 +491,25 @@ namespace llvm { /// BuildSchedGraph - Build SUnits and set up their Preds and Succs /// to form the scheduling dependency graph. /// - virtual void BuildSchedGraph() = 0; + virtual void BuildSchedGraph(AliasAnalysis *AA) = 0; /// ComputeLatency - Compute node latency. /// virtual void ComputeLatency(SUnit *SU) = 0; + /// ComputeOperandLatency - Override dependence edge latency using + /// operand use/def information + /// + virtual void ComputeOperandLatency(SUnit *Def, SUnit *Use, + SDep& dep) const { }; + /// Schedule - Order nodes according to selected style, filling /// in the Sequence member. /// virtual void Schedule() = 0; - /// ForceUnitLatencies - Return true if all scheduling edges should be given a - /// latency value of one. The default is to return false; schedulers may + /// ForceUnitLatencies - Return true if all scheduling edges should be given + /// a latency value of one. The default is to return false; schedulers may /// override this as needed. virtual bool ForceUnitLatencies() const { return false; } @@ -504,27 +517,11 @@ namespace llvm { /// void EmitNoop(); - void AddMemOperand(MachineInstr *MI, const MachineMemOperand &MO); - void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap); - - private: - /// EmitLiveInCopy - Emit a copy for a live in physical register. If the - /// physical register has only a single copy use, then coalesced the copy - /// if possible. - void EmitLiveInCopy(MachineBasicBlock *MBB, - MachineBasicBlock::iterator &InsertPos, - unsigned VirtReg, unsigned PhysReg, - const TargetRegisterClass *RC, - DenseMap<MachineInstr*, unsigned> &CopyRegMap); - - /// EmitLiveInCopies - If this is the first basic block in the function, - /// and if it has live ins that need to be copied into vregs, emit the - /// copies into the top of the block. - void EmitLiveInCopies(MachineBasicBlock *MBB); }; - class SUnitIterator : public forward_iterator<SUnit, ptrdiff_t> { + class SUnitIterator : public std::iterator<std::forward_iterator_tag, + SUnit, ptrdiff_t> { SUnit *Node; unsigned Operand; @@ -536,7 +533,7 @@ namespace llvm { bool operator!=(const SUnitIterator& x) const { return !operator==(x); } const SUnitIterator &operator=(const SUnitIterator &I) { - assert(I.Node == Node && "Cannot assign iterators to two different nodes!"); + assert(I.Node==Node && "Cannot assign iterators to two different nodes!"); Operand = I.Operand; return *this; } diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 369882d..09e3e88 100644 --- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -43,6 +43,11 @@ public: return NoHazard; } + /// Reset - This callback is invoked when a new block of + /// instructions is about to be schedule. The hazard state should be + /// set to an initialized state. + virtual void Reset() {} + /// EmitInstruction - This callback is invoked when an instruction is /// emitted, to advance the hazard state. virtual void EmitInstruction(SUnit *) {} diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 8abd78d..e0198ef 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/RecyclingAllocator.h" #include "llvm/Target/TargetMachine.h" #include <cassert> #include <vector> @@ -37,7 +38,7 @@ class FunctionLoweringInfo; template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> { private: - mutable ilist_node<SDNode> Sentinel; + mutable ilist_half_node<SDNode> Sentinel; public: SDNode *createSentinel() const { return static_cast<SDNode*>(&Sentinel); @@ -78,6 +79,7 @@ class SelectionDAG { FunctionLoweringInfo &FLI; MachineModuleInfo *MMI; DwarfWriter *DW; + LLVMContext* Context; /// EntryNode - The starting token. SDNode EntryNode; @@ -98,7 +100,7 @@ class SelectionDAG { NodeAllocatorType NodeAllocator; /// CSEMap - This structure is used to memoize nodes, automatically performing - /// CSE with existing nodes with a duplicate is requested. + /// CSE with existing nodes when a duplicate is requested. FoldingSet<SDNode> CSEMap; /// OperandAllocator - Pool allocation for machine-opcode SDNode operands. @@ -138,6 +140,7 @@ public: FunctionLoweringInfo &getFunctionLoweringInfo() const { return FLI; } MachineModuleInfo *getMachineModuleInfo() const { return MMI; } DwarfWriter *getDwarfWriter() const { return DW; } + LLVMContext *getContext() const {return Context; } /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. /// @@ -242,70 +245,70 @@ public: /// getVTList - Return an SDVTList that represents the list of values /// specified. - SDVTList getVTList(MVT VT); - SDVTList getVTList(MVT VT1, MVT VT2); - SDVTList getVTList(MVT VT1, MVT VT2, MVT VT3); - SDVTList getVTList(MVT VT1, MVT VT2, MVT VT3, MVT VT4); - SDVTList getVTList(const MVT *VTs, unsigned NumVTs); + SDVTList getVTList(EVT VT); + SDVTList getVTList(EVT VT1, EVT VT2); + SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3); + SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4); + SDVTList getVTList(const EVT *VTs, unsigned NumVTs); //===--------------------------------------------------------------------===// // Node creation methods. // - SDValue getConstant(uint64_t Val, MVT VT, bool isTarget = false); - SDValue getConstant(const APInt &Val, MVT VT, bool isTarget = false); - SDValue getConstant(const ConstantInt &Val, MVT VT, bool isTarget = false); + SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false); + SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false); + SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false); SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false); - SDValue getTargetConstant(uint64_t Val, MVT VT) { + SDValue getTargetConstant(uint64_t Val, EVT VT) { return getConstant(Val, VT, true); } - SDValue getTargetConstant(const APInt &Val, MVT VT) { + SDValue getTargetConstant(const APInt &Val, EVT VT) { return getConstant(Val, VT, true); } - SDValue getTargetConstant(const ConstantInt &Val, MVT VT) { + SDValue getTargetConstant(const ConstantInt &Val, EVT VT) { return getConstant(Val, VT, true); } - SDValue getConstantFP(double Val, MVT VT, bool isTarget = false); - SDValue getConstantFP(const APFloat& Val, MVT VT, bool isTarget = false); - SDValue getConstantFP(const ConstantFP &CF, MVT VT, bool isTarget = false); - SDValue getTargetConstantFP(double Val, MVT VT) { + SDValue getConstantFP(double Val, EVT VT, bool isTarget = false); + SDValue getConstantFP(const APFloat& Val, EVT VT, bool isTarget = false); + SDValue getConstantFP(const ConstantFP &CF, EVT VT, bool isTarget = false); + SDValue getTargetConstantFP(double Val, EVT VT) { return getConstantFP(Val, VT, true); } - SDValue getTargetConstantFP(const APFloat& Val, MVT VT) { + SDValue getTargetConstantFP(const APFloat& Val, EVT VT) { return getConstantFP(Val, VT, true); } - SDValue getTargetConstantFP(const ConstantFP &Val, MVT VT) { + SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) { return getConstantFP(Val, VT, true); } - SDValue getGlobalAddress(const GlobalValue *GV, MVT VT, + SDValue getGlobalAddress(const GlobalValue *GV, EVT VT, int64_t offset = 0, bool isTargetGA = false, unsigned char TargetFlags = 0); - SDValue getTargetGlobalAddress(const GlobalValue *GV, MVT VT, + SDValue getTargetGlobalAddress(const GlobalValue *GV, EVT VT, int64_t offset = 0, unsigned char TargetFlags = 0) { return getGlobalAddress(GV, VT, offset, true, TargetFlags); } - SDValue getFrameIndex(int FI, MVT VT, bool isTarget = false); - SDValue getTargetFrameIndex(int FI, MVT VT) { + SDValue getFrameIndex(int FI, EVT VT, bool isTarget = false); + SDValue getTargetFrameIndex(int FI, EVT VT) { return getFrameIndex(FI, VT, true); } - SDValue getJumpTable(int JTI, MVT VT, bool isTarget = false, + SDValue getJumpTable(int JTI, EVT VT, bool isTarget = false, unsigned char TargetFlags = 0); - SDValue getTargetJumpTable(int JTI, MVT VT, unsigned char TargetFlags = 0) { + SDValue getTargetJumpTable(int JTI, EVT VT, unsigned char TargetFlags = 0) { return getJumpTable(JTI, VT, true, TargetFlags); } - SDValue getConstantPool(Constant *C, MVT VT, + SDValue getConstantPool(Constant *C, EVT VT, unsigned Align = 0, int Offs = 0, bool isT=false, unsigned char TargetFlags = 0); - SDValue getTargetConstantPool(Constant *C, MVT VT, + SDValue getTargetConstantPool(Constant *C, EVT VT, unsigned Align = 0, int Offset = 0, unsigned char TargetFlags = 0) { return getConstantPool(C, VT, Align, Offset, true, TargetFlags); } - SDValue getConstantPool(MachineConstantPoolValue *C, MVT VT, + SDValue getConstantPool(MachineConstantPoolValue *C, EVT VT, unsigned Align = 0, int Offs = 0, bool isT=false, unsigned char TargetFlags = 0); SDValue getTargetConstantPool(MachineConstantPoolValue *C, - MVT VT, unsigned Align = 0, + EVT VT, unsigned Align = 0, int Offset = 0, unsigned char TargetFlags=0) { return getConstantPool(C, VT, Align, Offset, true, TargetFlags); } @@ -313,15 +316,14 @@ public: // to provide debug info for the BB at that time, so keep this one around. SDValue getBasicBlock(MachineBasicBlock *MBB); SDValue getBasicBlock(MachineBasicBlock *MBB, DebugLoc dl); - SDValue getExternalSymbol(const char *Sym, MVT VT); - SDValue getExternalSymbol(const char *Sym, DebugLoc dl, MVT VT); - SDValue getTargetExternalSymbol(const char *Sym, MVT VT, + SDValue getExternalSymbol(const char *Sym, EVT VT); + SDValue getExternalSymbol(const char *Sym, DebugLoc dl, EVT VT); + SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned char TargetFlags = 0); - SDValue getArgFlags(ISD::ArgFlagsTy Flags); - SDValue getValueType(MVT); - SDValue getRegister(unsigned Reg, MVT VT); + SDValue getValueType(EVT); + SDValue getRegister(unsigned Reg, EVT VT); SDValue getDbgStopPoint(DebugLoc DL, SDValue Root, - unsigned Line, unsigned Col, Value *CU); + unsigned Line, unsigned Col, MDNode *CU); SDValue getLabel(unsigned Opcode, DebugLoc dl, SDValue Root, unsigned LabelID); @@ -348,7 +350,7 @@ public: return getNode(ISD::CopyToReg, dl, VTs, Ops, Flag.getNode() ? 4 : 3); } - SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, MVT VT) { + SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT) { SDVTList VTs = getVTList(VT, MVT::Other); SDValue Ops[] = { Chain, getRegister(Reg, VT) }; return getNode(ISD::CopyFromReg, dl, VTs, Ops, 2); @@ -357,7 +359,7 @@ public: // This version of the getCopyFromReg method takes an extra operand, which // indicates that there is potentially an incoming flag value (if Flag is not // null) and that there should be a flag result. - SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, MVT VT, + SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT, SDValue Flag) { SDVTList VTs = getVTList(VT, MVT::Other, MVT::Flag); SDValue Ops[] = { Chain, getRegister(Reg, VT), Flag }; @@ -368,7 +370,7 @@ public: /// Returns the ConvertRndSat Note: Avoid using this node because it may /// disappear in the future and most targets don't support it. - SDValue getConvertRndSat(MVT VT, DebugLoc dl, SDValue Val, SDValue DTy, + SDValue getConvertRndSat(EVT VT, DebugLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); @@ -376,15 +378,23 @@ public: /// elements in VT, which must be a vector type, must match the number of /// mask elements NumElts. A integer mask element equal to -1 is treated as /// undefined. - SDValue getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, + SDValue getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, const int *MaskElts); + /// getSExtOrTrunc - Convert Op, which must be of integer type, to the + /// integer type VT, by either sign-extending or truncating it. + SDValue getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + + /// getZExtOrTrunc - Convert Op, which must be of integer type, to the + /// integer type VT, by either zero-extending or truncating it. + SDValue getZExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + /// getZeroExtendInReg - Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. - SDValue getZeroExtendInReg(SDValue Op, DebugLoc DL, MVT SrcTy); + SDValue getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT SrcTy); /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). - SDValue getNOT(DebugLoc DL, SDValue Val, MVT VT); + SDValue getNOT(DebugLoc DL, SDValue Val, EVT VT); /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have /// a flag result (to ensure it's not CSE'd). CALLSEQ_START does not have a @@ -413,36 +423,36 @@ public: } /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful DebugLoc. - SDValue getUNDEF(MVT VT) { + SDValue getUNDEF(EVT VT) { return getNode(ISD::UNDEF, DebugLoc::getUnknownLoc(), VT); } /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does /// not have a useful DebugLoc. - SDValue getGLOBAL_OFFSET_TABLE(MVT VT) { + SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { return getNode(ISD::GLOBAL_OFFSET_TABLE, DebugLoc::getUnknownLoc(), VT); } /// getNode - Gets or creates the specified node. /// - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT); - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT, SDValue N); - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT, SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N1, SDValue N2); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, const SDUse *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, const SDValue *Ops, unsigned NumOps); SDValue getNode(unsigned Opcode, DebugLoc DL, - const std::vector<MVT> &ResultTys, + const std::vector<EVT> &ResultTys, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, const MVT *VTs, unsigned NumVTs, + SDValue getNode(unsigned Opcode, DebugLoc DL, const EVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps); SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, const SDValue *Ops, unsigned NumOps); @@ -458,6 +468,12 @@ public: SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); + /// getStackArgumentTokenFactor - Compute a TokenFactor to force all + /// the incoming stack arguments to be loaded from the stack. This is + /// used in tail call lowering to protect stack arguments from being + /// clobbered. + SDValue getStackArgumentTokenFactor(SDValue Chain); + SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, @@ -475,7 +491,7 @@ public: /// getSetCC - Helper function to make it easier to build SetCC's if you just /// have an ISD::CondCode instead of an SDValue. /// - SDValue getSetCC(DebugLoc DL, MVT VT, SDValue LHS, SDValue RHS, + SDValue getSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond) { return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } @@ -483,7 +499,7 @@ public: /// getVSetCC - Helper function to make it easier to build VSetCC's nodes /// if you just have an ISD::CondCode instead of an SDValue. /// - SDValue getVSetCC(DebugLoc DL, MVT VT, SDValue LHS, SDValue RHS, + SDValue getVSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond) { return getNode(ISD::VSETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } @@ -499,82 +515,89 @@ public: /// getVAArg - VAArg produces a result and token chain, and takes a pointer /// and a source value as input. - SDValue getVAArg(MVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + SDValue getVAArg(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, SDValue SV); /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 3 operands - SDValue getAtomic(unsigned Opcode, DebugLoc dl, MVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, const Value* PtrVal, unsigned Alignment=0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Cmp, SDValue Swp, + MachineMemOperand *MMO); /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 2 operands. - SDValue getAtomic(unsigned Opcode, DebugLoc dl, MVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value* PtrVal, unsigned Alignment = 0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Val, + MachineMemOperand *MMO); /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a - /// result and takes a list of operands. + /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, + /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not + /// less than FIRST_TARGET_MEMORY_OPCODE. SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, - const MVT *VTs, unsigned NumVTs, + const EVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps, - MVT MemVT, const Value *srcValue, int SVOff, + EVT MemVT, const Value *srcValue, int SVOff, unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, const SDValue *Ops, unsigned NumOps, - MVT MemVT, const Value *srcValue, int SVOff, + EVT MemVT, const Value *srcValue, int SVOff, unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachineMemOperand *MMO); + /// getMergeValues - Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl); - /// getCall - Create a CALL node from the given information. - /// - SDValue getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs, - bool IsTailCall, bool isInreg, SDVTList VTs, - const SDValue *Operands, unsigned NumOperands, - unsigned NumFixedArgs); - /// getLoad - Loads are not normal binary operators: their result type is not /// determined by their operands, and they produce a value AND a token chain. /// - SDValue getLoad(MVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + SDValue getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, const Value *SV, int SVOffset, bool isVolatile=false, unsigned Alignment=0); - SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, MVT VT, + SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, SDValue Chain, SDValue Ptr, const Value *SV, - int SVOffset, MVT EVT, bool isVolatile=false, + int SVOffset, EVT MemVT, bool isVolatile=false, unsigned Alignment=0); SDValue getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); SDValue getLoad(ISD::MemIndexedMode AM, DebugLoc dl, ISD::LoadExtType ExtType, - MVT VT, SDValue Chain, - SDValue Ptr, SDValue Offset, - const Value *SV, int SVOffset, MVT EVT, - bool isVolatile=false, unsigned Alignment=0); + EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, + const Value *SV, int SVOffset, EVT MemVT, + bool isVolatile=false, unsigned Alignment=0); + SDValue getLoad(ISD::MemIndexedMode AM, DebugLoc dl, ISD::LoadExtType ExtType, + EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, + EVT MemVT, MachineMemOperand *MMO); /// getStore - Helper function to build ISD::STORE nodes. /// SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, bool isVolatile=false, unsigned Alignment=0); + SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, - const Value *SV, int SVOffset, MVT TVT, + const Value *SV, int SVOffset, EVT TVT, bool isVolatile=false, unsigned Alignment=0); + SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + EVT TVT, MachineMemOperand *MMO); SDValue getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); - /// getMemOperand - Construct a node to track a memory reference - /// through the backend. - SDValue getMemOperand(const MachineMemOperand &MO); - /// getShiftAmountOperand - Return the specified value casted to /// the target's desired shift amount type. SDValue getShiftAmountOperand(SDValue Op); @@ -600,91 +623,104 @@ public: /// specified node to have the specified return type, Target opcode, and /// operands. Note that target opcodes are stored as /// ~TargetOpcode in the node opcode field. The resultant node is returned. - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT, SDValue Op1); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT, + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1, SDValue Op2); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT, + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT, + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, const SDValue *Ops, unsigned NumOps); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT1, MVT VT2); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT1, - MVT VT2, const SDValue *Ops, unsigned NumOps); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT1, - MVT VT2, MVT VT3, const SDValue *Ops, unsigned NumOps); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, MVT VT1, - MVT VT2, MVT VT3, MVT VT4, const SDValue *Ops, + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, EVT VT3, const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, + EVT VT2, EVT VT3, EVT VT4, const SDValue *Ops, unsigned NumOps); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT1, - MVT VT2, SDValue Op1); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT1, - MVT VT2, SDValue Op1, SDValue Op2); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT1, - MVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT1, - MVT VT2, MVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs, const SDValue *Ops, unsigned NumOps); /// MorphNodeTo - These *mutate* the specified node to have the specified /// return type, opcode, and operands. - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT, SDValue Op1); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT, + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, SDValue Op1); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, SDValue Op1, SDValue Op2); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT, + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT, + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, const SDValue *Ops, unsigned NumOps); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1, MVT VT2); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1, - MVT VT2, const SDValue *Ops, unsigned NumOps); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1, - MVT VT2, MVT VT3, const SDValue *Ops, unsigned NumOps); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1, - MVT VT2, SDValue Op1); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1, - MVT VT2, SDValue Op1, SDValue Op2); - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1, - MVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, EVT VT2); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, const SDValue *Ops, unsigned NumOps); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, EVT VT3, const SDValue *Ops, unsigned NumOps); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, SDValue Op1); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, const SDValue *Ops, unsigned NumOps); - /// getTargetNode - These are used for target selectors to create a new node - /// with specified return type(s), target opcode, and operands. + /// getMachineNode - These are used for target selectors to create a new node + /// with specified return type(s), MachineInstr opcode, and operands. /// - /// Note that getTargetNode returns the resultant node. If there is already a - /// node of the specified opcode and operands, it returns that node instead of - /// the current one. - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, SDValue Op1); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, SDValue Op1, - SDValue Op2); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, - SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, - const SDValue *Ops, unsigned NumOps); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, MVT VT2); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, MVT VT2, - SDValue Op1); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, - MVT VT2, SDValue Op1, SDValue Op2); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, - MVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, MVT VT2, - const SDValue *Ops, unsigned NumOps); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, MVT VT2, MVT VT3, - SDValue Op1, SDValue Op2); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, MVT VT2, MVT VT3, - SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, MVT VT2, MVT VT3, - const SDValue *Ops, unsigned NumOps); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, MVT VT2, MVT VT3, - MVT VT4, const SDValue *Ops, unsigned NumOps); - SDNode *getTargetNode(unsigned Opcode, DebugLoc dl, - const std::vector<MVT> &ResultTys, const SDValue *Ops, - unsigned NumOps); + /// Note that getMachineNode returns the resultant node. If there is already + /// a node of the specified opcode and operands, it returns that node instead + /// of the current one. + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + SDValue Op1); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, EVT VT4, const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, + const std::vector<EVT> &ResultTys, const SDValue *Ops, + unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// getTargetExtractSubreg - A convenience function for creating + /// TargetInstrInfo::EXTRACT_SUBREG nodes. + SDValue getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand); + + /// getTargetInsertSubreg - A convenience function for creating + /// TargetInstrInfo::INSERT_SUBREG nodes. + SDValue getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand, SDValue Subreg); /// getNodeIfExists - Get the specified node if it's already available, or /// else return NULL. @@ -792,20 +828,20 @@ public: /// CreateStackTemporary - Create a stack temporary, suitable for holding the /// specified value type. If minAlign is specified, the slot size will have /// at least that alignment. - SDValue CreateStackTemporary(MVT VT, unsigned minAlign = 1); + SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1); /// CreateStackTemporary - Create a stack temporary suitable for holding /// either of the specified value types. - SDValue CreateStackTemporary(MVT VT1, MVT VT2); + SDValue CreateStackTemporary(EVT VT1, EVT VT2); /// FoldConstantArithmetic - SDValue FoldConstantArithmetic(unsigned Opcode, - MVT VT, + EVT VT, ConstantSDNode *Cst1, ConstantSDNode *Cst2); /// FoldSetCC - Constant fold a setcc to true or false. - SDValue FoldSetCC(MVT VT, SDValue N1, + SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, DebugLoc dl); /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We @@ -835,6 +871,9 @@ public: /// class to allow target nodes to be understood. unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; + /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN. + bool isKnownNeverNaN(SDValue Op) const; + /// isVerifiedDebugInfoDesc - Returns true if the specified SDValue has /// been verified as a debug information descriptor. bool isVerifiedDebugInfoDesc(SDValue Op) const; @@ -855,7 +894,7 @@ private: void DeleteNodeNotInCSEMaps(SDNode *N); void DeallocateNode(SDNode *N); - unsigned getMVTAlignment(MVT MemoryVT) const; + unsigned getEVTAlignment(EVT MemoryVT) const; void allnodes_clear(); @@ -866,7 +905,7 @@ private: std::vector<CondCodeSDNode*> CondCodeNodes; std::vector<SDNode*> ValueTypeNodes; - std::map<MVT, SDNode*, MVT::compareRawBits> ExtendedValueTypeNodes; + std::map<EVT, SDNode*, EVT::compareRawBits> ExtendedValueTypeNodes; StringMap<SDNode*> ExternalSymbols; std::map<std::pair<std::string, unsigned char>,SDNode*> TargetExternalSymbols; diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index d2c0dc4..2b713f1 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -19,6 +19,7 @@ #include "llvm/Pass.h" #include "llvm/Constant.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineFunctionPass.h" namespace llvm { class FastISel; @@ -39,7 +40,7 @@ namespace llvm { /// SelectionDAGISel - This is the common base class used for SelectionDAG-based /// pattern-matching instruction selectors. -class SelectionDAGISel : public FunctionPass { +class SelectionDAGISel : public MachineFunctionPass { public: const TargetMachine &TM; TargetLowering &TLI; @@ -62,9 +63,9 @@ public: virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual bool runOnFunction(Function &Fn); + virtual bool runOnMachineFunction(MachineFunction &MF); - unsigned MakeReg(MVT VT); + unsigned MakeReg(EVT VT); virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {} virtual void InstructionSelect() = 0; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 9752537..d7c8f1c 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -22,18 +22,15 @@ #include "llvm/Constants.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/iterator.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/RecyclingAllocator.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include <cassert> -#include <climits> namespace llvm { @@ -52,7 +49,7 @@ template <typename T> struct ilist_traits; /// SelectionDAG::getVTList(...). /// struct SDVTList { - const MVT *VTs; + const EVT *VTs; unsigned int NumVTs; }; @@ -97,7 +94,7 @@ namespace ISD { AssertSext, AssertZext, // Various leaf nodes. - BasicBlock, VALUETYPE, ARG_FLAGS, CONDCODE, Register, + BasicBlock, VALUETYPE, CONDCODE, Register, Constant, ConstantFP, GlobalAddress, GlobalTLSAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol, @@ -121,6 +118,10 @@ namespace ISD { // address of the exception block on entry to an landing pad block. EXCEPTIONADDR, + // RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the + // address of the Language Specific Data Area for the enclosing function. + LSDAADDR, + // RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents // the selection index of the exception thrown. EHSELECTION, @@ -180,38 +181,6 @@ namespace ISD { // UNDEF - An undefined node UNDEF, - /// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG, FLAG0, ..., FLAGn) - This node - /// represents the formal arguments for a function. CC# is a Constant value - /// indicating the calling convention of the function, and ISVARARG is a - /// flag that indicates whether the function is varargs or not. This node - /// has one result value for each incoming argument, plus one for the output - /// chain. It must be custom legalized. See description of CALL node for - /// FLAG argument contents explanation. - /// - FORMAL_ARGUMENTS, - - /// RV1, RV2...RVn, CHAIN = CALL(CHAIN, CALLEE, - /// ARG0, FLAG0, ARG1, FLAG1, ... ARGn, FLAGn) - /// This node represents a fully general function call, before the legalizer - /// runs. This has one result value for each argument / flag pair, plus - /// a chain result. It must be custom legalized. Flag argument indicates - /// misc. argument attributes. Currently: - /// Bit 0 - signness - /// Bit 1 - 'inreg' attribute - /// Bit 2 - 'sret' attribute - /// Bit 4 - 'byval' attribute - /// Bit 5 - 'nest' attribute - /// Bit 6-9 - alignment of byval structures - /// Bit 10-26 - size of byval structures - /// Bits 31:27 - argument ABI alignment in the first argument piece and - /// alignment '1' in other argument pieces. - /// - /// CALL nodes use the CallSDNode subclass of SDNode, which - /// additionally carries information about the calling convention, - /// whether the call is varargs, and if it's marked as a tail call. - /// - CALL, - // EXTRACT_ELEMENT - This is used to get the lower or upper (determined by // a Constant, which is required to be operand #1) half of the integer or // float value specified as operand #0. This is only for use before @@ -225,9 +194,9 @@ namespace ISD { // MERGE_VALUES - This node takes multiple discrete operands and returns // them all as its individual results. This nodes has exactly the same - // number of inputs and outputs, and is only valid before legalization. - // This node is useful for some pieces of the code generator that want to - // think about a single node with multiple results, not multiple nodes. + // number of inputs and outputs. This node is useful for some pieces of the + // code generator that want to think about a single node with multiple + // results, not multiple nodes. MERGE_VALUES, // Simple integer binary arithmetic operators. @@ -303,7 +272,9 @@ namespace ISD { INSERT_VECTOR_ELT, /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR - /// identified by the (potentially variable) element number IDX. + /// identified by the (potentially variable) element number IDX. If the + /// return type is an integer type larger than the element type of the + /// vector, the result is extended to the width of the return type. EXTRACT_VECTOR_ELT, /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of @@ -318,7 +289,7 @@ namespace ISD { EXTRACT_SUBVECTOR, /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as - /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int + /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int /// values that indicate which value (or undef) each result element will /// get. These constant ints are accessible through the /// ShuffleVectorSDNode class. This is quite similar to the Altivec @@ -363,12 +334,11 @@ namespace ISD { // them with (op #2) as a CondCodeSDNode. SETCC, - // Vector SetCC operator - This evaluates to a vector of integer elements - // with the high bit in each element set to true if the comparison is true - // and false if the comparison is false. All other bits in each element - // are undefined. The operands to this are the left and right operands - // to compare (ops #0, and #1) and the condition code to compare them with - // (op #2) as a CondCodeSDNode. + // RESULT = VSETCC(LHS, RHS, COND) operator - This evaluates to a vector of + // integer elements with all bits of the result elements set to true if the + // comparison is true or all cleared if the comparison is false. The + // operands to this are the left and right operands to compare (LHS/RHS) and + // the condition code to compare them with (COND) as a CondCodeSDNode. VSETCC, // SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded @@ -514,12 +484,6 @@ namespace ISD { // chain, cc, lhs, rhs, block to branch to if condition is true. BR_CC, - // RET - Return from function. The first operand is the chain, - // and any subsequent operands are pairs of return value and return value - // attributes (see CALL for description of attributes) for the function. - // This operation can have variable number of operands. - RET, - // INLINEASM - Represents an inline asm block. This node always has two // return values: a chain and a flag result. The inputs are as follows: // Operand #0 : Input chain. @@ -535,12 +499,6 @@ namespace ISD { DBG_LABEL, EH_LABEL, - // DECLARE - Represents a llvm.dbg.declare intrinsic. It's used to track - // local variable declarations for debugging information. First operand is - // a chain, while the next two operands are first two arguments (address - // and variable) of a llvm.dbg.declare instruction. - DECLARE, - // STACKSAVE - STACKSAVE has one operand, an input chain. It produces a // value, the same type as the pointer type for the system, and an output // chain. @@ -575,11 +533,6 @@ namespace ISD { // make reference to a value in the LLVM IR. SRCVALUE, - // MEMOPERAND - This is a node that contains a MachineMemOperand which - // records information about a memory reference. This is used to make - // AliasAnalysis queries from the backend. - MEMOPERAND, - // PCMARKER - This corresponds to the pcmarker intrinsic. PCMARKER, @@ -656,10 +609,17 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, - // BUILTIN_OP_END - This must be the last enum value in this list. + /// BUILTIN_OP_END - This must be the last enum value in this list. + /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END }; + /// FIRST_TARGET_MEMORY_OPCODE - Target-specific pre-isel operations + /// which do not reference a specific memory location should be less than + /// this value. Those that do must not be less than this value, and can + /// be used with SelectionDAG::getMemIntrinsicNode. + static const int FIRST_TARGET_MEMORY_OPCODE = 1 << 14; + /// Node predicates /// isBuildVectorAllOnes - Return true if the specified node is a @@ -893,7 +853,7 @@ public: /// getValueType - Return the ValueType of the referenced return value. /// - inline MVT getValueType() const; + inline EVT getValueType() const; /// getValueSizeInBits - Returns the size of the value in bits. /// @@ -906,6 +866,7 @@ public: inline unsigned getNumOperands() const; inline const SDValue &getOperand(unsigned i) const; inline uint64_t getConstantOperandVal(unsigned i) const; + inline bool isTargetMemoryOpcode() const; inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; @@ -1002,7 +963,7 @@ public: /// getResNo - Convenience function for get().getResNo(). unsigned getResNo() const { return Val.getResNo(); } /// getValueType - Convenience function for get().getValueType(). - MVT getValueType() const { return Val.getValueType(); } + EVT getValueType() const { return Val.getValueType(); } /// operator== - Convenience function for get().operator== bool operator==(const SDValue &V) const { @@ -1070,17 +1031,17 @@ class SDNode : public FoldingSetNode, public ilist_node<SDNode> { private: /// NodeType - The operation that this node performs. /// - short NodeType; + int16_t NodeType; /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true, /// then they will be delete[]'d when the node is destroyed. - unsigned short OperandsNeedDelete : 1; + uint16_t OperandsNeedDelete : 1; protected: /// SubclassData - This member is defined by this class, but is not used for /// anything. Subclasses can use it to hold whatever state they find useful. /// This field is initialized to zero by the ctor. - unsigned short SubclassData : 15; + uint16_t SubclassData : 15; private: /// NodeId - Unique id per SDNode in the DAG. @@ -1092,7 +1053,7 @@ private: /// ValueList - The types of the values this node defines. SDNode's may /// define multiple values simultaneously. - const MVT *ValueList; + const EVT *ValueList; /// UseList - List of uses for this SDNode. SDUse *UseList; @@ -1104,7 +1065,7 @@ private: DebugLoc debugLoc; /// getValueTypeList - Return a pointer to the specified value type. - static const MVT *getValueTypeList(MVT VT); + static const EVT *getValueTypeList(EVT VT); friend class SelectionDAG; friend struct ilist_traits<SDNode>; @@ -1124,6 +1085,13 @@ public: /// \<target\>ISD namespace). bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } + /// isTargetMemoryOpcode - Test if this node has a target-specific + /// memory-referencing opcode (in the \<target\>ISD namespace and + /// greater than FIRST_TARGET_MEMORY_OPCODE). + bool isTargetMemoryOpcode() const { + return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; + } + /// isMachineOpcode - Test if this node has a post-isel opcode, directly /// corresponding to a MachineInstr opcode. bool isMachineOpcode() const { return NodeType < 0; } @@ -1168,14 +1136,16 @@ public: /// use_iterator - This class provides iterator support for SDUse /// operands that use a specific SDNode. class use_iterator - : public forward_iterator<SDUse, ptrdiff_t> { + : public std::iterator<std::forward_iterator_tag, SDUse, ptrdiff_t> { SDUse *Op; explicit use_iterator(SDUse *op) : Op(op) { } friend class SDNode; public: - typedef forward_iterator<SDUse, ptrdiff_t>::reference reference; - typedef forward_iterator<SDUse, ptrdiff_t>::pointer pointer; + typedef std::iterator<std::forward_iterator_tag, + SDUse, ptrdiff_t>::reference reference; + typedef std::iterator<std::forward_iterator_tag, + SDUse, ptrdiff_t>::pointer pointer; use_iterator(const use_iterator &I) : Op(I.Op) {} use_iterator() : Op(0) {} @@ -1278,7 +1248,7 @@ public: /// to which the flag operand points. Otherwise return NULL. SDNode *getFlaggedNode() const { if (getNumOperands() != 0 && - getOperand(getNumOperands()-1).getValueType() == MVT::Flag) + getOperand(getNumOperands()-1).getValueType().getSimpleVT() == MVT::Flag) return getOperand(getNumOperands()-1).getNode(); return 0; } @@ -1306,7 +1276,7 @@ public: /// getValueType - Return the type of a specified result. /// - MVT getValueType(unsigned ResNo) const { + EVT getValueType(unsigned ResNo) const { assert(ResNo < NumValues && "Illegal result number!"); return ValueList[ResNo]; } @@ -1317,7 +1287,7 @@ public: return getValueType(ResNo).getSizeInBits(); } - typedef const MVT* value_iterator; + typedef const EVT* value_iterator; value_iterator value_begin() const { return ValueList; } value_iterator value_end() const { return ValueList+NumValues; } @@ -1332,6 +1302,7 @@ public: void dump() const; void dumpr() const; void dump(const SelectionDAG *G) const; + void dumpr(const SelectionDAG *G) const; static bool classof(const SDNode *) { return true; } @@ -1344,7 +1315,7 @@ public: void addUse(SDUse &U) { U.addToList(&UseList); } protected: - static SDVTList getSDVTList(MVT VT) { + static SDVTList getSDVTList(EVT VT) { SDVTList Ret = { getValueTypeList(VT), 1 }; return Ret; } @@ -1438,7 +1409,7 @@ protected: inline unsigned SDValue::getOpcode() const { return Node->getOpcode(); } -inline MVT SDValue::getValueType() const { +inline EVT SDValue::getValueType() const { return Node->getValueType(ResNo); } inline unsigned SDValue::getNumOperands() const { @@ -1453,6 +1424,9 @@ inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { inline bool SDValue::isTargetOpcode() const { return Node->isTargetOpcode(); } +inline bool SDValue::isTargetMemoryOpcode() const { + return Node->isTargetMemoryOpcode(); +} inline bool SDValue::isMachineOpcode() const { return Node->isMachineOpcode(); } @@ -1549,45 +1523,57 @@ public: class MemSDNode : public SDNode { private: // MemoryVT - VT of in-memory value. - MVT MemoryVT; - - //! SrcValue - Memory location for alias analysis. - const Value *SrcValue; + EVT MemoryVT; - //! SVOffset - Memory location offset. Note that base is defined in MemSDNode - int SVOffset; +protected: + /// MMO - Memory reference information. + MachineMemOperand *MMO; public: - MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, MVT MemoryVT, - const Value *srcValue, int SVOff, - unsigned alignment, bool isvolatile); + MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, + MachineMemOperand *MMO); MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, - unsigned NumOps, MVT MemoryVT, const Value *srcValue, int SVOff, - unsigned alignment, bool isvolatile); + unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); + + bool readMem() const { return MMO->isLoad(); } + bool writeMem() const { return MMO->isStore(); } /// Returns alignment and volatility of the memory access - unsigned getAlignment() const { return (1u << (SubclassData >> 6)) >> 1; } - bool isVolatile() const { return (SubclassData >> 5) & 1; } + unsigned getOriginalAlignment() const { + return MMO->getBaseAlignment(); + } + unsigned getAlignment() const { + return MMO->getAlignment(); + } /// getRawSubclassData - Return the SubclassData value, which contains an - /// encoding of the alignment and volatile information, as well as bits - /// used by subclasses. This function should only be used to compute a - /// FoldingSetNodeID value. + /// encoding of the volatile flag, as well as bits used by subclasses. This + /// function should only be used to compute a FoldingSetNodeID value. unsigned getRawSubclassData() const { return SubclassData; } + bool isVolatile() const { return (SubclassData >> 5) & 1; } + /// Returns the SrcValue and offset that describes the location of the access - const Value *getSrcValue() const { return SrcValue; } - int getSrcValueOffset() const { return SVOffset; } + const Value *getSrcValue() const { return MMO->getValue(); } + int64_t getSrcValueOffset() const { return MMO->getOffset(); } /// getMemoryVT - Return the type of the in-memory value. - MVT getMemoryVT() const { return MemoryVT; } + EVT getMemoryVT() const { return MemoryVT; } /// getMemOperand - Return a MachineMemOperand object describing the memory /// reference performed by operation. - MachineMemOperand getMemOperand() const; + MachineMemOperand *getMemOperand() const { return MMO; } + + /// refineAlignment - Update this MemSDNode's MachineMemOperand information + /// to reflect the alignment of NewMMO, if it has a greater alignment. + /// This must only be used when the new alignment applies to all users of + /// this MachineMemOperand. + void refineAlignment(const MachineMemOperand *NewMMO) { + MMO->refineAlignment(NewMMO); + } const SDValue &getChain() const { return getOperand(0); } const SDValue &getBasePtr() const { @@ -1613,9 +1599,7 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || - N->getOpcode() == ISD::INTRINSIC_W_CHAIN || - N->getOpcode() == ISD::INTRINSIC_VOID || - N->isTargetOpcode(); + N->isTargetMemoryOpcode(); } }; @@ -1633,19 +1617,20 @@ public: // Swp: swap value // SrcVal: address to update as a Value (used for MemOperand) // Align: alignment of memory - AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, MVT MemVT, + AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, const Value* SrcVal, - unsigned Align=0) - : MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, - Align, /*isVolatile=*/true) { + SDValue Cmp, SDValue Swp, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } - AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, MVT MemVT, + AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Val, const Value* SrcVal, unsigned Align=0) - : MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, - Align, /*isVolatile=*/true) { + SDValue Val, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); InitOperands(Ops, Chain, Ptr, Val); } @@ -1675,24 +1660,18 @@ public: } }; -/// MemIntrinsicSDNode - This SDNode is used for target intrinsic that touches -/// memory and need an associated memory operand. -/// +/// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch +/// memory and need an associated MachineMemOperand. Its opcode may be +/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, or a target-specific opcode with a +/// value not less than FIRST_TARGET_MEMORY_OPCODE. class MemIntrinsicSDNode : public MemSDNode { - bool ReadMem; // Intrinsic reads memory - bool WriteMem; // Intrinsic writes memory public: MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, unsigned NumOps, - MVT MemoryVT, const Value *srcValue, int SVO, - unsigned Align, bool Vol, bool ReadMem, bool WriteMem) - : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, srcValue, SVO, Align, Vol), - ReadMem(ReadMem), WriteMem(WriteMem) { + EVT MemoryVT, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) { } - bool readMem() const { return ReadMem; } - bool writeMem() const { return WriteMem; } - // Methods to support isa and dyn_cast static bool classof(const MemIntrinsicSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -1700,7 +1679,7 @@ public: // early a node with a target opcode can be of this class return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || N->getOpcode() == ISD::INTRINSIC_VOID || - N->isTargetOpcode(); + N->isTargetMemoryOpcode(); } }; @@ -1720,7 +1699,7 @@ class ShuffleVectorSDNode : public SDNode { const int *Mask; protected: friend class SelectionDAG; - ShuffleVectorSDNode(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, + ShuffleVectorSDNode(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, const int *M) : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { InitOperands(Ops, N1, N2); @@ -1728,7 +1707,7 @@ protected: public: void getMask(SmallVectorImpl<int> &M) const { - MVT VT = getValueType(0); + EVT VT = getValueType(0); M.clear(); for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) M.push_back(Mask[i]); @@ -1743,7 +1722,7 @@ public: assert(isSplat() && "Cannot get splat index for non-splat!"); return Mask[0]; } - static bool isSplatMask(const int *Mask, MVT VT); + static bool isSplatMask(const int *Mask, EVT VT); static bool classof(const ShuffleVectorSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -1754,7 +1733,7 @@ public: class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; - ConstantSDNode(bool isTarget, const ConstantInt *val, MVT VT) + ConstantSDNode(bool isTarget, const ConstantInt *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, DebugLoc::getUnknownLoc(), getSDVTList(VT)), Value(val) { } @@ -1778,7 +1757,7 @@ public: class ConstantFPSDNode : public SDNode { const ConstantFP *Value; friend class SelectionDAG; - ConstantFPSDNode(bool isTarget, const ConstantFP *val, MVT VT) + ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, DebugLoc::getUnknownLoc(), getSDVTList(VT)), Value(val) { } @@ -1807,7 +1786,7 @@ public: } bool isExactlyValue(const APFloat& V) const; - bool isValueValidForType(MVT VT, const APFloat& Val); + bool isValueValidForType(EVT VT, const APFloat& Val); static bool classof(const ConstantFPSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -1821,7 +1800,7 @@ class GlobalAddressSDNode : public SDNode { int64_t Offset; unsigned char TargetFlags; friend class SelectionDAG; - GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA, MVT VT, + GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA, EVT VT, int64_t o, unsigned char TargetFlags); public: @@ -1843,7 +1822,7 @@ public: class FrameIndexSDNode : public SDNode { int FI; friend class SelectionDAG; - FrameIndexSDNode(int fi, MVT VT, bool isTarg) + FrameIndexSDNode(int fi, EVT VT, bool isTarg) : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, DebugLoc::getUnknownLoc(), getSDVTList(VT)), FI(fi) { } @@ -1862,7 +1841,7 @@ class JumpTableSDNode : public SDNode { int JTI; unsigned char TargetFlags; friend class SelectionDAG; - JumpTableSDNode(int jti, MVT VT, bool isTarg, unsigned char TF) + JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF) : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, DebugLoc::getUnknownLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { } @@ -1887,7 +1866,7 @@ class ConstantPoolSDNode : public SDNode { unsigned Alignment; // Minimum alignment requirement of CP (not log2 value). unsigned char TargetFlags; friend class SelectionDAG; - ConstantPoolSDNode(bool isTarget, Constant *c, MVT VT, int o, unsigned Align, + ConstantPoolSDNode(bool isTarget, Constant *c, EVT VT, int o, unsigned Align, unsigned char TF) : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, DebugLoc::getUnknownLoc(), @@ -1896,7 +1875,7 @@ class ConstantPoolSDNode : public SDNode { Val.ConstVal = c; } ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, - MVT VT, int o, unsigned Align, unsigned char TF) + EVT VT, int o, unsigned Align, unsigned char TF) : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, DebugLoc::getUnknownLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { @@ -1988,10 +1967,6 @@ public: /// used when the SelectionDAG needs to make a simple reference to something /// in the LLVM IR representation. /// -/// Note that this is not used for carrying alias information; that is done -/// with MemOperandSDNode, which includes a Value which is required to be a -/// pointer, and several other fields specific to memory references. -/// class SrcValueSDNode : public SDNode { const Value *V; friend class SelectionDAG; @@ -2011,32 +1986,10 @@ public: }; -/// MemOperandSDNode - An SDNode that holds a MachineMemOperand. This is -/// used to represent a reference to memory after ISD::LOAD -/// and ISD::STORE have been lowered. -/// -class MemOperandSDNode : public SDNode { - friend class SelectionDAG; - /// Create a MachineMemOperand node - explicit MemOperandSDNode(const MachineMemOperand &mo) - : SDNode(ISD::MEMOPERAND, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), MO(mo) {} - -public: - /// MO - The contained MachineMemOperand. - const MachineMemOperand MO; - - static bool classof(const MemOperandSDNode *) { return true; } - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MEMOPERAND; - } -}; - - class RegisterSDNode : public SDNode { unsigned Reg; friend class SelectionDAG; - RegisterSDNode(unsigned reg, MVT VT) + RegisterSDNode(unsigned reg, EVT VT) : SDNode(ISD::Register, DebugLoc::getUnknownLoc(), getSDVTList(VT)), Reg(reg) { } @@ -2054,10 +2007,10 @@ class DbgStopPointSDNode : public SDNode { SDUse Chain; unsigned Line; unsigned Column; - Value *CU; + MDNode *CU; friend class SelectionDAG; DbgStopPointSDNode(SDValue ch, unsigned l, unsigned c, - Value *cu) + MDNode *cu) : SDNode(ISD::DBG_STOPPOINT, DebugLoc::getUnknownLoc(), getSDVTList(MVT::Other)), Line(l), Column(c), CU(cu) { InitOperands(&Chain, ch); @@ -2065,7 +2018,7 @@ class DbgStopPointSDNode : public SDNode { public: unsigned getLine() const { return Line; } unsigned getColumn() const { return Column; } - Value *getCompileUnit() const { return CU; } + MDNode *getCompileUnit() const { return CU; } static bool classof(const DbgStopPointSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -2096,7 +2049,7 @@ class ExternalSymbolSDNode : public SDNode { unsigned char TargetFlags; friend class SelectionDAG; - ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, MVT VT) + ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT) : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, DebugLoc::getUnknownLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { @@ -2135,7 +2088,7 @@ public: class CvtRndSatSDNode : public SDNode { ISD::CvtCode CvtCode; friend class SelectionDAG; - explicit CvtRndSatSDNode(MVT VT, DebugLoc dl, const SDValue *Ops, + explicit CvtRndSatSDNode(EVT VT, DebugLoc dl, const SDValue *Ops, unsigned NumOps, ISD::CvtCode Code) : SDNode(ISD::CONVERT_RNDSAT, dl, getSDVTList(VT), Ops, NumOps), CvtCode(Code) { @@ -2233,93 +2186,54 @@ namespace ISD { /// getRawBits - Represent the flags as a bunch of bits. uint64_t getRawBits() const { return Flags; } }; -} - -/// ARG_FLAGSSDNode - Leaf node holding parameter flags. -class ARG_FLAGSSDNode : public SDNode { - ISD::ArgFlagsTy TheFlags; - friend class SelectionDAG; - explicit ARG_FLAGSSDNode(ISD::ArgFlagsTy Flags) - : SDNode(ISD::ARG_FLAGS, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), TheFlags(Flags) { - } -public: - ISD::ArgFlagsTy getArgFlags() const { return TheFlags; } - - static bool classof(const ARG_FLAGSSDNode *) { return true; } - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::ARG_FLAGS; - } -}; - -/// CallSDNode - Node for calls -- ISD::CALL. -class CallSDNode : public SDNode { - unsigned CallingConv; - bool IsVarArg; - bool IsTailCall; - unsigned NumFixedArgs; - // We might eventually want a full-blown Attributes for the result; that - // will expand the size of the representation. At the moment we only - // need Inreg. - bool Inreg; - friend class SelectionDAG; - CallSDNode(unsigned cc, DebugLoc dl, bool isvararg, bool istailcall, - bool isinreg, SDVTList VTs, const SDValue *Operands, - unsigned numOperands, unsigned numFixedArgs) - : SDNode(ISD::CALL, dl, VTs, Operands, numOperands), - CallingConv(cc), IsVarArg(isvararg), IsTailCall(istailcall), - NumFixedArgs(numFixedArgs), Inreg(isinreg) {} -public: - unsigned getCallingConv() const { return CallingConv; } - unsigned isVarArg() const { return IsVarArg; } - unsigned isTailCall() const { return IsTailCall; } - unsigned isInreg() const { return Inreg; } - - /// Set this call to not be marked as a tail call. Normally setter - /// methods in SDNodes are unsafe because it breaks the CSE map, - /// but we don't include the tail call flag for calls so it's ok - /// in this case. - void setNotTailCall() { IsTailCall = false; } - - SDValue getChain() const { return getOperand(0); } - SDValue getCallee() const { return getOperand(1); } - unsigned getNumArgs() const { return (getNumOperands() - 2) / 2; } - unsigned getNumFixedArgs() const { - if (isVarArg()) - return NumFixedArgs; - else - return getNumArgs(); - } - SDValue getArg(unsigned i) const { return getOperand(2+2*i); } - SDValue getArgFlagsVal(unsigned i) const { - return getOperand(3+2*i); - } - ISD::ArgFlagsTy getArgFlags(unsigned i) const { - return cast<ARG_FLAGSSDNode>(getArgFlagsVal(i).getNode())->getArgFlags(); - } - - unsigned getNumRetVals() const { return getNumValues() - 1; } - MVT getRetValType(unsigned i) const { return getValueType(i); } + /// InputArg - This struct carries flags and type information about a + /// single incoming (formal) argument or incoming (from the perspective + /// of the caller) return value virtual register. + /// + struct InputArg { + ArgFlagsTy Flags; + EVT VT; + bool Used; + + InputArg() : VT(MVT::Other), Used(false) {} + InputArg(ISD::ArgFlagsTy flags, EVT vt, bool used) + : Flags(flags), VT(vt), Used(used) { + assert(VT.isSimple() && + "InputArg value type must be Simple!"); + } + }; - static bool classof(const CallSDNode *) { return true; } - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::CALL; - } -}; + /// OutputArg - This struct carries flags and a value for a + /// single outgoing (actual) argument or outgoing (from the perspective + /// of the caller) return value virtual register. + /// + struct OutputArg { + ArgFlagsTy Flags; + SDValue Val; + bool IsFixed; + + OutputArg() : IsFixed(false) {} + OutputArg(ISD::ArgFlagsTy flags, SDValue val, bool isfixed) + : Flags(flags), Val(val), IsFixed(isfixed) { + assert(Val.getValueType().isSimple() && + "OutputArg value type must be Simple!"); + } + }; +} -/// VTSDNode - This class is used to represent MVT's, which are used +/// VTSDNode - This class is used to represent EVT's, which are used /// to parameterize some operations. class VTSDNode : public SDNode { - MVT ValueType; + EVT ValueType; friend class SelectionDAG; - explicit VTSDNode(MVT VT) + explicit VTSDNode(EVT VT) : SDNode(ISD::VALUETYPE, DebugLoc::getUnknownLoc(), getSDVTList(MVT::Other)), ValueType(VT) { } public: - MVT getVT() const { return ValueType; } + EVT getVT() const { return ValueType; } static bool classof(const VTSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -2340,9 +2254,8 @@ class LSBaseSDNode : public MemSDNode { public: LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands, unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, - MVT VT, const Value *SV, int SVO, unsigned Align, bool Vol) - : MemSDNode(NodeTy, dl, VTs, VT, SV, SVO, Align, Vol) { - assert(Align != 0 && "Loads and stores should have non-zero aligment"); + EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, dl, VTs, MemVT, MMO) { SubclassData |= AM << 2; assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); InitOperands(Ops, Operands, numOperands); @@ -2378,12 +2291,14 @@ public: class LoadSDNode : public LSBaseSDNode { friend class SelectionDAG; LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, ISD::LoadExtType ETy, MVT LVT, - const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, + MachineMemOperand *MMO) : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, - VTs, AM, LVT, SV, O, Align, Vol) { + VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)ETy; assert(getExtensionType() == ETy && "LoadExtType encoding error!"); + assert(readMem() && "Load MachineMemOperand is not a load!"); + assert(!writeMem() && "Load MachineMemOperand is a store!"); } public: @@ -2407,12 +2322,14 @@ public: class StoreSDNode : public LSBaseSDNode { friend class SelectionDAG; StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, MVT SVT, - const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, - VTs, AM, SVT, SV, O, Align, Vol) { + VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)isTrunc; assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); + assert(!readMem() && "Store MachineMemOperand is a load!"); + assert(writeMem() && "Store MachineMemOperand is not a store!"); } public: @@ -2431,8 +2348,47 @@ public: } }; +/// MachineSDNode - An SDNode that represents everything that will be needed +/// to construct a MachineInstr. These nodes are created during the +/// instruction selection proper phase. +/// +class MachineSDNode : public SDNode { +public: + typedef MachineMemOperand **mmo_iterator; + +private: + friend class SelectionDAG; + MachineSDNode(unsigned Opc, const DebugLoc DL, SDVTList VTs) + : SDNode(Opc, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + + /// LocalOperands - Operands for this instruction, if they fit here. If + /// they don't, this field is unused. + SDUse LocalOperands[4]; + + /// MemRefs - Memory reference descriptions for this instruction. + mmo_iterator MemRefs; + mmo_iterator MemRefsEnd; + +public: + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + + /// setMemRefs - Assign this MachineSDNodes's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } + + static bool classof(const MachineSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->isMachineOpcode(); + } +}; -class SDNodeIterator : public forward_iterator<SDNode, ptrdiff_t> { +class SDNodeIterator : public std::iterator<std::forward_iterator_tag, + SDNode, ptrdiff_t> { SDNode *Node; unsigned Operand; @@ -2490,7 +2446,7 @@ typedef LoadSDNode LargestSDNode; /// MostAlignedSDNode - The SDNode class with the greatest alignment /// requirement. /// -typedef ARG_FLAGSSDNode MostAlignedSDNode; +typedef GlobalAddressSDNode MostAlignedSDNode; namespace ISD { /// isNormalLoad - Returns true if the specified node is a non-extending diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index e661c58..1f0dd21 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -23,8 +23,10 @@ namespace llvm { class Type; + class LLVMContext; + struct EVT; - struct MVT { // MVT = Machine Value Type + class MVT { // MVT = Machine Value Type public: enum SimpleValueType { // If you change this numbering, you must change the values in @@ -59,184 +61,368 @@ namespace llvm { v8i16 = 21, // 8 x i16 v16i16 = 22, // 16 x i16 v2i32 = 23, // 2 x i32 - v3i32 = 24, // 3 x i32 - v4i32 = 25, // 4 x i32 - v8i32 = 26, // 8 x i32 - v1i64 = 27, // 1 x i64 - v2i64 = 28, // 2 x i64 - v4i64 = 29, // 4 x i64 - - v2f32 = 30, // 2 x f32 - v3f32 = 31, // 3 x f32 - v4f32 = 32, // 4 x f32 - v8f32 = 33, // 8 x f32 - v2f64 = 34, // 2 x f64 - v4f64 = 35, // 4 x f64 - + v4i32 = 24, // 4 x i32 + v8i32 = 25, // 8 x i32 + v1i64 = 26, // 1 x i64 + v2i64 = 27, // 2 x i64 + v4i64 = 28, // 4 x i64 + + v2f32 = 29, // 2 x f32 + v4f32 = 30, // 4 x f32 + v8f32 = 31, // 8 x f32 + v2f64 = 32, // 2 x f64 + v4f64 = 33, // 4 x f64 + FIRST_VECTOR_VALUETYPE = v2i8, LAST_VECTOR_VALUETYPE = v4f64, - LAST_VALUETYPE = 36, // This always remains at the end of the list. + LAST_VALUETYPE = 34, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. - // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors + // EVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors // This value must be a multiple of 32. MAX_ALLOWED_VALUETYPE = 64, + // Metadata - This is MDNode or MDString. + Metadata = 250, + // iPTRAny - An int value the size of the pointer of the current // target to any address space. This must only be used internal to // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. - iPTRAny = 252, + iPTRAny = 251, + + // vAny - A vector with any length and element size. This is used + // for intrinsics that have overloadings based on vector types. + // This is only for tblgen's consumption! + vAny = 252, // fAny - Any floating-point or vector floating-point value. This is used // for intrinsics that have overloadings based on floating-point types. // This is only for tblgen's consumption! - fAny = 253, + fAny = 253, // iAny - An integer or vector integer value of any bit width. This is // used for intrinsics that have overloadings based on integer bit widths. // This is only for tblgen's consumption! - iAny = 254, + iAny = 254, // iPTR - An int value the size of the pointer of the current // target. This should only be used internal to tblgen! - iPTR = 255, + iPTR = 255, // LastSimpleValueType - The greatest valid SimpleValueType value. - LastSimpleValueType = 255 - }; + LastSimpleValueType = 255, - private: - /// This union holds low-level value types. Valid values include any of - /// the values in the SimpleValueType enum, or any value returned from one - /// of the MVT methods. Any value type equal to one of the SimpleValueType - /// enum values is a "simple" value type. All others are "extended". - /// - /// Note that simple doesn't necessary mean legal for the target machine. - /// All legal value types must be simple, but often there are some simple - /// value types that are not legal. - /// - union { - uintptr_t V; - const Type *LLVMTy; + // INVALID_SIMPLE_VALUE_TYPE - Simple value types greater than or equal + // to this are considered extended value types. + INVALID_SIMPLE_VALUE_TYPE = LastSimpleValueType + 1 }; - public: - MVT() {} - MVT(SimpleValueType S) : V(S) {} + SimpleValueType SimpleTy; + + MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {} + MVT(SimpleValueType SVT) : SimpleTy(SVT) { } + + bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } + bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } + bool operator==(const MVT& S) const { return SimpleTy == S.SimpleTy; } + bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } + bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. + bool isFloatingPoint() const { + return ((SimpleTy >= MVT::f32 && SimpleTy <= MVT::ppcf128) || + (SimpleTy >= MVT::v2f32 && SimpleTy <= MVT::v4f64)); + } + + /// isInteger - Return true if this is an integer, or a vector integer type. + bool isInteger() const { + return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && + SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || + (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v4i64)); + } - bool operator==(const MVT VT) const { - return getRawBits() == VT.getRawBits(); + /// isVector - Return true if this is a vector value type. + bool isVector() const { + return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); } - bool operator!=(const MVT VT) const { - return getRawBits() != VT.getRawBits(); + + /// isPow2VectorType - Retuns true if the given vector is a power of 2. + bool isPow2VectorType() const { + unsigned NElts = getVectorNumElements(); + return !(NElts & (NElts - 1)); } - /// getFloatingPointVT - Returns the MVT that represents a floating point - /// type with the given number of bits. There are two floating point types - /// with 128 bits - this returns f128 rather than ppcf128. + /// getPow2VectorType - Widens the length of the given vector EVT up to + /// the nearest power of 2 and returns that type. + MVT getPow2VectorType() const { + if (!isPow2VectorType()) { + unsigned NElts = getVectorNumElements(); + unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); + return MVT::getVectorVT(getVectorElementType(), Pow2NElts); + } + else { + return *this; + } + } + + MVT getVectorElementType() const { + switch (SimpleTy) { + default: + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case v2i8 : + case v4i8 : + case v8i8 : + case v16i8: + case v32i8: return i8; + case v2i16: + case v4i16: + case v8i16: + case v16i16: return i16; + case v2i32: + case v4i32: + case v8i32: return i32; + case v1i64: + case v2i64: + case v4i64: return i64; + case v2f32: + case v4f32: + case v8f32: return f32; + case v2f64: + case v4f64: return f64; + } + } + + unsigned getVectorNumElements() const { + switch (SimpleTy) { + default: + return ~0U; + case v32i8: return 32; + case v16i8: + case v16i16: return 16; + case v8i8 : + case v8i16: + case v8i32: + case v8f32: return 8; + case v4i8: + case v4i16: + case v4i32: + case v4i64: + case v4f32: + case v4f64: return 4; + case v2i8: + case v2i16: + case v2i32: + case v2i64: + case v2f32: + case v2f64: return 2; + case v1i64: return 1; + } + } + + unsigned getSizeInBits() const { + switch (SimpleTy) { + case iPTR: + assert(0 && "Value type size is target-dependent. Ask TLI."); + case iPTRAny: + case iAny: + case fAny: + assert(0 && "Value type is overloaded."); + default: + assert(0 && "getSizeInBits called on extended MVT."); + case i1 : return 1; + case i8 : return 8; + case i16 : + case v2i8: return 16; + case f32 : + case i32 : + case v4i8: + case v2i16: return 32; + case f64 : + case i64 : + case v8i8: + case v4i16: + case v2i32: + case v1i64: + case v2f32: return 64; + case f80 : return 80; + case f128: + case ppcf128: + case i128: + case v16i8: + case v8i16: + case v4i32: + case v2i64: + case v4f32: + case v2f64: return 128; + case v32i8: + case v16i16: + case v8i32: + case v4i64: + case v8f32: + case v4f64: return 256; + } + } + static MVT getFloatingPointVT(unsigned BitWidth) { switch (BitWidth) { default: assert(false && "Bad bit width!"); case 32: - return f32; + return MVT::f32; case 64: - return f64; + return MVT::f64; case 80: - return f80; + return MVT::f80; case 128: - return f128; + return MVT::f128; } } - - /// getIntegerVT - Returns the MVT that represents an integer with the given - /// number of bits. + static MVT getIntegerVT(unsigned BitWidth) { switch (BitWidth) { default: - break; + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); case 1: - return i1; + return MVT::i1; case 8: - return i8; + return MVT::i8; case 16: - return i16; + return MVT::i16; case 32: - return i32; + return MVT::i32; case 64: - return i64; + return MVT::i64; case 128: - return i128; + return MVT::i128; } - return getExtendedIntegerVT(BitWidth); } - - /// getVectorVT - Returns the MVT that represents a vector NumElements in - /// length, where each element is of type VT. + static MVT getVectorVT(MVT VT, unsigned NumElements) { - switch (VT.V) { + switch (VT.SimpleTy) { default: break; - case i8: - if (NumElements == 2) return v2i8; - if (NumElements == 4) return v4i8; - if (NumElements == 8) return v8i8; - if (NumElements == 16) return v16i8; - if (NumElements == 32) return v32i8; + case MVT::i8: + if (NumElements == 2) return MVT::v2i8; + if (NumElements == 4) return MVT::v4i8; + if (NumElements == 8) return MVT::v8i8; + if (NumElements == 16) return MVT::v16i8; + if (NumElements == 32) return MVT::v32i8; break; - case i16: - if (NumElements == 2) return v2i16; - if (NumElements == 4) return v4i16; - if (NumElements == 8) return v8i16; - if (NumElements == 16) return v16i16; + case MVT::i16: + if (NumElements == 2) return MVT::v2i16; + if (NumElements == 4) return MVT::v4i16; + if (NumElements == 8) return MVT::v8i16; + if (NumElements == 16) return MVT::v16i16; break; - case i32: - if (NumElements == 2) return v2i32; - if (NumElements == 3) return v3i32; - if (NumElements == 4) return v4i32; - if (NumElements == 8) return v8i32; + case MVT::i32: + if (NumElements == 2) return MVT::v2i32; + if (NumElements == 4) return MVT::v4i32; + if (NumElements == 8) return MVT::v8i32; break; - case i64: - if (NumElements == 1) return v1i64; - if (NumElements == 2) return v2i64; - if (NumElements == 4) return v4i64; + case MVT::i64: + if (NumElements == 1) return MVT::v1i64; + if (NumElements == 2) return MVT::v2i64; + if (NumElements == 4) return MVT::v4i64; break; - case f32: - if (NumElements == 2) return v2f32; - if (NumElements == 3) return v3f32; - if (NumElements == 4) return v4f32; - if (NumElements == 8) return v8f32; + case MVT::f32: + if (NumElements == 2) return MVT::v2f32; + if (NumElements == 4) return MVT::v4f32; + if (NumElements == 8) return MVT::v8f32; break; - case f64: - if (NumElements == 2) return v2f64; - if (NumElements == 4) return v4f64; + case MVT::f64: + if (NumElements == 2) return MVT::v2f64; + if (NumElements == 4) return MVT::v4f64; break; } - return getExtendedVectorVT(VT, NumElements); + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); } - - /// getIntVectorWithNumElements - Return any integer vector type that has - /// the specified number of elements. + static MVT getIntVectorWithNumElements(unsigned NumElts) { switch (NumElts) { - default: return getVectorVT(i8, NumElts); - case 1: return v1i64; - case 2: return v2i32; - case 3: return v3i32; - case 4: return v4i16; - case 8: return v8i8; - case 16: return v16i8; + default: return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case 1: return MVT::v1i64; + case 2: return MVT::v2i32; + case 4: return MVT::v4i16; + case 8: return MVT::v8i8; + case 16: return MVT::v16i8; + } + } + }; + + struct EVT { // EVT = Extended Value Type + private: + MVT V; + const Type *LLVMTy; + + public: + EVT() : V((MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE)), + LLVMTy(0) {} + EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(0) { } + EVT(MVT S) : V(S), LLVMTy(0) {} + + bool operator==(const EVT VT) const { + if (V.SimpleTy == VT.V.SimpleTy) { + if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return LLVMTy == VT.LLVMTy; + return true; + } + return false; + } + bool operator!=(const EVT VT) const { + if (V.SimpleTy == VT.V.SimpleTy) { + if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return LLVMTy != VT.LLVMTy; + return false; } + return true; + } + + /// getFloatingPointVT - Returns the EVT that represents a floating point + /// type with the given number of bits. There are two floating point types + /// with 128 bits - this returns f128 rather than ppcf128. + static EVT getFloatingPointVT(unsigned BitWidth) { + return MVT::getFloatingPointVT(BitWidth); + } + + /// getIntegerVT - Returns the EVT that represents an integer with the given + /// number of bits. + static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) { + MVT M = MVT::getIntegerVT(BitWidth); + if (M.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return getExtendedIntegerVT(Context, BitWidth); + else + return M; + } + + /// getVectorVT - Returns the EVT that represents a vector NumElements in + /// length, where each element is of type VT. + static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements) { + MVT M = MVT::getVectorVT(VT.V, NumElements); + if (M.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return getExtendedVectorVT(Context, VT, NumElements); + else + return M; + } + + /// getIntVectorWithNumElements - Return any integer vector type that has + /// the specified number of elements. + static EVT getIntVectorWithNumElements(LLVMContext &C, unsigned NumElts) { + MVT M = MVT::getIntVectorWithNumElements(NumElts); + if (M.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return getVectorVT(C, MVT::i8, NumElts); + else + return M; } - /// isSimple - Test if the given MVT is simple (as opposed to being + /// isSimple - Test if the given EVT is simple (as opposed to being /// extended). bool isSimple() const { - return V <= LastSimpleValueType; + return V.SimpleTy <= MVT::LastSimpleValueType; } - /// isExtended - Test if the given MVT is extended (as opposed to + /// isExtended - Test if the given EVT is extended (as opposed to /// being simple). bool isExtended() const { return !isSimple(); @@ -245,44 +431,53 @@ namespace llvm { /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return isSimple() ? - ((V >= f32 && V <= ppcf128) || - (V >= v2f32 && V <= v4f64)) : isExtendedFloatingPoint(); + ((V >= MVT::f32 && V <= MVT::ppcf128) || + (V >= MVT::v2f32 && V <= MVT::v4f64)) : isExtendedFloatingPoint(); } /// isInteger - Return true if this is an integer, or a vector integer type. bool isInteger() const { return isSimple() ? - ((V >= FIRST_INTEGER_VALUETYPE && V <= LAST_INTEGER_VALUETYPE) || - (V >= v2i8 && V <= v4i64)) : isExtendedInteger(); + ((V >= MVT::FIRST_INTEGER_VALUETYPE && + V <= MVT::LAST_INTEGER_VALUETYPE) || + (V >= MVT::v2i8 && V <= MVT::v4i64)) : isExtendedInteger(); } /// isVector - Return true if this is a vector value type. bool isVector() const { return isSimple() ? - (V >= FIRST_VECTOR_VALUETYPE && V <= LAST_VECTOR_VALUETYPE) : + (V >= MVT::FIRST_VECTOR_VALUETYPE && V <= + MVT::LAST_VECTOR_VALUETYPE) : isExtendedVector(); } /// is64BitVector - Return true if this is a 64-bit vector type. bool is64BitVector() const { return isSimple() ? - (V==v8i8 || V==v4i16 || V==v2i32 || V==v1i64 || V==v2f32) : + (V==MVT::v8i8 || V==MVT::v4i16 || V==MVT::v2i32 || + V==MVT::v1i64 || V==MVT::v2f32) : isExtended64BitVector(); } /// is128BitVector - Return true if this is a 128-bit vector type. bool is128BitVector() const { return isSimple() ? - (V==v16i8 || V==v8i16 || V==v4i32 || - V==v2i64 || V==v4f32 || V==v2f64) : + (V==MVT::v16i8 || V==MVT::v8i16 || V==MVT::v4i32 || + V==MVT::v2i64 || V==MVT::v4f32 || V==MVT::v2f64) : isExtended128BitVector(); } /// is256BitVector - Return true if this is a 256-bit vector type. inline bool is256BitVector() const { - return isSimple() ? - (V==v8f32 || V==v4f64 || V==v32i8 || V==v16i16 || V==v8i32 || - V==v4i64) : isExtended256BitVector(); + return isSimple() ? + (V==MVT::v8f32 || V==MVT::v4f64 || V==MVT::v32i8 || + V==MVT::v16i16 || V==MVT::v8i32 || V==MVT::v4i64) : + isExtended256BitVector(); + } + + /// isOverloaded - Return true if this is an overloaded type for TableGen. + bool isOverloaded() const { + return (V==MVT::iAny || V==MVT::fAny || V==MVT::vAny || V==MVT::iPTRAny); } /// isByteSized - Return true if the bit size is a multiple of 8. @@ -297,165 +492,88 @@ namespace llvm { } /// bitsEq - Return true if this has the same number of bits as VT. - bool bitsEq(MVT VT) const { + bool bitsEq(EVT VT) const { return getSizeInBits() == VT.getSizeInBits(); } /// bitsGT - Return true if this has more bits than VT. - bool bitsGT(MVT VT) const { + bool bitsGT(EVT VT) const { return getSizeInBits() > VT.getSizeInBits(); } /// bitsGE - Return true if this has no less bits than VT. - bool bitsGE(MVT VT) const { + bool bitsGE(EVT VT) const { return getSizeInBits() >= VT.getSizeInBits(); } /// bitsLT - Return true if this has less bits than VT. - bool bitsLT(MVT VT) const { + bool bitsLT(EVT VT) const { return getSizeInBits() < VT.getSizeInBits(); } /// bitsLE - Return true if this has no more bits than VT. - bool bitsLE(MVT VT) const { + bool bitsLE(EVT VT) const { return getSizeInBits() <= VT.getSizeInBits(); } /// getSimpleVT - Return the SimpleValueType held in the specified - /// simple MVT. - SimpleValueType getSimpleVT() const { + /// simple EVT. + MVT getSimpleVT() const { assert(isSimple() && "Expected a SimpleValueType!"); - return SimpleValueType(V); + return V; } /// getVectorElementType - Given a vector type, return the type of /// each element. - MVT getVectorElementType() const { + EVT getVectorElementType() const { assert(isVector() && "Invalid vector type!"); - switch (V) { - default: + if (isSimple()) + return V.getVectorElementType(); + else return getExtendedVectorElementType(); - case v2i8 : - case v4i8 : - case v8i8 : - case v16i8: - case v32i8: return i8; - case v2i16: - case v4i16: - case v8i16: - case v16i16: return i16; - case v2i32: - case v3i32: - case v4i32: - case v8i32: return i32; - case v1i64: - case v2i64: - case v4i64: return i64; - case v2f32: - case v3f32: - case v4f32: - case v8f32: return f32; - case v2f64: - case v4f64: return f64; - } } /// getVectorNumElements - Given a vector type, return the number of /// elements it contains. unsigned getVectorNumElements() const { assert(isVector() && "Invalid vector type!"); - switch (V) { - default: + if (isSimple()) + return V.getVectorNumElements(); + else return getExtendedVectorNumElements(); - case v32i8: return 32; - case v16i8: - case v16i16: return 16; - case v8i8 : - case v8i16: - case v8i32: - case v8f32: return 8; - case v4i8: - case v4i16: - case v4i32: - case v4i64: - case v4f32: - case v4f64: return 4; - case v3i32: - case v3f32: return 3; - case v2i8: - case v2i16: - case v2i32: - case v2i64: - case v2f32: - case v2f64: return 2; - case v1i64: return 1; - } } /// getSizeInBits - Return the size of the specified value type in bits. unsigned getSizeInBits() const { - switch (V) { - case iPTR: - assert(0 && "Value type size is target-dependent. Ask TLI."); - case iPTRAny: - case iAny: - case fAny: - assert(0 && "Value type is overloaded."); - default: + if (isSimple()) + return V.getSizeInBits(); + else return getExtendedSizeInBits(); - case i1 : return 1; - case i8 : return 8; - case i16 : - case v2i8: return 16; - case f32 : - case i32 : - case v4i8: - case v2i16: return 32; - case f64 : - case i64 : - case v8i8: - case v4i16: - case v2i32: - case v1i64: - case v2f32: return 64; - case f80 : return 80; - case v3i32: - case v3f32: return 96; - case f128: - case ppcf128: - case i128: - case v16i8: - case v8i16: - case v4i32: - case v2i64: - case v4f32: - case v2f64: return 128; - case v32i8: - case v16i16: - case v8i32: - case v4i64: - case v8f32: - case v4f64: return 256; - } + } + + /// getStoreSize - Return the number of bytes overwritten by a store + /// of the specified value type. + unsigned getStoreSize() const { + return (getSizeInBits() + 7) / 8; } /// getStoreSizeInBits - Return the number of bits overwritten by a store /// of the specified value type. unsigned getStoreSizeInBits() const { - return (getSizeInBits() + 7)/8*8; + return getStoreSize() * 8; } - /// getRoundIntegerType - Rounds the bit-width of the given integer MVT up + /// getRoundIntegerType - Rounds the bit-width of the given integer EVT up /// to the nearest power of two (and at least to eight), and returns the - /// integer MVT with that number of bits. - MVT getRoundIntegerType() const { + /// integer EVT with that number of bits. + EVT getRoundIntegerType(LLVMContext &Context) const { assert(isInteger() && !isVector() && "Invalid integer type!"); unsigned BitWidth = getSizeInBits(); if (BitWidth <= 8) - return i8; + return EVT(MVT::i8); else - return getIntegerVT(1 << Log2_32_Ceil(BitWidth)); + return getIntegerVT(Context, 1 << Log2_32_Ceil(BitWidth)); } /// isPow2VectorType - Retuns true if the given vector is a power of 2. @@ -464,41 +582,48 @@ namespace llvm { return !(NElts & (NElts - 1)); } - /// getPow2VectorType - Widens the length of the given vector MVT up to + /// getPow2VectorType - Widens the length of the given vector EVT up to /// the nearest power of 2 and returns that type. - MVT getPow2VectorType() const { + EVT getPow2VectorType(LLVMContext &Context) const { if (!isPow2VectorType()) { unsigned NElts = getVectorNumElements(); unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); - return MVT::getVectorVT(getVectorElementType(), Pow2NElts); + return EVT::getVectorVT(Context, getVectorElementType(), Pow2NElts); } else { return *this; } } - /// getMVTString - This function returns value type as a string, + /// getEVTString - This function returns value type as a string, /// e.g. "i32". - std::string getMVTString() const; + std::string getEVTString() const; - /// getTypeForMVT - This method returns an LLVM type corresponding to the - /// specified MVT. For integer types, this returns an unsigned type. Note + /// getTypeForEVT - This method returns an LLVM type corresponding to the + /// specified EVT. For integer types, this returns an unsigned type. Note /// that this will abort for types that cannot be represented. - const Type *getTypeForMVT() const; + const Type *getTypeForEVT(LLVMContext &Context) const; - /// getMVT - Return the value type corresponding to the specified type. + /// getEVT - Return the value type corresponding to the specified type. /// This returns all pointers as iPTR. If HandleUnknown is true, unknown /// types are returned as Other, otherwise they are invalid. - static MVT getMVT(const Type *Ty, bool HandleUnknown = false); + static EVT getEVT(const Type *Ty, bool HandleUnknown = false); - /// getRawBits - Represent the type as a bunch of bits. - uintptr_t getRawBits() const { return V; } + intptr_t getRawBits() { + if (V.SimpleTy <= MVT::LastSimpleValueType) + return V.SimpleTy; + else + return (intptr_t)(LLVMTy); + } /// compareRawBits - A meaningless but well-behaved order, useful for /// constructing containers. struct compareRawBits { - bool operator()(MVT L, MVT R) const { - return L.getRawBits() < R.getRawBits(); + bool operator()(EVT L, EVT R) const { + if (L.V.SimpleTy == R.V.SimpleTy) + return L.LLVMTy < R.LLVMTy; + else + return L.V.SimpleTy < R.V.SimpleTy; } }; @@ -506,15 +631,16 @@ namespace llvm { // Methods for handling the Extended-type case in functions above. // These are all out-of-line to prevent users of this header file // from having a dependency on Type.h. - static MVT getExtendedIntegerVT(unsigned BitWidth); - static MVT getExtendedVectorVT(MVT VT, unsigned NumElements); + static EVT getExtendedIntegerVT(LLVMContext &C, unsigned BitWidth); + static EVT getExtendedVectorVT(LLVMContext &C, EVT VT, + unsigned NumElements); bool isExtendedFloatingPoint() const; bool isExtendedInteger() const; bool isExtendedVector() const; bool isExtended64BitVector() const; bool isExtended128BitVector() const; bool isExtended256BitVector() const; - MVT getExtendedVectorElementType() const; + EVT getExtendedVectorElementType() const; unsigned getExtendedVectorNumElements() const; unsigned getExtendedSizeInBits() const; }; diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index 7f6728b..986555b 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -44,23 +44,26 @@ def v4i16 : ValueType<64 , 20>; // 4 x i16 vector value def v8i16 : ValueType<128, 21>; // 8 x i16 vector value def v16i16 : ValueType<256, 22>; // 16 x i16 vector value def v2i32 : ValueType<64 , 23>; // 2 x i32 vector value -def v3i32 : ValueType<96 , 24>; // 3 x i32 vector value -def v4i32 : ValueType<128, 25>; // 4 x i32 vector value -def v8i32 : ValueType<256, 26>; // 8 x f32 vector value -def v1i64 : ValueType<64 , 27>; // 1 x i64 vector value -def v2i64 : ValueType<128, 28>; // 2 x i64 vector value -def v4i64 : ValueType<256, 29>; // 4 x f64 vector value +def v4i32 : ValueType<128, 24>; // 4 x i32 vector value +def v8i32 : ValueType<256, 25>; // 8 x i32 vector value +def v1i64 : ValueType<64 , 26>; // 1 x i64 vector value +def v2i64 : ValueType<128, 27>; // 2 x i64 vector value +def v4i64 : ValueType<256, 28>; // 4 x f64 vector value + +def v2f32 : ValueType<64, 29>; // 2 x f32 vector value +def v4f32 : ValueType<128, 30>; // 4 x f32 vector value +def v8f32 : ValueType<256, 31>; // 8 x f32 vector value +def v2f64 : ValueType<128, 32>; // 2 x f64 vector value +def v4f64 : ValueType<256, 33>; // 4 x f64 vector value + +def MetadataVT: ValueType<0, 250>; // Metadata -def v2f32 : ValueType<64, 30>; // 2 x f32 vector value -def v3f32 : ValueType<96 , 31>; // 3 x f32 vector value -def v4f32 : ValueType<128, 32>; // 4 x f32 vector value -def v8f32 : ValueType<256, 33>; // 8 x f32 vector value -def v2f64 : ValueType<128, 34>; // 2 x f64 vector value -def v4f64 : ValueType<256, 35>; // 4 x f64 vector value - // Pseudo valuetype mapped to the current pointer size to any address space. // Should only be used in TableGen. -def iPTRAny : ValueType<0, 252>; +def iPTRAny : ValueType<0, 251>; + +// Pseudo valuetype to represent "vector of any size" +def vAny : ValueType<0 , 252>; // Pseudo valuetype to represent "float of any format" def fAny : ValueType<0 , 253>; |