#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/DebugLoc.h"
+#include "llvm/Support/DebugLoc.h"
#include "llvm/Target/TargetMachine.h"
#include <climits>
#include <map>
class TargetMachine;
class TargetRegisterClass;
class TargetSubtarget;
+ class TargetLoweringObjectFile;
class Value;
// FIXME: should this be here?
/// target-specific constructs to SelectionDAG operators.
///
class TargetLowering {
+ TargetLowering(const TargetLowering&); // DO NOT IMPLEMENT
+ void operator=(const TargetLowering&); // DO NOT IMPLEMENT
public:
/// LegalizeAction - This enum indicates whether operations are valid for a
/// target, and if not, what action should be used to make them valid.
Custom // Use the LowerOperation hook to implement custom lowering.
};
- enum OutOfRangeShiftAmount {
- Undefined, // Oversized shift amounts are undefined (default).
- Mask, // Shift amounts are auto masked (anded) to value size.
- Extend // Oversized shift pulls in zeros or sign bits.
- };
-
enum BooleanContent { // How the target represents true/false values.
UndefinedBooleanContent, // Only bit 0 counts, the rest can hold garbage.
ZeroOrOneBooleanContent, // All bits zero except for bit 0.
SchedulingForRegPressure // Scheduling for lowest register pressure.
};
- explicit TargetLowering(TargetMachine &TM);
+ /// NOTE: The constructor takes ownership of TLOF.
+ explicit TargetLowering(TargetMachine &TM, TargetLoweringObjectFile *TLOF);
virtual ~TargetLowering();
TargetMachine &getTargetMachine() const { return TM; }
const TargetData *getTargetData() const { return TD; }
+ TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; }
bool isBigEndian() const { return !IsLittleEndian; }
bool isLittleEndian() const { return IsLittleEndian; }
- MVT getPointerTy() const { return PointerTy; }
- MVT getShiftAmountTy() const { return ShiftAmountTy; }
- OutOfRangeShiftAmount getShiftAmountFlavor() const {return ShiftAmtHandling; }
+ MVT::SimpleValueType getPointerTy() const { return PointerTy; }
+ MVT::SimpleValueType getShiftAmountTy() const { return ShiftAmountTy; }
/// usesGlobalOffsetTable - Return true if this target uses a GOT for PIC
/// codegen.
/// the condition operand of SELECT and BRCOND nodes. In the case of
/// BRCOND the argument passed is MVT::Other since there are no other
/// operands to get a type hint from.
- virtual MVT getSetCCResultType(MVT VT) const;
+ virtual
+ MVT::SimpleValueType getSetCCResultType(MVT VT) const;
/// getBooleanContents - For targets without i1 registers, this gives the
/// nature of the high-bits of boolean values held in types wider than i1.
/// getRegClassFor - Return the register class that should be used for the
/// specified value type. This may only be called on legal types.
TargetRegisterClass *getRegClassFor(MVT VT) const {
- assert((unsigned)VT.getSimpleVT() < array_lengthof(RegClassForVT));
+ assert(VT.isSimple() && "getRegClassFor called on illegal type!");
TargetRegisterClass *RC = RegClassForVT[VT.getSimpleVT()];
assert(RC && "This value type is not natively supported!");
return RC;
/// ValueTypeActions - This is a bitvector that contains two bits for each
/// value type, where the two bits correspond to the LegalizeAction enum.
/// This can be queried with "getTypeAction(VT)".
- uint32_t ValueTypeActions[2];
+ /// dimension by (MVT::MAX_ALLOWED_VALUETYPE/32) * 2
+ uint32_t ValueTypeActions[(MVT::MAX_ALLOWED_VALUETYPE/32)*2];
public:
ValueTypeActionImpl() {
ValueTypeActions[0] = ValueTypeActions[1] = 0;
+ ValueTypeActions[2] = ValueTypeActions[3] = 0;
}
ValueTypeActionImpl(const ValueTypeActionImpl &RHS) {
ValueTypeActions[0] = RHS.ValueTypeActions[0];
ValueTypeActions[1] = RHS.ValueTypeActions[1];
+ ValueTypeActions[2] = RHS.ValueTypeActions[2];
+ ValueTypeActions[3] = RHS.ValueTypeActions[3];
}
LegalizeAction getTypeAction(MVT VT) const {
return getTypeAction(NVT) == Promote ? getTypeToTransformTo(NVT) : NVT;
}
assert(0 && "Unsupported extended type!");
- return MVT(); // Not reached
+ return MVT(MVT::Other); // Not reached
}
/// getTypeToExpandTo - For types supported by the target, this is an
/// support *some* VECTOR_SHUFFLE operations, those with specific masks.
/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values
/// are assumed to be legal.
- virtual bool isShuffleMaskLegal(const int *Mask, MVT VT) const {
+ virtual bool isShuffleMaskLegal(const SmallVectorImpl<int> &Mask,
+ MVT VT) const {
return true;
}
/// used by Targets can use this to indicate if there is a suitable
/// VECTOR_SHUFFLE that can be used to replace a VAND with a constant
/// pool entry.
- virtual bool isVectorClearMaskLegal(const int *Mask, MVT VT) const {
+ virtual bool isVectorClearMaskLegal(const SmallVectorImpl<int> &Mask,
+ MVT VT) const {
return false;
}
/// for it.
LegalizeAction getOperationAction(unsigned Op, MVT VT) const {
if (VT.isExtended()) return Expand;
- assert(Op < array_lengthof(OpActions) &&
- (unsigned)VT.getSimpleVT() < sizeof(OpActions[0])*4 &&
+ assert(Op < array_lengthof(OpActions[0]) &&
+ (unsigned)VT.getSimpleVT() < sizeof(OpActions[0][0])*8 &&
"Table isn't big enough!");
- return (LegalizeAction)((OpActions[Op] >> (2*VT.getSimpleVT())) & 3);
+ unsigned I = (unsigned) VT.getSimpleVT();
+ unsigned J = I & 31;
+ I = I >> 5;
+ return (LegalizeAction)((OpActions[I][Op] >> (J*2) ) & 3);
}
/// isOperationLegalOrCustom - Return true if the specified operation is
/// for it.
LegalizeAction
getIndexedLoadAction(unsigned IdxMode, MVT VT) const {
- assert(IdxMode < array_lengthof(IndexedModeActions[0]) &&
- (unsigned)VT.getSimpleVT() < sizeof(IndexedModeActions[0][0])*4 &&
+ assert( IdxMode < array_lengthof(IndexedModeActions[0][0]) &&
+ ((unsigned)VT.getSimpleVT()) < MVT::LAST_VALUETYPE &&
"Table isn't big enough!");
- return (LegalizeAction)((IndexedModeActions[0][IdxMode] >>
- (2*VT.getSimpleVT())) & 3);
+ return (LegalizeAction)((IndexedModeActions[(unsigned)VT.getSimpleVT()][0][IdxMode]));
}
/// isIndexedLoadLegal - Return true if the specified indexed load is legal
/// for it.
LegalizeAction
getIndexedStoreAction(unsigned IdxMode, MVT VT) const {
- assert(IdxMode < array_lengthof(IndexedModeActions[1]) &&
- (unsigned)VT.getSimpleVT() < sizeof(IndexedModeActions[1][0])*4 &&
+ assert(IdxMode < array_lengthof(IndexedModeActions[0][1]) &&
+ (unsigned)VT.getSimpleVT() < MVT::LAST_VALUETYPE &&
"Table isn't big enough!");
- return (LegalizeAction)((IndexedModeActions[1][IdxMode] >>
- (2*VT.getSimpleVT())) & 3);
+ return (LegalizeAction)((IndexedModeActions[(unsigned)VT.getSimpleVT()][1][IdxMode]));
}
/// isIndexedStoreLegal - Return true if the specified indexed load is legal
return getRegisterType(getTypeToTransformTo(VT));
}
assert(0 && "Unsupported extended type!");
- return MVT(); // Not reached
+ return MVT(MVT::Other); // Not reached
}
/// getNumRegisters - Return the number of registers that this ValueType will
return allowUnalignedMemoryAccesses;
}
+ /// This function returns true if the target would benefit from code placement
+ /// optimization.
+ /// @brief Determine if the target should perform code placement optimization.
+ bool shouldOptimizeCodePlacement() const {
+ return benefitFromCodePlacementOpt;
+ }
+
/// getOptimalMemOpType - Returns the target specific optimal type for load
/// and store operations as a result of memset, memcpy, and memmove lowering.
/// It returns MVT::iAny if SelectionDAG should be responsible for
/// determining it.
virtual MVT getOptimalMemOpType(uint64_t Size, unsigned Align,
- bool isSrcConst, bool isSrcStr) const {
+ bool isSrcConst, bool isSrcStr,
+ SelectionDAG &DAG) const {
return MVT::iAny;
}
/// PIC relocation models.
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
+ /// getFunctionAlignment - Return the Log2 alignment of this function.
+ virtual unsigned getFunctionAlignment(const Function *) const = 0;
+
//===--------------------------------------------------------------------===//
// TargetLowering Optimization Methods
//
struct DAGCombinerInfo {
void *DC; // The DAG Combiner object.
bool BeforeLegalize;
+ bool BeforeLegalizeOps;
bool CalledByLegalizer;
public:
SelectionDAG &DAG;
- DAGCombinerInfo(SelectionDAG &dag, bool bl, bool cl, void *dc)
- : DC(dc), BeforeLegalize(bl), CalledByLegalizer(cl), DAG(dag) {}
+ DAGCombinerInfo(SelectionDAG &dag, bool bl, bool blo, bool cl, void *dc)
+ : DC(dc), BeforeLegalize(bl), BeforeLegalizeOps(blo),
+ CalledByLegalizer(cl), DAG(dag) {}
bool isBeforeLegalize() const { return BeforeLegalize; }
+ bool isBeforeLegalizeOps() const { return BeforeLegalizeOps; }
bool isCalledByLegalizer() const { return CalledByLegalizer; }
void AddToWorklist(SDNode *N);
virtual bool
isGAPlusOffset(SDNode *N, GlobalValue* &GA, int64_t &Offset) const;
- /// isConsecutiveLoad - Return true if LD (which must be a LoadSDNode) is
- /// loading 'Bytes' bytes from a location that is 'Dist' units away from the
- /// location that the 'Base' load is loading from.
- bool isConsecutiveLoad(SDNode *LD, SDNode *Base, unsigned Bytes, int Dist,
- const MachineFrameInfo *MFI) const;
+ /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a
+ /// location that is 'Dist' units away from the location that the 'Base' load
+ /// is loading from.
+ bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes,
+ int Dist, const MachineFrameInfo *MFI) const;
/// PerformDAGCombine - This method will be invoked for all target nodes and
/// for any target-independent nodes that the target has registered with
/// setShiftAmountType - Describe the type that should be used for shift
/// amounts. This type defaults to the pointer type.
- void setShiftAmountType(MVT VT) { ShiftAmountTy = VT; }
+ void setShiftAmountType(MVT::SimpleValueType VT) { ShiftAmountTy = VT; }
/// setBooleanContents - Specify how the target extends the result of a
/// boolean value from i1 to a wider type. See getBooleanContents.
SchedPreferenceInfo = Pref;
}
- /// setShiftAmountFlavor - Describe how the target handles out of range shift
- /// amounts.
- void setShiftAmountFlavor(OutOfRangeShiftAmount OORSA) {
- ShiftAmtHandling = OORSA;
- }
-
/// setUseUnderscoreSetJmp - Indicate whether this target prefers to
/// use _setjmp to implement llvm.setjmp or the non _ version.
/// Defaults to false.
/// with the specified type and indicate what to do about it.
void setOperationAction(unsigned Op, MVT VT,
LegalizeAction Action) {
- assert((unsigned)VT.getSimpleVT() < sizeof(OpActions[0])*4 &&
- Op < array_lengthof(OpActions) && "Table isn't big enough!");
- OpActions[Op] &= ~(uint64_t(3UL) << VT.getSimpleVT()*2);
- OpActions[Op] |= (uint64_t)Action << VT.getSimpleVT()*2;
+ assert((unsigned)VT.getSimpleVT() < sizeof(OpActions[0][0])*8 &&
+ Op < array_lengthof(OpActions[0]) && "Table isn't big enough!");
+ unsigned I = (unsigned) VT.getSimpleVT();
+ unsigned J = I & 31;
+ I = I >> 5;
+ OpActions[I][Op] &= ~(uint64_t(3UL) << (J*2));
+ OpActions[I][Op] |= (uint64_t)Action << (J*2);
}
/// setLoadExtAction - Indicate that the specified load with extension does
/// TargetLowering.cpp
void setIndexedLoadAction(unsigned IdxMode, MVT VT,
LegalizeAction Action) {
- assert((unsigned)VT.getSimpleVT() < sizeof(IndexedModeActions[0])*4 &&
- IdxMode < array_lengthof(IndexedModeActions[0]) &&
+ assert((unsigned)VT.getSimpleVT() < MVT::LAST_VALUETYPE &&
+ IdxMode < array_lengthof(IndexedModeActions[0][0]) &&
"Table isn't big enough!");
- IndexedModeActions[0][IdxMode] &= ~(uint64_t(3UL) << VT.getSimpleVT()*2);
- IndexedModeActions[0][IdxMode] |= (uint64_t)Action << VT.getSimpleVT()*2;
+ IndexedModeActions[(unsigned)VT.getSimpleVT()][0][IdxMode] = (uint8_t)Action;
}
/// setIndexedStoreAction - Indicate that the specified indexed store does or
/// TargetLowering.cpp
void setIndexedStoreAction(unsigned IdxMode, MVT VT,
LegalizeAction Action) {
- assert((unsigned)VT.getSimpleVT() < sizeof(IndexedModeActions[1][0])*4 &&
- IdxMode < array_lengthof(IndexedModeActions[1]) &&
+ assert((unsigned)VT.getSimpleVT() < MVT::LAST_VALUETYPE &&
+ IdxMode < array_lengthof(IndexedModeActions[0][1] ) &&
"Table isn't big enough!");
- IndexedModeActions[1][IdxMode] &= ~(uint64_t(3UL) << VT.getSimpleVT()*2);
- IndexedModeActions[1][IdxMode] |= (uint64_t)Action << VT.getSimpleVT()*2;
+ IndexedModeActions[(unsigned)VT.getSimpleVT()][1][IdxMode] = (uint8_t)Action;
}
/// setConvertAction - Indicate that the specified conversion does or does
assert(0 && "Not Implemented");
return NULL; // this is here to silence compiler errors
}
+
//===--------------------------------------------------------------------===//
// Lowering methods - These methods must be implemented by targets so that
// the SelectionDAGLowering code knows how to lower these.
//
- /// LowerArguments - This hook must be implemented to indicate how we should
- /// lower the arguments for the specified function, into the specified DAG.
- virtual void
- LowerArguments(Function &F, SelectionDAG &DAG,
- SmallVectorImpl<SDValue>& ArgValues, DebugLoc dl);
+ /// LowerFormalArguments - This hook must be implemented to lower the
+ /// incoming (formal) arguments, described by the Ins array, into the
+ /// specified DAG. The implementation should fill in the InVals array
+ /// with legal-type argument values, and return the resulting token
+ /// chain value.
+ ///
+ virtual SDValue
+ LowerFormalArguments(SDValue Chain,
+ unsigned CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
+ assert(0 && "Not Implemented");
+ return SDValue(); // this is here to silence compiler errors
+ }
- /// LowerCallTo - This hook lowers an abstract call to a function into an
+ /// LowerCallTo - This function lowers an abstract call to a function into an
/// actual call. This returns a pair of operands. The first element is the
/// return value for the function (if RetTy is not VoidTy). The second
- /// element is the outgoing token chain.
+ /// element is the outgoing token chain. It calls LowerCall to do the actual
+ /// lowering.
struct ArgListEntry {
SDValue Node;
const Type* Ty;
isSRet(false), isNest(false), isByVal(false), Alignment(0) { }
};
typedef std::vector<ArgListEntry> ArgListTy;
- virtual std::pair<SDValue, SDValue>
+ std::pair<SDValue, SDValue>
LowerCallTo(SDValue Chain, const Type *RetTy, bool RetSExt, bool RetZExt,
- bool isVarArg, bool isInreg, unsigned CallingConv,
- bool isTailCall, SDValue Callee, ArgListTy &Args,
- SelectionDAG &DAG, DebugLoc dl);
+ bool isVarArg, bool isInreg, unsigned NumFixedArgs,
+ unsigned CallConv, bool isTailCall, bool isReturnValueUsed,
+ SDValue Callee, ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl);
+
+ /// LowerCall - This hook must be implemented to lower calls into the
+ /// the specified DAG. The outgoing arguments to the call are described
+ /// by the Outs array, and the values to be returned by the call are
+ /// described by the Ins array. The implementation should fill in the
+ /// InVals array with legal-type return values from the call, and return
+ /// the resulting token chain value.
+ ///
+ /// The isTailCall flag here is normative. If it is true, the
+ /// implementation must emit a tail call. The
+ /// IsEligibleForTailCallOptimization hook should be used to catch
+ /// cases that cannot be handled.
+ ///
+ virtual SDValue
+ LowerCall(SDValue Chain, SDValue Callee,
+ unsigned CallConv, bool isVarArg, bool isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
+ assert(0 && "Not Implemented");
+ return SDValue(); // this is here to silence compiler errors
+ }
+
+ /// LowerReturn - This hook must be implemented to lower outgoing
+ /// return values, described by the Outs array, into the specified
+ /// DAG. The implementation should return the resulting token chain
+ /// value.
+ ///
+ virtual SDValue
+ LowerReturn(SDValue Chain, unsigned CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) {
+ assert(0 && "Not Implemented");
+ return SDValue(); // this is here to silence compiler errors
+ }
/// EmitTargetCodeForMemcpy - Emit target-specific code that performs a
/// memcpy. This can be used by targets to provide code sequences for cases
/// IsEligibleForTailCallOptimization - Check whether the call is eligible for
/// tail call optimization. Targets which want to do tail call optimization
- /// should override this function.
- virtual bool IsEligibleForTailCallOptimization(CallSDNode *Call,
- SDValue Ret,
- SelectionDAG &DAG) const {
+ /// should override this function.
+ virtual bool
+ IsEligibleForTailCallOptimization(SDValue Callee,
+ unsigned CalleeCC,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ SelectionDAG& DAG) const {
+ // Conservative default: no calls are eligible.
return false;
}
- /// CheckTailCallReturnConstraints - Check whether CALL node immediatly
- /// preceeds the RET node and whether the return uses the result of the node
- /// or is a void return. This function can be used by the target to determine
- /// eligiblity of tail call optimization.
- static bool CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret);
-
/// GetPossiblePreceedingTailCall - Get preceeding TailCallNodeOpCode node if
/// it exists. Skip a possible ISD::TokenFactor.
static SDValue GetPossiblePreceedingTailCall(SDValue Chain,
// Inline Asm Support hooks
//
+ /// ExpandInlineAsm - This hook allows the target to expand an inline asm
+ /// call to be explicit llvm code if it wants to. This is useful for
+ /// turning simple inline asms into LLVM intrinsics, which gives the
+ /// compiler more information about the behavior of the code.
+ virtual bool ExpandInlineAsm(CallInst *CI) const {
+ return false;
+ }
+
enum ConstraintType {
C_Register, // Constraint represents specific register(s).
C_RegisterClass, // Constraint represents any of register(s) in class.
/// isLegalAddressingMode - Return true if the addressing mode represented by
/// AM is legal for this target, for a load/store of the specified type.
+ /// The type may be VoidTy, in which case only return true if the addressing
+ /// mode is legal for a load/store of any legal type.
/// TODO: Handle pre/postinc as well.
virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const;
return false;
}
+ /// isNarrowingProfitable - Return true if it's profitable to narrow
+ /// operations of type VT1 to VT2. e.g. on x86, it's profitable to narrow
+ /// from i32 to i8 but not from i32 to i16.
+ virtual bool isNarrowingProfitable(MVT VT1, MVT VT2) const {
+ return false;
+ }
+
//===--------------------------------------------------------------------===//
// Div utility functions
//
private:
TargetMachine &TM;
const TargetData *TD;
+ TargetLoweringObjectFile &TLOF;
/// PointerTy - The type to use for pointers, usually i32 or i64.
///
- MVT PointerTy;
+ MVT::SimpleValueType PointerTy;
/// IsLittleEndian - True if this is a little endian target.
///
/// ShiftAmountTy - The type to use for shift amounts, usually i8 or whatever
/// PointerTy is.
- MVT ShiftAmountTy;
-
- OutOfRangeShiftAmount ShiftAmtHandling;
+ MVT::SimpleValueType ShiftAmountTy;
/// BooleanContents - Information about the contents of the high-bits in
/// boolean values held in a type wider than i1. See getBooleanContents.
/// Most operations are Legal (aka, supported natively by the target), but
/// operations that are not should be described. Note that operations on
/// non-legal value types are not described here.
- uint64_t OpActions[ISD::BUILTIN_OP_END];
+ /// This array is accessed using VT.getSimpleVT(), so it is subject to
+ /// the MVT::MAX_ALLOWED_VALUETYPE * 2 bits.
+ uint64_t OpActions[MVT::MAX_ALLOWED_VALUETYPE/(sizeof(uint64_t)*4)][ISD::BUILTIN_OP_END];
/// LoadExtActions - For each load of load extension type and each value type,
/// keep a LegalizeAction that indicates how instruction selection should deal
/// indicates how instruction selection should deal with the store.
uint64_t TruncStoreActions[MVT::LAST_VALUETYPE];
- /// IndexedModeActions - For each indexed mode and each value type, keep a
- /// pair of LegalizeAction that indicates how instruction selection should
- /// deal with the load / store.
- uint64_t IndexedModeActions[2][ISD::LAST_INDEXED_MODE];
+ /// IndexedModeActions - For each indexed mode and each value type,
+ /// keep a pair of LegalizeAction that indicates how instruction
+ /// selection should deal with the load / store. The first
+ /// dimension is now the value_type for the reference. The second
+ /// dimension is the load [0] vs. store[1]. The third dimension
+ /// represents the various modes for load store.
+ uint8_t IndexedModeActions[MVT::LAST_VALUETYPE][2][ISD::LAST_INDEXED_MODE];
/// ConvertActions - For each conversion from source type to destination type,
/// keep a LegalizeAction that indicates how instruction selection should
/// operations when copying small arrays and other similar tasks.
/// @brief Indicate whether the target permits unaligned memory accesses.
bool allowUnalignedMemoryAccesses;
+
+ /// This field specifies whether the target can benefit from code placement
+ /// optimization.
+ bool benefitFromCodePlacementOpt;
};
} // end llvm namespace