blob: dbd9b391f4a431fc3eadc410114aec273894aea1 [file] [log] [blame]
//===-- llvm/CodeGen/SelectionDAGISel.h - Common Base Class------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the SelectionDAGISel class, which is used as the common
// base class for SelectionDAG-based instruction selectors.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_SELECTIONDAGISEL_H
#define LLVM_CODEGEN_SELECTIONDAGISEL_H
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/IR/BasicBlock.h"
#include <memory>
namespace llvm {
class AAResults;
class AssumptionCache;
class TargetInstrInfo;
class TargetMachine;
class SelectionDAGBuilder;
class SDValue;
class MachineRegisterInfo;
class MachineFunction;
class OptimizationRemarkEmitter;
class TargetLowering;
class TargetLibraryInfo;
class FunctionLoweringInfo;
class SwiftErrorValueTracking;
class GCFunctionInfo;
class ScheduleDAGSDNodes;
/// SelectionDAGISel - This is the common base class used for SelectionDAG-based
/// pattern-matching instruction selectors.
class SelectionDAGISel : public MachineFunctionPass {
public:
TargetMachine &TM;
const TargetLibraryInfo *LibInfo;
std::unique_ptr<FunctionLoweringInfo> FuncInfo;
SwiftErrorValueTracking *SwiftError;
MachineFunction *MF;
MachineRegisterInfo *RegInfo;
SelectionDAG *CurDAG;
std::unique_ptr<SelectionDAGBuilder> SDB;
AAResults *AA = nullptr;
AssumptionCache *AC = nullptr;
GCFunctionInfo *GFI = nullptr;
CodeGenOptLevel OptLevel;
const TargetInstrInfo *TII;
const TargetLowering *TLI;
bool FastISelFailed;
SmallPtrSet<const Instruction *, 4> ElidedArgCopyInstrs;
/// Current optimization remark emitter.
/// Used to report things like combines and FastISel failures.
std::unique_ptr<OptimizationRemarkEmitter> ORE;
/// True if the function currently processing is in the function printing list
/// (i.e. `-filter-print-funcs`).
/// This is primarily used by ISEL_DUMP, which spans in multiple member
/// functions. Storing the filter result here so that we only need to do the
/// filtering once.
bool MatchFilterFuncName = false;
explicit SelectionDAGISel(char &ID, TargetMachine &tm,
CodeGenOptLevel OL = CodeGenOptLevel::Default);
~SelectionDAGISel() override;
const TargetLowering *getTargetLowering() const { return TLI; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnMachineFunction(MachineFunction &MF) override;
virtual void emitFunctionEntryCode() {}
/// PreprocessISelDAG - This hook allows targets to hack on the graph before
/// instruction selection starts.
virtual void PreprocessISelDAG() {}
/// PostprocessISelDAG() - This hook allows the target to hack on the graph
/// right after selection.
virtual void PostprocessISelDAG() {}
/// Main hook for targets to transform nodes into machine nodes.
virtual void Select(SDNode *N) = 0;
/// SelectInlineAsmMemoryOperand - Select the specified address as a target
/// addressing mode, according to the specified constraint. If this does
/// not match or is not implemented, return true. The resultant operands
/// (which will appear in the machine instruction) should be added to the
/// OutOps vector.
virtual bool
SelectInlineAsmMemoryOperand(const SDValue &Op,
InlineAsm::ConstraintCode ConstraintID,
std::vector<SDValue> &OutOps) {
return true;
}
/// IsProfitableToFold - Returns true if it's profitable to fold the specific
/// operand node N of U during instruction selection that starts at Root.
virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const;
/// IsLegalToFold - Returns true if the specific operand node N of
/// U can be folded during instruction selection that starts at Root.
/// FIXME: This is a static member function because the MSP430/X86
/// targets, which uses it during isel. This could become a proper member.
static bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root,
CodeGenOptLevel OptLevel,
bool IgnoreChains = false);
static void InvalidateNodeId(SDNode *N);
static int getUninvalidatedNodeId(SDNode *N);
static void EnforceNodeIdInvariant(SDNode *N);
// Opcodes used by the DAG state machine:
enum BuiltinOpcodes {
OPC_Scope,
OPC_RecordNode,
OPC_RecordChild0,
OPC_RecordChild1,
OPC_RecordChild2,
OPC_RecordChild3,
OPC_RecordChild4,
OPC_RecordChild5,
OPC_RecordChild6,
OPC_RecordChild7,
OPC_RecordMemRef,
OPC_CaptureGlueInput,
OPC_MoveChild,
OPC_MoveChild0,
OPC_MoveChild1,
OPC_MoveChild2,
OPC_MoveChild3,
OPC_MoveChild4,
OPC_MoveChild5,
OPC_MoveChild6,
OPC_MoveChild7,
OPC_MoveSibling,
OPC_MoveSibling0,
OPC_MoveSibling1,
OPC_MoveSibling2,
OPC_MoveSibling3,
OPC_MoveSibling4,
OPC_MoveSibling5,
OPC_MoveSibling6,
OPC_MoveSibling7,
OPC_MoveParent,
OPC_CheckSame,
OPC_CheckChild0Same,
OPC_CheckChild1Same,
OPC_CheckChild2Same,
OPC_CheckChild3Same,
OPC_CheckPatternPredicate,
OPC_CheckPatternPredicate0,
OPC_CheckPatternPredicate1,
OPC_CheckPatternPredicate2,
OPC_CheckPatternPredicate3,
OPC_CheckPatternPredicate4,
OPC_CheckPatternPredicate5,
OPC_CheckPatternPredicate6,
OPC_CheckPatternPredicate7,
OPC_CheckPatternPredicateTwoByte,
OPC_CheckPredicate,
OPC_CheckPredicate0,
OPC_CheckPredicate1,
OPC_CheckPredicate2,
OPC_CheckPredicate3,
OPC_CheckPredicate4,
OPC_CheckPredicate5,
OPC_CheckPredicate6,
OPC_CheckPredicate7,
OPC_CheckPredicateWithOperands,
OPC_CheckOpcode,
OPC_SwitchOpcode,
OPC_CheckType,
// Space-optimized forms that implicitly encode VT.
OPC_CheckTypeI32,
OPC_CheckTypeI64,
OPC_CheckTypeRes,
OPC_SwitchType,
OPC_CheckChild0Type,
OPC_CheckChild1Type,
OPC_CheckChild2Type,
OPC_CheckChild3Type,
OPC_CheckChild4Type,
OPC_CheckChild5Type,
OPC_CheckChild6Type,
OPC_CheckChild7Type,
OPC_CheckChild0TypeI32,
OPC_CheckChild1TypeI32,
OPC_CheckChild2TypeI32,
OPC_CheckChild3TypeI32,
OPC_CheckChild4TypeI32,
OPC_CheckChild5TypeI32,
OPC_CheckChild6TypeI32,
OPC_CheckChild7TypeI32,
OPC_CheckChild0TypeI64,
OPC_CheckChild1TypeI64,
OPC_CheckChild2TypeI64,
OPC_CheckChild3TypeI64,
OPC_CheckChild4TypeI64,
OPC_CheckChild5TypeI64,
OPC_CheckChild6TypeI64,
OPC_CheckChild7TypeI64,
OPC_CheckInteger,
OPC_CheckChild0Integer,
OPC_CheckChild1Integer,
OPC_CheckChild2Integer,
OPC_CheckChild3Integer,
OPC_CheckChild4Integer,
OPC_CheckCondCode,
OPC_CheckChild2CondCode,
OPC_CheckValueType,
OPC_CheckComplexPat,
OPC_CheckComplexPat0,
OPC_CheckComplexPat1,
OPC_CheckComplexPat2,
OPC_CheckComplexPat3,
OPC_CheckComplexPat4,
OPC_CheckComplexPat5,
OPC_CheckComplexPat6,
OPC_CheckComplexPat7,
OPC_CheckAndImm,
OPC_CheckOrImm,
OPC_CheckImmAllOnesV,
OPC_CheckImmAllZerosV,
OPC_CheckFoldableChainNode,
OPC_EmitInteger,
// Space-optimized forms that implicitly encode integer VT.
OPC_EmitInteger8,
OPC_EmitInteger16,
OPC_EmitInteger32,
OPC_EmitInteger64,
OPC_EmitStringInteger,
// Space-optimized forms that implicitly encode integer VT.
OPC_EmitStringInteger32,
OPC_EmitRegister,
OPC_EmitRegisterI32,
OPC_EmitRegisterI64,
OPC_EmitRegister2,
OPC_EmitConvertToTarget,
OPC_EmitConvertToTarget0,
OPC_EmitConvertToTarget1,
OPC_EmitConvertToTarget2,
OPC_EmitConvertToTarget3,
OPC_EmitConvertToTarget4,
OPC_EmitConvertToTarget5,
OPC_EmitConvertToTarget6,
OPC_EmitConvertToTarget7,
OPC_EmitMergeInputChains,
OPC_EmitMergeInputChains1_0,
OPC_EmitMergeInputChains1_1,
OPC_EmitMergeInputChains1_2,
OPC_EmitCopyToReg,
OPC_EmitCopyToReg0,
OPC_EmitCopyToReg1,
OPC_EmitCopyToReg2,
OPC_EmitCopyToReg3,
OPC_EmitCopyToReg4,
OPC_EmitCopyToReg5,
OPC_EmitCopyToReg6,
OPC_EmitCopyToReg7,
OPC_EmitCopyToRegTwoByte,
OPC_EmitNodeXForm,
OPC_EmitNode,
// Space-optimized forms that implicitly encode number of result VTs.
OPC_EmitNode0,
OPC_EmitNode1,
OPC_EmitNode2,
// Space-optimized forms that implicitly encode EmitNodeInfo.
OPC_EmitNode0None,
OPC_EmitNode1None,
OPC_EmitNode2None,
OPC_EmitNode0Chain,
OPC_EmitNode1Chain,
OPC_EmitNode2Chain,
OPC_MorphNodeTo,
// Space-optimized forms that implicitly encode number of result VTs.
OPC_MorphNodeTo0,
OPC_MorphNodeTo1,
OPC_MorphNodeTo2,
// Space-optimized forms that implicitly encode EmitNodeInfo.
OPC_MorphNodeTo0None,
OPC_MorphNodeTo1None,
OPC_MorphNodeTo2None,
OPC_MorphNodeTo0Chain,
OPC_MorphNodeTo1Chain,
OPC_MorphNodeTo2Chain,
OPC_MorphNodeTo0GlueInput,
OPC_MorphNodeTo1GlueInput,
OPC_MorphNodeTo2GlueInput,
OPC_MorphNodeTo0GlueOutput,
OPC_MorphNodeTo1GlueOutput,
OPC_MorphNodeTo2GlueOutput,
OPC_CompleteMatch,
// Contains offset in table for pattern being selected
OPC_Coverage
};
enum {
OPFL_None = 0, // Node has no chain or glue input and isn't variadic.
OPFL_Chain = 1, // Node has a chain input.
OPFL_GlueInput = 2, // Node has a glue input.
OPFL_GlueOutput = 4, // Node has a glue output.
OPFL_MemRefs = 8, // Node gets accumulated MemRefs.
OPFL_Variadic0 = 1<<4, // Node is variadic, root has 0 fixed inputs.
OPFL_Variadic1 = 2<<4, // Node is variadic, root has 1 fixed inputs.
OPFL_Variadic2 = 3<<4, // Node is variadic, root has 2 fixed inputs.
OPFL_Variadic3 = 4<<4, // Node is variadic, root has 3 fixed inputs.
OPFL_Variadic4 = 5<<4, // Node is variadic, root has 4 fixed inputs.
OPFL_Variadic5 = 6<<4, // Node is variadic, root has 5 fixed inputs.
OPFL_Variadic6 = 7<<4, // Node is variadic, root has 6 fixed inputs.
OPFL_VariadicInfo = OPFL_Variadic6
};
/// getNumFixedFromVariadicInfo - Transform an EmitNode flags word into the
/// number of fixed arity values that should be skipped when copying from the
/// root.
static inline int getNumFixedFromVariadicInfo(unsigned Flags) {
return ((Flags&OPFL_VariadicInfo) >> 4)-1;
}
protected:
/// DAGSize - Size of DAG being instruction selected.
///
unsigned DAGSize = 0;
/// ReplaceUses - replace all uses of the old node F with the use
/// of the new node T.
void ReplaceUses(SDValue F, SDValue T) {
CurDAG->ReplaceAllUsesOfValueWith(F, T);
EnforceNodeIdInvariant(T.getNode());
}
/// ReplaceUses - replace all uses of the old nodes F with the use
/// of the new nodes T.
void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) {
CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num);
for (unsigned i = 0; i < Num; ++i)
EnforceNodeIdInvariant(T[i].getNode());
}
/// ReplaceUses - replace all uses of the old node F with the use
/// of the new node T.
void ReplaceUses(SDNode *F, SDNode *T) {
CurDAG->ReplaceAllUsesWith(F, T);
EnforceNodeIdInvariant(T);
}
/// Replace all uses of \c F with \c T, then remove \c F from the DAG.
void ReplaceNode(SDNode *F, SDNode *T) {
CurDAG->ReplaceAllUsesWith(F, T);
EnforceNodeIdInvariant(T);
CurDAG->RemoveDeadNode(F);
}
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
/// by tblgen. Others should not call it.
void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
const SDLoc &DL);
/// getPatternForIndex - Patterns selected by tablegen during ISEL
virtual StringRef getPatternForIndex(unsigned index) {
llvm_unreachable("Tblgen should generate the implementation of this!");
}
/// getIncludePathForIndex - get the td source location of pattern instantiation
virtual StringRef getIncludePathForIndex(unsigned index) {
llvm_unreachable("Tblgen should generate the implementation of this!");
}
bool shouldOptForSize(const MachineFunction *MF) const {
return CurDAG->shouldOptForSize();
}
public:
// Calls to these predicates are generated by tblgen.
bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS,
int64_t DesiredMaskS) const;
bool CheckOrMask(SDValue LHS, ConstantSDNode *RHS,
int64_t DesiredMaskS) const;
/// CheckPatternPredicate - This function is generated by tblgen in the
/// target. It runs the specified pattern predicate and returns true if it
/// succeeds or false if it fails. The number is a private implementation
/// detail to the code tblgen produces.
virtual bool CheckPatternPredicate(unsigned PredNo) const {
llvm_unreachable("Tblgen should generate the implementation of this!");
}
/// CheckNodePredicate - This function is generated by tblgen in the target.
/// It runs node predicate number PredNo and returns true if it succeeds or
/// false if it fails. The number is a private implementation
/// detail to the code tblgen produces.
virtual bool CheckNodePredicate(SDNode *N, unsigned PredNo) const {
llvm_unreachable("Tblgen should generate the implementation of this!");
}
/// CheckNodePredicateWithOperands - This function is generated by tblgen in
/// the target.
/// It runs node predicate number PredNo and returns true if it succeeds or
/// false if it fails. The number is a private implementation detail to the
/// code tblgen produces.
virtual bool CheckNodePredicateWithOperands(
SDNode *N, unsigned PredNo,
const SmallVectorImpl<SDValue> &Operands) const {
llvm_unreachable("Tblgen should generate the implementation of this!");
}
virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N,
unsigned PatternNo,
SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {
llvm_unreachable("Tblgen should generate the implementation of this!");
}
virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {
llvm_unreachable("Tblgen should generate this!");
}
void SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
unsigned TableSize);
/// Return true if complex patterns for this target can mutate the
/// DAG.
virtual bool ComplexPatternFuncMutatesDAG() const {
return false;
}
/// Return whether the node may raise an FP exception.
bool mayRaiseFPException(SDNode *Node) const;
bool isOrEquivalentToAdd(const SDNode *N) const;
private:
// Calls to these functions are generated by tblgen.
void Select_INLINEASM(SDNode *N);
void Select_READ_REGISTER(SDNode *Op);
void Select_WRITE_REGISTER(SDNode *Op);
void Select_UNDEF(SDNode *N);
void CannotYetSelect(SDNode *N);
void Select_FREEZE(SDNode *N);
void Select_ARITH_FENCE(SDNode *N);
void Select_MEMBARRIER(SDNode *N);
void pushStackMapLiveVariable(SmallVectorImpl<SDValue> &Ops, SDValue Operand,
SDLoc DL);
void Select_STACKMAP(SDNode *N);
void Select_PATCHPOINT(SDNode *N);
void Select_JUMP_TABLE_DEBUG_INFO(SDNode *N);
private:
void DoInstructionSelection();
SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList,
ArrayRef<SDValue> Ops, unsigned EmitNodeInfo);
/// Prepares the landing pad to take incoming values or do other EH
/// personality specific tasks. Returns true if the block should be
/// instruction selected, false if no code should be emitted for it.
bool PrepareEHLandingPad();
// Mark and Report IPToState for each Block under AsynchEH
void reportIPToStateForBlocks(MachineFunction *Fn);
/// Perform instruction selection on all basic blocks in the function.
void SelectAllBasicBlocks(const Function &Fn);
/// Perform instruction selection on a single basic block, for
/// instructions between \p Begin and \p End. \p HadTailCall will be set
/// to true if a call in the block was translated as a tail call.
void SelectBasicBlock(BasicBlock::const_iterator Begin,
BasicBlock::const_iterator End,
bool &HadTailCall);
void FinishBasicBlock();
void CodeGenAndEmitDAG();
/// Generate instructions for lowering the incoming arguments of the
/// given function.
void LowerArguments(const Function &F);
void ComputeLiveOutVRegInfo();
/// Create the scheduler. If a specific scheduler was specified
/// via the SchedulerRegistry, use it, otherwise select the
/// one preferred by the target.
///
ScheduleDAGSDNodes *CreateScheduler();
/// OpcodeOffset - This is a cache used to dispatch efficiently into isel
/// state machines that start with a OPC_SwitchOpcode node.
std::vector<unsigned> OpcodeOffset;
void UpdateChains(SDNode *NodeToMatch, SDValue InputChain,
SmallVectorImpl<SDNode *> &ChainNodesMatched,
bool isMorphNodeTo);
};
}
#endif /* LLVM_CODEGEN_SELECTIONDAGISEL_H */