From 37ed9c199ca639565f6ce88105f9e39e898d82d0 Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 1 Dec 2014 14:51:49 -0800 Subject: Update aosp/master LLVM for rebase to r222494. Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d --- include/llvm/Target/Target.td | 20 +- include/llvm/Target/TargetCallingConv.td | 16 ++ include/llvm/Target/TargetInstrInfo.h | 212 ++++++++++++++++++- include/llvm/Target/TargetIntrinsicInfo.h | 2 +- include/llvm/Target/TargetJITInfo.h | 137 ------------- include/llvm/Target/TargetLibraryInfo.h | 27 ++- include/llvm/Target/TargetLowering.h | 272 +++++++++++++++++++------ include/llvm/Target/TargetLoweringObjectFile.h | 5 +- include/llvm/Target/TargetMachine.h | 95 ++------- include/llvm/Target/TargetOpcodes.h | 8 +- include/llvm/Target/TargetOptions.h | 43 +++- include/llvm/Target/TargetRegisterInfo.h | 39 ++-- include/llvm/Target/TargetSchedule.td | 2 + include/llvm/Target/TargetSelectionDAG.td | 13 +- include/llvm/Target/TargetSelectionDAGInfo.h | 2 +- include/llvm/Target/TargetSubtargetInfo.h | 75 ++++++- 16 files changed, 648 insertions(+), 320 deletions(-) delete mode 100644 include/llvm/Target/TargetJITInfo.h (limited to 'include/llvm/Target') diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index f77cc7a..902647e 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -378,9 +378,18 @@ class Instruction { bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction. bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement? bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement? + bit isRegSequence = 0; // Is this instruction a kind of reg sequence? + // If so, make sure to override + // TargetInstrInfo::getRegSequenceLikeInputs. bit isPseudo = 0; // Is this instruction a pseudo-instruction? // If so, won't have encoding information for // the [MC]CodeEmitter stuff. + bit isExtractSubreg = 0; // Is this instruction a kind of extract subreg? + // If so, make sure to override + // TargetInstrInfo::getExtractSubregLikeInputs. + bit isInsertSubreg = 0; // Is this instruction a kind of insert subreg? + // If so, make sure to override + // TargetInstrInfo::getInsertSubregLikeInputs. // Side effect flags - When set, the flags have these meanings: // @@ -583,7 +592,6 @@ class Operand : DAGOperand { string PrintMethod = "printOperand"; string EncoderMethod = ""; string DecoderMethod = ""; - string AsmOperandLowerMethod = ?; string OperandType = "OPERAND_UNKNOWN"; dag MIOperandInfo = (ops); @@ -797,7 +805,7 @@ def DBG_VALUE : Instruction { } def REG_SEQUENCE : Instruction { let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins variable_ops); + let InOperandList = (ins unknown:$supersrc, variable_ops); let AsmString = ""; let neverHasSideEffects = 1; let isAsCheapAsAMove = 1; @@ -841,6 +849,14 @@ def PATCHPOINT : Instruction { let mayLoad = 1; let usesCustomInserter = 1; } +def LOAD_STACK_GUARD : Instruction { + let OutOperandList = (outs ptr_rc:$dst); + let InOperandList = (ins); + let mayLoad = 1; + bit isReMaterializable = 1; + let hasSideEffects = 0; + bit isPseudo = 1; +} } //===----------------------------------------------------------------------===// diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index 8f31e08..2e766c4 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -67,6 +67,9 @@ class CCIfSplit : CCIf<"ArgFlags.isSplit()", A> {} /// the specified action. class CCIfSRet : CCIf<"ArgFlags.isSRet()", A> {} +/// CCIfVarArg - If the current function is vararg - apply the action +class CCIfVarArg : CCIf<"State.isVarArg()", A> {} + /// CCIfNotVarArg - If the current function is not vararg - apply the action class CCIfNotVarArg : CCIf<"!State.isVarArg()", A> {} @@ -119,6 +122,12 @@ class CCPromoteToType : CCAction { ValueType DestTy = destTy; } +/// CCPromoteToUpperBitsInType - If applied, this promotes the specified current +/// value to the specified type and shifts the value into the upper bits. +class CCPromoteToUpperBitsInType : CCAction { + ValueType DestTy = destTy; +} + /// CCBitConvertToType - If applied, this bitconverts the specified current /// value to the specified type. class CCBitConvertToType : CCAction { @@ -141,6 +150,13 @@ class CCDelegateTo : CCAction { /// that the target supports. class CallingConv actions> { list Actions = actions; + bit Custom = 0; +} + +/// CustomCallingConv - An instance of this is used to declare calling +/// conventions that are implemented using a custom function of the same name. +class CustomCallingConv : CallingConv<[]> { + let Custom = 1; } /// CalleeSavedRegs - A list of callee saved registers for a given calling diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index a589d0e..a37a7f9 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -15,9 +15,11 @@ #define LLVM_TARGET_TARGETINSTRINFO_H #include "llvm/ADT/SmallSet.h" -#include "llvm/CodeGen/DFAPacketizer.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineCombinerPattern.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" namespace llvm { @@ -28,7 +30,7 @@ class MachineMemOperand; class MachineRegisterInfo; class MDNode; class MCInst; -class MCSchedModel; +struct MCSchedModel; class MCSymbolRefExpr; class SDNode; class ScheduleHazardRecognizer; @@ -38,6 +40,7 @@ class TargetRegisterClass; class TargetRegisterInfo; class BranchProbability; class TargetSubtargetInfo; +class DFAPacketizer; template class SmallVectorImpl; @@ -261,6 +264,85 @@ public: virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const; + /// A pair composed of a register and a sub-register index. + /// Used to give some type checking when modeling Reg:SubReg. + struct RegSubRegPair { + unsigned Reg; + unsigned SubReg; + RegSubRegPair(unsigned Reg = 0, unsigned SubReg = 0) + : Reg(Reg), SubReg(SubReg) {} + }; + /// A pair composed of a pair of a register and a sub-register index, + /// and another sub-register index. + /// Used to give some type checking when modeling Reg:SubReg1, SubReg2. + struct RegSubRegPairAndIdx : RegSubRegPair { + unsigned SubIdx; + RegSubRegPairAndIdx(unsigned Reg = 0, unsigned SubReg = 0, + unsigned SubIdx = 0) + : RegSubRegPair(Reg, SubReg), SubIdx(SubIdx) {} + }; + + /// Build the equivalent inputs of a REG_SEQUENCE for the given \p MI + /// and \p DefIdx. + /// \p [out] InputRegs of the equivalent REG_SEQUENCE. Each element of + /// the list is modeled as . + /// E.g., REG_SEQUENCE vreg1:sub1, sub0, vreg2, sub1 would produce + /// two elements: + /// - vreg1:sub1, sub0 + /// - vreg2<:0>, sub1 + /// + /// \returns true if it is possible to build such an input sequence + /// with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isRegSequence() or MI.isRegSequenceLike(). + /// + /// \note The generic implementation does not provide any support for + /// MI.isRegSequenceLike(). In other words, one has to override + /// getRegSequenceLikeInputs for target specific instructions. + bool + getRegSequenceInputs(const MachineInstr &MI, unsigned DefIdx, + SmallVectorImpl &InputRegs) const; + + /// Build the equivalent inputs of a EXTRACT_SUBREG for the given \p MI + /// and \p DefIdx. + /// \p [out] InputReg of the equivalent EXTRACT_SUBREG. + /// E.g., EXTRACT_SUBREG vreg1:sub1, sub0, sub1 would produce: + /// - vreg1:sub1, sub0 + /// + /// \returns true if it is possible to build such an input sequence + /// with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isExtractSubreg() or MI.isExtractSubregLike(). + /// + /// \note The generic implementation does not provide any support for + /// MI.isExtractSubregLike(). In other words, one has to override + /// getExtractSubregLikeInputs for target specific instructions. + bool + getExtractSubregInputs(const MachineInstr &MI, unsigned DefIdx, + RegSubRegPairAndIdx &InputReg) const; + + /// Build the equivalent inputs of a INSERT_SUBREG for the given \p MI + /// and \p DefIdx. + /// \p [out] BaseReg and \p [out] InsertedReg contain + /// the equivalent inputs of INSERT_SUBREG. + /// E.g., INSERT_SUBREG vreg0:sub0, vreg1:sub1, sub3 would produce: + /// - BaseReg: vreg0:sub0 + /// - InsertedReg: vreg1:sub1, sub3 + /// + /// \returns true if it is possible to build such an input sequence + /// with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isInsertSubreg() or MI.isInsertSubregLike(). + /// + /// \note The generic implementation does not provide any support for + /// MI.isInsertSubregLike(). In other words, one has to override + /// getInsertSubregLikeInputs for target specific instructions. + bool + getInsertSubregInputs(const MachineInstr &MI, unsigned DefIdx, + RegSubRegPair &BaseReg, + RegSubRegPairAndIdx &InsertedReg) const; + + /// produceSameValue - Return true if two machine instructions would produce /// identical values. By default, this is only true when the two instructions /// are deemed identical except for defs. If this function is called when the @@ -346,6 +428,26 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!"); } + /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold + /// either the instruction returned by getUnconditionalBranch or the + /// instruction returned by getTrap. This only makes sense because + /// getUnconditionalBranch returns a single, specific instruction. This + /// information is needed by the jumptable construction code, since it must + /// decide how many bytes to use for a jumptable entry so it can generate the + /// right mask. + /// + /// Note that if the jumptable instruction requires alignment, then that + /// alignment should be factored into this required bound so that the + /// resulting bound gives the right alignment for the instruction. + virtual unsigned getJumpInstrTableEntryBound() const { + // This method gets called by LLVMTargetMachine always, so it can't fail + // just because there happens to be no implementation for this target. + // Any code that tries to use a jumptable annotation without defining + // getUnconditionalBranch on the appropriate Target will fail anyway, and + // the value returned here won't matter in that case. + return 0; + } + /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic /// block at the specified instruction (i.e. instruction would be the start /// of a new basic block). @@ -572,6 +674,42 @@ public: const SmallVectorImpl &Ops, MachineInstr* LoadMI) const; + /// hasPattern - return true when there is potentially a faster code sequence + /// for an instruction chain ending in \p Root. All potential pattern are + /// returned in the \p Pattern vector. Pattern should be sorted in priority + /// order since the pattern evaluator stops checking as soon as it finds a + /// faster sequence. + /// \param Root - Instruction that could be combined with one of its operands + /// \param Pattern - Vector of possible combination pattern + + virtual bool hasPattern( + MachineInstr &Root, + SmallVectorImpl &Pattern) const { + return false; + } + + /// genAlternativeCodeSequence - when hasPattern() finds a pattern this + /// function generates the instructions that could replace the original code + /// sequence. The client has to decide whether the actual replacementment is + /// beneficial or not. + /// \param Root - Instruction that could be combined with one of its operands + /// \param P - Combination pattern for Root + /// \param InsInstrs - Vector of new instructions that implement P + /// \param DelInstrs - Old instructions, including Root, that could be replaced + /// by InsInstr + /// \param InstrIdxForVirtReg - map of virtual register to instruction in + /// InsInstr that defines it + virtual void genAlternativeCodeSequence( + MachineInstr &Root, MachineCombinerPattern::MC_PATTERN P, + SmallVectorImpl &InsInstrs, + SmallVectorImpl &DelInstrs, + DenseMap &InstrIdxForVirtReg) const { + return; + } + + /// useMachineCombiner - return true when a target supports MachineCombiner + virtual bool useMachineCombiner() const { return false; } + protected: /// foldMemoryOperandImpl - Target-dependent implementation for /// foldMemoryOperand. Target-independent code in foldMemoryOperand will @@ -593,6 +731,49 @@ protected: return nullptr; } + /// \brief Target-dependent implementation of getRegSequenceInputs. + /// + /// \returns true if it is possible to build the equivalent + /// REG_SEQUENCE inputs with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isRegSequenceLike(). + /// + /// \see TargetInstrInfo::getRegSequenceInputs. + virtual bool getRegSequenceLikeInputs( + const MachineInstr &MI, unsigned DefIdx, + SmallVectorImpl &InputRegs) const { + return false; + } + + /// \brief Target-dependent implementation of getExtractSubregInputs. + /// + /// \returns true if it is possible to build the equivalent + /// EXTRACT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isExtractSubregLike(). + /// + /// \see TargetInstrInfo::getExtractSubregInputs. + virtual bool getExtractSubregLikeInputs( + const MachineInstr &MI, unsigned DefIdx, + RegSubRegPairAndIdx &InputReg) const { + return false; + } + + /// \brief Target-dependent implementation of getInsertSubregInputs. + /// + /// \returns true if it is possible to build the equivalent + /// INSERT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. + /// + /// \pre MI.isInsertSubregLike(). + /// + /// \see TargetInstrInfo::getInsertSubregInputs. + virtual bool + getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, + RegSubRegPair &BaseReg, + RegSubRegPairAndIdx &InsertedReg) const { + return false; + } + public: /// canFoldMemoryOperand - Returns true for the specified load / store if /// folding is possible. @@ -686,10 +867,8 @@ public: MachineBasicBlock::iterator MI) const; - /// getNoopForMachoTarget - Return the noop instruction to use for a noop. - virtual void getNoopForMachoTarget(MCInst &NopInst) const { - // Default to just using 'nop' string. - } + /// Return the noop instruction to use for a noop. + virtual void getNoopForMachoTarget(MCInst &NopInst) const; /// isPredicated - Returns true if the instruction is already predicated. @@ -793,6 +972,7 @@ public: const MachineRegisterInfo *MRI) const { return false; } + virtual bool optimizeCondBranch(MachineInstr *MI) const { return false; } /// optimizeLoadInstr - Try to remove the load by folding it to a register /// operand at the use. We fold the load instructions if and only if the @@ -871,7 +1051,7 @@ public: SDNode *Node) const; /// Return the default expected latency for a def based on it's opcode. - unsigned defaultDefLatency(const MCSchedModel *SchedModel, + unsigned defaultDefLatency(const MCSchedModel &SchedModel, const MachineInstr *DefMI) const; int computeDefOperandLatency(const InstrItineraryData *ItinData, @@ -1026,11 +1206,25 @@ public: const TargetRegisterInfo *TRI) const {} /// Create machine specific model for scheduling. - virtual DFAPacketizer* - CreateTargetScheduleState(const TargetMachine*, const ScheduleDAG*) const { + virtual DFAPacketizer * + CreateTargetScheduleState(const TargetSubtargetInfo &) const { return nullptr; } + // areMemAccessesTriviallyDisjoint - Sometimes, it is possible for the target + // to tell, even without aliasing information, that two MIs access different + // memory addresses. This function returns true if two MIs access different + // memory addresses, and false otherwise. + virtual bool + areMemAccessesTriviallyDisjoint(MachineInstr *MIa, MachineInstr *MIb, + AliasAnalysis *AA = nullptr) const { + assert(MIa && (MIa->mayLoad() || MIa->mayStore()) && + "MIa must load from or modify a memory location"); + assert(MIb && (MIb->mayLoad() || MIb->mayStore()) && + "MIb must load from or modify a memory location"); + return false; + } + private: int CallFrameSetupOpcode, CallFrameDestroyOpcode; }; diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h index 6de264e..71c0166 100644 --- a/include/llvm/Target/TargetIntrinsicInfo.h +++ b/include/llvm/Target/TargetIntrinsicInfo.h @@ -52,7 +52,7 @@ public: /// Returns true if the intrinsic can be overloaded. virtual bool isOverloaded(unsigned IID) const = 0; - + /// Create or insert an LLVM Function declaration for an intrinsic, /// and return it. The Tys and numTys are for intrinsics with overloaded /// types. See above for more information. diff --git a/include/llvm/Target/TargetJITInfo.h b/include/llvm/Target/TargetJITInfo.h deleted file mode 100644 index f9bd0fb..0000000 --- a/include/llvm/Target/TargetJITInfo.h +++ /dev/null @@ -1,137 +0,0 @@ -//===- Target/TargetJITInfo.h - Target Information for JIT ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file exposes an abstract interface used by the Just-In-Time code -// generator to perform target-specific activities, such as emitting stubs. If -// a TargetMachine supports JIT code generation, it should provide one of these -// objects through the getJITInfo() method. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETJITINFO_H -#define LLVM_TARGET_TARGETJITINFO_H - -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/ErrorHandling.h" -#include - -namespace llvm { - class Function; - class GlobalValue; - class JITCodeEmitter; - class MachineRelocation; - - /// TargetJITInfo - Target specific information required by the Just-In-Time - /// code generator. - class TargetJITInfo { - virtual void anchor(); - public: - virtual ~TargetJITInfo() {} - - /// replaceMachineCodeForFunction - Make it so that calling the function - /// whose machine code is at OLD turns into a call to NEW, perhaps by - /// overwriting OLD with a branch to NEW. This is used for self-modifying - /// code. - /// - virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0; - - /// emitGlobalValueIndirectSym - Use the specified JITCodeEmitter object - /// to emit an indirect symbol which contains the address of the specified - /// ptr. - virtual void *emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, - JITCodeEmitter &JCE) { - llvm_unreachable("This target doesn't implement " - "emitGlobalValueIndirectSym!"); - } - - /// Records the required size and alignment for a call stub in bytes. - struct StubLayout { - size_t Size; - size_t Alignment; - }; - /// Returns the maximum size and alignment for a call stub on this target. - virtual StubLayout getStubLayout() { - llvm_unreachable("This target doesn't implement getStubLayout!"); - } - - /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a - /// small native function that simply calls the function at the specified - /// address. The JITCodeEmitter must already have storage allocated for the - /// stub. Return the address of the resultant function, which may have been - /// aligned from the address the JCE was set up to emit at. - virtual void *emitFunctionStub(const Function* F, void *Target, - JITCodeEmitter &JCE) { - llvm_unreachable("This target doesn't implement emitFunctionStub!"); - } - - /// getPICJumpTableEntry - Returns the value of the jumptable entry for the - /// specific basic block. - virtual uintptr_t getPICJumpTableEntry(uintptr_t BB, uintptr_t JTBase) { - llvm_unreachable("This target doesn't implement getPICJumpTableEntry!"); - } - - /// LazyResolverFn - This typedef is used to represent the function that - /// unresolved call points should invoke. This is a target specific - /// function that knows how to walk the stack and find out which stub the - /// call is coming from. - typedef void (*LazyResolverFn)(); - - /// JITCompilerFn - This typedef is used to represent the JIT function that - /// lazily compiles the function corresponding to a stub. The JIT keeps - /// track of the mapping between stubs and LLVM Functions, the target - /// provides the ability to figure out the address of a stub that is called - /// by the LazyResolverFn. - typedef void* (*JITCompilerFn)(void *); - - /// getLazyResolverFunction - This method is used to initialize the JIT, - /// giving the target the function that should be used to compile a - /// function, and giving the JIT the target function used to do the lazy - /// resolving. - virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn) { - llvm_unreachable("Not implemented for this target!"); - } - - /// relocate - Before the JIT can run a block of code that has been emitted, - /// it must rewrite the code to contain the actual addresses of any - /// referenced global symbols. - virtual void relocate(void *Function, MachineRelocation *MR, - unsigned NumRelocs, unsigned char* GOTBase) { - assert(NumRelocs == 0 && "This target does not have relocations!"); - } - - - /// allocateThreadLocalMemory - Each target has its own way of - /// handling thread local variables. This method returns a value only - /// meaningful to the target. - virtual char* allocateThreadLocalMemory(size_t size) { - llvm_unreachable("This target does not implement thread local storage!"); - } - - /// needsGOT - Allows a target to specify that it would like the - /// JIT to manage a GOT for it. - bool needsGOT() const { return useGOT; } - - /// hasCustomConstantPool - Allows a target to specify that constant - /// pool address resolution is handled by the target. - virtual bool hasCustomConstantPool() const { return false; } - - /// hasCustomJumpTables - Allows a target to specify that jumptables - /// are emitted by the target. - virtual bool hasCustomJumpTables() const { return false; } - - /// allocateSeparateGVMemory - If true, globals should be placed in - /// separately allocated heap memory rather than in the same - /// code memory allocated by JITCodeEmitter. - virtual bool allocateSeparateGVMemory() const { return false; } - protected: - bool useGOT; - }; -} // End llvm namespace - -#endif diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index 93c9aa3..249849b 100644 --- a/include/llvm/Target/TargetLibraryInfo.h +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -37,10 +37,18 @@ namespace llvm { ZdaPv, /// void operator delete[](void*, nothrow); ZdaPvRKSt9nothrow_t, + /// void operator delete[](void*, unsigned int); + ZdaPvj, + /// void operator delete[](void*, unsigned long); + ZdaPvm, /// void operator delete(void*); ZdlPv, /// void operator delete(void*, nothrow); ZdlPvRKSt9nothrow_t, + /// void operator delete(void*, unsigned int); + ZdlPvj, + /// void operator delete(void*, unsigned long); + ZdlPvm, /// void *new[](unsigned int); Znaj, /// void *new[](unsigned int, nothrow); @@ -65,7 +73,7 @@ namespace llvm { cxa_atexit, /// void __cxa_guard_abort(guard_t *guard); /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. - cxa_guard_abort, + cxa_guard_abort, /// int __cxa_guard_acquire(guard_t *guard); cxa_guard_acquire, /// void __cxa_guard_release(guard_t *guard); @@ -76,6 +84,11 @@ namespace llvm { dunder_isoc99_sscanf, /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); memcpy_chk, + /// void *__memmove_chk(void *s1, const void *s2, size_t n, + /// size_t s1size); + memmove_chk, + /// void *__memset_chk(void *s, char v, size_t n, size_t s1size); + memset_chk, /// double __sincospi_stret(double x); sincospi_stret, /// float __sincospif_stret(float x); @@ -90,8 +103,18 @@ namespace llvm { sqrtf_finite, /// long double __sqrt_finite(long double x); sqrtl_finite, + /// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size); + stpcpy_chk, + /// char *__stpncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + stpncpy_chk, + /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); + strcpy_chk, /// char * __strdup(const char *s); dunder_strdup, + /// char *__strncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + strncpy_chk, /// char *__strndup(const char *s, size_t n); dunder_strndup, /// char * __strtok_r(char *s, const char *delim, char **save_ptr); @@ -707,7 +730,7 @@ public: TargetLibraryInfo(); TargetLibraryInfo(const Triple &T); explicit TargetLibraryInfo(const TargetLibraryInfo &TLI); - + /// getLibFunc - Search for a particular function name. If it is one of the /// known library functions, return true and set F to the corresponding value. bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 5e9978d..882dab4 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -31,6 +31,7 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IRBuilder.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetCallingConv.h" @@ -136,10 +137,9 @@ public: llvm_unreachable("Invalid content kind"); } - /// NOTE: The constructor takes ownership of TLOF. - explicit TargetLoweringBase(const TargetMachine &TM, - const TargetLoweringObjectFile *TLOF); - virtual ~TargetLoweringBase(); + /// NOTE: The TargetMachine owns TLOF. + explicit TargetLoweringBase(const TargetMachine &TM); + virtual ~TargetLoweringBase() {} protected: /// \brief Initialize all of the actions to default values. @@ -148,7 +148,9 @@ protected: public: const TargetMachine &getTargetMachine() const { return TM; } const DataLayout *getDataLayout() const { return DL; } - const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; } + const TargetLoweringObjectFile &getObjFileLowering() const { + return *TM.getObjFileLowering(); + } bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } @@ -223,8 +225,8 @@ public: return BypassSlowDivWidths; } - /// Return true if pow2 div is cheaper than a chain of srl/add/sra. - bool isPow2DivCheap() const { return Pow2DivIsCheap; } + /// Return true if pow2 sdiv is cheaper than a chain of sra/srl/add/sra. + bool isPow2SDivCheap() const { return Pow2SDivIsCheap; } /// Return true if Flow Control is an expensive operation that should be /// avoided. @@ -262,10 +264,27 @@ public: return MaskAndBranchFoldingIsLegal; } - /// Return the ValueType of the result of SETCC operations. Also used to - /// obtain the target's preferred type for the condition operand of SELECT and - /// BRCOND nodes. In the case of BRCOND the argument passed is MVT::Other - /// since there are no other operands to get a type hint from. + /// Return true if the target can combine store(extractelement VectorTy, + /// Idx). + /// \p Cost[out] gives the cost of that transformation when this is true. + virtual bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, + unsigned &Cost) const { + return false; + } + + /// Return true if target supports floating point exceptions. + bool hasFloatingPointExceptions() const { + return HasFloatingPointExceptions; + } + + /// Return true if target always beneficiates from combining into FMA for a + /// given value type. This must typically return false on targets where FMA + /// takes more cycles to execute than FADD. + virtual bool enableAggressiveFMAFusion(EVT VT) const { + return false; + } + + /// Return the ValueType of the result of SETCC operations. virtual EVT getSetCCResultType(LLVMContext &Context, EVT VT) const; /// Return the ValueType for comparison libcalls. Comparions libcalls include @@ -426,10 +445,15 @@ public: EVT memVT; // memory VT const Value* ptrVal; // value representing memory location int offset; // offset off of ptrVal + unsigned size; // the size of the memory location + // (taken from memVT if zero) unsigned align; // alignment bool vol; // is volatile? bool readMem; // reads memory? bool writeMem; // writes memory? + + IntrinsicInfo() : opc(0), ptrVal(nullptr), offset(0), size(0), align(1), + vol(false), readMem(false), writeMem(false) {} }; /// Given an intrinsic, checks if on the target the intrinsic will need to map @@ -517,10 +541,12 @@ public: /// Return how this load with extension should be treated: either it is legal, /// needs to be promoted to a larger size, needs to be expanded to some other /// code sequence, or the target has a custom expander for it. - LegalizeAction getLoadExtAction(unsigned ExtType, MVT VT) const { - assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && + LegalizeAction getLoadExtAction(unsigned ExtType, EVT VT) const { + if (VT.isExtended()) return Expand; + unsigned I = (unsigned) VT.getSimpleVT().SimpleTy; + assert(ExtType < ISD::LAST_LOADEXT_TYPE && I < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)LoadExtActions[VT.SimpleTy][ExtType]; + return (LegalizeAction)LoadExtActions[I][ExtType]; } /// Return true if the specified load with extension is legal on this target. @@ -532,11 +558,13 @@ public: /// Return how this store with truncation should be treated: either it is /// legal, needs to be promoted to a larger size, needs to be expanded to some /// other code sequence, or the target has a custom expander for it. - LegalizeAction getTruncStoreAction(MVT ValVT, MVT MemVT) const { - assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && + LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const { + if (ValVT.isExtended() || MemVT.isExtended()) return Expand; + unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; + unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; + assert(ValI < MVT::LAST_VALUETYPE && MemI < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)TruncStoreActions[ValVT.SimpleTy] - [MemVT.SimpleTy]; + return (LegalizeAction)TruncStoreActions[ValI][MemI]; } /// Return true if the specified store with truncation is legal on this @@ -773,14 +801,15 @@ public: /// /// This function returns true if the target allows unaligned memory accesses /// of the specified type in the given address space. If true, it also returns - /// whether the unaligned memory access is "fast" in the third argument by + /// whether the unaligned memory access is "fast" in the last argument by /// reference. This is used, for example, in situations where an array /// copy/move/set is converted to a sequence of store operations. Its use /// helps to ensure that such replacements don't generate code that causes an /// alignment error (trap) on the target machine. - virtual bool allowsUnalignedMemoryAccesses(EVT, - unsigned AddrSpace = 0, - bool * /*Fast*/ = nullptr) const { + virtual bool allowsMisalignedMemoryAccesses(EVT, + unsigned AddrSpace = 0, + unsigned Align = 1, + bool * /*Fast*/ = nullptr) const { return false; } @@ -823,11 +852,6 @@ public: return UseUnderscoreLongJmp; } - /// Return whether the target can generate code for jump tables. - bool supportJumpTables() const { - return SupportJumpTables; - } - /// Return integer threshold on number of blocks to use jump tables rather /// than if sequence. int getMinimumJumpTableEntries() const { @@ -922,9 +946,13 @@ public: /// @} //===--------------------------------------------------------------------===// - /// \name Helpers for load-linked/store-conditional atomic expansion. + /// \name Helpers for atomic expansion. /// @{ + /// True if AtomicExpandPass should use emitLoadLinked/emitStoreConditional + /// and expand AtomicCmpXchgInst. + virtual bool hasLoadLinkedStoreConditional() const { return false; } + /// Perform a load-linked operation on Addr, returning a "Value *" with the /// corresponding pointee type. This may entail some non-trivial operations to /// truncate or reconstruct types that will be illegal in the backend. See @@ -941,15 +969,90 @@ public: llvm_unreachable("Store conditional unimplemented on this target"); } - /// Return true if the given (atomic) instruction should be expanded by the - /// IR-level AtomicExpandLoadLinked pass into a loop involving - /// load-linked/store-conditional pairs. Atomic stores will be expanded in the - /// same way as "atomic xchg" operations which ignore their output if needed. - virtual bool shouldExpandAtomicInIR(Instruction *Inst) const { + /// Inserts in the IR a target-specific intrinsic specifying a fence. + /// It is called by AtomicExpandPass before expanding an + /// AtomicRMW/AtomicCmpXchg/AtomicStore/AtomicLoad. + /// RMW and CmpXchg set both IsStore and IsLoad to true. + /// This function should either return a nullptr, or a pointer to an IR-level + /// Instruction*. Even complex fence sequences can be represented by a + /// single Instruction* through an intrinsic to be lowered later. + /// Backends with !getInsertFencesForAtomic() should keep a no-op here. + /// Backends should override this method to produce target-specific intrinsic + /// for their fences. + /// FIXME: Please note that the default implementation here in terms of + /// IR-level fences exists for historical/compatibility reasons and is + /// *unsound* ! Fences cannot, in general, be used to restore sequential + /// consistency. For example, consider the following example: + /// atomic x = y = 0; + /// int r1, r2, r3, r4; + /// Thread 0: + /// x.store(1); + /// Thread 1: + /// y.store(1); + /// Thread 2: + /// r1 = x.load(); + /// r2 = y.load(); + /// Thread 3: + /// r3 = y.load(); + /// r4 = x.load(); + /// r1 = r3 = 1 and r2 = r4 = 0 is impossible as long as the accesses are all + /// seq_cst. But if they are lowered to monotonic accesses, no amount of + /// IR-level fences can prevent it. + /// @{ + virtual Instruction* emitLeadingFence(IRBuilder<> &Builder, AtomicOrdering Ord, + bool IsStore, bool IsLoad) const { + if (!getInsertFencesForAtomic()) + return nullptr; + + if (isAtLeastRelease(Ord) && IsStore) + return Builder.CreateFence(Ord); + else + return nullptr; + } + + virtual Instruction* emitTrailingFence(IRBuilder<> &Builder, AtomicOrdering Ord, + bool IsStore, bool IsLoad) const { + if (!getInsertFencesForAtomic()) + return nullptr; + + if (isAtLeastAcquire(Ord)) + return Builder.CreateFence(Ord); + else + return nullptr; + } + /// @} + + /// Returns true if the given (atomic) store should be expanded by the + /// IR-level AtomicExpand pass into an "atomic xchg" which ignores its input. + virtual bool shouldExpandAtomicStoreInIR(StoreInst *SI) const { return false; } + /// Returns true if the given (atomic) load should be expanded by the + /// IR-level AtomicExpand pass into a load-linked instruction + /// (through emitLoadLinked()). + virtual bool shouldExpandAtomicLoadInIR(LoadInst *LI) const { return false; } + + /// Returns true if the given AtomicRMW should be expanded by the + /// IR-level AtomicExpand pass into a loop using LoadLinked/StoreConditional. + virtual bool shouldExpandAtomicRMWInIR(AtomicRMWInst *RMWI) const { + return false; + } + /// On some platforms, an AtomicRMW that never actually modifies the value + /// (such as fetch_add of 0) can be turned into a fence followed by an + /// atomic load. This may sound useless, but it makes it possible for the + /// processor to keep the cacheline shared, dramatically improving + /// performance. And such idempotent RMWs are useful for implementing some + /// kinds of locks, see for example (justification + benchmarks): + /// http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf + /// This method tries doing that transformation, returning the atomic load if + /// it succeeds, and nullptr otherwise. + /// If shouldExpandAtomicLoadInIR returns true on that load, it will undergo + /// another round of expansion. + virtual LoadInst *lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const { + return nullptr; + } //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. @@ -996,11 +1099,6 @@ protected: UseUnderscoreLongJmp = Val; } - /// Indicate whether the target can generate code for jump tables. - void setSupportJumpTables(bool Val) { - SupportJumpTables = Val; - } - /// Indicate the number of blocks to generate jump tables rather than if /// sequence. void setMinimumJumpTableEntries(int Val) { @@ -1058,15 +1156,21 @@ protected: /// possible, should be replaced by an alternate sequence of instructions not /// containing an integer divide. void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; } + + /// Tells the code generator that this target supports floating point + /// exceptions and cares about preserving floating point exception behavior. + void setHasFloatingPointExceptions(bool FPExceptions = true) { + HasFloatingPointExceptions = FPExceptions; + } /// Tells the code generator which bitwidths to bypass. void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) { BypassSlowDivWidths[SlowBitWidth] = FastBitWidth; } - /// Tells the code generator that it shouldn't generate srl/add/sra for a - /// signed divide by power of two, and let the target handle it. - void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap = isCheap; } + /// Tells the code generator that it shouldn't generate sra/srl/add/sra for a + /// signed divide by power of two; let the target handle it. + void setPow2SDivIsCheap(bool isCheap = true) { Pow2SDivIsCheap = isCheap; } /// Add the specified register class as an available regclass for the /// specified value type. This indicates the selector can handle values of @@ -1451,7 +1555,6 @@ public: private: const TargetMachine &TM; const DataLayout *DL; - const TargetLoweringObjectFile &TLOF; /// True if this is a little endian target. bool IsLittleEndian; @@ -1485,15 +1588,19 @@ private: /// div/rem when the operands are positive and less than 256. DenseMap BypassSlowDivWidths; - /// Tells the code generator that it shouldn't generate srl/add/sra for a - /// signed divide by power of two, and let the target handle it. - bool Pow2DivIsCheap; + /// Tells the code generator that it shouldn't generate sra/srl/add/sra for a + /// signed divide by power of two; let the target handle it. + bool Pow2SDivIsCheap; /// Tells the code generator that it shouldn't generate extra flow control /// instructions and should attempt to combine flow control instructions via /// predication. bool JumpIsExpensive; + /// Whether the target supports or cares about preserving floating point + /// exception behavior. + bool HasFloatingPointExceptions; + /// This target prefers to use _setjmp to implement llvm.setjmp. /// /// Defaults to false. @@ -1504,10 +1611,6 @@ private: /// Defaults to false. bool UseUnderscoreLongJmp; - /// Whether the target can generate code for jumptables. If it's not true, - /// then each jumptable must be lowered into if-then-else's. - bool SupportJumpTables; - /// Number of blocks threshold to use jump tables. int MinimumJumpTableEntries; @@ -1635,7 +1738,7 @@ public: LegalizeTypeAction LA = ValueTypeActions.getTypeAction(SVT); assert( - (LA == TypeLegal || + (LA == TypeLegal || LA == TypeSoftenFloat || ValueTypeActions.getTypeAction(NVT) != TypePromoteInteger) && "Promote may not follow Expand or Promote"); @@ -1861,9 +1964,8 @@ class TargetLowering : public TargetLoweringBase { void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION; public: - /// NOTE: The constructor takes ownership of TLOF. - explicit TargetLowering(const TargetMachine &TM, - const TargetLoweringObjectFile *TLOF); + /// NOTE: The TargetMachine owns TLOF. + explicit TargetLowering(const TargetMachine &TM); /// Returns true by value, base pointer and offset pointer and addressing mode /// by reference if the node's address can be legally represented as @@ -2324,9 +2426,9 @@ public: /// all the time, e.g. i1 on x86-64. It is also not necessary for non-C /// calling conventions. The frontend should handle this and include all of /// the necessary information. - virtual MVT getTypeForExtArgOrReturn(MVT VT, + virtual EVT getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT, ISD::NodeType /*ExtendKind*/) const { - MVT MinVT = getRegisterType(MVT::i32); + EVT MinVT = getRegisterType(Context, MVT::i32); return VT.bitsLT(MinVT) ? MinVT : VT; } @@ -2474,11 +2576,10 @@ public: unsigned getMatchedOperand() const; /// Copy constructor for copying from a ConstraintInfo. - AsmOperandInfo(const InlineAsm::ConstraintInfo &info) - : InlineAsm::ConstraintInfo(info), - ConstraintType(TargetLowering::C_Unknown), - CallOperandVal(nullptr), ConstraintVT(MVT::Other) { - } + AsmOperandInfo(InlineAsm::ConstraintInfo Info) + : InlineAsm::ConstraintInfo(std::move(Info)), + ConstraintType(TargetLowering::C_Unknown), CallOperandVal(nullptr), + ConstraintVT(MVT::Other) {} }; typedef std::vector AsmOperandInfoVector; @@ -2545,6 +2646,45 @@ public: SDValue BuildUDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, bool IsAfterLegalization, std::vector *Created) const; + virtual SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, + SelectionDAG &DAG, + std::vector *Created) const { + return SDValue(); + } + + /// Hooks for building estimates in place of slower divisions and square + /// roots. + + /// Return a reciprocal square root estimate value for the input operand. + /// The RefinementSteps output is the number of Newton-Raphson refinement + /// iterations required to generate a sufficient (though not necessarily + /// IEEE-754 compliant) estimate for the value type. + /// The boolean UseOneConstNR output is used to select a Newton-Raphson + /// algorithm implementation that uses one constant or two constants. + /// A target may choose to implement its own refinement within this function. + /// If that's true, then return '0' as the number of RefinementSteps to avoid + /// any further refinement of the estimate. + /// An empty SDValue return means no estimate sequence can be created. + virtual SDValue getRsqrtEstimate(SDValue Operand, + DAGCombinerInfo &DCI, + unsigned &RefinementSteps, + bool &UseOneConstNR) const { + return SDValue(); + } + + /// Return a reciprocal estimate value for the input operand. + /// The RefinementSteps output is the number of Newton-Raphson refinement + /// iterations required to generate a sufficient (though not necessarily + /// IEEE-754 compliant) estimate for the value type. + /// A target may choose to implement its own refinement within this function. + /// If that's true, then return '0' as the number of RefinementSteps to avoid + /// any further refinement of the estimate. + /// An empty SDValue return means no estimate sequence can be created. + virtual SDValue getRecipEstimate(SDValue Operand, + DAGCombinerInfo &DCI, + unsigned &RefinementSteps) const { + return SDValue(); + } //===--------------------------------------------------------------------===// // Legalization utility functions @@ -2564,6 +2704,12 @@ public: SDValue LH = SDValue(), SDValue RL = SDValue(), SDValue RH = SDValue()) const; + /// Expand float(f32) to SINT(i64) conversion + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandFP_TO_SINT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + //===--------------------------------------------------------------------===// // Instruction Emitting Hooks // @@ -2583,6 +2729,12 @@ public: /// ARM 's' setting instructions. virtual void AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const; + + /// If this function returns true, SelectionDAGBuilder emits a + /// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector. + virtual bool useLoadStackGuardNode() const { + return false; + } }; /// Given an LLVM IR type and return type attributes, compute the return value diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 419eced..7fcb171 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -70,7 +70,8 @@ public: /// Given a constant with the SectionKind, return a section that it should be /// placed in. - virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + virtual const MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const; /// Classify the specified global variable into a set of target independent /// categories embodied in SectionKind. @@ -159,7 +160,7 @@ public: protected: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler &Mang, const TargetMachine &TM) const; + Mangler &Mang, const TargetMachine &TM) const = 0; }; } // end namespace llvm diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index b263c57..a4f95c0 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -24,7 +24,6 @@ namespace llvm { class InstrItineraryData; -class JITCodeEmitter; class GlobalValue; class Mangler; class MCAsmInfo; @@ -35,9 +34,7 @@ class Target; class DataLayout; class TargetLibraryInfo; class TargetFrameLowering; -class TargetInstrInfo; class TargetIntrinsicInfo; -class TargetJITInfo; class TargetLowering; class TargetPassConfig; class TargetRegisterInfo; @@ -47,6 +44,7 @@ class ScalarTargetTransformInfo; class VectorTargetTransformInfo; class formatted_raw_ostream; class raw_ostream; +class TargetLoweringObjectFile; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { @@ -87,47 +85,27 @@ protected: // Can only create subclasses. unsigned RequireStructuredCFG : 1; public: + mutable TargetOptions Options; + virtual ~TargetMachine(); const Target &getTarget() const { return TheTarget; } - const StringRef getTargetTriple() const { return TargetTriple; } - const StringRef getTargetCPU() const { return TargetCPU; } - const StringRef getTargetFeatureString() const { return TargetFS; } + StringRef getTargetTriple() const { return TargetTriple; } + StringRef getTargetCPU() const { return TargetCPU; } + StringRef getTargetFeatureString() const { return TargetFS; } /// getSubtargetImpl - virtual method implemented by subclasses that returns /// a reference to that target's TargetSubtargetInfo-derived member variable. virtual const TargetSubtargetInfo *getSubtargetImpl() const { return nullptr; } - - mutable TargetOptions Options; - - /// \brief Reset the target options based on the function's attributes. - void resetTargetOptions(const MachineFunction *MF) const; - - // Interfaces to the major aspects of target machine information: - // - // -- Instruction opcode and operand information - // -- Pipelines and scheduling information - // -- Stack frame information - // -- Selection DAG lowering information - // - // N.B. These objects may change during compilation. It's not safe to cache - // them between functions. - virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; } - virtual const TargetFrameLowering *getFrameLowering() const { - return nullptr; + virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const { + return getSubtargetImpl(); } - virtual const TargetLowering *getTargetLowering() const { return nullptr; } - virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const { + virtual TargetLoweringObjectFile *getObjFileLowering() const { return nullptr; } - virtual const DataLayout *getDataLayout() const { return nullptr; } - - /// getMCAsmInfo - Return target specific asm information. - /// - const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } /// getSubtarget - This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being @@ -135,27 +113,23 @@ public: template const STC &getSubtarget() const { return *static_cast(getSubtargetImpl()); } + template const STC &getSubtarget(const Function *) const { + return *static_cast(getSubtargetImpl()); + } + + /// \brief Reset the target options based on the function's attributes. + // FIXME: Remove TargetOptions that affect per-function code generation + // from TargetMachine. + void resetTargetOptions(const Function &F) const; - /// getRegisterInfo - If register information is available, return it. If - /// not, return null. This is kept separate from RegInfo until RegInfo has - /// details of graph coloring register allocation removed from it. + /// getMCAsmInfo - Return target specific asm information. /// - virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; } + const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } /// getIntrinsicInfo - If intrinsic information is available, return it. If /// not, return null. /// - virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr;} - - /// getJITInfo - If this target supports a JIT, return information for it, - /// otherwise return null. - /// - virtual TargetJITInfo *getJITInfo() { return nullptr; } - - /// getInstrItineraryData - Returns instruction itinerary data for the target - /// or specific subtarget. - /// - virtual const InstrItineraryData *getInstrItineraryData() const { + virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr; } @@ -233,18 +207,6 @@ public: return true; } - /// addPassesToEmitMachineCode - Add passes to the specified pass manager to - /// get machine code emitted. This uses a JITCodeEmitter object to handle - /// actually outputting the machine code and resolving things like the address - /// of functions. This method returns true if machine code emission is - /// not supported. - /// - virtual bool addPassesToEmitMachineCode(PassManagerBase &, - JITCodeEmitter &, - bool /*DisableVerify*/ = true) { - return true; - } - /// addPassesToEmitMC - Add passes to the specified pass manager to get /// machine code emitted with the MCJIT. This method returns true if machine /// code is not supported. It fills the MCContext Ctx pointer which can be @@ -291,15 +253,6 @@ public: AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr) override; - /// addPassesToEmitMachineCode - Add passes to the specified pass manager to - /// get machine code emitted. This uses a JITCodeEmitter object to handle - /// actually outputting the machine code and resolving things like the address - /// of functions. This method returns true if machine code emission is - /// not supported. - /// - bool addPassesToEmitMachineCode(PassManagerBase &PM, JITCodeEmitter &MCE, - bool DisableVerify = true) override; - /// addPassesToEmitMC - Add passes to the specified pass manager to get /// machine code emitted with the MCJIT. This method returns true if machine /// code is not supported. It fills the MCContext Ctx pointer which can be @@ -307,14 +260,6 @@ public: /// bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, raw_ostream &OS, bool DisableVerify = true) override; - - /// addCodeEmitter - This pass should be overridden by the target to add a - /// code emitter, if supported. If this is not supported, 'true' should be - /// returned. - virtual bool addCodeEmitter(PassManagerBase &, - JITCodeEmitter &) { - return true; - } }; } // End llvm namespace diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h index abb3eca..1fbd2ae 100644 --- a/include/llvm/Target/TargetOpcodes.h +++ b/include/llvm/Target/TargetOpcodes.h @@ -104,7 +104,13 @@ enum { /// support optimizations for dynamic languages (such as javascript) that /// rewrite calls to runtimes with more efficient code sequences. /// This also implies a stack map. - PATCHPOINT = 18 + PATCHPOINT = 18, + + /// This pseudo-instruction loads the stack guard value. Targets which need + /// to prevent the stack guard value or address from being spilled to the + /// stack should override TargetLowering::emitLoadStackGuardNode and + /// additionally expand this pseudo after register allocation. + LOAD_STACK_GUARD = 19 }; } // end namespace TargetOpcode } // end namespace llvm diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 922fae5..73014d8 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -50,6 +50,21 @@ namespace llvm { }; } + namespace ThreadModel { + enum Model { + POSIX, // POSIX Threads + Single // Single Threaded Environment + }; + } + + enum class CFIntegrity { + Sub, // Use subtraction-based checks. + Ror, // Use rotation-based checks. + Add // Use addition-based checks. This depends on having + // sufficient alignment in the code and is usually not + // feasible. + }; + class TargetOptions { public: TargetOptions() @@ -63,9 +78,11 @@ namespace llvm { EnableFastISel(false), PositionIndependentExecutable(false), UseInitArray(false), DisableIntegratedAS(false), CompressDebugSections(false), FunctionSections(false), - DataSections(false), TrapUnreachable(false), TrapFuncName(""), + DataSections(false), TrapUnreachable(false), TrapFuncName(), FloatABIType(FloatABI::Default), - AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single) {} + AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single), + FCFI(false), ThreadModel(ThreadModel::POSIX), + CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -220,6 +237,28 @@ namespace llvm { /// create for functions that have the jumptable attribute. JumpTable::JumpTableType JTType; + /// FCFI - This flags controls whether or not forward-edge control-flow + /// integrity is applied. + bool FCFI; + + /// ThreadModel - This flag specifies the type of threading model to assume + /// for things like atomics + ThreadModel::Model ThreadModel; + + /// CFIType - This flag specifies the type of control-flow integrity check + /// to add as a preamble to indirect calls. + CFIntegrity CFIType; + + /// CFIEnforcing - This flags controls whether or not CFI violations cause + /// the program to halt. + bool CFIEnforcing; + + /// getCFIFuncName - If this returns a non-empty string, then this is the + /// name of the function that will be called for each CFI violation in + /// non-enforcing mode. + std::string CFIFuncName; + StringRef getCFIFuncName() const; + /// Machine level options. MCTargetOptions MCOptions; }; diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index c6f3fbf..16b72a9 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -18,7 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/IR/CallingConv.h" #include "llvm/MC/MCRegisterInfo.h" #include @@ -52,10 +52,6 @@ public: /// unsigned getID() const { return MC->getID(); } - /// getName() - Return the register class name for debugging. - /// - const char *getName() const { return MC->getName(); } - /// begin/end - Return all of the registers in this class. /// iterator begin() const { return MC->begin(); } @@ -101,9 +97,9 @@ public: /// hasType - return true if this TargetRegisterClass has the ValueType vt. /// - bool hasType(EVT vt) const { + bool hasType(MVT vt) const { for(int i = 0; VTs[i] != MVT::Other; ++i) - if (EVT(VTs[i]) == vt) + if (MVT(VTs[i]) == vt) return true; return false; } @@ -306,7 +302,7 @@ public: /// register of the given type, picking the most sub register class of /// the right type that contains this physreg. const TargetRegisterClass * - getMinimalPhysRegClass(unsigned Reg, EVT VT = MVT::Other) const; + getMinimalPhysRegClass(unsigned Reg, MVT VT = MVT::Other) const; /// getAllocatableClass - Return the maximal subclass of the given register /// class that is alloctable, or NULL. @@ -506,6 +502,10 @@ public: return composeSubRegIndicesImpl(a, b); } + /// Debugging helper: dump register in human readable form to dbgs() stream. + static void dumpReg(unsigned Reg, unsigned SubRegIndex = 0, + const TargetRegisterInfo* TRI = nullptr); + protected: /// Overridden by TableGen in targets that have sub-registers. virtual unsigned composeSubRegIndicesImpl(unsigned, unsigned) const { @@ -561,6 +561,11 @@ public: return RegClassBegin[i]; } + /// getRegClassName - Returns the name of the register class. + const char *getRegClassName(const TargetRegisterClass *Class) const { + return MCRegisterInfo::getRegClassName(Class->MC); + } + /// getCommonSubClass - find the largest common subclass of A and B. Return /// NULL if there is no common subclass. const TargetRegisterClass * @@ -683,12 +688,6 @@ public: /// (3) Bottom-up allocation is no longer guaranteed to optimally color. virtual bool reverseLocalAssignment() const { return false; } - /// Allow the target to override register assignment heuristics based on the - /// live range size. If this returns false, then local live ranges are always - /// assigned in order regardless of their size. This is a temporary hook for - /// debugging downstream codegen failures exposed by regalloc. - virtual bool mayOverrideLocalAssignment() const { return true; } - /// Allow the target to override the cost of using a callee-saved register for /// the first time. Default value of 0 means we will use a callee-saved /// register if it is available. @@ -808,6 +807,18 @@ public: RegScavenger *RS = nullptr) const = 0; //===--------------------------------------------------------------------===// + /// Subtarget Hooks + + /// \brief SrcRC and DstRC will be morphed into NewRC if this returns true. + virtual bool shouldCoalesce(MachineInstr *MI, + const TargetRegisterClass *SrcRC, + unsigned SubReg, + const TargetRegisterClass *DstRC, + unsigned DstSubReg, + const TargetRegisterClass *NewRC) const + { return true; } + + //===--------------------------------------------------------------------===// /// Debug information queries. /// getFrameRegister - This method should return the register used as a base diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index e6eeb88..89db37c 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -88,6 +88,8 @@ class SchedMachineModel { // Per-cycle resources tables. ProcessorItineraries Itineraries = NoItineraries; + bit PostRAScheduler = 0; // Enable Post RegAlloc Scheduler pass. + // Subtargets that define a model for only a subset of instructions // that have a scheduling class (itinerary class or SchedRW list) // and may actually be generated for that subtarget must clear this diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 16cfff1..f63afd7 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -162,6 +162,10 @@ def SDTBr : SDTypeProfile<0, 1, [ // br SDTCisVT<0, OtherVT> ]>; +def SDTBrCC : SDTypeProfile<0, 4, [ // brcc + SDTCisVT<0, OtherVT>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> +]>; + def SDTBrcond : SDTypeProfile<0, 2, [ // brcond SDTCisInt<0>, SDTCisVT<1, OtherVT> ]>; @@ -205,7 +209,7 @@ def SDTPrefetch : SDTypeProfile<0, 4, [ // prefetch SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>, SDTCisInt<1> ]>; -def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barier +def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barrier SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, SDTCisInt<0> ]>; @@ -369,6 +373,8 @@ def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>; def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; +def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>; +def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>; def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>; def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>; def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>; @@ -392,14 +398,15 @@ def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>; def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>; def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; -def f16_to_f32 : SDNode<"ISD::FP16_TO_FP32", SDTIntToFPOp>; -def f32_to_f16 : SDNode<"ISD::FP32_TO_FP16", SDTFPToIntOp>; +def f16_to_fp : SDNode<"ISD::FP16_TO_FP" , SDTIntToFPOp>; +def fp_to_f16 : SDNode<"ISD::FP_TO_FP16" , SDTFPToIntOp>; def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; def select : SDNode<"ISD::SELECT" , SDTSelect>; def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; +def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>; def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index 78a2db1..d1a3fcf 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -46,7 +46,7 @@ public: /// more efficient than using a library call. This function can return a null /// SDValue if the target declines to use custom code and a different /// lowering strategy should be used. - /// + /// /// If AlwaysInline is true, the size is constant and the target should not /// emit any calls and is strongly encouraged to attempt to emit inline code /// even if it is beyond the usual threshold because this intrinsic is being diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index bbb83ef..80ff9e3 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -14,17 +14,24 @@ #ifndef LLVM_TARGET_TARGETSUBTARGETINFO_H #define LLVM_TARGET_TARGETSUBTARGETINFO_H +#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/CodeGen.h" namespace llvm { +class DataLayout; class MachineFunction; class MachineInstr; class SDep; class SUnit; +class TargetFrameLowering; +class TargetInstrInfo; +class TargetLowering; class TargetRegisterClass; +class TargetRegisterInfo; class TargetSchedModel; +class TargetSelectionDAGInfo; struct MachineSchedPolicy; template class SmallVectorImpl; @@ -47,6 +54,38 @@ public: virtual ~TargetSubtargetInfo(); + // Interfaces to the major aspects of target machine information: + // + // -- Instruction opcode and operand information + // -- Pipelines and scheduling information + // -- Stack frame information + // -- Selection DAG lowering information + // + // N.B. These objects may change during compilation. It's not safe to cache + // them between functions. + virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; } + virtual const TargetFrameLowering *getFrameLowering() const { + return nullptr; + } + virtual const TargetLowering *getTargetLowering() const { return nullptr; } + virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const { + return nullptr; + } + virtual const DataLayout *getDataLayout() const { return nullptr; } + + /// getRegisterInfo - If register information is available, return it. If + /// not, return null. This is kept separate from RegInfo until RegInfo has + /// details of graph coloring register allocation removed from it. + /// + virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; } + + /// getInstrItineraryData - Returns instruction itinerary data for the target + /// or specific subtarget. + /// + virtual const InstrItineraryData *getInstrItineraryData() const { + return nullptr; + } + /// Resolve a SchedClass at runtime, where SchedClass identifies an /// MCSchedClassDesc with the isVariant property. This may return the ID of /// another variant SchedClass, but repeated invocation must quickly terminate @@ -74,7 +113,7 @@ public: virtual bool enablePostMachineScheduler() const; /// \brief True if the subtarget should run the atomic expansion pass. - virtual bool enableAtomicExpandLoadLinked() const; + virtual bool enableAtomicExpand() const; /// \brief Override generic scheduling policy within a region. /// @@ -91,14 +130,24 @@ public: virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep& dep) const { } - // enablePostRAScheduler - If the target can benefit from post-regalloc - // scheduling and the specified optimization level meets the requirement - // return true to enable post-register-allocation scheduling. In - // CriticalPathRCs return any register classes that should only be broken - // if on the critical path. - virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, - AntiDepBreakMode& Mode, - RegClassVector& CriticalPathRCs) const; + // For use with PostRAScheduling: get the anti-dependence breaking that should + // be performed before post-RA scheduling. + virtual AntiDepBreakMode getAntiDepBreakMode() const { + return ANTIDEP_NONE; + } + + // For use with PostRAScheduling: in CriticalPathRCs, return any register + // classes that should only be considered for anti-dependence breaking if they + // are on the critical path. + virtual void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { + return CriticalPathRCs.clear(); + } + + // For use with PostRAScheduling: get the minimum optimization level needed + // to enable post-RA scheduling. + virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const { + return CodeGenOpt::Default; + } /// \brief True if the subtarget should run the local reassignment /// heuristic of the register allocator. @@ -113,8 +162,12 @@ public: /// \brief Enable the use of the early if conversion pass. virtual bool enableEarlyIfConversion() const { return false; } - /// \brief Reset the features for the subtarget. - virtual void resetSubtargetFeatures(const MachineFunction *MF) { } + /// \brief Return PBQPConstraint(s) for the target. + /// + /// Override to provide custom PBQP constraints. + virtual std::unique_ptr getCustomPBQPConstraints() const { + return nullptr; + } }; } // End llvm namespace -- cgit v1.1