diff options
Diffstat (limited to 'include/llvm/Target')
-rw-r--r-- | include/llvm/Target/GenericOpcodes.td | 121 | ||||
-rw-r--r-- | include/llvm/Target/GlobalISel/RegisterBank.td | 16 | ||||
-rw-r--r-- | include/llvm/Target/GlobalISel/SelectionDAGCompat.td (renamed from include/llvm/Target/TargetGlobalISel.td) | 24 | ||||
-rw-r--r-- | include/llvm/Target/GlobalISel/Target.td | 56 | ||||
-rw-r--r-- | include/llvm/Target/Target.td | 33 | ||||
-rw-r--r-- | include/llvm/Target/TargetCallingConv.h | 202 | ||||
-rw-r--r-- | include/llvm/Target/TargetInstrInfo.h | 140 | ||||
-rw-r--r-- | include/llvm/Target/TargetLowering.h | 154 | ||||
-rw-r--r-- | include/llvm/Target/TargetLoweringObjectFile.h | 50 | ||||
-rw-r--r-- | include/llvm/Target/TargetMachine.h | 12 | ||||
-rw-r--r-- | include/llvm/Target/TargetOpcodes.def | 55 | ||||
-rw-r--r-- | include/llvm/Target/TargetOptions.h | 89 | ||||
-rw-r--r-- | include/llvm/Target/TargetRegisterInfo.h | 12 | ||||
-rw-r--r-- | include/llvm/Target/TargetSchedule.td | 5 | ||||
-rw-r--r-- | include/llvm/Target/TargetSelectionDAG.td | 22 | ||||
-rw-r--r-- | include/llvm/Target/TargetSubtargetInfo.h | 8 |
16 files changed, 687 insertions, 312 deletions
diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index 8694eb5797d04..de3796cd4ee56 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -91,6 +91,21 @@ def G_FCONSTANT : Instruction { let hasSideEffects = 0; } +def G_VASTART : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$list); + let hasSideEffects = 0; + let mayStore = 1; +} + +def G_VAARG : Instruction { + let OutOperandList = (outs type0:$val); + let InOperandList = (ins type1:$list, unknown:$align); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + //------------------------------------------------------------------------------ // Binary ops. //------------------------------------------------------------------------------ @@ -103,13 +118,6 @@ def G_ADD : Instruction { let isCommutable = 1; } -// Generic pointer offset. -def G_GEP : Instruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = 0; -} - // Generic subtraction. def G_SUB : Instruction { let OutOperandList = (outs type0:$dst); @@ -224,6 +232,19 @@ def G_SELECT : Instruction { let hasSideEffects = 0; } +// Generic pointer offset. +def G_GEP : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type1:$src2); + let hasSideEffects = 0; +} + +def G_PTR_MASK : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src, unknown:$bits); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Overflow ops //------------------------------------------------------------------------------ @@ -273,10 +294,34 @@ def G_SMULO : Instruction { let isCommutable = 1; } +// Multiply two numbers at twice the incoming bit width (unsigned) and return +// the high half of the result. +def G_UMULH : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Multiply two numbers at twice the incoming bit width (signed) and return +// the high half of the result. +def G_SMULH : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + //------------------------------------------------------------------------------ // Floating Point Unary Ops. //------------------------------------------------------------------------------ +def G_FNEG : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src); + let hasSideEffects = 0; +} + def G_FPEXT : Instruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins type1:$src); @@ -355,6 +400,13 @@ def G_FREM : Instruction { let hasSideEffects = 0; } +// Floating point exponentiation. +def G_FPOW : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Memory ops //------------------------------------------------------------------------------ @@ -383,17 +435,24 @@ def G_STORE : Instruction { // indexes. This will almost certainly be mapped to sub-register COPYs after // register banks have been selected. def G_EXTRACT : Instruction { + let OutOperandList = (outs type0:$res); + let InOperandList = (ins type1:$src, unknown:$offset); + let hasSideEffects = 0; +} + +// Extract multiple registers specified size, starting from blocks given by +// indexes. This will almost certainly be mapped to sub-register COPYs after +// register banks have been selected. +def G_UNMERGE_VALUES : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let hasSideEffects = 0; } -// Insert a sequence of smaller registers into a larger one at the specified -// indices (interleaved with the values in the operand list "op0, bit0, op1, -// bit1, ...")). +// Insert a smaller register into a larger one at the specified bit-index. def G_INSERT : Instruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, variable_ops); + let InOperandList = (ins type0:$src, type1:$op, unknown:$offset); let hasSideEffects = 0; } @@ -406,6 +465,12 @@ def G_SEQUENCE : Instruction { let hasSideEffects = 0; } +def G_MERGE_VALUES : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins variable_ops); + let hasSideEffects = 0; +} + // Intrinsic without side effects. def G_INTRINSIC : Instruction { let OutOperandList = (outs); @@ -445,4 +510,38 @@ def G_BRCOND : Instruction { let isTerminator = 1; } +// Generic indirect branch. +def G_BRINDIRECT : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; + let isBranch = 1; + let isTerminator = 1; +} + +//------------------------------------------------------------------------------ +// Vector ops +//------------------------------------------------------------------------------ + +// Generic insertelement. +def G_INSERT_VECTOR_ELT : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); + let hasSideEffects = 0; +} + +// Generic extractelement. +def G_EXTRACT_VECTOR_ELT : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src, type2:$idx); + let hasSideEffects = 0; +} + +// Generic shufflevector. +def G_SHUFFLE_VECTOR: Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$v1, type1:$v2, type2:$mask); + let hasSideEffects = 0; +} + // TODO: Add the other generic opcodes. diff --git a/include/llvm/Target/GlobalISel/RegisterBank.td b/include/llvm/Target/GlobalISel/RegisterBank.td new file mode 100644 index 0000000000000..4dfd139e9fb6f --- /dev/null +++ b/include/llvm/Target/GlobalISel/RegisterBank.td @@ -0,0 +1,16 @@ +//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +class RegisterBank<string name, list<RegisterClass> classes> { + string Name = name; + list<RegisterClass> RegisterClasses = classes; +} diff --git a/include/llvm/Target/TargetGlobalISel.td b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index 0727c9802e5e4..9f034220815f2 100644 --- a/include/llvm/Target/TargetGlobalISel.td +++ b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -25,5 +25,29 @@ class GINodeEquiv<Instruction i, SDNode node> { SDNode Node = node; } +def : GINodeEquiv<G_ZEXT, zext>; +def : GINodeEquiv<G_SEXT, sext>; def : GINodeEquiv<G_ADD, add>; +def : GINodeEquiv<G_SUB, sub>; +def : GINodeEquiv<G_MUL, mul>; + +def : GINodeEquiv<G_OR, or>; +def : GINodeEquiv<G_XOR, xor>; +def : GINodeEquiv<G_AND, and>; + +def : GINodeEquiv<G_SHL, shl>; +def : GINodeEquiv<G_LSHR, srl>; +def : GINodeEquiv<G_ASHR, sra>; + +def : GINodeEquiv<G_SDIV, sdiv>; +def : GINodeEquiv<G_UDIV, udiv>; +def : GINodeEquiv<G_SREM, srem>; +def : GINodeEquiv<G_UREM, urem>; + def : GINodeEquiv<G_BR, br>; + +// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern. +// Should be used on defs that subclass GIComplexOperandMatcher<>. +class GIComplexPatternEquiv<ComplexPattern seldag> { + ComplexPattern SelDAGEquivalent = seldag; +} diff --git a/include/llvm/Target/GlobalISel/Target.td b/include/llvm/Target/GlobalISel/Target.td new file mode 100644 index 0000000000000..fa1a424b58954 --- /dev/null +++ b/include/llvm/Target/GlobalISel/Target.td @@ -0,0 +1,56 @@ +//===- Target.td - Define GlobalISel rules -----------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces used to support +// SelectionDAG instruction selection patterns (specified in +// TargetSelectionDAG.td) when generating GlobalISel instruction selectors. +// +// This is intended as a compatibility layer, to enable reuse of target +// descriptions written for SelectionDAG without requiring explicit GlobalISel +// support. It will eventually supersede SelectionDAG patterns. +// +//===----------------------------------------------------------------------===// + +// Definitions that inherit from LLT define types that will be used in the +// GlobalISel matcher. +class LLT; + +def s32 : LLT; +def s64 : LLT; + +// Defines a matcher for complex operands. This is analogous to ComplexPattern +// from SelectionDAG. +// +// Definitions that inherit from this may also inherit from +// GIComplexPatternEquiv to enable the import of SelectionDAG patterns involving +// those ComplexPatterns. +class GIComplexOperandMatcher<LLT type, dag operands, string matcherfn> { + // The expected type of the root of the match. + // + // TODO: We should probably support, any-type, any-scalar, and multiple types + // in the future. + LLT Type = type; + + // The operands that result from a successful match + // Should be of the form '(ops ty1, ty2, ...)' where ty1/ty2 are definitions + // that inherit from Operand. + // + // FIXME: Which definition is used for ty1/ty2 doesn't actually matter at the + // moment. Only the number of operands is used. + dag Operands = operands; + + // The function that determines whether the operand matches. It should be of + // the form: + // bool select(const MatchOperand &Root, MatchOperand &Result1) + // and should have the same number of ResultX arguments as the number of + // result operands. It must return true on successful match and false + // otherwise. If it returns true, then all the ResultX arguments must be + // overwritten. + string MatcherFn = matcherfn; +} diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 729d7669e0fae..b21689e0e1346 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -402,11 +402,8 @@ class Instruction { // If so, make sure to override // TargetInstrInfo::getInsertSubregLikeInputs. - // Side effect flags - When set, the flags have these meanings: - // - // hasSideEffects - The instruction has side effects that are not - // captured by any operands of the instruction or other flags. - // + // Does the instruction have side effects that are not captured by any + // operands of the instruction or other flags? bit hasSideEffects = ?; // Is this instruction a "real" instruction (with a distinct machine @@ -951,11 +948,12 @@ def LOCAL_ESCAPE : Instruction { let hasSideEffects = 0; let hasCtrlDep = 1; } -def FAULTING_LOAD_OP : Instruction { +def FAULTING_OP : Instruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins variable_ops); let usesCustomInserter = 1; let mayLoad = 1; + let mayStore = 1; let isTerminator = 1; let isBranch = 1; } @@ -998,6 +996,15 @@ def PATCHABLE_TAIL_CALL : Instruction { let hasSideEffects = 1; let isReturn = 1; } +def FENTRY_CALL : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let AsmString = "# FEntry call"; + let usesCustomInserter = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; +} // Generic opcodes used in GlobalISel. include "llvm/Target/GenericOpcodes.td" @@ -1342,6 +1349,16 @@ include "llvm/Target/TargetCallingConv.td" include "llvm/Target/TargetSelectionDAG.td" //===----------------------------------------------------------------------===// -// Pull in the common support for Global ISel generation. +// Pull in the common support for Global ISel register bank info generation. +// +include "llvm/Target/GlobalISel/RegisterBank.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for DAG isel generation. +// +include "llvm/Target/GlobalISel/Target.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for the Global ISel DAG-based selector generation. // -include "llvm/Target/TargetGlobalISel.td" +include "llvm/Target/GlobalISel/SelectionDAGCompat.td" diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index be09236cdab02..4f750b8a289ff 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -14,146 +14,120 @@ #ifndef LLVM_TARGET_TARGETCALLINGCONV_H #define LLVM_TARGET_TARGETCALLINGCONV_H +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" +#include <cassert> #include <climits> +#include <cstdint> namespace llvm { - namespace ISD { + struct ArgFlagsTy { private: - static const uint64_t NoFlagSet = 0ULL; - static const uint64_t ZExt = 1ULL<<0; ///< Zero extended - static const uint64_t ZExtOffs = 0; - static const uint64_t SExt = 1ULL<<1; ///< Sign extended - static const uint64_t SExtOffs = 1; - static const uint64_t InReg = 1ULL<<2; ///< Passed in register - static const uint64_t InRegOffs = 2; - static const uint64_t SRet = 1ULL<<3; ///< Hidden struct-ret ptr - static const uint64_t SRetOffs = 3; - static const uint64_t ByVal = 1ULL<<4; ///< Struct passed by value - static const uint64_t ByValOffs = 4; - static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain - static const uint64_t NestOffs = 5; - static const uint64_t Returned = 1ULL<<6; ///< Always returned - static const uint64_t ReturnedOffs = 6; - static const uint64_t ByValAlign = 0xFULL<<7; ///< Struct alignment - static const uint64_t ByValAlignOffs = 7; - static const uint64_t Split = 1ULL<<11; - static const uint64_t SplitOffs = 11; - static const uint64_t InAlloca = 1ULL<<12; ///< Passed with inalloca - static const uint64_t InAllocaOffs = 12; - static const uint64_t SplitEnd = 1ULL<<13; ///< Last part of a split - static const uint64_t SplitEndOffs = 13; - static const uint64_t SwiftSelf = 1ULL<<14; ///< Swift self parameter - static const uint64_t SwiftSelfOffs = 14; - static const uint64_t SwiftError = 1ULL<<15; ///< Swift error parameter - static const uint64_t SwiftErrorOffs = 15; - static const uint64_t Hva = 1ULL << 16; ///< HVA field for - ///< vectorcall - static const uint64_t HvaOffs = 16; - static const uint64_t HvaStart = 1ULL << 17; ///< HVA structure start - ///< for vectorcall - static const uint64_t HvaStartOffs = 17; - static const uint64_t SecArgPass = 1ULL << 18; ///< Second argument - ///< pass for vectorcall - static const uint64_t SecArgPassOffs = 18; - static const uint64_t OrigAlign = 0x1FULL<<27; - static const uint64_t OrigAlignOffs = 27; - static const uint64_t ByValSize = 0x3fffffffULL<<32; ///< Struct size - static const uint64_t ByValSizeOffs = 32; - static const uint64_t InConsecutiveRegsLast = 0x1ULL<<62; ///< Struct size - static const uint64_t InConsecutiveRegsLastOffs = 62; - static const uint64_t InConsecutiveRegs = 0x1ULL<<63; ///< Struct size - static const uint64_t InConsecutiveRegsOffs = 63; - - static const uint64_t One = 1ULL; ///< 1 of this type, for shifts - - uint64_t Flags; + unsigned IsZExt : 1; ///< Zero extended + unsigned IsSExt : 1; ///< Sign extended + unsigned IsInReg : 1; ///< Passed in register + unsigned IsSRet : 1; ///< Hidden struct-ret ptr + unsigned IsByVal : 1; ///< Struct passed by value + unsigned IsNest : 1; ///< Nested fn static chain + unsigned IsReturned : 1; ///< Always returned + unsigned IsSplit : 1; + unsigned IsInAlloca : 1; ///< Passed with inalloca + unsigned IsSplitEnd : 1; ///< Last part of a split + unsigned IsSwiftSelf : 1; ///< Swift self parameter + unsigned IsSwiftError : 1; ///< Swift error parameter + unsigned IsHva : 1; ///< HVA field for + unsigned IsHvaStart : 1; ///< HVA structure start + unsigned IsSecArgPass : 1; ///< Second argument + unsigned ByValAlign : 4; ///< Log 2 of byval alignment + unsigned OrigAlign : 5; ///< Log 2 of original alignment + unsigned IsInConsecutiveRegsLast : 1; + unsigned IsInConsecutiveRegs : 1; + unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate + + unsigned ByValSize; ///< Byval struct size public: - ArgFlagsTy() : Flags(0) { } + ArgFlagsTy() + : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0), + IsReturned(0), IsSplit(0), IsInAlloca(0), IsSplitEnd(0), + IsSwiftSelf(0), IsSwiftError(0), IsHva(0), IsHvaStart(0), + IsSecArgPass(0), ByValAlign(0), OrigAlign(0), + IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), + IsCopyElisionCandidate(0), ByValSize(0) { + static_assert(sizeof(*this) == 2 * sizeof(unsigned), "flags are too big"); + } - bool isZExt() const { return Flags & ZExt; } - void setZExt() { Flags |= One << ZExtOffs; } + bool isZExt() const { return IsZExt; } + void setZExt() { IsZExt = 1; } - bool isSExt() const { return Flags & SExt; } - void setSExt() { Flags |= One << SExtOffs; } + bool isSExt() const { return IsSExt; } + void setSExt() { IsSExt = 1; } - bool isInReg() const { return Flags & InReg; } - void setInReg() { Flags |= One << InRegOffs; } + bool isInReg() const { return IsInReg; } + void setInReg() { IsInReg = 1; } - bool isSRet() const { return Flags & SRet; } - void setSRet() { Flags |= One << SRetOffs; } + bool isSRet() const { return IsSRet; } + void setSRet() { IsSRet = 1; } - bool isByVal() const { return Flags & ByVal; } - void setByVal() { Flags |= One << ByValOffs; } + bool isByVal() const { return IsByVal; } + void setByVal() { IsByVal = 1; } - bool isInAlloca() const { return Flags & InAlloca; } - void setInAlloca() { Flags |= One << InAllocaOffs; } + bool isInAlloca() const { return IsInAlloca; } + void setInAlloca() { IsInAlloca = 1; } - bool isSwiftSelf() const { return Flags & SwiftSelf; } - void setSwiftSelf() { Flags |= One << SwiftSelfOffs; } + bool isSwiftSelf() const { return IsSwiftSelf; } + void setSwiftSelf() { IsSwiftSelf = 1; } - bool isSwiftError() const { return Flags & SwiftError; } - void setSwiftError() { Flags |= One << SwiftErrorOffs; } + bool isSwiftError() const { return IsSwiftError; } + void setSwiftError() { IsSwiftError = 1; } - bool isHva() const { return Flags & Hva; } - void setHva() { Flags |= One << HvaOffs; } + bool isHva() const { return IsHva; } + void setHva() { IsHva = 1; } - bool isHvaStart() const { return Flags & HvaStart; } - void setHvaStart() { Flags |= One << HvaStartOffs; } + bool isHvaStart() const { return IsHvaStart; } + void setHvaStart() { IsHvaStart = 1; } - bool isSecArgPass() const { return Flags & SecArgPass; } - void setSecArgPass() { Flags |= One << SecArgPassOffs; } + bool isSecArgPass() const { return IsSecArgPass; } + void setSecArgPass() { IsSecArgPass = 1; } - bool isNest() const { return Flags & Nest; } - void setNest() { Flags |= One << NestOffs; } + bool isNest() const { return IsNest; } + void setNest() { IsNest = 1; } - bool isReturned() const { return Flags & Returned; } - void setReturned() { Flags |= One << ReturnedOffs; } + bool isReturned() const { return IsReturned; } + void setReturned() { IsReturned = 1; } - bool isInConsecutiveRegs() const { return Flags & InConsecutiveRegs; } - void setInConsecutiveRegs() { Flags |= One << InConsecutiveRegsOffs; } + bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; } + void setInConsecutiveRegs() { IsInConsecutiveRegs = 1; } - bool isInConsecutiveRegsLast() const { return Flags & InConsecutiveRegsLast; } - void setInConsecutiveRegsLast() { Flags |= One << InConsecutiveRegsLastOffs; } + bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; } + void setInConsecutiveRegsLast() { IsInConsecutiveRegsLast = 1; } - unsigned getByValAlign() const { - return (unsigned) - ((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2); - } - void setByValAlign(unsigned A) { - Flags = (Flags & ~ByValAlign) | - (uint64_t(Log2_32(A) + 1) << ByValAlignOffs); - } + bool isSplit() const { return IsSplit; } + void setSplit() { IsSplit = 1; } - bool isSplit() const { return Flags & Split; } - void setSplit() { Flags |= One << SplitOffs; } + bool isSplitEnd() const { return IsSplitEnd; } + void setSplitEnd() { IsSplitEnd = 1; } - bool isSplitEnd() const { return Flags & SplitEnd; } - void setSplitEnd() { Flags |= One << SplitEndOffs; } + bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; } + void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; } - unsigned getOrigAlign() const { - return (unsigned) - ((One << ((Flags & OrigAlign) >> OrigAlignOffs)) / 2); - } - void setOrigAlign(unsigned A) { - Flags = (Flags & ~OrigAlign) | - (uint64_t(Log2_32(A) + 1) << OrigAlignOffs); + unsigned getByValAlign() const { return (1U << ByValAlign) / 2; } + void setByValAlign(unsigned A) { + ByValAlign = Log2_32(A) + 1; + assert(getByValAlign() == A && "bitfield overflow"); } - unsigned getByValSize() const { - return (unsigned)((Flags & ByValSize) >> ByValSizeOffs); - } - void setByValSize(unsigned S) { - Flags = (Flags & ~ByValSize) | (uint64_t(S) << ByValSizeOffs); + unsigned getOrigAlign() const { return (1U << OrigAlign) / 2; } + void setOrigAlign(unsigned A) { + OrigAlign = Log2_32(A) + 1; + assert(getOrigAlign() == A && "bitfield overflow"); } - /// getRawBits - Represent the flags as a bunch of bits. - uint64_t getRawBits() const { return Flags; } + unsigned getByValSize() const { return ByValSize; } + void setByValSize(unsigned S) { ByValSize = S; } }; /// InputArg - This struct carries flags and type information about a @@ -162,9 +136,9 @@ namespace ISD { /// struct InputArg { ArgFlagsTy Flags; - MVT VT; + MVT VT = MVT::Other; EVT ArgVT; - bool Used; + bool Used = false; /// Index original Function's argument. unsigned OrigArgIndex; @@ -176,7 +150,7 @@ namespace ISD { /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12. unsigned PartOffset; - InputArg() : VT(MVT::Other), Used(false) {} + InputArg() = default; InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, unsigned partOffs) : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) { @@ -204,7 +178,7 @@ namespace ISD { EVT ArgVT; /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". - bool IsFixed; + bool IsFixed = false; /// Index original Function's argument. unsigned OrigArgIndex; @@ -214,7 +188,7 @@ namespace ISD { /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12. unsigned PartOffset; - OutputArg() : IsFixed(false) {} + OutputArg() = default; OutputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool isfixed, unsigned origIdx, unsigned partOffs) : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx), @@ -223,8 +197,8 @@ namespace ISD { ArgVT = argvt; } }; -} // end namespace ISD -} // end llvm namespace +} // end namespace ISD +} // end namespace llvm #endif // LLVM_TARGET_TARGETCALLINGCONV_H diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 247d694f2e47d..0dc9cf70d3350 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -152,6 +152,31 @@ public: unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + /// Returns true if the argument is a frame pseudo instruction. + bool isFrameInstr(const MachineInstr &I) const { + return I.getOpcode() == getCallFrameSetupOpcode() || + I.getOpcode() == getCallFrameDestroyOpcode(); + } + + /// Returns true if the argument is a frame setup pseudo instruction. + bool isFrameSetup(const MachineInstr &I) const { + return I.getOpcode() == getCallFrameSetupOpcode(); + } + + /// Returns size of the frame associated with the given frame instruction. + /// For frame setup instruction this is frame that is set up space set up + /// after the instruction. For frame destroy instruction this is the frame + /// freed by the caller. + /// Note, in some cases a call frame (or a part of it) may be prepared prior + /// to the frame setup instruction. It occurs in the calls that involve + /// inalloca arguments. This function reports only the size of the frame part + /// that is set up between the frame setup and destroy pseudo instructions. + int64_t getFrameSize(const MachineInstr &I) const { + assert(isFrameInstr(I)); + assert(I.getOperand(0).getImm() >= 0); + return I.getOperand(0).getImm(); + } + unsigned getCatchReturnOpcode() const { return CatchRetOpcode; } unsigned getReturnOpcode() const { return ReturnOpcode; } @@ -1070,15 +1095,6 @@ public: llvm_unreachable("target did not implement shouldClusterMemOps()"); } - /// Can this target fuse the given instructions if they are scheduled - /// adjacent. Note that you have to add: - /// DAG.addMutation(createMacroFusionDAGMutation()); - /// to TargetPassConfig::createMachineScheduler() to have an effect. - virtual bool shouldScheduleAdjacent(const MachineInstr &First, - const MachineInstr &Second) const { - llvm_unreachable("target did not implement shouldScheduleAdjacent()"); - } - /// Reverses the branch condition of the specified condition list, /// returning false on success and true if it cannot be reversed. virtual @@ -1108,6 +1124,25 @@ public: /// terminator instruction that has not been predicated. virtual bool isUnpredicatedTerminator(const MachineInstr &MI) const; + /// Returns true if MI is an unconditional tail call. + virtual bool isUnconditionalTailCall(const MachineInstr &MI) const { + return false; + } + + /// Returns true if the tail call can be made conditional on BranchCond. + virtual bool + canMakeTailCallConditional(SmallVectorImpl<MachineOperand> &Cond, + const MachineInstr &TailCall) const { + return false; + } + + /// Replace the conditional branch in MBB with a conditional tail call. + virtual void replaceBranchWithTailCall(MachineBasicBlock &MBB, + SmallVectorImpl<MachineOperand> &Cond, + const MachineInstr &TailCall) const { + llvm_unreachable("Target didn't implement replaceBranchWithTailCall!"); + } + /// Convert the instruction into a predicated instruction. /// It returns true if the operation was successful. virtual bool PredicateInstruction(MachineInstr &MI, @@ -1132,7 +1167,7 @@ public: /// 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 { + virtual bool isPredicable(const MachineInstr &MI) const { return MI.getDesc().isPredicable(); } @@ -1427,10 +1462,17 @@ public: return nullptr; } - // 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. + /// 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. + /// + /// Assumes any physical registers used to compute addresses have the same + /// value for both instructions. (This is the most useful assumption for + /// post-RA scheduling.) + /// + /// See also MachineInstr::mayAlias, which is implemented on top of this + /// function. virtual bool areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb, AliasAnalysis *AA = nullptr) const { @@ -1486,11 +1528,79 @@ public: return None; } - /// Determines whether |Inst| is a tail call instruction. + /// Determines whether \p Inst is a tail call instruction. Override this + /// method on targets that do not properly set MCID::Return and MCID::Call on + /// tail call instructions." virtual bool isTailCall(const MachineInstr &Inst) const { + return Inst.isReturn() && Inst.isCall(); + } + + /// True if the instruction is bound to the top of its basic block and no + /// other instructions shall be inserted before it. This can be implemented + /// to prevent register allocator to insert spills before such instructions. + virtual bool isBasicBlockPrologue(const MachineInstr &MI) const { return false; } + /// \brief Return how many instructions would be saved by outlining a + /// sequence containing \p SequenceSize instructions that appears + /// \p Occurrences times in a module. + virtual unsigned getOutliningBenefit(size_t SequenceSize, size_t Occurrences, + bool CanBeTailCall) const { + llvm_unreachable( + "Target didn't implement TargetInstrInfo::getOutliningBenefit!"); + } + + /// Represents how an instruction should be mapped by the outliner. + /// \p Legal instructions are those which are safe to outline. + /// \p Illegal instructions are those which cannot be outlined. + /// \p Invisible instructions are instructions which can be outlined, but + /// shouldn't actually impact the outlining result. + enum MachineOutlinerInstrType {Legal, Illegal, Invisible}; + + /// Returns how or if \p MI should be outlined. + virtual MachineOutlinerInstrType getOutliningType(MachineInstr &MI) const { + llvm_unreachable( + "Target didn't implement TargetInstrInfo::getOutliningType!"); + } + + /// Insert a custom epilogue for outlined functions. + /// This may be empty, in which case no epilogue or return statement will be + /// emitted. + virtual void insertOutlinerEpilogue(MachineBasicBlock &MBB, + MachineFunction &MF, + bool IsTailCall) const { + llvm_unreachable( + "Target didn't implement TargetInstrInfo::insertOutlinerEpilogue!"); + } + + /// Insert a call to an outlined function into the program. + /// Returns an iterator to the spot where we inserted the call. This must be + /// implemented by the target. + virtual MachineBasicBlock::iterator + insertOutlinedCall(Module &M, MachineBasicBlock &MBB, + MachineBasicBlock::iterator &It, MachineFunction &MF, + bool IsTailCall) const { + llvm_unreachable( + "Target didn't implement TargetInstrInfo::insertOutlinedCall!"); + } + + /// Insert a custom prologue for outlined functions. + /// This may be empty, in which case no prologue will be emitted. + virtual void insertOutlinerPrologue(MachineBasicBlock &MBB, + MachineFunction &MF, + bool IsTailCall) const { + llvm_unreachable( + "Target didn't implement TargetInstrInfo::insertOutlinerPrologue!"); + } + + /// Return true if the function can safely be outlined from. + /// By default, this means that the function has no red zone. + virtual bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const { + llvm_unreachable("Target didn't implement " + "TargetInstrInfo::isFunctionSafeToOutlineFrom!"); + } + private: unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode; unsigned CatchRetOpcode; diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 3728a7a8cb179..85297ae837c56 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -25,13 +25,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/Attributes.h" @@ -163,6 +164,35 @@ public: // or custom. }; + class ArgListEntry { + public: + Value *Val = nullptr; + SDValue Node = SDValue(); + Type *Ty = nullptr; + bool IsSExt : 1; + bool IsZExt : 1; + bool IsInReg : 1; + bool IsSRet : 1; + bool IsNest : 1; + bool IsByVal : 1; + bool IsInAlloca : 1; + bool IsReturned : 1; + bool IsSwiftSelf : 1; + bool IsSwiftError : 1; + uint16_t Alignment = 0; + + ArgListEntry() + : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), + IsNest(false), IsByVal(false), IsInAlloca(false), IsReturned(false), + IsSwiftSelf(false), IsSwiftError(false) {} + + void setAttributes(ImmutableCallSite *CS, unsigned ArgIdx); + }; + typedef std::vector<ArgListEntry> ArgListTy; + + virtual void markLibCallAttributes(MachineFunction *MF, unsigned CC, + ArgListTy &Args) const {}; + static ISD::NodeType getExtendForContent(BooleanContent Content) { switch (Content) { case UndefinedBooleanContent: @@ -254,9 +284,7 @@ public: /// several shifts, adds, and multiplies for this target. /// The definition of "cheaper" may depend on whether we're optimizing /// for speed or for size. - virtual bool isIntDivCheap(EVT VT, AttributeSet Attr) const { - return false; - } + virtual bool isIntDivCheap(EVT VT, AttributeList Attr) const { return false; } /// Return true if the target can handle a standalone remainder operation. virtual bool hasStandaloneRem(EVT VT) const { @@ -363,6 +391,9 @@ public: return false; } + /// Returns if it's reasonable to merge stores to MemVT size. + virtual bool canMergeStoresTo(EVT MemVT) const { return true; } + /// \brief Return true if it is cheap to speculate a call to intrinsic cttz. virtual bool isCheapToSpeculateCttz() const { return false; @@ -395,16 +426,33 @@ public: /// \brief Return if the target supports combining a /// chain like: /// \code - /// %andResult = and %val1, #imm-with-one-bit-set; + /// %andResult = and %val1, #mask /// %icmpResult = icmp %andResult, 0 - /// br i1 %icmpResult, label %dest1, label %dest2 /// \endcode /// into a single machine instruction of a form like: /// \code - /// brOnBitSet %register, #bitNumber, dest + /// cc = test %register, #mask /// \endcode - bool isMaskAndBranchFoldingLegal() const { - return MaskAndBranchFoldingIsLegal; + virtual bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const { + return false; + } + + /// Use bitwise logic to make pairs of compares more efficient. For example: + /// and (seteq A, B), (seteq C, D) --> seteq (or (xor A, B), (xor C, D)), 0 + /// This should be true when it takes more than one instruction to lower + /// setcc (cmp+set on x86 scalar), when bitwise ops are faster than logic on + /// condition bits (crand on PowerPC), and/or when reducing cmp+br is a win. + virtual bool convertSetCCLogicToBitwiseLogic(EVT VT) const { + return false; + } + + /// Return the preferred operand type if the target has a quick way to compare + /// integer values of the given size. Assume that any legal integer type can + /// be compared efficiently. Targets may override this to allow illegal wide + /// types to return a vector type if there is support to compare that type. + virtual MVT hasFastEqualityCompare(unsigned NumBits) const { + MVT VT = MVT::getIntegerVT(NumBits); + return isTypeLegal(VT) ? VT : MVT::INVALID_SIMPLE_VALUE_TYPE; } /// Return true if the target should transform: @@ -987,6 +1035,11 @@ public: return GatherAllAliasesMaxDepth; } + /// Returns the size of the platform's va_list object. + virtual unsigned getVaListSizeInBits(const DataLayout &DL) const { + return getPointerTy(DL).getSizeInBits(); + } + /// \brief Get maximum # of store operations permitted for llvm.memset /// /// This function returns the maximum number of store operations permitted @@ -1384,6 +1437,13 @@ public: Action != TypeSplitVector; } + /// Return true if a select of constants (select Cond, C1, C2) should be + /// transformed into simple math ops with the condition value. For example: + /// select Cond, C1, C1-1 --> add (zext Cond), C1-1 + virtual bool convertSelectOfConstantsToMath() const { + return false; + } + //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. @@ -1490,7 +1550,8 @@ protected: void computeRegisterProperties(const TargetRegisterInfo *TRI); /// Indicate that the specified operation does not work with the specified - /// type and indicate what to do about it. + /// type and indicate what to do about it. Note that VT may refer to either + /// the type of a result or that of an operand of Op. void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action) { assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); @@ -1642,10 +1703,9 @@ public: /// possible to be done in the address mode for that operand. This hook lets /// targets also pass back when this should be done on intrinsics which /// load/store. - virtual bool GetAddrModeArguments(IntrinsicInst * /*I*/, + virtual bool getAddrModeArguments(IntrinsicInst * /*I*/, SmallVectorImpl<Value*> &/*Ops*/, - Type *&/*AccessTy*/, - unsigned AddrSpace = 0) const { + Type *&/*AccessTy*/) const { return false; } @@ -2197,10 +2257,6 @@ protected: /// the branch is usually predicted right. bool PredictableSelectIsExpensive; - /// MaskAndBranchFoldingIsLegal - Indicates if the target supports folding - /// a mask of a single bit, a compare, and a branch into a single instruction. - bool MaskAndBranchFoldingIsLegal; - /// \see enableExtLdPromotion. bool EnableExtLdPromotion; @@ -2357,11 +2413,11 @@ public: /// expression and return a mask of KnownOne and KnownZero bits for the /// expression (used to simplify the caller). The KnownZero/One bits may only /// be accurate for those bits in the DemandedMask. - /// \p AssumeSingleUse When this paramater is true, this function will + /// \p AssumeSingleUse When this parameter is true, this function will /// attempt to simplify \p Op even if there are multiple uses. /// Callers are responsible for correctly updating the DAG based on the /// results of this function, because simply replacing replacing TLO.Old - /// with TLO.New will be incorrect when this paramater is true and TLO.Old + /// with TLO.New will be incorrect when this parameter is true and TLO.Old /// has multiple uses. bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, APInt &KnownZero, APInt &KnownOne, @@ -2369,17 +2425,27 @@ public: unsigned Depth = 0, bool AssumeSingleUse = false) const; + /// Helper wrapper around SimplifyDemandedBits + bool SimplifyDemandedBits(SDValue Op, APInt &DemandedMask, + DAGCombinerInfo &DCI) const; + /// Determine which of the bits specified in Mask are known to be either zero - /// or one and return them in the KnownZero/KnownOne bitsets. + /// or one and return them in the KnownZero/KnownOne bitsets. The DemandedElts + /// argument allows us to only collect the known bits that are shared by the + /// requested vector elements. virtual void computeKnownBitsForTargetNode(const SDValue Op, APInt &KnownZero, APInt &KnownOne, + const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth = 0) const; /// This method can be implemented by targets that want to expose additional - /// information about sign bits to the DAG Combiner. + /// information about sign bits to the DAG Combiner. The DemandedElts + /// argument allows us to only collect the minimum sign bits that are shared + /// by the requested vector elements. virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, + const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth = 0) const; @@ -2536,30 +2602,6 @@ public: llvm_unreachable("Not Implemented"); } - struct ArgListEntry { - SDValue Node; - Type* Ty; - bool isSExt : 1; - bool isZExt : 1; - bool isInReg : 1; - bool isSRet : 1; - bool isNest : 1; - bool isByVal : 1; - bool isInAlloca : 1; - bool isReturned : 1; - bool isSwiftSelf : 1; - bool isSwiftError : 1; - uint16_t Alignment; - - ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), - isSRet(false), isNest(false), isByVal(false), isInAlloca(false), - isReturned(false), isSwiftSelf(false), isSwiftError(false), - Alignment(0) {} - - void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); - }; - typedef std::vector<ArgListEntry> ArgListTy; - /// This structure contains all information that is necessary for lowering /// calls. It is passed to TLI::LowerCallTo when the SelectionDAG builder /// needs to lower a call, and targets will see this struct in their LowerCall @@ -2609,6 +2651,20 @@ public: return *this; } + // setCallee with target/module-specific attributes + CallLoweringInfo &setLibCallee(CallingConv::ID CC, Type *ResultType, + SDValue Target, ArgListTy &&ArgsList) { + RetTy = ResultType; + Callee = Target; + CallConv = CC; + NumFixedArgs = Args.size(); + Args = std::move(ArgsList); + + DAG.getTargetLoweringInfo().markLibCallAttributes( + &(DAG.getMachineFunction()), CC, Args); + return *this; + } + CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList) { RetTy = ResultType; @@ -2624,15 +2680,15 @@ public: ImmutableCallSite &Call) { RetTy = ResultType; - IsInReg = Call.paramHasAttr(0, Attribute::InReg); + IsInReg = Call.hasRetAttr(Attribute::InReg); DoesNotReturn = Call.doesNotReturn() || (!Call.isInvoke() && isa<UnreachableInst>(Call.getInstruction()->getNextNode())); IsVarArg = FTy->isVarArg(); IsReturnValueUsed = !Call.getInstruction()->use_empty(); - RetSExt = Call.paramHasAttr(0, Attribute::SExt); - RetZExt = Call.paramHasAttr(0, Attribute::ZExt); + RetSExt = Call.hasRetAttr(Attribute::SExt); + RetZExt = Call.hasRetAttr(Attribute::ZExt); Callee = Target; @@ -3183,7 +3239,7 @@ private: /// Given an LLVM IR type and return type attributes, compute the return value /// EVTs and flags, and optionally also the offsets, if the return value is /// being lowered to memory. -void GetReturnInfo(Type *ReturnType, AttributeSet attr, +void GetReturnInfo(Type *ReturnType, AttributeList attr, SmallVectorImpl<ISD::OutputArg> &Outs, const TargetLowering &TLI, const DataLayout &DL); diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 72bae0a38e657..0ffd4b7f8c786 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -16,37 +16,35 @@ #define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/SectionKind.h" +#include <cstdint> namespace llvm { - class MachineModuleInfo; - class Mangler; - class MCContext; - class MCExpr; - class MCSection; - class MCSymbol; - class MCSymbolRefExpr; - class MCStreamer; - class MCValue; - class ConstantExpr; - class GlobalValue; - class TargetMachine; + +class GlobalValue; +class MachineModuleInfo; +class Mangler; +class MCContext; +class MCExpr; +class MCSection; +class MCSymbol; +class MCSymbolRefExpr; +class MCStreamer; +class MCValue; +class TargetMachine; class TargetLoweringObjectFile : public MCObjectFileInfo { - MCContext *Ctx; + MCContext *Ctx = nullptr; /// Name-mangler for global names. Mangler *Mang = nullptr; - TargetLoweringObjectFile( - const TargetLoweringObjectFile&) = delete; - void operator=(const TargetLoweringObjectFile&) = delete; - protected: - bool SupportIndirectSymViaGOTPCRel; - bool SupportGOTPCRelWithOffset; + bool SupportIndirectSymViaGOTPCRel = false; + bool SupportGOTPCRelWithOffset = true; /// This section contains the static constructor pointer list. MCSection *StaticCtorSection; @@ -55,15 +53,15 @@ protected: MCSection *StaticDtorSection; public: + TargetLoweringObjectFile() = default; + TargetLoweringObjectFile(const TargetLoweringObjectFile &) = delete; + TargetLoweringObjectFile & + operator=(const TargetLoweringObjectFile &) = delete; + virtual ~TargetLoweringObjectFile(); + MCContext &getContext() const { return *Ctx; } Mangler &getMangler() const { return *Mang; } - TargetLoweringObjectFile() - : MCObjectFileInfo(), Ctx(nullptr), Mang(nullptr), - SupportIndirectSymViaGOTPCRel(false), SupportGOTPCRelWithOffset(true) {} - - virtual ~TargetLoweringObjectFile(); - /// This method must be called before any actual lowering is done. This /// specifies the current context for codegen, and gives the lowering /// implementations a chance to set up their default sections. @@ -194,4 +192,4 @@ protected: } // end namespace llvm -#endif +#endif // LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index b1d8f8f1e9173..73ae2ad129881 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -34,6 +34,7 @@ class MCRegisterInfo; class MCSubtargetInfo; class MCSymbol; class raw_pwrite_stream; +class PassManagerBuilder; class Target; class TargetIntrinsicInfo; class TargetIRAnalysis; @@ -205,10 +206,9 @@ public: /// uses this to answer queries about the IR. virtual TargetIRAnalysis getTargetIRAnalysis(); - /// Add target-specific function passes that should be run as early as - /// possible in the optimization pipeline. Most TargetMachines have no such - /// passes. - virtual void addEarlyAsPossiblePasses(PassManagerBase &) {} + /// Allow the target to modify the pass manager, e.g. by calling + /// PassManagerBuilder::addExtension. + virtual void adjustPassManager(PassManagerBuilder &) {} /// 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 @@ -268,8 +268,8 @@ class LLVMTargetMachine : public TargetMachine { protected: // Can only create subclasses. LLVMTargetMachine(const Target &T, StringRef DataLayoutString, const Triple &TargetTriple, StringRef CPU, StringRef FS, - TargetOptions Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL); + const TargetOptions &Options, Reloc::Model RM, + CodeModel::Model CM, CodeGenOpt::Level OL); void initAsmInfo(); public: diff --git a/include/llvm/Target/TargetOpcodes.def b/include/llvm/Target/TargetOpcodes.def index edb9b7350ca79..96db6e0a97698 100644 --- a/include/llvm/Target/TargetOpcodes.def +++ b/include/llvm/Target/TargetOpcodes.def @@ -107,6 +107,9 @@ HANDLE_TARGET_OPCODE(LIFETIME_END) /// that must lie within the function and not contain another stackmap. HANDLE_TARGET_OPCODE(STACKMAP) +/// FEntry all - This is a marker instruction which gets translated into a raw fentry call. +HANDLE_TARGET_OPCODE(FENTRY_CALL) + /// Patchable call instruction - this instruction represents a call to a /// constant address, followed by a series of NOPs. It is intended to /// support optimizations for dynamic languages (such as javascript) that @@ -131,11 +134,13 @@ HANDLE_TARGET_OPCODE(STATEPOINT) /// frame index of the local stack allocation. HANDLE_TARGET_OPCODE(LOCAL_ESCAPE) -/// Loading instruction that may page fault, bundled with associated +/// Wraps a machine instruction which can fault, bundled with associated +/// information on how to handle such a fault. +/// For example loading instruction that may page fault, bundled with associated /// information on how to handle such a page fault. It is intended to support /// "zero cost" null checks in managed languages by allowing LLVM to fold /// comparisons into existing memory operations. -HANDLE_TARGET_OPCODE(FAULTING_LOAD_OP) +HANDLE_TARGET_OPCODE(FAULTING_OP) /// Wraps a machine instruction to add patchability constraints. An /// instruction wrapped in PATCHABLE_OP has to either have a minimum @@ -224,6 +229,8 @@ HANDLE_TARGET_OPCODE(G_GLOBAL_VALUE) /// (typically a sub-register COPY after instruction selection). HANDLE_TARGET_OPCODE(G_EXTRACT) +HANDLE_TARGET_OPCODE(G_UNMERGE_VALUES) + /// Generic instruction to insert blocks of bits from the registers given into /// the source. HANDLE_TARGET_OPCODE(G_INSERT) @@ -232,6 +239,8 @@ HANDLE_TARGET_OPCODE(G_INSERT) /// larger register. HANDLE_TARGET_OPCODE(G_SEQUENCE) +HANDLE_TARGET_OPCODE(G_MERGE_VALUES) + /// Generic pointer to int conversion. HANDLE_TARGET_OPCODE(G_PTRTOINT) @@ -251,6 +260,9 @@ HANDLE_TARGET_OPCODE(G_STORE) /// Generic conditional branch instruction. HANDLE_TARGET_OPCODE(G_BRCOND) +/// Generic indirect branch instruction. +HANDLE_TARGET_OPCODE(G_BRINDIRECT) + /// Generic intrinsic use (without side effects). HANDLE_TARGET_OPCODE(G_INTRINSIC) @@ -272,6 +284,12 @@ HANDLE_TARGET_OPCODE(G_CONSTANT) /// Generic floating constant. HANDLE_TARGET_OPCODE(G_FCONSTANT) +/// Generic va_start instruction. Stores to its one pointer operand. +HANDLE_TARGET_OPCODE(G_VASTART) + +/// Generic va_start instruction. Stores to its one pointer operand. +HANDLE_TARGET_OPCODE(G_VAARG) + // Generic sign extend HANDLE_TARGET_OPCODE(G_SEXT) @@ -320,6 +338,14 @@ HANDLE_TARGET_OPCODE(G_UMULO) /// overflow flag. HANDLE_TARGET_OPCODE(G_SMULO) +// Multiply two numbers at twice the incoming bit width (unsigned) and return +// the high half of the result. +HANDLE_TARGET_OPCODE(G_UMULH) + +// Multiply two numbers at twice the incoming bit width (signed) and return +// the high half of the result. +HANDLE_TARGET_OPCODE(G_SMULH) + /// Generic FP addition. HANDLE_TARGET_OPCODE(G_FADD) @@ -335,7 +361,13 @@ HANDLE_TARGET_OPCODE(G_FDIV) /// Generic FP remainder. HANDLE_TARGET_OPCODE(G_FREM) -/// Generic float to signed-int conversion +/// Generic FP exponentiation. +HANDLE_TARGET_OPCODE(G_FPOW) + +/// Generic FP negation. +HANDLE_TARGET_OPCODE(G_FNEG) + +/// Generic FP extension. HANDLE_TARGET_OPCODE(G_FPEXT) /// Generic float to signed-int conversion @@ -353,18 +385,31 @@ HANDLE_TARGET_OPCODE(G_SITOFP) /// Generic unsigned-int to float conversion HANDLE_TARGET_OPCODE(G_UITOFP) -/// Generic unsigned-int to float conversion +/// Generic pointer offset HANDLE_TARGET_OPCODE(G_GEP) +/// Clear the specified number of low bits in a pointer. This rounds the value +/// *down* to the given alignment. +HANDLE_TARGET_OPCODE(G_PTR_MASK) + /// Generic BRANCH instruction. This is an unconditional branch. HANDLE_TARGET_OPCODE(G_BR) +/// Generic insertelement. +HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT) + +/// Generic extractelement. +HANDLE_TARGET_OPCODE(G_EXTRACT_VECTOR_ELT) + +/// Generic shufflevector. +HANDLE_TARGET_OPCODE(G_SHUFFLE_VECTOR) + // TODO: Add more generic opcodes as we move along. /// Marker for the end of the generic opcode. /// This is used to check if an opcode is in the range of the /// generic opcodes. -HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BR) +HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_SHUFFLE_VECTOR) /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific post-isel opcode values start here. diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index f5134d99b0392..7cc33f2fdccbb 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -99,22 +99,16 @@ namespace llvm { class TargetOptions { public: TargetOptions() - : PrintMachineCode(false), LessPreciseFPMADOption(false), - UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), - NoTrappingFPMath(false), + : PrintMachineCode(false), UnsafeFPMath(false), NoInfsFPMath(false), + NoNaNsFPMath(false), NoTrappingFPMath(false), + NoSignedZerosFPMath(false), HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false), - GuaranteedTailCallOpt(false), StackAlignmentOverride(0), - StackSymbolOrdering(true), EnableFastISel(false), UseInitArray(false), + GuaranteedTailCallOpt(false), StackSymbolOrdering(true), + EnableFastISel(false), UseInitArray(false), DisableIntegratedAS(false), CompressDebugSections(false), RelaxELFRelocations(false), FunctionSections(false), DataSections(false), UniqueSectionNames(true), TrapUnreachable(false), - EmulatedTLS(false), EnableIPRA(false), - FloatABIType(FloatABI::Default), - AllowFPOpFusion(FPOpFusion::Standard), - ThreadModel(ThreadModel::POSIX), - EABIVersion(EABI::Default), DebuggerTuning(DebuggerKind::Default), - FPDenormalMode(FPDenormal::IEEE), - ExceptionModel(ExceptionHandling::None) {} + EmulatedTLS(false), EnableIPRA(false) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -125,20 +119,11 @@ namespace llvm { /// optimization should be disabled for the given machine function. bool DisableFramePointerElim(const MachineFunction &MF) const; - /// LessPreciseFPMAD - This flag is enabled when the - /// -enable-fp-mad is specified on the command line. When this flag is off - /// (the default), the code generator is not allowed to generate mad - /// (multiply add) if the result is "less precise" than doing those - /// operations individually. - unsigned LessPreciseFPMADOption : 1; - bool LessPreciseFPMAD() const; - /// UnsafeFPMath - This flag is enabled when the /// -enable-unsafe-fp-math flag is specified on the command line. When /// this flag is off (the default), the code generator is not allowed to /// produce results that are "less precise" than IEEE allows. This includes /// use of X86 instructions like FSIN and FCOS instead of libcalls. - /// UnsafeFPMath implies LessPreciseFPMAD. unsigned UnsafeFPMath : 1; /// NoInfsFPMath - This flag is enabled when the @@ -153,11 +138,17 @@ namespace llvm { /// assume the FP arithmetic arguments and results are never NaNs. unsigned NoNaNsFPMath : 1; - /// NoTrappingFPMath - This flag is enabled when the - /// -enable-no-trapping-fp-math is specified on the command line. This + /// NoTrappingFPMath - This flag is enabled when the + /// -enable-no-trapping-fp-math is specified on the command line. This /// specifies that there are no trap handlers to handle exceptions. unsigned NoTrappingFPMath : 1; + /// NoSignedZerosFPMath - This flag is enabled when the + /// -enable-no-signed-zeros-fp-math is specified on the command line. This + /// specifies that optimizations are allowed to treat the sign of a zero + /// argument or result as insignificant. + unsigned NoSignedZerosFPMath : 1; + /// HonorSignDependentRoundingFPMath - This returns true when the /// -enable-sign-dependent-rounding-fp-math is specified. If this returns /// false (the default), the code generator is allowed to assume that the @@ -182,7 +173,7 @@ namespace llvm { unsigned GuaranteedTailCallOpt : 1; /// StackAlignmentOverride - Override default stack alignment for target. - unsigned StackAlignmentOverride; + unsigned StackAlignmentOverride = 0; /// StackSymbolOrdering - When true, this will allow CodeGen to order /// the local stack symbols (for code size, code locality, or any other @@ -231,7 +222,7 @@ namespace llvm { /// 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; + FloatABI::ABIType FloatABIType = FloatABI::Default; /// AllowFPOpFusion - This flag is set by the -fuse-fp-ops=xxx option. /// This controls the creation of fused FP ops that store intermediate @@ -249,65 +240,29 @@ namespace llvm { /// optimizers. Fused operations that are explicitly specified (e.g. FMA /// via the llvm.fma.* intrinsic) will always be honored, regardless of /// the value of this option. - FPOpFusion::FPOpFusionMode AllowFPOpFusion; + FPOpFusion::FPOpFusionMode AllowFPOpFusion = FPOpFusion::Standard; /// ThreadModel - This flag specifies the type of threading model to assume /// for things like atomics - ThreadModel::Model ThreadModel; + ThreadModel::Model ThreadModel = ThreadModel::POSIX; /// EABIVersion - This flag specifies the EABI version - EABI EABIVersion; + EABI EABIVersion = EABI::Default; /// Which debugger to tune for. - DebuggerKind DebuggerTuning; + DebuggerKind DebuggerTuning = DebuggerKind::Default; /// FPDenormalMode - This flags specificies which denormal numbers the code /// is permitted to require. - FPDenormal::DenormalMode FPDenormalMode; + FPDenormal::DenormalMode FPDenormalMode = FPDenormal::IEEE; /// What exception model to use - ExceptionHandling ExceptionModel; + ExceptionHandling ExceptionModel = ExceptionHandling::None; /// Machine level options. MCTargetOptions MCOptions; }; -// Comparison operators: - - -inline bool operator==(const TargetOptions &LHS, - const TargetOptions &RHS) { -#define ARE_EQUAL(X) LHS.X == RHS.X - return - ARE_EQUAL(UnsafeFPMath) && - ARE_EQUAL(NoInfsFPMath) && - ARE_EQUAL(NoNaNsFPMath) && - ARE_EQUAL(NoTrappingFPMath) && - ARE_EQUAL(HonorSignDependentRoundingFPMathOption) && - ARE_EQUAL(NoZerosInBSS) && - ARE_EQUAL(GuaranteedTailCallOpt) && - ARE_EQUAL(StackAlignmentOverride) && - ARE_EQUAL(EnableFastISel) && - ARE_EQUAL(UseInitArray) && - ARE_EQUAL(TrapUnreachable) && - ARE_EQUAL(EmulatedTLS) && - ARE_EQUAL(FloatABIType) && - ARE_EQUAL(AllowFPOpFusion) && - ARE_EQUAL(ThreadModel) && - ARE_EQUAL(EABIVersion) && - ARE_EQUAL(DebuggerTuning) && - ARE_EQUAL(FPDenormalMode) && - ARE_EQUAL(ExceptionModel) && - ARE_EQUAL(MCOptions) && - ARE_EQUAL(EnableIPRA); -#undef ARE_EQUAL -} - -inline bool operator!=(const TargetOptions &LHS, - const TargetOptions &RHS) { - return !(LHS == RHS); -} - } // End llvm namespace #endif diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 3080e9a32c3ac..3f5daea63ab59 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -45,6 +45,7 @@ public: // Instance variables filled by tablegen, do not use! const MCRegisterClass *MC; + const uint16_t SpillSize, SpillAlignment; const vt_iterator VTs; const uint32_t *SubClassMask; const uint16_t *SuperRegIndices; @@ -94,10 +95,10 @@ public: /// Return the size of the register in bytes, which is also the size /// of a stack slot allocated to hold a spilled copy of this register. - unsigned getSize() const { return MC->getSize(); } + unsigned getSize() const { return SpillSize; } /// Return the minimum required alignment for a register of this class. - unsigned getAlignment() const { return MC->getAlignment(); } + unsigned getAlignment() const { return SpillAlignment; } /// Return the cost of copying a value between two registers in this class. /// A negative number means the register class is very expensive @@ -426,7 +427,9 @@ public: /// this target. The register should be in the order of desired callee-save /// stack frame offset. The first register is closest to the incoming stack /// pointer if stack grows down, and vice versa. - /// + /// Notice: This function does not take into account disabled CSRs. + /// In most cases you will want to use instead the function + /// getCalleeSavedRegs that is implemented in MachineRegisterInfo. virtual const MCPhysReg* getCalleeSavedRegs(const MachineFunction *MF) const = 0; @@ -633,6 +636,9 @@ public: /// regclass_iterator regclass_begin() const { return RegClassBegin; } regclass_iterator regclass_end() const { return RegClassEnd; } + iterator_range<regclass_iterator> regclasses() const { + return make_range(regclass_begin(), regclass_end()); + } unsigned getNumRegClasses() const { return (unsigned)(regclass_end()-regclass_begin()); diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 74b98ac5f6c5d..d342e4fe26135 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -139,7 +139,7 @@ class ProcResourceKind; // changes this to an in-order issue/dispatch resource. In this case, // the scheduler counts down from the cycle that the instruction // issues in-order, forcing a stall whenever a subsequent instruction -// requires the same resource until the number of ResourceCyles +// requires the same resource until the number of ResourceCycles // specified in WriteRes expire. Setting BufferSize=1 changes this to // an in-order latency resource. In this case, the scheduler models // producer/consumer stalls between instructions that use the @@ -255,6 +255,9 @@ class ProcWriteResources<list<ProcResourceKind> resources> { // Allow a processor to mark some scheduling classes as unsupported // for stronger verification. bit Unsupported = 0; + // Allow a processor to mark some scheduling classes as single-issue. + // SingleIssue is an alias for Begin/End Group. + bit SingleIssue = 0; SchedMachineModel SchedModel = ?; } diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 55e2c2bce3db9..45a842f77a21a 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -136,30 +136,34 @@ def SDTIntUnaryOp : SDTypeProfile<1, 1, [ // ctlz SDTCisSameAs<0, 1>, SDTCisInt<0> ]>; def SDTIntExtendOp : SDTypeProfile<1, 1, [ // sext, zext, anyext - SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0> + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> ]>; def SDTIntTruncOp : SDTypeProfile<1, 1, [ // trunc - SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1> + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> ]>; def SDTFPUnaryOp : SDTypeProfile<1, 1, [ // fneg, fsqrt, etc SDTCisSameAs<0, 1>, SDTCisFP<0> ]>; def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround - SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1> + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> ]>; def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend - SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0> + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> ]>; def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp - SDTCisFP<0>, SDTCisInt<1> + SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1> ]>; def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int - SDTCisInt<0>, SDTCisFP<1> + SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1> ]>; def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisVT<2, OtherVT>, SDTCisVTSmallerThanOp<2, 1> ]>; +def SDTExtInvec : SDTypeProfile<1, 1, [ // sext_invec + SDTCisInt<0>, SDTCisVec<0>, SDTCisInt<1>, SDTCisVec<1>, + SDTCisOpSmallerThanOp<1, 0>, SDTCisSameSizeAs<0,1> +]>; def SDTSetCC : SDTypeProfile<1, 3, [ // setcc SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> @@ -170,7 +174,7 @@ def SDTSelect : SDTypeProfile<1, 3, [ // select ]>; def SDTVSelect : SDTypeProfile<1, 3, [ // vselect - SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1> + SDTCisVec<0>, SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1> ]>; def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc @@ -406,6 +410,10 @@ def umax : SDNode<"ISD::UMAX" , SDTIntBinOp, [SDNPCommutative, SDNPAssociative]>; def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; +def sext_invec : SDNode<"ISD::SIGN_EXTEND_VECTOR_INREG", SDTExtInvec>; +def zext_invec : SDNode<"ISD::ZERO_EXTEND_VECTOR_INREG", SDTExtInvec>; + +def abs : SDNode<"ISD::ABS" , SDTIntUnaryOp>; def bitreverse : SDNode<"ISD::BITREVERSE" , SDTIntUnaryOp>; def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index 0b43515960216..83950a9cd027a 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -20,6 +20,7 @@ #include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/ScheduleDAGMutation.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/CodeGen.h" #include <memory> @@ -143,6 +144,9 @@ public: /// TargetLowering preference). It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; + /// \brief Support printing of [latency:throughput] comment in output .S file. + virtual bool supportPrintSchedInfo() const { return false; } + /// \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; } @@ -227,6 +231,10 @@ public: /// Please use MachineRegisterInfo::subRegLivenessEnabled() instead where /// possible. virtual bool enableSubRegLiveness() const { return false; } + + /// Returns string representation of scheduler comment + std::string getSchedInfoStr(const MachineInstr &MI) const override; + std::string getSchedInfoStr(MCInst const &MCI) const override; }; } // end namespace llvm |