diff options
Diffstat (limited to 'include/llvm/Target')
-rw-r--r-- | include/llvm/Target/Target.td | 20 | ||||
-rw-r--r-- | include/llvm/Target/TargetCallingConv.h | 1 | ||||
-rw-r--r-- | include/llvm/Target/TargetFrameLowering.h | 45 | ||||
-rw-r--r-- | include/llvm/Target/TargetInstrInfo.h | 396 | ||||
-rw-r--r-- | include/llvm/Target/TargetIntrinsicInfo.h | 4 | ||||
-rw-r--r-- | include/llvm/Target/TargetLibraryInfo.h | 802 | ||||
-rw-r--r-- | include/llvm/Target/TargetLowering.h | 348 | ||||
-rw-r--r-- | include/llvm/Target/TargetLoweringObjectFile.h | 77 | ||||
-rw-r--r-- | include/llvm/Target/TargetMachine.h | 204 | ||||
-rw-r--r-- | include/llvm/Target/TargetOptions.h | 84 | ||||
-rw-r--r-- | include/llvm/Target/TargetRegisterInfo.h | 42 | ||||
-rw-r--r-- | include/llvm/Target/TargetSelectionDAG.td | 32 | ||||
-rw-r--r-- | include/llvm/Target/TargetSelectionDAGInfo.h | 5 | ||||
-rw-r--r-- | include/llvm/Target/TargetSubtargetInfo.h | 44 |
14 files changed, 672 insertions, 1432 deletions
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 6c970d0c19db..ec8a12df9fc6 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -207,6 +207,12 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // The function should return 0 to select the default order defined by // MemberList, 1 to select the first AltOrders entry and so on. code AltOrderSelect = [{}]; + + // Specify allocation priority for register allocators using a greedy + // heuristic. Classes with higher priority values are assigned first. This is + // useful as it is sometimes beneficial to assign registers to highly + // constrained classes first. The value has to be in the range [0,63]. + int AllocationPriority = 0; } // The memberList in a RegisterClass is a dag of set operations. TableGen @@ -1000,6 +1006,15 @@ class InstAlias<string Asm, dag Result, int Emit = 1> { // Predicates - Predicates that must be true for this to match. list<Predicate> Predicates = []; + + // If the instruction specified in Result has defined an AsmMatchConverter + // then setting this to 1 will cause the alias to use the AsmMatchConverter + // function when converting the OperandVector into an MCInst instead of the + // function that is generated by the dag Result. + // Setting this to 0 will cause the alias to ignore the Result instruction's + // defined AsmMatchConverter and instead use the function generated by the + // dag Result. + bit UseInstAsmMatchConverter = 1; } //===----------------------------------------------------------------------===// @@ -1015,6 +1030,11 @@ class AsmWriter { // name. string AsmWriterClassName = "InstPrinter"; + // PassSubtarget - Determines whether MCSubtargetInfo should be passed to + // the various print methods. + // FIXME: Remove after all ports are updated. + int PassSubtarget = 0; + // Variant - AsmWriters can be of multiple different variants. Variants are // used to support targets that need to emit assembly code in ways that are // mostly the same for different targets, but have minor differences in diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index 9071bfeec7ed..9d4e7a04d905 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -18,6 +18,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include <string> +#include <limits.h> namespace llvm { diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index 277bd98d371c..0e317247a59f 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -130,21 +130,26 @@ public: /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. - virtual void emitPrologue(MachineFunction &MF) const = 0; + virtual void emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; /// Adjust the prologue to have the function use segmented stacks. This works /// by adding a check even before the "normal" function prologue. - virtual void adjustForSegmentedStacks(MachineFunction &MF) const { } + virtual void adjustForSegmentedStacks(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} /// Adjust the prologue to add Erlang Run-Time System (ERTS) specific code in /// the assembly prologue to explicitly handle the stack. - virtual void adjustForHiPEPrologue(MachineFunction &MF) const { } + virtual void adjustForHiPEPrologue(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} /// Adjust the prologue to add an allocation at a fixed offset from the frame /// pointer. - virtual void adjustForFrameAllocatePrologue(MachineFunction &MF) const { } + virtual void + adjustForFrameAllocatePrologue(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee /// saved registers and returns true if it isn't possible / profitable to do @@ -168,6 +173,9 @@ public: return false; } + /// Return true if the target needs to disable frame pointer elimination. + virtual bool noFramePointerElim(const MachineFunction &MF) const; + /// hasFP - Return true if the specified function should have a dedicated /// frame pointer register. For most targets this is true only if the function /// has variable sized allocas or if frame pointer elimination is disabled. @@ -193,6 +201,11 @@ public: return hasReservedCallFrame(MF) || hasFP(MF); } + // needsFrameIndexResolution - Do we need to perform FI resolution for + // this function. Normally, this is required only when the function + // has any stack objects. However, targets may want to override this. + virtual bool needsFrameIndexResolution(const MachineFunction &MF) const; + /// getFrameIndexOffset - Returns the displacement from the frame register to /// the stack frame of the specified index. virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const; @@ -244,6 +257,30 @@ public: llvm_unreachable("Call Frame Pseudo Instructions do not exist on this " "target!"); } + + /// Check whether or not the given \p MBB can be used as a prologue + /// for the target. + /// The prologue will be inserted first in this basic block. + /// This method is used by the shrink-wrapping pass to decide if + /// \p MBB will be correctly handled by the target. + /// As soon as the target enable shrink-wrapping without overriding + /// this method, we assume that each basic block is a valid + /// prologue. + virtual bool canUseAsPrologue(const MachineBasicBlock &MBB) const { + return true; + } + + /// Check whether or not the given \p MBB can be used as a epilogue + /// for the target. + /// The epilogue will be inserted before the first terminator of that block. + /// This method is used by the shrink-wrapping pass to decide if + /// \p MBB will be correctly handled by the target. + /// As soon as the target enable shrink-wrapping without overriding + /// this method, we assume that each basic block is a valid + /// epilogue. + virtual bool canUseAsEpilogue(const MachineBasicBlock &MBB) const { + return true; + } }; } // End llvm namespace diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index e8a50fff1fe8..5ec15658b696 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -50,26 +50,28 @@ template<class T> class SmallVectorImpl; /// TargetInstrInfo - Interface to description of machine instruction set /// class TargetInstrInfo : public MCInstrInfo { - TargetInstrInfo(const TargetInstrInfo &) LLVM_DELETED_FUNCTION; - void operator=(const TargetInstrInfo &) LLVM_DELETED_FUNCTION; + TargetInstrInfo(const TargetInstrInfo &) = delete; + void operator=(const TargetInstrInfo &) = delete; public: - TargetInstrInfo(int CFSetupOpcode = -1, int CFDestroyOpcode = -1) + TargetInstrInfo(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u) : CallFrameSetupOpcode(CFSetupOpcode), CallFrameDestroyOpcode(CFDestroyOpcode) { } virtual ~TargetInstrInfo(); - /// getRegClass - Givem a machine instruction descriptor, returns the register + /// Given a machine instruction descriptor, returns the register /// class constraint for OpNum, or NULL. const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) const; - /// isTriviallyReMaterializable - Return true if the instruction is trivially - /// rematerializable, meaning it has no side effects and requires no operands - /// that aren't always available. + /// Return true if the instruction is trivially rematerializable, meaning it + /// has no side effects and requires no operands that aren't always available. + /// This means the only allowed uses are constants and unallocatable physical + /// registers so that the instructions result is independent of the place + /// in the function. bool isTriviallyReMaterializable(const MachineInstr *MI, AliasAnalysis *AA = nullptr) const { return MI->getOpcode() == TargetOpcode::IMPLICIT_DEF || @@ -79,35 +81,34 @@ public: } protected: - /// isReallyTriviallyReMaterializable - For instructions with opcodes for - /// which the M_REMATERIALIZABLE flag is set, this hook lets the target - /// specify whether the instruction is actually trivially rematerializable, - /// taking into consideration its operands. This predicate must return false - /// if the instruction has any side effects other than producing a value, or - /// if it requres any address registers that are not always available. + /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is + /// set, this hook lets the target specify whether the instruction is actually + /// trivially rematerializable, taking into consideration its operands. This + /// predicate must return false if the instruction has any side effects other + /// than producing a value, or if it requres any address registers that are + /// not always available. + /// Requirements must be check as stated in isTriviallyReMaterializable() . virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI, AliasAnalysis *AA) const { return false; } private: - /// isReallyTriviallyReMaterializableGeneric - For instructions with opcodes - /// for which the M_REMATERIALIZABLE flag is set and the target hook - /// isReallyTriviallyReMaterializable returns false, this function does - /// target-independent tests to determine if the instruction is really - /// trivially rematerializable. + /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is + /// set and the target hook isReallyTriviallyReMaterializable returns false, + /// this function does target-independent tests to determine if the + /// instruction is really trivially rematerializable. bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, AliasAnalysis *AA) const; public: - /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the - /// frame setup/destroy instructions if they exist (-1 otherwise). Some - /// targets use pseudo instructions in order to abstract away the difference - /// between operating with a frame pointer and operating without, through the - /// use of these two instructions. + /// These methods return the opcode of the frame setup/destroy instructions + /// if they exist (-1 otherwise). Some targets use pseudo instructions in + /// order to abstract away the difference between operating with a frame + /// pointer and operating without, through the use of these two instructions. /// - int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } - int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } + unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } /// Returns the actual stack pointer adjustment made by an instruction /// as part of a call sequence. By default, only call frame setup/destroy @@ -115,19 +116,18 @@ public: /// to enable more fine-grained adjustment, or adjust by a different value. virtual int getSPAdjust(const MachineInstr *MI) const; - /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" - /// extension instruction. That is, it's like a copy where it's legal for the - /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns - /// true, then it's expected the pre-extension value is available as a subreg - /// of the result register. This also returns the sub-register index in - /// SubIdx. + /// Return true if the instruction is a "coalescable" extension instruction. + /// That is, it's like a copy where it's legal for the source to overlap the + /// destination. e.g. X86::MOVSX64rr32. If this returns true, then it's + /// expected the pre-extension value is available as a subreg of the result + /// register. This also returns the sub-register index in SubIdx. virtual bool isCoalescableExtInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg, unsigned &SubIdx) const { return false; } - /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// If the specified machine instruction is a direct /// load from a stack slot, return the virtual or physical register number of /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has @@ -137,26 +137,24 @@ public: return 0; } - /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination - /// stack locations as well. This uses a heuristic so it isn't - /// reliable for correctness. + /// Check for post-frame ptr elimination stack locations as well. + /// This uses a heuristic so it isn't reliable for correctness. virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const { return 0; } - /// hasLoadFromStackSlot - If the specified machine instruction has - /// a load from a stack slot, return true along with the FrameIndex - /// of the loaded stack slot and the machine mem operand containing - /// the reference. If not, return false. Unlike - /// isLoadFromStackSlot, this returns true for any instructions that - /// loads from the stack. This is just a hint, as some cases may be - /// missed. + /// If the specified machine instruction has a load from a stack slot, + /// return true along with the FrameIndex of the loaded stack slot and the + /// machine mem operand containing the reference. + /// If not, return false. Unlike isLoadFromStackSlot, this returns true for + /// any instructions that loads from the stack. This is just a hint, as some + /// cases may be missed. virtual bool hasLoadFromStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, int &FrameIndex) const; - /// isStoreToStackSlot - If the specified machine instruction is a direct + /// If the specified machine instruction is a direct /// store to a stack slot, return the virtual or physical register number of /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has @@ -166,25 +164,24 @@ public: return 0; } - /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination - /// stack locations as well. This uses a heuristic so it isn't - /// reliable for correctness. + /// Check for post-frame ptr elimination stack locations as well. + /// This uses a heuristic, so it isn't reliable for correctness. virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const { return 0; } - /// hasStoreToStackSlot - If the specified machine instruction has a - /// store to a stack slot, return true along with the FrameIndex of - /// the loaded stack slot and the machine mem operand containing the - /// reference. If not, return false. Unlike isStoreToStackSlot, + /// If the specified machine instruction has a store to a stack slot, + /// return true along with the FrameIndex of the loaded stack slot and the + /// machine mem operand containing the reference. + /// If not, return false. Unlike isStoreToStackSlot, /// this returns true for any instructions that stores to the /// stack. This is just a hint, as some cases may be missed. virtual bool hasStoreToStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, int &FrameIndex) const; - /// isStackSlotCopy - Return true if the specified machine instruction + /// Return true if the specified machine instruction /// is a copy of one stack slot to another and has no other effect. /// Provide the identity of the two frame indices. virtual bool isStackSlotCopy(const MachineInstr *MI, int &DestFrameIndex, @@ -207,10 +204,9 @@ public: /// this, particularly to support spilled vector registers. virtual bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx, unsigned &Size, unsigned &Offset, - const TargetMachine *TM) const; + const MachineFunction &MF) const; - /// isAsCheapAsAMove - Return true if the instruction is as cheap as a move - /// instruction. + /// Return true if the instruction is as cheap as a move instruction. /// /// Targets for different archs need to override this, and different /// micro-architectures can also be finely tuned inside. @@ -218,7 +214,7 @@ public: return MI->isAsCheapAsAMove(); } - /// reMaterialize - Re-issue the specified 'original' instruction at the + /// Re-issue the specified 'original' instruction at the /// specific location targeting a new destination register. /// The register in Orig->getOperand(0).getReg() will be substituted by /// DestReg:SubIdx. Any existing subreg index is preserved or composed with @@ -229,7 +225,7 @@ public: const MachineInstr *Orig, const TargetRegisterInfo &TRI) const; - /// duplicate - Create a duplicate of the Orig instruction in MF. This is like + /// Create a duplicate of the Orig instruction in MF. This is like /// MachineFunction::CloneMachineInstr(), but the target may update operands /// that are required to be unique. /// @@ -237,7 +233,7 @@ public: virtual MachineInstr *duplicate(MachineInstr *Orig, MachineFunction &MF) const; - /// convertToThreeAddress - This method must be implemented by targets that + /// This method must be implemented by targets that /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target /// may be able to convert a two-address instruction into one or more true /// three-address instructions on demand. This allows the X86 target (for @@ -253,10 +249,10 @@ public: return nullptr; } - /// commuteInstruction - If a target has any instructions that are - /// commutable but require converting to different instructions or making - /// non-trivial changes to commute them, this method can overloaded to do - /// that. The default implementation simply swaps the commutable operands. + /// If a target has any instructions that are commutable but require + /// converting to different instructions or making non-trivial changes to + /// commute them, this method can overloaded to do that. + /// The default implementation simply swaps the commutable operands. /// If NewMI is false, MI is modified in place and returned; otherwise, a /// new machine instruction is created and returned. Do not call this /// method for a non-commutable instruction, but there may be some cases @@ -264,8 +260,8 @@ public: virtual MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI = false) const; - /// findCommutedOpIndices - If specified MI is commutable, return the two - /// operand indices that would swap value. Return false if the instruction + /// If specified MI is commutable, return the two operand indices that would + /// swap value. Return false if the instruction /// is not in a form which this routine understands. virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const; @@ -349,8 +345,8 @@ public: RegSubRegPairAndIdx &InsertedReg) const; - /// produceSameValue - Return true if two machine instructions would produce - /// identical values. By default, this is only true when the two instructions + /// 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 /// IR is still in SSA form, the caller can pass the MachineRegisterInfo for /// aggressive checks. @@ -358,7 +354,7 @@ public: const MachineInstr *MI1, const MachineRegisterInfo *MRI = nullptr) const; - /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning + /// Analyze the branching code at the end of MBB, returning /// true if it cannot be understood (e.g. it's a switch dispatch or isn't /// implemented for a target). Upon success, this returns false and returns /// with the following information in various cases: @@ -390,15 +386,15 @@ public: return true; } - /// RemoveBranch - Remove the branching code at the end of the specific MBB. + /// Remove the branching code at the end of the specific MBB. /// This is only invoked in cases where AnalyzeBranch returns success. It /// returns the number of instructions that were removed. virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { llvm_unreachable("Target didn't implement TargetInstrInfo::RemoveBranch!"); } - /// InsertBranch - Insert branch code into the end of the specified - /// MachineBasicBlock. The operands to this method are the same as those + /// Insert branch code into the end of the specified MachineBasicBlock. + /// The operands to this method are the same as those /// returned by AnalyzeBranch. This is only invoked in cases where /// AnalyzeBranch returns success. It returns the number of instructions /// inserted. @@ -414,14 +410,13 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::InsertBranch!"); } - /// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything - /// after it, replacing it with an unconditional branch to NewDest. This is - /// used by the tail merging pass. + /// Delete the instruction OldInst and everything after it, replacing it with + /// an unconditional branch to NewDest. This is used by the tail merging pass. virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const; - /// getUnconditionalBranch - Get an instruction that performs an unconditional - /// branch to the given symbol. + /// Get an instruction that performs an unconditional branch to the given + /// symbol. virtual void getUnconditionalBranch(MCInst &MI, const MCSymbolRefExpr *BranchTarget) const { @@ -429,12 +424,12 @@ public: "TargetInstrInfo::getUnconditionalBranch!"); } - /// getTrap - Get a machine trap instruction + /// Get a machine trap instruction. virtual void getTrap(MCInst &MI) const { llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!"); } - /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold + /// 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 @@ -454,7 +449,7 @@ public: return 0; } - /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic + /// 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). virtual bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, @@ -462,7 +457,7 @@ public: return true; } - /// isProfitableToIfCvt - Return true if it's profitable to predicate + /// Return true if it's profitable to predicate /// instructions with accumulated instruction latency of "NumCycles" /// of the specified basic block, where the probability of the instructions /// being executed is given by Probability, and Confidence is a measure @@ -474,7 +469,7 @@ public: return false; } - /// isProfitableToIfCvt - Second variant of isProfitableToIfCvt, this one + /// Second variant of isProfitableToIfCvt. This one /// checks for the case where two basic blocks from true and false path /// of a if-then-else (diamond) are predicated on mutally exclusive /// predicates, where the probability of the true path being taken is given @@ -489,9 +484,9 @@ public: return false; } - /// isProfitableToDupForIfCvt - Return true if it's profitable for - /// if-converter to duplicate instructions of specified accumulated - /// instruction latencies in the specified MBB to enable if-conversion. + /// Return true if it's profitable for if-converter to duplicate instructions + /// of specified accumulated instruction latencies in the specified MBB to + /// enable if-conversion. /// The probability of the instructions being executed is given by /// Probability, and Confidence is a measure of our confidence that it /// will be properly predicted. @@ -501,7 +496,7 @@ public: return false; } - /// isProfitableToUnpredicate - Return true if it's profitable to unpredicate + /// Return true if it's profitable to unpredicate /// one side of a 'diamond', i.e. two sides of if-else predicated on mutually /// exclusive predicates. /// e.g. @@ -517,7 +512,7 @@ public: return false; } - /// canInsertSelect - Return true if it is possible to insert a select + /// Return true if it is possible to insert a select /// instruction that chooses between TrueReg and FalseReg based on the /// condition code in Cond. /// @@ -542,9 +537,8 @@ public: return false; } - /// insertSelect - Insert a select instruction into MBB before I that will - /// copy TrueReg to DstReg when Cond is true, and FalseReg to DstReg when - /// Cond is false. + /// Insert a select instruction into MBB before I that will copy TrueReg to + /// DstReg when Cond is true, and FalseReg to DstReg when Cond is false. /// /// This function can only be called after canInsertSelect() returned true. /// The condition in Cond comes from AnalyzeBranch, and it can be assumed @@ -566,7 +560,7 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!"); } - /// analyzeSelect - Analyze the given select instruction, returning true if + /// Analyze the given select instruction, returning true if /// it cannot be understood. It is assumed that MI->isSelect() is true. /// /// When successful, return the controlling condition and the operands that @@ -592,7 +586,7 @@ public: return true; } - /// optimizeSelect - Given a select instruction that was understood by + /// Given a select instruction that was understood by /// analyzeSelect and returned Optimizable = true, attempt to optimize MI by /// merging it with one of its operands. Returns NULL on failure. /// @@ -614,7 +608,7 @@ public: llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!"); } - /// copyPhysReg - Emit instructions to copy a pair of physical registers. + /// Emit instructions to copy a pair of physical registers. /// /// This function should support copies within any legal register class as /// well as any cross-class copies created during instruction selection. @@ -629,11 +623,10 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!"); } - /// storeRegToStackSlot - Store the specified register of the given register - /// class to the specified stack frame index. The store instruction is to be - /// added to the given machine basic block before the specified machine - /// instruction. If isKill is true, the register operand is the last use and - /// must be marked kill. + /// Store the specified register of the given register class to the specified + /// stack frame index. The store instruction is to be added to the given + /// machine basic block before the specified machine instruction. If isKill + /// is true, the register operand is the last use and must be marked kill. virtual void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, @@ -643,10 +636,9 @@ public: "TargetInstrInfo::storeRegToStackSlot!"); } - /// loadRegFromStackSlot - Load the specified register of the given register - /// class from the specified stack frame index. The load instruction is to be - /// added to the given machine basic block before the specified machine - /// instruction. + /// Load the specified register of the given register class from the specified + /// stack frame index. The load instruction is to be added to the given + /// machine basic block before the specified machine instruction. virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, @@ -656,7 +648,7 @@ public: "TargetInstrInfo::loadRegFromStackSlot!"); } - /// expandPostRAPseudo - This function is called for all pseudo instructions + /// This function is called for all pseudo instructions /// that remain after register allocation. Many pseudo instructions are /// created to help register allocation. This is the place to convert them /// into real instructions. The target can edit MI in place, or it can insert @@ -666,46 +658,42 @@ public: return false; } - /// foldMemoryOperand - Attempt to fold a load or store of the specified stack + /// Attempt to fold a load or store of the specified stack /// slot into the specified machine instruction for the specified operand(s). /// If this is possible, a new instruction is returned with the specified /// operand folded, otherwise NULL is returned. /// The new instruction is inserted before MI, and the client is responsible /// for removing the old instruction. - MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI, - const SmallVectorImpl<unsigned> &Ops, - int FrameIndex) const; - - /// foldMemoryOperand - Same as the previous version except it allows folding - /// of any load and store from / to any address, not just from a specific - /// stack slot. - MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI, - const SmallVectorImpl<unsigned> &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 + MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI, + ArrayRef<unsigned> Ops, int FrameIndex) const; + + /// Same as the previous version except it allows folding of any load and + /// store from / to any address, not just from a specific stack slot. + MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI, + ArrayRef<unsigned> Ops, + MachineInstr *LoadMI) const; + + /// Return true when there is potentially a faster code sequence + /// for an instruction chain ending in \p Root. All potential patterns 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<MachineCombinerPattern::MC_PATTERN> &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. + /// 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 replacement 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 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( @@ -716,27 +704,27 @@ public: return; } - /// useMachineCombiner - return true when a target supports MachineCombiner + /// 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 + /// Target-dependent implementation for foldMemoryOperand. + /// Target-independent code in foldMemoryOperand will /// take care of adding a MachineMemOperand to the newly created instruction. - virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, - MachineInstr* MI, - const SmallVectorImpl<unsigned> &Ops, - int FrameIndex) const { + virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, + ArrayRef<unsigned> Ops, + int FrameIndex) const { return nullptr; } - /// foldMemoryOperandImpl - Target-dependent implementation for - /// foldMemoryOperand. Target-independent code in foldMemoryOperand will + /// Target-dependent implementation for foldMemoryOperand. + /// Target-independent code in foldMemoryOperand will /// take care of adding a MachineMemOperand to the newly created instruction. - virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, - MachineInstr* MI, - const SmallVectorImpl<unsigned> &Ops, - MachineInstr* LoadMI) const { + virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, + ArrayRef<unsigned> Ops, + MachineInstr *LoadMI) const { return nullptr; } @@ -784,11 +772,9 @@ protected: } public: - /// canFoldMemoryOperand - Returns true for the specified load / store if - /// folding is possible. - virtual - bool canFoldMemoryOperand(const MachineInstr *MI, - const SmallVectorImpl<unsigned> &Ops) const; + /// Returns true for the specified load / store if folding is possible. + virtual bool canFoldMemoryOperand(const MachineInstr *MI, + ArrayRef<unsigned> Ops) const; /// unfoldMemoryOperand - Separate a single instruction which folded a load or /// a store or a load and a store into two or more instruction. If this is @@ -804,7 +790,7 @@ public: return false; } - /// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new + /// Returns the opcode of the would be new /// instruction after load / store are unfolded from an instruction of the /// specified opcode. It returns zero if the specified unfolding is not /// possible. If LoadRegIndex is non-null, it is filled in with the operand @@ -816,19 +802,18 @@ public: return 0; } - /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler - /// to determine if two loads are loading from the same base address. It - /// should only return true if the base pointers are the same and the - /// only differences between the two addresses are the offset. It also returns - /// the offsets by reference. + /// This is used by the pre-regalloc scheduler to determine if two loads are + /// loading from the same base address. It should only return true if the base + /// pointers are the same and the only differences between the two addresses + /// are the offset. It also returns the offsets by reference. virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, int64_t &Offset2) const { return false; } - /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to - /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should - /// be scheduled togther. On some targets if two loads are loading from + /// This is a used by the pre-regalloc scheduler to determine (in conjunction + /// with areLoadsFromSameBasePtr) if two loads should be scheduled together. + /// On some targets if two loads are loading from /// addresses in the same cache line, it's better if they are scheduled /// together. This function takes two integers that represent the load offsets /// from the common base address. It returns true if it decides it's desirable @@ -840,7 +825,7 @@ public: return false; } - /// \brief Get the base register and byte offset of a load/store instr. + /// Get the base register and byte offset of a load/store instr. virtual bool getLdStBaseRegImmOfs(MachineInstr *LdSt, unsigned &BaseReg, unsigned &Offset, const TargetRegisterInfo *TRI) const { @@ -855,23 +840,21 @@ public: return false; } - /// \brief Can this target fuse the given instructions if they are scheduled + /// Can this target fuse the given instructions if they are scheduled /// adjacent. virtual bool shouldScheduleAdjacent(MachineInstr* First, MachineInstr *Second) const { return false; } - /// ReverseBranchCondition - Reverses the branch condition of the specified - /// condition list, returning false on success and true if it cannot be - /// reversed. + /// Reverses the branch condition of the specified condition list, + /// returning false on success and true if it cannot be reversed. virtual bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { return true; } - /// insertNoop - Insert a noop into the instruction stream at the specified - /// point. + /// Insert a noop into the instruction stream at the specified point. virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; @@ -880,23 +863,22 @@ public: virtual void getNoopForMachoTarget(MCInst &NopInst) const; - /// isPredicated - Returns true if the instruction is already predicated. - /// + /// Returns true if the instruction is already predicated. virtual bool isPredicated(const MachineInstr *MI) const { return false; } - /// isUnpredicatedTerminator - Returns true if the instruction is a + /// Returns true if the instruction is a /// terminator instruction that has not been predicated. virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; - /// PredicateInstruction - Convert the instruction into a predicated - /// instruction. It returns true if the operation was successful. + /// Convert the instruction into a predicated instruction. + /// It returns true if the operation was successful. virtual bool PredicateInstruction(MachineInstr *MI, const SmallVectorImpl<MachineOperand> &Pred) const; - /// SubsumesPredicate - Returns true if the first specified predicate + /// Returns true if the first specified predicate /// subsumes the second, e.g. GE subsumes GT. virtual bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, @@ -904,7 +886,7 @@ public: return false; } - /// DefinesPredicate - If the specified instruction defines any predicate + /// If the specified instruction defines any predicate /// or condition code register(s) used for predication, returns true as well /// as the definition predicate(s) by reference. virtual bool DefinesPredicate(MachineInstr *MI, @@ -912,22 +894,21 @@ public: return false; } - /// isPredicable - Return true if the specified instruction can be predicated. + /// Return true if the specified instruction can be predicated. /// By default, this returns true for every instruction with a /// PredicateOperand. virtual bool isPredicable(MachineInstr *MI) const { return MI->getDesc().isPredicable(); } - /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine + /// Return true if it's safe to move a machine /// instruction that defines the specified register class. virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { return true; } - /// isSchedulingBoundary - Test if the given instruction should be - /// considered a scheduling boundary. This primarily includes labels and - /// terminators. + /// Test if the given instruction should be considered a scheduling boundary. + /// This primarily includes labels and terminators. virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const; @@ -937,23 +918,20 @@ public: virtual unsigned getInlineAsmLength(const char *Str, const MCAsmInfo &MAI) const; - /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer to - /// use for this target when scheduling the machine instructions before - /// register allocation. + /// Allocate and return a hazard recognizer to use for this target when + /// scheduling the machine instructions before register allocation. virtual ScheduleHazardRecognizer* CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const; - /// CreateTargetMIHazardRecognizer - Allocate and return a hazard recognizer - /// to use for this target when scheduling the machine instructions before - /// register allocation. + /// Allocate and return a hazard recognizer to use for this target when + /// scheduling the machine instructions before register allocation. virtual ScheduleHazardRecognizer* CreateTargetMIHazardRecognizer(const InstrItineraryData*, const ScheduleDAG *DAG) const; - /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard - /// recognizer to use for this target when scheduling the machine instructions - /// after register allocation. + /// Allocate and return a hazard recognizer to use for this target when + /// scheduling the machine instructions after register allocation. virtual ScheduleHazardRecognizer* CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, const ScheduleDAG *DAG) const; @@ -962,7 +940,7 @@ public: /// targets may choose to honor. bool usePreRAHazardRecognizer() const; - /// analyzeCompare - For a comparison instruction, return the source registers + /// For a comparison instruction, return the source registers /// in SrcReg and SrcReg2 if having two register operands, and the value it /// compares against in CmpValue. Return true if the comparison instruction /// can be analyzed. @@ -972,7 +950,7 @@ public: return false; } - /// optimizeCompareInstr - See if the comparison instruction can be converted + /// See if the comparison instruction can be converted /// into something more efficient. E.g., on ARM most instructions can set the /// flags register, obviating the need for a separate CMP. virtual bool optimizeCompareInstr(MachineInstr *CmpInstr, @@ -983,8 +961,8 @@ public: } 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 + /// 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 /// def and use are in the same BB. We only look at one load and see /// whether it can be folded into MI. FoldAsLoadDefReg is the virtual register /// defined by the load we are trying to fold. DefMI returns the machine @@ -997,8 +975,8 @@ public: return nullptr; } - /// FoldImmediate - 'Reg' is known to be defined by a move immediate - /// instruction, try to fold the immediate into the use instruction. + /// 'Reg' is known to be defined by a move immediate instruction, + /// try to fold the immediate into the use instruction. /// If MRI->hasOneNonDBGUse(Reg) is true, and this function returns true, /// then the caller may assume that DefMI has been erased from its parent /// block. The caller may assume that it will not be erased by this @@ -1008,14 +986,14 @@ public: return false; } - /// getNumMicroOps - Return the number of u-operations the given machine + /// Return the number of u-operations the given machine /// instruction will be decoded to on the target cpu. The itinerary's /// IssueWidth is the number of microops that can be dispatched each /// cycle. An instruction with zero microops takes no dispatch resources. virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr *MI) const; - /// isZeroCost - Return true for pseudo instructions that don't consume any + /// Return true for pseudo instructions that don't consume any /// machine resources in their current form. These are common cases that the /// scheduler should consider free, rather than conservatively handling them /// as instructions with no itinerary. @@ -1027,27 +1005,27 @@ public: SDNode *DefNode, unsigned DefIdx, SDNode *UseNode, unsigned UseIdx) const; - /// getOperandLatency - Compute and return the use operand latency of a given - /// pair of def and use. + /// Compute and return the use operand latency of a given pair of def and use. /// In most cases, the static scheduling itinerary was enough to determine the /// operand latency. But it may not be possible for instructions with variable /// number of defs / uses. /// - /// This is a raw interface to the itinerary that may be directly overriden by - /// a target. Use computeOperandLatency to get the best estimate of latency. + /// This is a raw interface to the itinerary that may be directly overridden + /// by a target. Use computeOperandLatency to get the best estimate of + /// latency. virtual int getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, unsigned UseIdx) const; - /// computeOperandLatency - Compute and return the latency of the given data + /// Compute and return the latency of the given data /// dependent def and use when the operand indices are already known. unsigned computeOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, unsigned UseIdx) const; - /// getInstrLatency - Compute the instruction latency of a given instruction. + /// Compute the instruction latency of a given instruction. /// If the instruction has higher cost when predicated, it's returned via /// PredCost. virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, @@ -1066,14 +1044,13 @@ public: int computeDefOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI) const; - /// isHighLatencyDef - Return true if this opcode has high latency to its - /// result. + /// Return true if this opcode has high latency to its result. virtual bool isHighLatencyDef(int opc) const { return false; } - /// hasHighOperandLatency - Compute operand latency between a def of 'Reg' - /// and an use in the current loop, return true if the target considered + /// Compute operand latency between a def of 'Reg' + /// and a use in the current loop. Return true if the target considered /// it 'high'. This is used by optimization passes such as machine LICM to - /// determine whether it makes sense to hoist an instruction out even in + /// determine whether it makes sense to hoist an instruction out even in a /// high register pressure situation. virtual bool hasHighOperandLatency(const InstrItineraryData *ItinData, @@ -1083,19 +1060,19 @@ public: return false; } - /// hasLowDefLatency - Compute operand latency of a def of 'Reg', return true + /// Compute operand latency of a def of 'Reg'. Return true /// if the target considered it 'low'. virtual bool hasLowDefLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx) const; - /// verifyInstruction - Perform target specific instruction verification. + /// Perform target-specific instruction verification. virtual bool verifyInstruction(const MachineInstr *MI, StringRef &ErrInfo) const { return true; } - /// getExecutionDomain - Return the current execution domain and bit mask of + /// Return the current execution domain and bit mask of /// possible domains for instruction. /// /// Some micro-architectures have multiple execution domains, and multiple @@ -1119,15 +1096,14 @@ public: return std::make_pair(0, 0); } - /// setExecutionDomain - Change the opcode of MI to execute in Domain. + /// Change the opcode of MI to execute in Domain. /// /// The bit (1 << Domain) must be set in the mask returned from /// getExecutionDomain(MI). - /// virtual void setExecutionDomain(MachineInstr *MI, unsigned Domain) const {} - /// getPartialRegUpdateClearance - Returns the preferred minimum clearance + /// Returns the preferred minimum clearance /// before an instruction with an unwanted partial register update. /// /// Some instructions only write part of a register, and implicitly need to @@ -1176,7 +1152,7 @@ public: /// \brief Return the minimum clearance before an instruction that reads an /// unused register. /// - /// For example, AVX instructions may copy part of an register operand into + /// For example, AVX instructions may copy part of a register operand into /// the unused high bits of the destination register. /// /// vcvtsi2sdq %rax, %xmm0<undef>, %xmm14 @@ -1193,7 +1169,7 @@ public: return 0; } - /// breakPartialRegDependency - Insert a dependency-breaking instruction + /// Insert a dependency-breaking instruction /// before MI to eliminate an unwanted dependency on OpNum. /// /// If it wasn't possible to avoid a def in the last N instructions before MI @@ -1220,10 +1196,10 @@ public: return nullptr; } - // areMemAccessesTriviallyDisjoint - Sometimes, it is possible for the target + // 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. + // memory addresses and false otherwise. virtual bool areMemAccessesTriviallyDisjoint(MachineInstr *MIa, MachineInstr *MIb, AliasAnalysis *AA = nullptr) const { @@ -1234,8 +1210,16 @@ public: return false; } + /// \brief Return the value to use for the MachineCSE's LookAheadLimit, + /// which is a heuristic used for CSE'ing phys reg defs. + virtual unsigned getMachineCSELookAheadLimit () const { + // The default lookahead is small to prevent unprofitable quadratic + // behavior. + return 5; + } + private: - int CallFrameSetupOpcode, CallFrameDestroyOpcode; + unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode; }; } // End llvm namespace diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h index 71c0166d49b0..c630f5b12a15 100644 --- a/include/llvm/Target/TargetIntrinsicInfo.h +++ b/include/llvm/Target/TargetIntrinsicInfo.h @@ -28,8 +28,8 @@ class Type; /// TargetIntrinsicInfo - Interface to description of machine instruction set /// class TargetIntrinsicInfo { - TargetIntrinsicInfo(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION; - void operator=(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION; + TargetIntrinsicInfo(const TargetIntrinsicInfo &) = delete; + void operator=(const TargetIntrinsicInfo &) = delete; public: TargetIntrinsicInfo(); virtual ~TargetIntrinsicInfo(); diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h deleted file mode 100644 index 46f87b93b001..000000000000 --- a/include/llvm/Target/TargetLibraryInfo.h +++ /dev/null @@ -1,802 +0,0 @@ -//===-- llvm/Target/TargetLibraryInfo.h - Library information ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETLIBRARYINFO_H -#define LLVM_TARGET_TARGETLIBRARYINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Pass.h" - -namespace llvm { - class Triple; - - namespace LibFunc { - enum Func { - /// int _IO_getc(_IO_FILE * __fp); - under_IO_getc, - /// int _IO_putc(int __c, _IO_FILE * __fp); - under_IO_putc, - /// void operator delete[](void*); - 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); - ZnajRKSt9nothrow_t, - /// void *new[](unsigned long); - Znam, - /// void *new[](unsigned long, nothrow); - ZnamRKSt9nothrow_t, - /// void *new(unsigned int); - Znwj, - /// void *new(unsigned int, nothrow); - ZnwjRKSt9nothrow_t, - /// void *new(unsigned long); - Znwm, - /// void *new(unsigned long, nothrow); - ZnwmRKSt9nothrow_t, - /// double __cospi(double x); - cospi, - /// float __cospif(float x); - cospif, - /// int __cxa_atexit(void (*f)(void *), void *p, void *d); - 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, - /// int __cxa_guard_acquire(guard_t *guard); - cxa_guard_acquire, - /// void __cxa_guard_release(guard_t *guard); - cxa_guard_release, - /// int __isoc99_scanf (const char *format, ...) - dunder_isoc99_scanf, - /// int __isoc99_sscanf(const char *s, const char *format, ...) - 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); - sincospif_stret, - /// double __sinpi(double x); - sinpi, - /// float __sinpif(float x); - sinpif, - /// double __sqrt_finite(double x); - sqrt_finite, - /// float __sqrt_finite(float x); - 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); - dunder_strtok_r, - /// int abs(int j); - abs, - /// int access(const char *path, int amode); - access, - /// double acos(double x); - acos, - /// float acosf(float x); - acosf, - /// double acosh(double x); - acosh, - /// float acoshf(float x); - acoshf, - /// long double acoshl(long double x); - acoshl, - /// long double acosl(long double x); - acosl, - /// double asin(double x); - asin, - /// float asinf(float x); - asinf, - /// double asinh(double x); - asinh, - /// float asinhf(float x); - asinhf, - /// long double asinhl(long double x); - asinhl, - /// long double asinl(long double x); - asinl, - /// double atan(double x); - atan, - /// double atan2(double y, double x); - atan2, - /// float atan2f(float y, float x); - atan2f, - /// long double atan2l(long double y, long double x); - atan2l, - /// float atanf(float x); - atanf, - /// double atanh(double x); - atanh, - /// float atanhf(float x); - atanhf, - /// long double atanhl(long double x); - atanhl, - /// long double atanl(long double x); - atanl, - /// double atof(const char *str); - atof, - /// int atoi(const char *str); - atoi, - /// long atol(const char *str); - atol, - /// long long atoll(const char *nptr); - atoll, - /// int bcmp(const void *s1, const void *s2, size_t n); - bcmp, - /// void bcopy(const void *s1, void *s2, size_t n); - bcopy, - /// void bzero(void *s, size_t n); - bzero, - /// void *calloc(size_t count, size_t size); - calloc, - /// double cbrt(double x); - cbrt, - /// float cbrtf(float x); - cbrtf, - /// long double cbrtl(long double x); - cbrtl, - /// double ceil(double x); - ceil, - /// float ceilf(float x); - ceilf, - /// long double ceill(long double x); - ceill, - /// int chmod(const char *path, mode_t mode); - chmod, - /// int chown(const char *path, uid_t owner, gid_t group); - chown, - /// void clearerr(FILE *stream); - clearerr, - /// int closedir(DIR *dirp); - closedir, - /// double copysign(double x, double y); - copysign, - /// float copysignf(float x, float y); - copysignf, - /// long double copysignl(long double x, long double y); - copysignl, - /// double cos(double x); - cos, - /// float cosf(float x); - cosf, - /// double cosh(double x); - cosh, - /// float coshf(float x); - coshf, - /// long double coshl(long double x); - coshl, - /// long double cosl(long double x); - cosl, - /// char *ctermid(char *s); - ctermid, - /// double exp(double x); - exp, - /// double exp10(double x); - exp10, - /// float exp10f(float x); - exp10f, - /// long double exp10l(long double x); - exp10l, - /// double exp2(double x); - exp2, - /// float exp2f(float x); - exp2f, - /// long double exp2l(long double x); - exp2l, - /// float expf(float x); - expf, - /// long double expl(long double x); - expl, - /// double expm1(double x); - expm1, - /// float expm1f(float x); - expm1f, - /// long double expm1l(long double x); - expm1l, - /// double fabs(double x); - fabs, - /// float fabsf(float x); - fabsf, - /// long double fabsl(long double x); - fabsl, - /// int fclose(FILE *stream); - fclose, - /// FILE *fdopen(int fildes, const char *mode); - fdopen, - /// int feof(FILE *stream); - feof, - /// int ferror(FILE *stream); - ferror, - /// int fflush(FILE *stream); - fflush, - /// int ffs(int i); - ffs, - /// int ffsl(long int i); - ffsl, - /// int ffsll(long long int i); - ffsll, - /// int fgetc(FILE *stream); - fgetc, - /// int fgetpos(FILE *stream, fpos_t *pos); - fgetpos, - /// char *fgets(char *s, int n, FILE *stream); - fgets, - /// int fileno(FILE *stream); - fileno, - /// int fiprintf(FILE *stream, const char *format, ...); - fiprintf, - /// void flockfile(FILE *file); - flockfile, - /// double floor(double x); - floor, - /// float floorf(float x); - floorf, - /// long double floorl(long double x); - floorl, - /// double fmax(double x, double y); - fmax, - /// float fmaxf(float x, float y); - fmaxf, - /// long double fmaxl(long double x, long double y); - fmaxl, - /// double fmin(double x, double y); - fmin, - /// float fminf(float x, float y); - fminf, - /// long double fminl(long double x, long double y); - fminl, - /// double fmod(double x, double y); - fmod, - /// float fmodf(float x, float y); - fmodf, - /// long double fmodl(long double x, long double y); - fmodl, - /// FILE *fopen(const char *filename, const char *mode); - fopen, - /// FILE *fopen64(const char *filename, const char *opentype) - fopen64, - /// int fprintf(FILE *stream, const char *format, ...); - fprintf, - /// int fputc(int c, FILE *stream); - fputc, - /// int fputs(const char *s, FILE *stream); - fputs, - /// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); - fread, - /// void free(void *ptr); - free, - /// double frexp(double num, int *exp); - frexp, - /// float frexpf(float num, int *exp); - frexpf, - /// long double frexpl(long double num, int *exp); - frexpl, - /// int fscanf(FILE *stream, const char *format, ... ); - fscanf, - /// int fseek(FILE *stream, long offset, int whence); - fseek, - /// int fseeko(FILE *stream, off_t offset, int whence); - fseeko, - /// int fseeko64(FILE *stream, off64_t offset, int whence) - fseeko64, - /// int fsetpos(FILE *stream, const fpos_t *pos); - fsetpos, - /// int fstat(int fildes, struct stat *buf); - fstat, - /// int fstat64(int filedes, struct stat64 *buf) - fstat64, - /// int fstatvfs(int fildes, struct statvfs *buf); - fstatvfs, - /// int fstatvfs64(int fildes, struct statvfs64 *buf); - fstatvfs64, - /// long ftell(FILE *stream); - ftell, - /// off_t ftello(FILE *stream); - ftello, - /// off64_t ftello64(FILE *stream) - ftello64, - /// int ftrylockfile(FILE *file); - ftrylockfile, - /// void funlockfile(FILE *file); - funlockfile, - /// size_t fwrite(const void *ptr, size_t size, size_t nitems, - /// FILE *stream); - fwrite, - /// int getc(FILE *stream); - getc, - /// int getc_unlocked(FILE *stream); - getc_unlocked, - /// int getchar(void); - getchar, - /// char *getenv(const char *name); - getenv, - /// int getitimer(int which, struct itimerval *value); - getitimer, - /// int getlogin_r(char *name, size_t namesize); - getlogin_r, - /// struct passwd *getpwnam(const char *name); - getpwnam, - /// char *gets(char *s); - gets, - /// int gettimeofday(struct timeval *tp, void *tzp); - gettimeofday, - /// uint32_t htonl(uint32_t hostlong); - htonl, - /// uint16_t htons(uint16_t hostshort); - htons, - /// int iprintf(const char *format, ...); - iprintf, - /// int isascii(int c); - isascii, - /// int isdigit(int c); - isdigit, - /// long int labs(long int j); - labs, - /// int lchown(const char *path, uid_t owner, gid_t group); - lchown, - /// double ldexp(double x, int n); - ldexp, - /// float ldexpf(float x, int n); - ldexpf, - /// long double ldexpl(long double x, int n); - ldexpl, - /// long long int llabs(long long int j); - llabs, - /// double log(double x); - log, - /// double log10(double x); - log10, - /// float log10f(float x); - log10f, - /// long double log10l(long double x); - log10l, - /// double log1p(double x); - log1p, - /// float log1pf(float x); - log1pf, - /// long double log1pl(long double x); - log1pl, - /// double log2(double x); - log2, - /// float log2f(float x); - log2f, - /// double long double log2l(long double x); - log2l, - /// double logb(double x); - logb, - /// float logbf(float x); - logbf, - /// long double logbl(long double x); - logbl, - /// float logf(float x); - logf, - /// long double logl(long double x); - logl, - /// int lstat(const char *path, struct stat *buf); - lstat, - /// int lstat64(const char *path, struct stat64 *buf); - lstat64, - /// void *malloc(size_t size); - malloc, - /// void *memalign(size_t boundary, size_t size); - memalign, - /// void *memccpy(void *s1, const void *s2, int c, size_t n); - memccpy, - /// void *memchr(const void *s, int c, size_t n); - memchr, - /// int memcmp(const void *s1, const void *s2, size_t n); - memcmp, - /// void *memcpy(void *s1, const void *s2, size_t n); - memcpy, - /// void *memmove(void *s1, const void *s2, size_t n); - memmove, - // void *memrchr(const void *s, int c, size_t n); - memrchr, - /// void *memset(void *b, int c, size_t len); - memset, - /// void memset_pattern16(void *b, const void *pattern16, size_t len); - memset_pattern16, - /// int mkdir(const char *path, mode_t mode); - mkdir, - /// time_t mktime(struct tm *timeptr); - mktime, - /// double modf(double x, double *iptr); - modf, - /// float modff(float, float *iptr); - modff, - /// long double modfl(long double value, long double *iptr); - modfl, - /// double nearbyint(double x); - nearbyint, - /// float nearbyintf(float x); - nearbyintf, - /// long double nearbyintl(long double x); - nearbyintl, - /// uint32_t ntohl(uint32_t netlong); - ntohl, - /// uint16_t ntohs(uint16_t netshort); - ntohs, - /// int open(const char *path, int oflag, ... ); - open, - /// int open64(const char *filename, int flags[, mode_t mode]) - open64, - /// DIR *opendir(const char *dirname); - opendir, - /// int pclose(FILE *stream); - pclose, - /// void perror(const char *s); - perror, - /// FILE *popen(const char *command, const char *mode); - popen, - /// int posix_memalign(void **memptr, size_t alignment, size_t size); - posix_memalign, - /// double pow(double x, double y); - pow, - /// float powf(float x, float y); - powf, - /// long double powl(long double x, long double y); - powl, - /// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); - pread, - /// int printf(const char *format, ...); - printf, - /// int putc(int c, FILE *stream); - putc, - /// int putchar(int c); - putchar, - /// int puts(const char *s); - puts, - /// ssize_t pwrite(int fildes, const void *buf, size_t nbyte, - /// off_t offset); - pwrite, - /// void qsort(void *base, size_t nel, size_t width, - /// int (*compar)(const void *, const void *)); - qsort, - /// ssize_t read(int fildes, void *buf, size_t nbyte); - read, - /// ssize_t readlink(const char *path, char *buf, size_t bufsize); - readlink, - /// void *realloc(void *ptr, size_t size); - realloc, - /// void *reallocf(void *ptr, size_t size); - reallocf, - /// char *realpath(const char *file_name, char *resolved_name); - realpath, - /// int remove(const char *path); - remove, - /// int rename(const char *old, const char *new); - rename, - /// void rewind(FILE *stream); - rewind, - /// double rint(double x); - rint, - /// float rintf(float x); - rintf, - /// long double rintl(long double x); - rintl, - /// int rmdir(const char *path); - rmdir, - /// double round(double x); - round, - /// float roundf(float x); - roundf, - /// long double roundl(long double x); - roundl, - /// int scanf(const char *restrict format, ... ); - scanf, - /// void setbuf(FILE *stream, char *buf); - setbuf, - /// int setitimer(int which, const struct itimerval *value, - /// struct itimerval *ovalue); - setitimer, - /// int setvbuf(FILE *stream, char *buf, int type, size_t size); - setvbuf, - /// double sin(double x); - sin, - /// float sinf(float x); - sinf, - /// double sinh(double x); - sinh, - /// float sinhf(float x); - sinhf, - /// long double sinhl(long double x); - sinhl, - /// long double sinl(long double x); - sinl, - /// int siprintf(char *str, const char *format, ...); - siprintf, - /// int snprintf(char *s, size_t n, const char *format, ...); - snprintf, - /// int sprintf(char *str, const char *format, ...); - sprintf, - /// double sqrt(double x); - sqrt, - /// float sqrtf(float x); - sqrtf, - /// long double sqrtl(long double x); - sqrtl, - /// int sscanf(const char *s, const char *format, ... ); - sscanf, - /// int stat(const char *path, struct stat *buf); - stat, - /// int stat64(const char *path, struct stat64 *buf); - stat64, - /// int statvfs(const char *path, struct statvfs *buf); - statvfs, - /// int statvfs64(const char *path, struct statvfs64 *buf) - statvfs64, - /// char *stpcpy(char *s1, const char *s2); - stpcpy, - /// char *stpncpy(char *s1, const char *s2, size_t n); - stpncpy, - /// int strcasecmp(const char *s1, const char *s2); - strcasecmp, - /// char *strcat(char *s1, const char *s2); - strcat, - /// char *strchr(const char *s, int c); - strchr, - /// int strcmp(const char *s1, const char *s2); - strcmp, - /// int strcoll(const char *s1, const char *s2); - strcoll, - /// char *strcpy(char *s1, const char *s2); - strcpy, - /// size_t strcspn(const char *s1, const char *s2); - strcspn, - /// char *strdup(const char *s1); - strdup, - /// size_t strlen(const char *s); - strlen, - /// int strncasecmp(const char *s1, const char *s2, size_t n); - strncasecmp, - /// char *strncat(char *s1, const char *s2, size_t n); - strncat, - /// int strncmp(const char *s1, const char *s2, size_t n); - strncmp, - /// char *strncpy(char *s1, const char *s2, size_t n); - strncpy, - /// char *strndup(const char *s1, size_t n); - strndup, - /// size_t strnlen(const char *s, size_t maxlen); - strnlen, - /// char *strpbrk(const char *s1, const char *s2); - strpbrk, - /// char *strrchr(const char *s, int c); - strrchr, - /// size_t strspn(const char *s1, const char *s2); - strspn, - /// char *strstr(const char *s1, const char *s2); - strstr, - /// double strtod(const char *nptr, char **endptr); - strtod, - /// float strtof(const char *nptr, char **endptr); - strtof, - // char *strtok(char *s1, const char *s2); - strtok, - // char *strtok_r(char *s, const char *sep, char **lasts); - strtok_r, - /// long int strtol(const char *nptr, char **endptr, int base); - strtol, - /// long double strtold(const char *nptr, char **endptr); - strtold, - /// long long int strtoll(const char *nptr, char **endptr, int base); - strtoll, - /// unsigned long int strtoul(const char *nptr, char **endptr, int base); - strtoul, - /// unsigned long long int strtoull(const char *nptr, char **endptr, - /// int base); - strtoull, - /// size_t strxfrm(char *s1, const char *s2, size_t n); - strxfrm, - /// int system(const char *command); - system, - /// double tan(double x); - tan, - /// float tanf(float x); - tanf, - /// double tanh(double x); - tanh, - /// float tanhf(float x); - tanhf, - /// long double tanhl(long double x); - tanhl, - /// long double tanl(long double x); - tanl, - /// clock_t times(struct tms *buffer); - times, - /// FILE *tmpfile(void); - tmpfile, - /// FILE *tmpfile64(void) - tmpfile64, - /// int toascii(int c); - toascii, - /// double trunc(double x); - trunc, - /// float truncf(float x); - truncf, - /// long double truncl(long double x); - truncl, - /// int uname(struct utsname *name); - uname, - /// int ungetc(int c, FILE *stream); - ungetc, - /// int unlink(const char *path); - unlink, - /// int unsetenv(const char *name); - unsetenv, - /// int utime(const char *path, const struct utimbuf *times); - utime, - /// int utimes(const char *path, const struct timeval times[2]); - utimes, - /// void *valloc(size_t size); - valloc, - /// int vfprintf(FILE *stream, const char *format, va_list ap); - vfprintf, - /// int vfscanf(FILE *stream, const char *format, va_list arg); - vfscanf, - /// int vprintf(const char *restrict format, va_list ap); - vprintf, - /// int vscanf(const char *format, va_list arg); - vscanf, - /// int vsnprintf(char *s, size_t n, const char *format, va_list ap); - vsnprintf, - /// int vsprintf(char *s, const char *format, va_list ap); - vsprintf, - /// int vsscanf(const char *s, const char *format, va_list arg); - vsscanf, - /// ssize_t write(int fildes, const void *buf, size_t nbyte); - write, - - NumLibFuncs - }; - } - -/// TargetLibraryInfo - This immutable pass captures information about what -/// library functions are available for the current target, and allows a -/// frontend to disable optimizations through -fno-builtin etc. -class TargetLibraryInfo : public ImmutablePass { - virtual void anchor(); - unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; - llvm::DenseMap<unsigned, std::string> CustomNames; - static const char* StandardNames[LibFunc::NumLibFuncs]; - - enum AvailabilityState { - StandardName = 3, // (memset to all ones) - CustomName = 1, - Unavailable = 0 // (memset to all zeros) - }; - void setState(LibFunc::Func F, AvailabilityState State) { - AvailableArray[F/4] &= ~(3 << 2*(F&3)); - AvailableArray[F/4] |= State << 2*(F&3); - } - AvailabilityState getState(LibFunc::Func F) const { - return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3); - } - -public: - static char ID; - 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; - - /// has - This function is used by optimizations that want to match on or form - /// a given library function. - bool has(LibFunc::Func F) const { - return getState(F) != Unavailable; - } - - /// hasOptimizedCodeGen - Return true if the function is both available as - /// a builtin and a candidate for optimized code generation. - bool hasOptimizedCodeGen(LibFunc::Func F) const { - if (getState(F) == Unavailable) - return false; - switch (F) { - default: break; - case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: - case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: - case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: - case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: - case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: - case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: - case LibFunc::sqrtl_finite: - case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: - case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: - case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: - case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: - case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: - case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: - case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: - case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: - case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: - case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: - case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: - case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: - case LibFunc::memchr: - return true; - } - return false; - } - - StringRef getName(LibFunc::Func F) const { - AvailabilityState State = getState(F); - if (State == Unavailable) - return StringRef(); - if (State == StandardName) - return StandardNames[F]; - assert(State == CustomName); - return CustomNames.find(F)->second; - } - - /// setUnavailable - this can be used by whatever sets up TargetLibraryInfo to - /// ban use of specific library functions. - void setUnavailable(LibFunc::Func F) { - setState(F, Unavailable); - } - - void setAvailable(LibFunc::Func F) { - setState(F, StandardName); - } - - void setAvailableWithName(LibFunc::Func F, StringRef Name) { - if (StandardNames[F] != Name) { - setState(F, CustomName); - CustomNames[F] = Name; - assert(CustomNames.find(F) != CustomNames.end()); - } else { - setState(F, StandardName); - } - } - - /// disableAllFunctions - This disables all builtins, which is used for - /// options like -fno-builtin. - void disableAllFunctions(); -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 43d6f2772c5e..e2fe9e85fc92 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -77,8 +77,8 @@ namespace llvm { /// This base class for TargetLowering contains the SelectionDAG-independent /// parts that can be used from the rest of CodeGen. class TargetLoweringBase { - TargetLoweringBase(const TargetLoweringBase&) LLVM_DELETED_FUNCTION; - void operator=(const TargetLoweringBase&) LLVM_DELETED_FUNCTION; + TargetLoweringBase(const TargetLoweringBase&) = delete; + void operator=(const TargetLoweringBase&) = delete; public: /// This enum indicates whether operations are valid for a target, and if not, @@ -100,7 +100,8 @@ public: TypeExpandFloat, // Split this float into two of half the size. TypeScalarizeVector, // Replace this one-element vector with its element. TypeSplitVector, // Split this vector into two of half the size. - TypeWidenVector // This vector should be widened into a larger vector. + TypeWidenVector, // This vector should be widened into a larger vector. + TypePromoteFloat // Replace this float with a larger one. }; /// LegalizeKind holds the legalization kind that needs to happen to EVT @@ -123,6 +124,18 @@ public: // mask (ex: x86 blends). }; + /// Enum that specifies what a AtomicRMWInst is expanded to, if at all. Exists + /// because different targets have different levels of support for these + /// atomic RMW instructions, and also have different options w.r.t. what they + /// should expand to. + enum class AtomicRMWExpansionKind { + None, // Don't expand the instruction. + LLSC, // Expand the instruction into loadlinked/storeconditional; used + // by ARM/AArch64. Implies `hasLoadLinkedStoreConditional` + // returns true. + CmpXChg, // Expand the instruction into cmpxchg; used by at least X86. + }; + static ISD::NodeType getExtendForContent(BooleanContent Content) { switch (Content) { case UndefinedBooleanContent: @@ -148,13 +161,11 @@ protected: public: const TargetMachine &getTargetMachine() const { return TM; } - const DataLayout *getDataLayout() const { return DL; } - const TargetLoweringObjectFile &getObjFileLowering() const { - return *TM.getObjFileLowering(); - } + const DataLayout *getDataLayout() const { return TM.getDataLayout(); } bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } + virtual bool useSoftFloat() const { return false; } /// Return the pointer type for the given address space, defaults to /// the pointer type from the data layout. @@ -247,19 +258,29 @@ public: /// isLoadBitCastBeneficial() - Return true if the following transform /// is beneficial. /// fold (conv (load x)) -> (load (conv*)x) - /// On architectures that don't natively support some vector loads efficiently, - /// casting the load to a smaller vector of larger types and loading - /// is more efficient, however, this can be undone by optimizations in + /// On architectures that don't natively support some vector loads + /// efficiently, casting the load to a smaller vector of larger types and + /// loading is more efficient, however, this can be undone by optimizations in /// dag combiner. - virtual bool isLoadBitCastBeneficial(EVT /* Load */, EVT /* Bitcast */) const { + virtual bool isLoadBitCastBeneficial(EVT /* Load */, + EVT /* Bitcast */) const { return true; } + /// Return true if it is expected to be cheaper to do a store of a non-zero + /// vector constant with the given size and type for the address space than to + /// store the individual scalar element constants. + virtual bool storeOfVectorConstantIsCheap(EVT MemVT, + unsigned NumElem, + unsigned AddrSpace) const { + return false; + } + /// \brief Return true if it is cheap to speculate a call to intrinsic cttz. virtual bool isCheapToSpeculateCttz() const { return false; } - + /// \brief Return true if it is cheap to speculate a call to intrinsic ctlz. virtual bool isCheapToSpeculateCtlz() const { return false; @@ -562,7 +583,8 @@ 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, EVT ValVT, EVT MemVT) const { + LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, + EVT MemVT) const { if (ValVT.isExtended() || MemVT.isExtended()) return Expand; unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; @@ -577,6 +599,14 @@ public: getLoadExtAction(ExtType, ValVT, MemVT) == Legal; } + /// Return true if the specified load with extension is legal or custom + /// on this target. + bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const { + return ValVT.isSimple() && MemVT.isSimple() && + (getLoadExtAction(ExtType, ValVT, MemVT) == Legal || + getLoadExtAction(ExtType, ValVT, MemVT) == Custom); + } + /// 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. @@ -954,17 +984,20 @@ public: return false; } - /// Returns the maximal possible offset which can be used for loads / stores - /// from the global. - virtual unsigned getMaximalGlobalOffset() const { - return 0; - } - /// Returns true if a cast between SrcAS and DestAS is a noop. virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { return false; } + /// Return true if the pointer arguments to CI should be aligned by aligning + /// the object whose address is being passed. If so then MinSize is set to the + /// minimum size the object must be to be aligned and PrefAlign is set to the + /// preferred alignment. + virtual bool shouldAlignPointerArgs(CallInst * /*CI*/, unsigned & /*MinSize*/, + unsigned & /*PrefAlign*/) const { + return false; + } + //===--------------------------------------------------------------------===// /// \name Helpers for TargetTransformInfo implementations /// @{ @@ -1031,8 +1064,9 @@ public: /// 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 { + virtual Instruction *emitLeadingFence(IRBuilder<> &Builder, + AtomicOrdering Ord, bool IsStore, + bool IsLoad) const { if (!getInsertFencesForAtomic()) return nullptr; @@ -1042,8 +1076,9 @@ public: return nullptr; } - virtual Instruction* emitTrailingFence(IRBuilder<> &Builder, AtomicOrdering Ord, - bool IsStore, bool IsLoad) const { + virtual Instruction *emitTrailingFence(IRBuilder<> &Builder, + AtomicOrdering Ord, bool IsStore, + bool IsLoad) const { if (!getInsertFencesForAtomic()) return nullptr; @@ -1060,15 +1095,21 @@ public: return false; } + /// Returns true if arguments should be sign-extended in lib calls. + virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { + return IsSigned; + } + /// 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; + /// Returns how the IR-level AtomicExpand pass should expand the given + /// AtomicRMW, if at all. Default is to never expand. + virtual AtomicRMWExpansionKind + shouldExpandAtomicRMWInIR(AtomicRMWInst *) const { + return AtomicRMWExpansionKind::None; } /// On some platforms, an AtomicRMW that never actually modifies the value @@ -1082,17 +1123,33 @@ public: /// 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 { + virtual LoadInst * + lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const { return nullptr; } + + /// Returns true if we should normalize + /// select(N0&N1, X, Y) => select(N0, select(N1, X, Y), Y) and + /// select(N0|N1, X, Y) => select(N0, select(N1, X, Y, Y)) if it is likely + /// that it saves us from materializing N0 and N1 in an integer register. + /// Targets that are able to perform and/or on flags should return false here. + virtual bool shouldNormalizeToSelectSequence(LLVMContext &Context, + EVT VT) const { + // If a target has multiple condition registers, then it likely has logical + // operations on those registers. + if (hasMultipleConditionRegisters()) + return false; + // Only do the transform if the value won't be split into multiple + // registers. + LegalizeTypeAction Action = getTypeAction(Context, VT); + return Action != TypeExpandInteger && Action != TypeExpandFloat && + Action != TypeSplitVector; + } + //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. // - - /// \brief Reset the operation actions based on target options. - virtual void resetOperationActions() {} - protected: /// Specify how the target extends the result of integer and floating point /// boolean values from i1 to a wider type. See getBooleanContents. @@ -1230,12 +1287,12 @@ protected: /// Return the largest legal super-reg register class of the register class /// for the specified type and its associated "cost". - virtual std::pair<const TargetRegisterClass*, uint8_t> - findRepresentativeClass(MVT VT) const; + virtual std::pair<const TargetRegisterClass *, uint8_t> + findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const; /// Once all of the register classes are added, this allows us to compute /// derived properties we expose. - void computeRegisterProperties(); + void computeRegisterProperties(const TargetRegisterInfo *TRI); /// Indicate that the specified operation does not work with the specified /// type and indicate what to do about it. @@ -1455,6 +1512,35 @@ public: return false; } + virtual bool isProfitableToHoist(Instruction *I) const { return true; } + + /// Return true if the extension represented by \p I is free. + /// Unlikely the is[Z|FP]ExtFree family which is based on types, + /// this method can use the context provided by \p I to decide + /// whether or not \p I is free. + /// This method extends the behavior of the is[Z|FP]ExtFree family. + /// In other words, if is[Z|FP]Free returns true, then this method + /// returns true as well. The converse is not true. + /// The target can perform the adequate checks by overriding isExtFreeImpl. + /// \pre \p I must be a sign, zero, or fp extension. + bool isExtFree(const Instruction *I) const { + switch (I->getOpcode()) { + case Instruction::FPExt: + if (isFPExtFree(EVT::getEVT(I->getType()))) + return true; + break; + case Instruction::ZExt: + if (isZExtFree(I->getOperand(0)->getType(), I->getType())) + return true; + break; + case Instruction::SExt: + break; + default: + llvm_unreachable("Instruction is not an extension"); + } + return isExtFreeImpl(I); + } + /// Return true if any actual instruction that defines a value of type Ty1 /// implicitly zero-extends the value to Ty2 in the result register. /// @@ -1517,6 +1603,10 @@ public: return false; } + /// Return true if folding a vector load into ExtVal (a sign, zero, or any + /// extend node) is profitable. + virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const { return false; } + /// Return true if an fneg operation is free to the point where it is never /// worthwhile to replace it with a bitwise operation. virtual bool isFNegFree(EVT VT) const { @@ -1606,7 +1696,6 @@ public: private: const TargetMachine &TM; - const DataLayout *DL; /// True if this is a little endian target. bool IsLittleEndian; @@ -1783,136 +1872,8 @@ private: ValueTypeActionImpl ValueTypeActions; -public: - LegalizeKind - getTypeConversion(LLVMContext &Context, EVT VT) const { - // If this is a simple type, use the ComputeRegisterProp mechanism. - if (VT.isSimple()) { - MVT SVT = VT.getSimpleVT(); - assert((unsigned)SVT.SimpleTy < array_lengthof(TransformToType)); - MVT NVT = TransformToType[SVT.SimpleTy]; - LegalizeTypeAction LA = ValueTypeActions.getTypeAction(SVT); - - assert( - (LA == TypeLegal || LA == TypeSoftenFloat || - ValueTypeActions.getTypeAction(NVT) != TypePromoteInteger) - && "Promote may not follow Expand or Promote"); - - if (LA == TypeSplitVector) - return LegalizeKind(LA, EVT::getVectorVT(Context, - SVT.getVectorElementType(), - SVT.getVectorNumElements()/2)); - if (LA == TypeScalarizeVector) - return LegalizeKind(LA, SVT.getVectorElementType()); - return LegalizeKind(LA, NVT); - } - - // Handle Extended Scalar Types. - if (!VT.isVector()) { - assert(VT.isInteger() && "Float types must be simple"); - unsigned BitSize = VT.getSizeInBits(); - // First promote to a power-of-two size, then expand if necessary. - if (BitSize < 8 || !isPowerOf2_32(BitSize)) { - EVT NVT = VT.getRoundIntegerType(Context); - assert(NVT != VT && "Unable to round integer VT"); - LegalizeKind NextStep = getTypeConversion(Context, NVT); - // Avoid multi-step promotion. - if (NextStep.first == TypePromoteInteger) return NextStep; - // Return rounded integer type. - return LegalizeKind(TypePromoteInteger, NVT); - } - - return LegalizeKind(TypeExpandInteger, - EVT::getIntegerVT(Context, VT.getSizeInBits()/2)); - } - - // Handle vector types. - unsigned NumElts = VT.getVectorNumElements(); - EVT EltVT = VT.getVectorElementType(); - - // Vectors with only one element are always scalarized. - if (NumElts == 1) - return LegalizeKind(TypeScalarizeVector, EltVT); - - // Try to widen vector elements until the element type is a power of two and - // promote it to a legal type later on, for example: - // <3 x i8> -> <4 x i8> -> <4 x i32> - if (EltVT.isInteger()) { - // Vectors with a number of elements that is not a power of two are always - // widened, for example <3 x i8> -> <4 x i8>. - if (!VT.isPow2VectorType()) { - NumElts = (unsigned)NextPowerOf2(NumElts); - EVT NVT = EVT::getVectorVT(Context, EltVT, NumElts); - return LegalizeKind(TypeWidenVector, NVT); - } - - // Examine the element type. - LegalizeKind LK = getTypeConversion(Context, EltVT); - - // If type is to be expanded, split the vector. - // <4 x i140> -> <2 x i140> - if (LK.first == TypeExpandInteger) - return LegalizeKind(TypeSplitVector, - EVT::getVectorVT(Context, EltVT, NumElts / 2)); - - // Promote the integer element types until a legal vector type is found - // or until the element integer type is too big. If a legal type was not - // found, fallback to the usual mechanism of widening/splitting the - // vector. - EVT OldEltVT = EltVT; - while (1) { - // Increase the bitwidth of the element to the next pow-of-two - // (which is greater than 8 bits). - EltVT = EVT::getIntegerVT(Context, 1 + EltVT.getSizeInBits() - ).getRoundIntegerType(Context); - - // Stop trying when getting a non-simple element type. - // Note that vector elements may be greater than legal vector element - // types. Example: X86 XMM registers hold 64bit element on 32bit - // systems. - if (!EltVT.isSimple()) break; - - // Build a new vector type and check if it is legal. - MVT NVT = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts); - // Found a legal promoted vector type. - if (NVT != MVT() && ValueTypeActions.getTypeAction(NVT) == TypeLegal) - return LegalizeKind(TypePromoteInteger, - EVT::getVectorVT(Context, EltVT, NumElts)); - } - - // Reset the type to the unexpanded type if we did not find a legal vector - // type with a promoted vector element type. - EltVT = OldEltVT; - } - - // Try to widen the vector until a legal type is found. - // If there is no wider legal type, split the vector. - while (1) { - // Round up to the next power of 2. - NumElts = (unsigned)NextPowerOf2(NumElts); - - // If there is no simple vector type with this many elements then there - // cannot be a larger legal vector type. Note that this assumes that - // there are no skipped intermediate vector types in the simple types. - if (!EltVT.isSimple()) break; - MVT LargerVector = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts); - if (LargerVector == MVT()) break; - - // If this type is legal then widen the vector. - if (ValueTypeActions.getTypeAction(LargerVector) == TypeLegal) - return LegalizeKind(TypeWidenVector, LargerVector); - } - - // Widen odd vectors to next power of two. - if (!VT.isPow2VectorType()) { - EVT NVT = VT.getPow2VectorType(Context); - return LegalizeKind(TypeWidenVector, NVT); - } - - // Vectors with illegal element types are expanded. - EVT NVT = EVT::getVectorVT(Context, EltVT, VT.getVectorNumElements() / 2); - return LegalizeKind(TypeSplitVector, NVT); - } +private: + LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const; private: std::vector<std::pair<MVT, const TargetRegisterClass*> > AvailableRegClasses; @@ -1943,6 +1904,11 @@ private: CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; protected: + /// Return true if the extension represented by \p I is free. + /// \pre \p I is a sign, zero, or fp extension and + /// is[Z|FP]ExtFree of the related types is not true. + virtual bool isExtFreeImpl(const Instruction *I) const { return false; } + /// \brief Specify maximum number of store instructions per memset call. /// /// When lowering \@llvm.memset this field specifies the maximum number of @@ -2010,7 +1976,8 @@ protected: /// Replace/modify any TargetFrameIndex operands with a targte-dependent /// sequence of memory operands that is recognized by PrologEpilogInserter. - MachineBasicBlock *emitPatchPoint(MachineInstr *MI, MachineBasicBlock *MBB) const; + MachineBasicBlock *emitPatchPoint(MachineInstr *MI, + MachineBasicBlock *MBB) const; }; /// This class defines information used to lower LLVM code to legal SelectionDAG @@ -2019,8 +1986,8 @@ protected: /// This class also defines callbacks that targets must implement to lower /// target-specific constructs to SelectionDAG operators. class TargetLowering : public TargetLoweringBase { - TargetLowering(const TargetLowering&) LLVM_DELETED_FUNCTION; - void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION; + TargetLowering(const TargetLowering&) = delete; + void operator=(const TargetLowering&) = delete; public: /// NOTE: The TargetMachine owns TLOF. @@ -2080,6 +2047,7 @@ public: ISD::CondCode &CCCode, SDLoc DL) const; /// Returns a pair of (return value, chain). + /// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC. std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, const SDValue *Ops, unsigned NumOps, bool isSigned, @@ -2171,8 +2139,7 @@ public: void AddToWorklist(SDNode *N); void RemoveFromWorklist(SDNode *N); - SDValue CombineTo(SDNode *N, const std::vector<SDValue> &To, - bool AddTo = true); + SDValue CombineTo(SDNode *N, ArrayRef<SDValue> To, bool AddTo = true); SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true); SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo = true); @@ -2653,7 +2620,8 @@ public: /// specific constraints and their prefixes, and also tie in the associated /// operand values. If this returns an empty vector, and if the constraint /// string itself isn't empty, there was an error parsing. - virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; + virtual AsmOperandInfoVector ParseConstraints(const TargetRegisterInfo *TRI, + ImmutableCallSite CS) const; /// Examine constraint type and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. @@ -2684,10 +2652,19 @@ public: /// pointer. /// /// This should only be used for C_Register constraints. On error, this - /// returns a register number of 0 and a null register class pointer.. - virtual std::pair<unsigned, const TargetRegisterClass*> - getRegForInlineAsmConstraint(const std::string &Constraint, - MVT VT) const; + /// returns a register number of 0 and a null register class pointer. + virtual std::pair<unsigned, const TargetRegisterClass *> + getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + const std::string &Constraint, MVT VT) const; + + virtual unsigned + getInlineAsmMemConstraint(const std::string &ConstraintCode) const { + if (ConstraintCode == "i") + return InlineAsm::Constraint_i; + else if (ConstraintCode == "m") + return InlineAsm::Constraint_m; + return InlineAsm::Constraint_Unknown; + } /// Try to replace an X constraint, which matches anything, with another that /// has more specific requirements based on the type of the corresponding @@ -2725,7 +2702,7 @@ public: /// 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 @@ -2736,10 +2713,9 @@ public: /// 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 { + virtual SDValue getRsqrtEstimate(SDValue Operand, DAGCombinerInfo &DCI, + unsigned &RefinementSteps, + bool &UseOneConstNR) const { return SDValue(); } @@ -2751,8 +2727,7 @@ public: /// 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, + virtual SDValue getRecipEstimate(SDValue Operand, DAGCombinerInfo &DCI, unsigned &RefinementSteps) const { return SDValue(); } @@ -2791,6 +2766,8 @@ public: /// is created but not inserted into any basic blocks, and this method is /// called to expand it into a sequence of instructions, potentially also /// creating new basic blocks and control flow. + /// As long as the returned basic block is different (i.e., we created a new + /// one), the custom inserter is free to modify the rest of \p MBB. virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; @@ -2806,11 +2783,6 @@ public: virtual bool useLoadStackGuardNode() const { return false; } - - /// Returns true if arguments should be sign-extended in lib calls. - virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { - return IsSigned; - } }; /// 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 73bf56f018e9..2a17bd200f4d 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -29,22 +29,29 @@ namespace llvm { class MCSymbol; class MCSymbolRefExpr; class MCStreamer; + class MCValue; class ConstantExpr; class GlobalValue; class TargetMachine; class TargetLoweringObjectFile : public MCObjectFileInfo { MCContext *Ctx; - const DataLayout *DL; TargetLoweringObjectFile( - const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION; - void operator=(const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION; + const TargetLoweringObjectFile&) = delete; + void operator=(const TargetLoweringObjectFile&) = delete; + +protected: + const DataLayout *DL; + bool SupportIndirectSymViaGOTPCRel; + bool SupportGOTPCRelWithOffset; public: MCContext &getContext() const { return *Ctx; } - TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr) {} + TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr), + SupportIndirectSymViaGOTPCRel(false), + SupportGOTPCRelWithOffset(true) {} virtual ~TargetLoweringObjectFile(); @@ -70,8 +77,8 @@ public: /// Given a constant with the SectionKind, return a section that it should be /// placed in. - virtual const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const; + virtual MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const; /// Classify the specified global variable into a set of target independent /// categories embodied in SectionKind. @@ -81,23 +88,32 @@ public: /// This method computes the appropriate section to emit the specified global /// variable or function definition. This should not be passed external (or /// available externally) globals. - const MCSection *SectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const; + MCSection *SectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, const TargetMachine &TM) const; /// This method computes the appropriate section to emit the specified global /// variable or function definition. This should not be passed external (or /// available externally) globals. - const MCSection *SectionForGlobal(const GlobalValue *GV, - Mangler &Mang, - const TargetMachine &TM) const { + MCSection *SectionForGlobal(const GlobalValue *GV, Mangler &Mang, + const TargetMachine &TM) const { return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM); } + virtual void getNameWithPrefix(SmallVectorImpl<char> &OutName, + const GlobalValue *GV, + bool CannotUsePrivateLabel, Mangler &Mang, + const TargetMachine &TM) const; + + virtual MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const; + + virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const; + /// Targets should implement this method to assign a section to globals with /// an explicit section specfied. The implementation of this method can /// assume that GV->hasSection() is true. - virtual const MCSection * + virtual MCSection * getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const = 0; @@ -131,13 +147,13 @@ public: getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding, MCStreamer &Streamer) const; - virtual const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const { + virtual MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const { return StaticCtorSection; } - virtual const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const { + virtual MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const { return StaticDtorSection; } @@ -151,10 +167,31 @@ public: return nullptr; } + /// \brief Target supports replacing a data "PC"-relative access to a symbol + /// through another symbol, by accessing the later via a GOT entry instead? + bool supportIndirectSymViaGOTPCRel() const { + return SupportIndirectSymViaGOTPCRel; + } + + /// \brief Target GOT "PC"-relative relocation supports encoding an additional + /// binary expression with an offset? + bool supportGOTPCRelWithOffset() const { + return SupportGOTPCRelWithOffset; + } + + /// \brief Get the target specific PC relative GOT entry relocation + virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym, + const MCValue &MV, + int64_t Offset, + MachineModuleInfo *MMI, + MCStreamer &Streamer) const { + return nullptr; + } + protected: - virtual const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler &Mang, const TargetMachine &TM) const = 0; + virtual MCSection *SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, 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 a4f95c061283..2a1ce0483e10 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -15,6 +15,7 @@ #define LLVM_TARGET_TARGETMACHINE_H #include "llvm/ADT/StringRef.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetOptions.h" @@ -29,21 +30,25 @@ class Mangler; class MCAsmInfo; class MCCodeGenInfo; class MCContext; +class MCInstrInfo; +class MCRegisterInfo; +class MCSubtargetInfo; class MCSymbol; class Target; class DataLayout; class TargetLibraryInfo; class TargetFrameLowering; +class TargetIRAnalysis; class TargetIntrinsicInfo; class TargetLowering; class TargetPassConfig; class TargetRegisterInfo; class TargetSelectionDAGInfo; class TargetSubtargetInfo; -class ScalarTargetTransformInfo; -class VectorTargetTransformInfo; +class TargetTransformInfo; class formatted_raw_ostream; class raw_ostream; +class raw_pwrite_stream; class TargetLoweringObjectFile; // The old pass manager infrastructure is hidden in a legacy namespace now. @@ -54,34 +59,41 @@ using legacy::PassManagerBase; //===----------------------------------------------------------------------===// /// -/// TargetMachine - Primary interface to the complete machine description for -/// the target machine. All target-specific information should be accessible -/// through this interface. +/// Primary interface to the complete machine description for the target +/// machine. All target-specific information should be accessible through this +/// interface. /// class TargetMachine { - TargetMachine(const TargetMachine &) LLVM_DELETED_FUNCTION; - void operator=(const TargetMachine &) LLVM_DELETED_FUNCTION; + TargetMachine(const TargetMachine &) = delete; + void operator=(const TargetMachine &) = delete; protected: // Can only create subclasses. - TargetMachine(const Target &T, StringRef TargetTriple, - StringRef CPU, StringRef FS, const TargetOptions &Options); + TargetMachine(const Target &T, StringRef DataLayoutString, + StringRef TargetTriple, StringRef CPU, StringRef FS, + const TargetOptions &Options); - /// TheTarget - The Target that this machine was created for. + /// The Target that this machine was created for. const Target &TheTarget; - /// TargetTriple, TargetCPU, TargetFS - Triple string, CPU name, and target - /// feature strings the TargetMachine instance is created with. + /// For ABI type size and alignment. + const DataLayout DL; + + /// Triple string, CPU name, and target feature strings the TargetMachine + /// instance is created with. std::string TargetTriple; std::string TargetCPU; std::string TargetFS; - /// CodeGenInfo - Low level target information such as relocation model. - /// Non-const to allow resetting optimization level per-function. + /// Low level target information such as relocation model. Non-const to + /// allow resetting optimization level per-function. MCCodeGenInfo *CodeGenInfo; - /// AsmInfo - Contains target specific asm information. - /// + /// Contains target specific asm information. const MCAsmInfo *AsmInfo; + const MCRegisterInfo *MRI; + const MCInstrInfo *MII; + const MCSubtargetInfo *STI; + unsigned RequireStructuredCFG : 1; public: @@ -95,40 +107,39 @@ public: 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; - } + /// Virtual method implemented by subclasses that returns a reference to that + /// target's TargetSubtargetInfo-derived member variable. virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const { - return getSubtargetImpl(); + return nullptr; } virtual TargetLoweringObjectFile *getObjFileLowering() const { return nullptr; } - /// getSubtarget - This method returns a pointer to the specified type of + /// This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being /// returned is of the correct type. - template<typename STC> const STC &getSubtarget() const { - return *static_cast<const STC*>(getSubtargetImpl()); - } - template <typename STC> const STC &getSubtarget(const Function *) const { - return *static_cast<const STC*>(getSubtargetImpl()); + template <typename STC> const STC &getSubtarget(const Function &F) const { + return *static_cast<const STC*>(getSubtargetImpl(F)); } + /// This method returns a pointer to the DataLayout for the target. It should + /// be unchanging for every subtarget. + const DataLayout *getDataLayout() const { return &DL; } + /// \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; - /// getMCAsmInfo - Return target specific asm information. - /// + /// Return target specific asm information. const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } - /// getIntrinsicInfo - If intrinsic information is available, return it. If - /// not, return null. - /// + const MCRegisterInfo *getMCRegisterInfo() const { return MRI; } + const MCInstrInfo *getMCInstrInfo() const { return MII; } + const MCSubtargetInfo *getMCSubtargetInfo() const { return STI; } + + /// If intrinsic information is available, return it. If not, return null. virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr; } @@ -136,20 +147,18 @@ public: bool requiresStructuredCFG() const { return RequireStructuredCFG; } void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; } - /// getRelocationModel - Returns the code generation relocation model. The - /// choices are static, PIC, and dynamic-no-pic, and target default. + /// Returns the code generation relocation model. The choices are static, PIC, + /// and dynamic-no-pic, and target default. Reloc::Model getRelocationModel() const; - /// getCodeModel - Returns the code model. The choices are small, kernel, - /// medium, large, and target default. + /// Returns the code model. The choices are small, kernel, medium, large, and + /// target default. CodeModel::Model getCodeModel() const; - /// getTLSModel - Returns the TLS model which should be used for the given - /// global variable. + /// Returns the TLS model which should be used for the given global variable. TLSModel::Model getTLSModel(const GlobalValue *GV) const; - /// getOptLevel - Returns the optimization level: None, Less, - /// Default, or Aggressive. + /// Returns the optimization level: None, Less, Default, or Aggressive. CodeGenOpt::Level getOptLevel() const; /// \brief Overrides the optimization level. @@ -159,47 +168,47 @@ public: bool shouldPrintMachineCode() const { return Options.PrintMachineCode; } - /// getAsmVerbosityDefault - Returns the default value of asm verbosity. + /// Returns the default value of asm verbosity. /// - bool getAsmVerbosityDefault() const ; - - /// setAsmVerbosityDefault - Set the default value of asm verbosity. Default - /// is false. - void setAsmVerbosityDefault(bool); - - /// getDataSections - Return true if data objects should be emitted into their - /// own section, corresponds to -fdata-sections. - bool getDataSections() const; - - /// getFunctionSections - Return true if functions should be emitted into - /// their own section, corresponding to -ffunction-sections. - bool getFunctionSections() const; + bool getAsmVerbosityDefault() const { + return Options.MCOptions.AsmVerbose; + } - /// setDataSections - Set if the data are emit into separate sections. - void setDataSections(bool); + bool getUniqueSectionNames() const { return Options.UniqueSectionNames; } - /// setFunctionSections - Set if the functions are emit into separate - /// sections. - void setFunctionSections(bool); + /// Return true if data objects should be emitted into their own section, + /// corresponds to -fdata-sections. + bool getDataSections() const { + return Options.DataSections; + } - /// \brief Register analysis passes for this target with a pass manager. - virtual void addAnalysisPasses(PassManagerBase &) {} + /// Return true if functions should be emitted into their own section, + /// corresponding to -ffunction-sections. + bool getFunctionSections() const { + return Options.FunctionSections; + } - /// CodeGenFileType - These enums are meant to be passed into - /// addPassesToEmitFile to indicate what type of file to emit, and returned by - /// it to indicate what type of file could actually be made. + /// \brief Get a \c TargetIRAnalysis appropriate for the target. + /// + /// This is used to construct the new pass manager's target IR analysis pass, + /// set up appropriately for this target machine. Even the old pass manager + /// uses this to answer queries about the IR. + virtual TargetIRAnalysis getTargetIRAnalysis(); + + /// These enums are meant to be passed into addPassesToEmitFile to indicate + /// what type of file to emit, and returned by it to indicate what type of + /// file could actually be made. enum CodeGenFileType { CGFT_AssemblyFile, CGFT_ObjectFile, CGFT_Null // Do not emit any output. }; - /// addPassesToEmitFile - Add passes to the specified pass manager to get the - /// specified file emitted. Typically this will involve several steps of code - /// generation. This method should return true if emission of this file type - /// is not supported, or false on success. - virtual bool addPassesToEmitFile(PassManagerBase &, - formatted_raw_ostream &, + /// Add passes to the specified pass manager to get the specified file + /// emitted. Typically this will involve several steps of code generation. + /// This method should return true if emission of this file type is not + /// supported, or false on success. + virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr, @@ -207,14 +216,13 @@ public: 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 - /// used to build custom MCStreamer. + /// 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 used to build custom + /// MCStreamer. /// - virtual bool addPassesToEmitMC(PassManagerBase &, - MCContext *&, - raw_ostream &, + virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&, + raw_pwrite_stream &, bool /*DisableVerify*/ = true) { return true; } @@ -224,42 +232,42 @@ public: MCSymbol *getSymbol(const GlobalValue *GV, Mangler &Mang) const; }; -/// LLVMTargetMachine - This class describes a target machine that is -/// implemented with the LLVM target-independent code generator. +/// This class describes a target machine that is implemented with the LLVM +/// target-independent code generator. /// class LLVMTargetMachine : public TargetMachine { protected: // Can only create subclasses. - LLVMTargetMachine(const Target &T, StringRef TargetTriple, - StringRef CPU, StringRef FS, TargetOptions Options, - Reloc::Model RM, CodeModel::Model CM, + LLVMTargetMachine(const Target &T, StringRef DataLayoutString, + StringRef TargetTriple, StringRef CPU, StringRef FS, + TargetOptions Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); void initAsmInfo(); public: - /// \brief Register analysis passes for this target with a pass manager. + /// \brief Get a TargetIRAnalysis implementation for the target. /// - /// This registers target independent analysis passes. - void addAnalysisPasses(PassManagerBase &PM) override; + /// This analysis will produce a TTI result which uses the common code + /// generator to answer queries about the IR. + TargetIRAnalysis getTargetIRAnalysis() override; - /// createPassConfig - Create a pass configuration object to be used by - /// addPassToEmitX methods for generating a pipeline of CodeGen passes. + /// Create a pass configuration object to be used by addPassToEmitX methods + /// for generating a pipeline of CodeGen passes. virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); - /// addPassesToEmitFile - Add passes to the specified pass manager to get the - /// specified file emitted. Typically this will involve several steps of code - /// generation. - bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, + /// Add passes to the specified pass manager to get the specified file + /// emitted. Typically this will involve several steps of code generation. + bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify = true, AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr) 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 - /// used to build custom MCStreamer. - /// + /// 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 used to build custom + /// MCStreamer. bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, - raw_ostream &OS, bool DisableVerify = true) override; + raw_pwrite_stream &OS, + bool DisableVerify = true) override; }; } // End llvm namespace diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 9ab8242578fd..07a8f6d3d4cd 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -20,14 +20,14 @@ namespace llvm { class MachineFunction; + class Module; class StringRef; - // Possible float ABI settings. Used with FloatABIType in TargetOptions.h. namespace FloatABI { enum ABIType { - Default, // Target-specific (either soft or hard depending on triple,etc). - Soft, // Soft float. - Hard // Hard float. + Default, // Target-specific (either soft or hard depending on triple, etc). + Soft, // Soft float. + Hard // Hard float. }; } @@ -57,43 +57,29 @@ namespace llvm { }; } - 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() - : PrintMachineCode(false), NoFramePointerElim(false), + : PrintMachineCode(false), LessPreciseFPMADOption(false), UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), - HonorSignDependentRoundingFPMathOption(false), UseSoftFloat(false), - NoZerosInBSS(false), JITEmitDebugInfo(false), - JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false), + HonorSignDependentRoundingFPMathOption(false), + NoZerosInBSS(false), + GuaranteedTailCallOpt(false), DisableTailCalls(false), StackAlignmentOverride(0), EnableFastISel(false), PositionIndependentExecutable(false), UseInitArray(false), DisableIntegratedAS(false), CompressDebugSections(false), FunctionSections(false), - DataSections(false), TrapUnreachable(false), TrapFuncName(), - FloatABIType(FloatABI::Default), + DataSections(false), UniqueSectionNames(true), TrapUnreachable(false), + TrapFuncName(), FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single), - FCFI(false), ThreadModel(ThreadModel::POSIX), - CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {} + ThreadModel(ThreadModel::POSIX) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging /// output from the code generator. unsigned PrintMachineCode : 1; - /// NoFramePointerElim - This flag is enabled when the -disable-fp-elim is - /// specified on the command line. If the target supports the frame pointer - /// elimination optimization, this option should disable it. - unsigned NoFramePointerElim : 1; - /// DisableFramePointerElim - This returns true if frame pointer elimination /// optimization should be disabled for the given machine function. bool DisableFramePointerElim(const MachineFunction &MF) const; @@ -136,26 +122,11 @@ namespace llvm { unsigned HonorSignDependentRoundingFPMathOption : 1; bool HonorSignDependentRoundingFPMath() const; - /// UseSoftFloat - This flag is enabled when the -soft-float flag is - /// specified on the command line. When this flag is on, the code generator - /// will generate libcalls to the software floating point library instead of - /// target FP instructions. - unsigned UseSoftFloat : 1; - /// NoZerosInBSS - By default some codegens place zero-initialized data to /// .bss section. This flag disables such behaviour (necessary, e.g. for /// crt*.o compiling). unsigned NoZerosInBSS : 1; - /// JITEmitDebugInfo - This flag indicates that the JIT should try to emit - /// debug information and notify a debugger about it. - unsigned JITEmitDebugInfo : 1; - - /// JITEmitDebugInfoToDisk - This flag indicates that the JIT should write - /// the object files generated by the JITEmitDebugInfo flag to disk. This - /// flag is hidden and is only for debugging the debug info. - unsigned JITEmitDebugInfoToDisk : 1; - /// GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is /// specified on the commandline. When the flag is on, participating targets /// will perform tail call optimization on all calls which use the fastcc @@ -198,6 +169,8 @@ namespace llvm { /// Emit data into separate sections. unsigned DataSections : 1; + unsigned UniqueSectionNames : 1; + /// Emit target-specific trap instruction for 'unreachable' IR instructions. unsigned TrapUnreachable : 1; @@ -210,9 +183,9 @@ namespace llvm { /// FloatABIType - This setting is set by -float-abi=xxx option is specfied /// on the command line. This setting may either be Default, Soft, or Hard. /// Default selects the target's default behavior. Soft selects the ABI for - /// UseSoftFloat, but does not indicate that FP hardware may not be used. - /// Such a combination is unfortunately popular (e.g. arm-apple-darwin). - /// Hard presumes that the normal FP ABI is used. + /// software floating point, but does not indicate that FP hardware may not + /// be used. Such a combination is unfortunately popular (e.g. + /// arm-apple-darwin). Hard presumes that the normal FP ABI is used. FloatABI::ABIType FloatABIType; /// AllowFPOpFusion - This flag is set by the -fuse-fp-ops=xxx option. @@ -237,28 +210,10 @@ 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; }; @@ -274,10 +229,7 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(NoInfsFPMath) && ARE_EQUAL(NoNaNsFPMath) && ARE_EQUAL(HonorSignDependentRoundingFPMathOption) && - ARE_EQUAL(UseSoftFloat) && ARE_EQUAL(NoZerosInBSS) && - ARE_EQUAL(JITEmitDebugInfo) && - ARE_EQUAL(JITEmitDebugInfoToDisk) && ARE_EQUAL(GuaranteedTailCallOpt) && ARE_EQUAL(DisableTailCalls) && ARE_EQUAL(StackAlignmentOverride) && @@ -289,11 +241,7 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(FloatABIType) && ARE_EQUAL(AllowFPOpFusion) && ARE_EQUAL(JTType) && - ARE_EQUAL(FCFI) && ARE_EQUAL(ThreadModel) && - ARE_EQUAL(CFIType) && - ARE_EQUAL(CFIEnforcing) && - ARE_EQUAL(CFIFuncName) && ARE_EQUAL(MCOptions); #undef ARE_EQUAL } diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index a7552565c938..121b8a232526 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -46,6 +46,11 @@ public: const uint32_t *SubClassMask; const uint16_t *SuperRegIndices; const unsigned LaneMask; + /// Classes with a higher priority value are assigned first by register + /// allocators using a greedy heuristic. The value is in the range [0,63]. + const uint8_t AllocationPriority; + /// Whether the class supports two (or more) disjunct subregister indices. + const bool HasDisjunctSubRegs; const sc_iterator SuperClasses; ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&); @@ -357,13 +362,13 @@ public: /// /// then: /// - /// getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B) != 0 + /// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0 /// /// The converse is not necessarily true. If two lane masks have a common /// bit, the corresponding sub-registers may not overlap, but it can be /// assumed that they usually will. + /// SubIdx == 0 is allowed, it has the lane mask ~0u. unsigned getSubRegIndexLaneMask(unsigned SubIdx) const { - // SubIdx == 0 is allowed, it has the lane mask ~0u. assert(SubIdx < getNumSubRegIndices() && "This is not a subregister index"); return SubRegIndexLaneMasks[SubIdx]; } @@ -425,10 +430,10 @@ public: /// closest to the incoming stack pointer if stack grows down, and vice versa. /// virtual const MCPhysReg* - getCalleeSavedRegs(const MachineFunction *MF = nullptr) const = 0; + getCalleeSavedRegs(const MachineFunction *MF) const = 0; /// getCallPreservedMask - Return a mask of call-preserved registers for the - /// given calling convention on the current sub-target. The mask should + /// given calling convention on the current function. The mask should /// include all call-preserved aliases. This is used by the register /// allocator to determine which registers can be live across a call. /// @@ -445,7 +450,8 @@ public: /// instructions should use implicit-def operands to indicate call clobbered /// registers. /// - virtual const uint32_t *getCallPreservedMask(CallingConv::ID) const { + virtual const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const { // The default mask clobbers everything. All targets should override. return nullptr; } @@ -622,8 +628,9 @@ public: /// legal to use in the current sub-target and has the same spill size. /// The returned register class can be used to create virtual registers which /// means that all its registers can be copied and spilled. - virtual const TargetRegisterClass* - getLargestLegalSuperClass(const TargetRegisterClass *RC) const { + virtual const TargetRegisterClass * + getLargestLegalSuperClass(const TargetRegisterClass *RC, + const MachineFunction &) const { /// The default implementation is very conservative and doesn't allow the /// register allocator to inflate register classes. return RC; @@ -655,7 +662,8 @@ public: /// Get the register unit pressure limit for this dimension. /// This limit must be adjusted dynamically for reserved registers. - virtual unsigned getRegPressureSetLimit(unsigned Idx) const = 0; + virtual unsigned getRegPressureSetLimit(const MachineFunction &MF, + unsigned Idx) const = 0; /// Get the dimensions of register pressure impacted by this register class. /// Returns a -1 terminated array of pressure set IDs. @@ -686,21 +694,13 @@ public: const MachineFunction &MF, const VirtRegMap *VRM = nullptr) const; - /// avoidWriteAfterWrite - Return true if the register allocator should avoid - /// writing a register from RC in two consecutive instructions. - /// This can avoid pipeline stalls on certain architectures. - /// It does cause increased register pressure, though. - virtual bool avoidWriteAfterWrite(const TargetRegisterClass *RC) const { - return false; - } - - /// UpdateRegAllocHint - A callback to allow target a chance to update + /// updateRegAllocHint - A callback to allow target a chance to update /// register allocation hints when a register is "changed" (e.g. coalesced) /// to another register. e.g. On ARM, some virtual registers should target /// register pairs, if one of pair is coalesced to another register, the /// allocation hint of the other half of the pair should be changed to point /// to the new register. - virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + virtual void updateRegAllocHint(unsigned Reg, unsigned NewReg, MachineFunction &MF) const { // Do nothing. } @@ -802,9 +802,9 @@ public: llvm_unreachable("resolveFrameIndex does not exist on this target"); } - /// isFrameOffsetLegal - Determine whether a given offset immediate is - /// encodable to resolve a frame index. - virtual bool isFrameOffsetLegal(const MachineInstr *MI, + /// isFrameOffsetLegal - Determine whether a given base register plus offset + /// immediate is encodable to resolve a frame index. + virtual bool isFrameOffsetLegal(const MachineInstr *MI, unsigned BaseReg, int64_t Offset) const { llvm_unreachable("isFrameOffsetLegal does not exist on this target"); } diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 907baa1b9b1f..7a788cef0237 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -68,6 +68,18 @@ class SDTCisSubVecOfVec<int ThisOp, int OtherOp> int OtherOpNum = OtherOp; } +// SDTCVecEltisVT - The specified operand is vector type with element type +// of VT. +class SDTCVecEltisVT<int OpNum, ValueType vt> : SDTypeConstraint<OpNum> { + ValueType VT = vt; +} + +// SDTCisSameNumEltsAs - The two specified operands have identical number +// of elements. +class SDTCisSameNumEltsAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { + int OtherOperandNum = OtherOp; +} + //===----------------------------------------------------------------------===// // Selection DAG Type Profile definitions. // @@ -196,6 +208,16 @@ def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3> ]>; +def SDTMaskedGather: SDTypeProfile<2, 3, [ // masked gather + SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<1, 3>, + SDTCisPtrTy<4>, SDTCVecEltisVT<1, i1>, SDTCisSameNumEltsAs<0, 1> +]>; + +def SDTMaskedScatter: SDTypeProfile<1, 3, [ // masked scatter + SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameNumEltsAs<0, 1>, + SDTCVecEltisVT<0, i1>, SDTCisPtrTy<3> +]>; + def SDTVecShuffle : SDTypeProfile<1, 2, [ SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> ]>; @@ -358,6 +380,10 @@ def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, [SDNPOutGlue]>; def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, [SDNPOutGlue, SDNPInGlue]>; +def smin : SDNode<"ISD::SMIN" , SDTIntBinOp>; +def smax : SDNode<"ISD::SMAX" , SDTIntBinOp>; +def umin : SDNode<"ISD::UMIN" , SDTIntBinOp>; +def umax : SDNode<"ISD::UMAX" , SDTIntBinOp>; def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; @@ -371,6 +397,7 @@ def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; +def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>; def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; @@ -380,6 +407,7 @@ def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>; +def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp>; def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>; def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>; @@ -466,6 +494,10 @@ def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def masked_scatter : SDNode<"ISD::MSCATTER", SDTMaskedScatter, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def masked_gather : SDNode<"ISD::MGATHER", SDTMaskedGather, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; // Do not use ld, st directly. Use load, extload, sextload, zextload, store, // and truncst (see below). diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index d1a3fcf4a50e..bacdd950705b 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -21,15 +21,14 @@ namespace llvm { class DataLayout; -class TargetMachine; //===----------------------------------------------------------------------===// /// TargetSelectionDAGInfo - Targets can subclass this to parameterize the /// SelectionDAG lowering and instruction selection process. /// class TargetSelectionDAGInfo { - TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; - void operator=(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; + TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) = delete; + void operator=(const TargetSelectionDAGInfo &) = delete; const DataLayout *DL; diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index 4ff88d07bf27..0f427901a8ec 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -42,15 +42,17 @@ template <typename T> class SmallVectorImpl; /// be exposed through a TargetSubtargetInfo-derived class. /// class TargetSubtargetInfo : public MCSubtargetInfo { - TargetSubtargetInfo(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION; - void operator=(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION; + TargetSubtargetInfo(const TargetSubtargetInfo &) = delete; + void operator=(const TargetSubtargetInfo &) = delete; + protected: // Can only create subclasses... TargetSubtargetInfo(); + public: // AntiDepBreakMode - Type of anti-dependence breaking that should // be performed before post-RA scheduling. typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode; - typedef SmallVectorImpl<const TargetRegisterClass*> RegClassVector; + typedef SmallVectorImpl<const TargetRegisterClass *> RegClassVector; virtual ~TargetSubtargetInfo(); @@ -71,7 +73,6 @@ public: 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 @@ -90,21 +91,30 @@ public: /// MCSchedClassDesc with the isVariant property. This may return the ID of /// another variant SchedClass, but repeated invocation must quickly terminate /// in a nonvariant SchedClass. - virtual unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *MI, - const TargetSchedModel* SchedModel) const { + virtual unsigned resolveSchedClass(unsigned SchedClass, + const MachineInstr *MI, + const TargetSchedModel *SchedModel) const { return 0; } - /// \brief Temporary API to test migration to MI scheduler. - bool useMachineScheduler() const; - /// \brief True if the subtarget should run MachineScheduler after aggressive /// coalescing. /// /// This currently replaces the SelectionDAG scheduler with the "source" order - /// scheduler. It does not yet disable the postRA scheduler. + /// scheduler (though see below for an option to turn this off and use the + /// TargetLowering preference). It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; + /// \brief True if the machine scheduler should disable the TLI preference + /// for preRA scheduling with the source level scheduler. + virtual bool enableMachineSchedDefaultSched() const { return true; } + + /// \brief True if the subtarget should enable joining global copies. + /// + /// By default this is enabled if the machine scheduler is enabled, but + /// can be overridden. + virtual bool enableJoinGlobalCopies() const; + /// \brief True if the subtarget should run PostMachineScheduler. /// /// This only takes effect if the target has configured the @@ -121,20 +131,16 @@ public: /// scheduling heuristics (no custom MachineSchedStrategy) to make /// changes to the generic scheduling policy. virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, - MachineInstr *begin, - MachineInstr *end, + MachineInstr *begin, MachineInstr *end, unsigned NumRegionInstrs) const {} // \brief Perform target specific adjustments to the latency of a schedule // dependency. - virtual void adjustSchedDependency(SUnit *def, SUnit *use, - SDep& dep) const { } + virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep &dep) 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; - } + 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 @@ -170,9 +176,7 @@ public: } /// Enable tracking of subregister liveness in register allocator. - virtual bool enableSubRegLiveness() const { - return false; - } + virtual bool enableSubRegLiveness() const { return false; } }; } // End llvm namespace |