mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-30 02:32:08 +00:00
d0fde30ce8
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9903 91177308-0d34-0410-b5e6-96231b3b80d8
371 lines
13 KiB
C++
371 lines
13 KiB
C++
//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG Rep. ----*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file declares the SelectionDAG class, which is used to represent an LLVM
|
|
// function in a low-level representation suitable for instruction selection.
|
|
// This DAG is constructed as the first step of instruction selection in order
|
|
// to allow implementation of machine specific optimizations and code
|
|
// simplifications.
|
|
//
|
|
// The representation used by the SelectionDAG is a target-independent
|
|
// representation, which is loosly modeled after the GCC RTL representation, but
|
|
// is significantly simpler.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_SELECTIONDAG_H
|
|
#define LLVM_CODEGEN_SELECTIONDAG_H
|
|
|
|
#include "llvm/CodeGen/ValueTypes.h"
|
|
#include "Support/DataTypes.h"
|
|
#include <map>
|
|
#include <vector>
|
|
#include <cassert>
|
|
|
|
namespace llvm {
|
|
|
|
class Value;
|
|
class Type;
|
|
class Instruction;
|
|
class CallInst;
|
|
class BasicBlock;
|
|
class MachineBasicBlock;
|
|
class MachineFunction;
|
|
class TargetMachine;
|
|
class SelectionDAGNode;
|
|
class SelectionDAGBlock;
|
|
class SelectionDAGBuilder;
|
|
class SelectionDAGTargetBuilder;
|
|
|
|
/// ISD namespace - This namespace contains an enum which represents all of the
|
|
/// SelectionDAG node types and value types.
|
|
///
|
|
namespace ISD {
|
|
enum NodeType {
|
|
// ChainNode nodes are used to sequence operations within a basic block
|
|
// which cannot be reordered (such as loads, stores, calls, etc).
|
|
// BlockChainNodes are used to connect the DAG's for different basic blocks
|
|
// into one big DAG.
|
|
ChainNode, BlockChainNode,
|
|
|
|
// ProtoNodes are nodes that are only half way constructed.
|
|
ProtoNode,
|
|
|
|
// Leaf nodes
|
|
Constant, FrameIndex, BasicBlock,
|
|
|
|
// Simple binary arithmetic operators
|
|
Plus, Minus, Times, SDiv, UDiv, SRem, URem,
|
|
|
|
// Bitwise operators
|
|
And, Or, Xor,
|
|
|
|
// Comparisons
|
|
SetEQ, SetNE, SetLT, SetLE, SetGT, SetGE,
|
|
|
|
// Control flow instructions
|
|
Br, BrCond, Switch, Ret, RetVoid,
|
|
|
|
// Other operators
|
|
Load, Store, PHI, Call,
|
|
|
|
// Unknown operators, of a specified arity
|
|
Unspec1, Unspec2
|
|
};
|
|
}
|
|
|
|
class SelectionDAG {
|
|
friend class SelectionDAGBuilder;
|
|
MachineFunction &F;
|
|
const TargetMachine &TM;
|
|
MVT::ValueType PointerType; // The ValueType the target uses for pointers
|
|
|
|
// ValueMap - The SelectionDAGNode for each LLVM value in the function.
|
|
std::map<const Value*, SelectionDAGNode*> ValueMap;
|
|
|
|
// BlockMap - The MachineBasicBlock created for each LLVM BasicBlock
|
|
std::map<const BasicBlock*, MachineBasicBlock*> BlockMap;
|
|
|
|
// Root - The root of the entire DAG
|
|
SelectionDAGNode *Root;
|
|
|
|
// AllNodes - All of the nodes in the DAG
|
|
std::vector<SelectionDAGNode*> AllNodes;
|
|
public:
|
|
/// SelectionDAG constructor - Build a SelectionDAG for the specified
|
|
/// function. Implemented in DAGBuilder.cpp
|
|
///
|
|
SelectionDAG(MachineFunction &F, const TargetMachine &TM,
|
|
SelectionDAGTargetBuilder &SDTB);
|
|
~SelectionDAG();
|
|
|
|
/// getValueType - Return the ValueType for the specified LLVM type. This
|
|
/// method works on all scalar LLVM types.
|
|
///
|
|
MVT::ValueType getValueType(const Type *Ty) const;
|
|
|
|
/// getRoot - Return the root of the current SelectionDAG.
|
|
///
|
|
SelectionDAGNode *getRoot() const { return Root; }
|
|
|
|
/// getMachineFunction - Return the MachineFunction object that this
|
|
/// SelectionDAG corresponds to.
|
|
///
|
|
MachineFunction &getMachineFunction() const { return F; }
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Addition and updating methods
|
|
//
|
|
|
|
/// addNode - Add the specified node to the SelectionDAG so that it will be
|
|
/// deleted when the DAG is...
|
|
///
|
|
SelectionDAGNode *addNode(SelectionDAGNode *N) {
|
|
AllNodes.push_back(N);
|
|
return N;
|
|
}
|
|
|
|
/// addNodeForValue - Add the specified node to the SelectionDAG so that it
|
|
/// will be deleted when the DAG is... and update the value map to indicate
|
|
/// that the specified DAG node computes the value. Note that it is an error
|
|
/// to specify multiple DAG nodes that compute the same value.
|
|
///
|
|
SelectionDAGNode *addNodeForValue(SelectionDAGNode *N, const Value *V) {
|
|
assert(ValueMap.count(V) == 0 && "Value already has a DAG node!");
|
|
return addNode(ValueMap[V] = N);
|
|
}
|
|
|
|
void dump() const;
|
|
private:
|
|
void addInstructionToDAG(const Instruction &I, const BasicBlock &BB);
|
|
};
|
|
|
|
|
|
/// SelectionDAGReducedValue - During the reducer pass we need the ability to
|
|
/// add an arbitrary (but usually 1 or 0) number of arbitrarily sized values to
|
|
/// the selection DAG. Because of this, we represent these values as a singly
|
|
/// linked list of values attached to the DAGNode. We end up putting the
|
|
/// arbitrary state for the value in subclasses of this node.
|
|
///
|
|
/// Note that this class does not have a virtual dtor, this is because we know
|
|
/// that the subclasses will not hold state that needs to be destroyed.
|
|
///
|
|
class SelectionDAGReducedValue {
|
|
unsigned Code;
|
|
SelectionDAGReducedValue *Next;
|
|
public:
|
|
SelectionDAGReducedValue(unsigned C) : Code(C), Next(0) {}
|
|
|
|
/// getValueCode - Return the code for this reducer value...
|
|
///
|
|
unsigned getValueCode() const { return Code; }
|
|
|
|
/// getNext - Return the next value in the list
|
|
///
|
|
const SelectionDAGReducedValue *getNext() const { return Next; }
|
|
void setNext(SelectionDAGReducedValue *N) { Next = N; }
|
|
|
|
SelectionDAGReducedValue *getNext() { return Next; }
|
|
};
|
|
|
|
|
|
|
|
/// SelectionDAGNode - Represents one node in the selection DAG.
|
|
///
|
|
class SelectionDAGNode {
|
|
std::vector<SelectionDAGNode*> Uses;
|
|
ISD::NodeType NodeType;
|
|
MVT::ValueType ValueType;
|
|
MachineBasicBlock *BB;
|
|
SelectionDAGReducedValue *ValList;
|
|
|
|
/// Costs - Each pair of elements of 'Costs' contains the cost of producing
|
|
/// the value with the target specific slot number and the production number
|
|
/// to use to produce it. A zero value for the production number indicates
|
|
/// that the cost has not yet been computed.
|
|
unsigned *Costs;
|
|
public:
|
|
SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT,
|
|
MachineBasicBlock *bb = 0)
|
|
: NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) {}
|
|
|
|
SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb,
|
|
SelectionDAGNode *N)
|
|
: NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) {
|
|
assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!");
|
|
Uses.reserve(1); Uses.push_back(N);
|
|
}
|
|
SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb,
|
|
SelectionDAGNode *N1, SelectionDAGNode *N2)
|
|
: NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) {
|
|
assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!");
|
|
Uses.reserve(2); Uses.push_back(N1); Uses.push_back(N2);
|
|
}
|
|
SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb,
|
|
SelectionDAGNode *N1, SelectionDAGNode *N2,
|
|
SelectionDAGNode *N3)
|
|
: NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) {
|
|
assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!");
|
|
Uses.reserve(3); Uses.push_back(N1); Uses.push_back(N2); Uses.push_back(N3);
|
|
}
|
|
|
|
~SelectionDAGNode() { delete [] Costs; delete ValList; }
|
|
|
|
void setNode(ISD::NodeType NT, MachineBasicBlock *bb) {
|
|
assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode);
|
|
NodeType = NT; BB = bb;
|
|
}
|
|
void setNode(ISD::NodeType NT, MachineBasicBlock *bb, SelectionDAGNode *N) {
|
|
assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode);
|
|
NodeType = NT; BB = bb; Uses.reserve(1); Uses.push_back(N);
|
|
}
|
|
void setNode(ISD::NodeType NT, MachineBasicBlock *bb,
|
|
SelectionDAGNode *N1, SelectionDAGNode *N2) {
|
|
assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode);
|
|
NodeType = NT; BB = bb;
|
|
Uses.reserve(1); Uses.push_back(N1); Uses.push_back(N2);
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Accessors
|
|
//
|
|
ISD::NodeType getNodeType() const { return NodeType; }
|
|
MVT::ValueType getValueType() const { return ValueType; }
|
|
MachineBasicBlock *getBB() const { return BB; }
|
|
|
|
SelectionDAGNode *getUse(unsigned Num) {
|
|
assert(Num < Uses.size() && "Invalid child # of SelectionDAGNode!");
|
|
return Uses[Num];
|
|
}
|
|
|
|
template<class Type>
|
|
Type *getValue(unsigned Code) const {
|
|
SelectionDAGReducedValue *Vals = ValList;
|
|
while (1) {
|
|
assert(Vals && "Code does not exist in this list!");
|
|
if (Vals->getValueCode() == Code)
|
|
return (Type*)Vals;
|
|
Vals = Vals->getNext();
|
|
}
|
|
}
|
|
|
|
template<class Type>
|
|
Type *hasValue(unsigned Code) const {
|
|
SelectionDAGReducedValue *Vals = ValList;
|
|
while (Vals) {
|
|
if (Vals->getValueCode() == Code)
|
|
return (Type*)Vals;
|
|
Vals = Vals->getNext();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void addValue(SelectionDAGReducedValue *New) {
|
|
assert(New->getNext() == 0);
|
|
New->setNext(ValList);
|
|
ValList = New;
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Utility methods used by the pattern matching instruction selector
|
|
//
|
|
|
|
/// getPatternFor - Return the pattern selected to compute the specified slot,
|
|
/// or zero if there is no pattern yet.
|
|
///
|
|
unsigned getPatternFor(unsigned Slot) const {
|
|
return Costs ? Costs[Slot*2] : 0;
|
|
}
|
|
|
|
/// getCostFor - Return the cost to compute the value corresponding to Slot.
|
|
///
|
|
unsigned getCostFor(unsigned Slot) const {
|
|
return Costs ? Costs[Slot*2+1] : 0;
|
|
}
|
|
|
|
/// setPatternCostFor - Sets the pattern and the cost for the specified slot
|
|
/// to the specified values. This allocates the Costs vector if necessary, so
|
|
/// you must specify the maximum number of slots that may be used.
|
|
///
|
|
void setPatternCostFor(unsigned Slot, unsigned Pattern, unsigned Cost,
|
|
unsigned NumSlots) {
|
|
if (Costs == 0) {
|
|
Costs = new unsigned[NumSlots*2];
|
|
for (unsigned i = 0; i != NumSlots*2; ++i) Costs[i] = 0;
|
|
}
|
|
Costs[Slot*2] = Pattern;
|
|
Costs[Slot*2+1] = Cost;
|
|
}
|
|
|
|
void dump() const;
|
|
private:
|
|
void printit(unsigned Offset, unsigned &LastID,
|
|
std::map<const SelectionDAGNode*, unsigned> &NodeIDs) const;
|
|
};
|
|
|
|
|
|
/// SelectionDAGTargetBuilder - This class must be implemented by the target, to
|
|
/// indicate how to perform the extremely target-specific tasks of building DAG
|
|
/// nodes to represent the calling convention used by the target.
|
|
///
|
|
struct SelectionDAGTargetBuilder {
|
|
/// expandArguments - This method is called once by the SelectionDAG
|
|
/// construction mechanisms to add DAG nodes for each formal argument to the
|
|
/// current function. If any of the incoming arguments lives on the stack,
|
|
/// this method should also create the stack slots for the arguments as
|
|
/// necessary.
|
|
virtual void expandArguments(SelectionDAG &SD) = 0;
|
|
|
|
/// expandCall - This method is called once per function call by the
|
|
/// SelectionDAG construction algorithm. It must add DAG nodes to the
|
|
/// SelectionDAG specified to perform that call.
|
|
virtual void expandCall(SelectionDAG &SD, CallInst &CI) = 0;
|
|
};
|
|
|
|
namespace ISD {
|
|
enum { // Builtin Slot numbers
|
|
Constant_i1_Slot,
|
|
Constant_i8_Slot,
|
|
Constant_i16_Slot,
|
|
Constant_i32_Slot,
|
|
Constant_i64_Slot,
|
|
Constant_f32_Slot,
|
|
Constant_f64_Slot,
|
|
|
|
FrameIndex_i32_Slot,
|
|
FrameIndex_i64_Slot,
|
|
BasicBlock_i32_Slot,
|
|
BasicBlock_i64_Slot,
|
|
NumBuiltinSlots
|
|
};
|
|
}
|
|
|
|
template<typename ValType, unsigned NodeCode>
|
|
struct ReducedValue : public SelectionDAGReducedValue {
|
|
ReducedValue(const ValType &V) : SelectionDAGReducedValue(NodeCode), Val(V) {}
|
|
ValType Val;
|
|
};
|
|
|
|
typedef ReducedValue<int, ISD::FrameIndex_i32_Slot > ReducedValue_FrameIndex_i32;
|
|
typedef ReducedValue<int, ISD::FrameIndex_i64_Slot > ReducedValue_FrameIndex_i64;
|
|
typedef ReducedValue<MachineBasicBlock*, ISD::BasicBlock_i32_Slot > ReducedValue_BasicBlock_i32;
|
|
typedef ReducedValue<MachineBasicBlock*, ISD::BasicBlock_i64_Slot > ReducedValue_BasicBlock_i64;
|
|
|
|
typedef ReducedValue<bool , ISD::Constant_i1_Slot > ReducedValue_Constant_i1;
|
|
typedef ReducedValue<unsigned char , ISD::Constant_i8_Slot > ReducedValue_Constant_i8;
|
|
typedef ReducedValue<unsigned short, ISD::Constant_i16_Slot> ReducedValue_Constant_i16;
|
|
typedef ReducedValue<unsigned , ISD::Constant_i32_Slot> ReducedValue_Constant_i32;
|
|
typedef ReducedValue<uint64_t , ISD::Constant_i64_Slot> ReducedValue_Constant_i64;
|
|
typedef ReducedValue<float , ISD::Constant_f32_Slot> ReducedValue_Constant_f32;
|
|
typedef ReducedValue<double , ISD::Constant_f64_Slot> ReducedValue_Constant_f64;
|
|
|
|
} // End llvm namespace
|
|
|
|
#endif
|