SelectionDAGBuilder.h [plain text]
#ifndef SELECTIONDAGBUILDER_H
#define SELECTIONDAGBUILDER_H
#include "llvm/Constants.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#ifndef NDEBUG
#include "llvm/ADT/SmallSet.h"
#endif
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/ErrorHandling.h"
#include <vector>
#include <set>
namespace llvm {
class AliasAnalysis;
class AllocaInst;
class BasicBlock;
class BitCastInst;
class BranchInst;
class CallInst;
class DbgValueInst;
class ExtractElementInst;
class ExtractValueInst;
class FCmpInst;
class FPExtInst;
class FPToSIInst;
class FPToUIInst;
class FPTruncInst;
class Function;
class FunctionLoweringInfo;
class GetElementPtrInst;
class GCFunctionInfo;
class ICmpInst;
class IntToPtrInst;
class IndirectBrInst;
class InvokeInst;
class InsertElementInst;
class InsertValueInst;
class Instruction;
class LoadInst;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
class MachineRegisterInfo;
class MDNode;
class PHINode;
class PtrToIntInst;
class ReturnInst;
class SDISelAsmOperandInfo;
class SExtInst;
class SelectInst;
class ShuffleVectorInst;
class SIToFPInst;
class StoreInst;
class SwitchInst;
class TargetData;
class TargetLowering;
class TruncInst;
class UIToFPInst;
class UnreachableInst;
class UnwindInst;
class VAArgInst;
class ZExtInst;
class SelectionDAGBuilder {
MachineBasicBlock *CurMBB;
DebugLoc CurDebugLoc;
DenseMap<const Value*, SDValue> NodeMap;
DenseMap<const Value*, SDValue> UnusedArgNodeMap;
public:
SmallVector<SDValue, 8> PendingLoads;
private:
SmallVector<SDValue, 8> PendingExports;
unsigned SDNodeOrder;
struct Case {
Constant* Low;
Constant* High;
MachineBasicBlock* BB;
Case() : Low(0), High(0), BB(0) { }
Case(Constant* low, Constant* high, MachineBasicBlock* bb) :
Low(low), High(high), BB(bb) { }
APInt size() const {
const APInt &rHigh = cast<ConstantInt>(High)->getValue();
const APInt &rLow = cast<ConstantInt>(Low)->getValue();
return (rHigh - rLow + 1ULL);
}
};
struct CaseBits {
uint64_t Mask;
MachineBasicBlock* BB;
unsigned Bits;
CaseBits(uint64_t mask, MachineBasicBlock* bb, unsigned bits):
Mask(mask), BB(bb), Bits(bits) { }
};
typedef std::vector<Case> CaseVector;
typedef std::vector<CaseBits> CaseBitsVector;
typedef CaseVector::iterator CaseItr;
typedef std::pair<CaseItr, CaseItr> CaseRange;
struct CaseRec {
CaseRec(MachineBasicBlock *bb, Constant *lt, Constant *ge, CaseRange r) :
CaseBB(bb), LT(lt), GE(ge), Range(r) {}
MachineBasicBlock *CaseBB;
Constant *LT;
Constant *GE;
CaseRange Range;
};
typedef std::vector<CaseRec> CaseRecVector;
struct CaseCmp {
bool operator()(const Case &C1, const Case &C2) {
assert(isa<ConstantInt>(C1.Low) && isa<ConstantInt>(C2.High));
const ConstantInt* CI1 = cast<const ConstantInt>(C1.Low);
const ConstantInt* CI2 = cast<const ConstantInt>(C2.High);
return CI1->getValue().slt(CI2->getValue());
}
};
struct CaseBitsCmp {
bool operator()(const CaseBits &C1, const CaseBits &C2) {
return C1.Bits > C2.Bits;
}
};
size_t Clusterify(CaseVector &Cases, const SwitchInst &SI);
struct CaseBlock {
CaseBlock(ISD::CondCode cc, Value *cmplhs, Value *cmprhs, Value *cmpmiddle,
MachineBasicBlock *truebb, MachineBasicBlock *falsebb,
MachineBasicBlock *me)
: CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs),
TrueBB(truebb), FalseBB(falsebb), ThisBB(me) {}
ISD::CondCode CC;
Value *CmpLHS, *CmpMHS, *CmpRHS;
MachineBasicBlock *TrueBB, *FalseBB;
MachineBasicBlock *ThisBB;
};
struct JumpTable {
JumpTable(unsigned R, unsigned J, MachineBasicBlock *M,
MachineBasicBlock *D): Reg(R), JTI(J), MBB(M), Default(D) {}
unsigned Reg;
unsigned JTI;
MachineBasicBlock *MBB;
MachineBasicBlock *Default;
};
struct JumpTableHeader {
JumpTableHeader(APInt F, APInt L, Value *SV, MachineBasicBlock *H,
bool E = false):
First(F), Last(L), SValue(SV), HeaderBB(H), Emitted(E) {}
APInt First;
APInt Last;
Value *SValue;
MachineBasicBlock *HeaderBB;
bool Emitted;
};
typedef std::pair<JumpTableHeader, JumpTable> JumpTableBlock;
struct BitTestCase {
BitTestCase(uint64_t M, MachineBasicBlock* T, MachineBasicBlock* Tr):
Mask(M), ThisBB(T), TargetBB(Tr) { }
uint64_t Mask;
MachineBasicBlock *ThisBB;
MachineBasicBlock *TargetBB;
};
typedef SmallVector<BitTestCase, 3> BitTestInfo;
struct BitTestBlock {
BitTestBlock(APInt F, APInt R, Value* SV,
unsigned Rg, bool E,
MachineBasicBlock* P, MachineBasicBlock* D,
const BitTestInfo& C):
First(F), Range(R), SValue(SV), Reg(Rg), Emitted(E),
Parent(P), Default(D), Cases(C) { }
APInt First;
APInt Range;
Value *SValue;
unsigned Reg;
bool Emitted;
MachineBasicBlock *Parent;
MachineBasicBlock *Default;
BitTestInfo Cases;
};
public:
TargetLowering &TLI;
SelectionDAG &DAG;
const TargetData *TD;
AliasAnalysis *AA;
std::vector<CaseBlock> SwitchCases;
std::vector<JumpTableBlock> JTCases;
std::vector<BitTestBlock> BitTestCases;
std::vector<std::pair<MachineInstr*, unsigned> > PHINodesToUpdate;
DenseMap<MachineBasicBlock*, MachineBasicBlock*> EdgeMapping;
DenseMap<Constant*, unsigned> ConstantsOut;
FunctionLoweringInfo &FuncInfo;
CodeGenOpt::Level OptLevel;
GCFunctionInfo *GFI;
bool HasTailCall;
LLVMContext *Context;
SelectionDAGBuilder(SelectionDAG &dag, TargetLowering &tli,
FunctionLoweringInfo &funcinfo,
CodeGenOpt::Level ol)
: SDNodeOrder(0), TLI(tli), DAG(dag), FuncInfo(funcinfo), OptLevel(ol),
HasTailCall(false), Context(dag.getContext()) {
}
void init(GCFunctionInfo *gfi, AliasAnalysis &aa);
void clear();
SDValue getRoot();
SDValue getControlRoot();
DebugLoc getCurDebugLoc() const { return CurDebugLoc; }
void setCurDebugLoc(DebugLoc dl) { CurDebugLoc = dl; }
unsigned getSDNodeOrder() const { return SDNodeOrder; }
void CopyValueToVirtualRegister(Value *V, unsigned Reg);
void AssignOrderingToNode(const SDNode *Node);
void visit(Instruction &I);
void visit(unsigned Opcode, User &I);
void setCurrentBasicBlock(MachineBasicBlock *MBB) { CurMBB = MBB; }
SDValue getValue(const Value *V);
void setValue(const Value *V, SDValue NewN) {
SDValue &N = NodeMap[V];
assert(N.getNode() == 0 && "Already set a value for this node!");
N = NewN;
}
void setUnusedArgValue(const Value *V, SDValue NewN) {
SDValue &N = UnusedArgNodeMap[V];
assert(N.getNode() == 0 && "Already set a value for this node!");
N = NewN;
}
void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo,
std::set<unsigned> &OutputRegs,
std::set<unsigned> &InputRegs);
void FindMergedConditions(Value *Cond, MachineBasicBlock *TBB,
MachineBasicBlock *FBB, MachineBasicBlock *CurBB,
unsigned Opc);
void EmitBranchForMergedCondition(Value *Cond, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
MachineBasicBlock *CurBB);
bool ShouldEmitAsBranches(const std::vector<CaseBlock> &Cases);
bool isExportableFromCurrentBlock(Value *V, const BasicBlock *FromBB);
void CopyToExportRegsIfNeeded(Value *V);
void ExportFromCurrentBlock(Value *V);
void LowerCallTo(CallSite CS, SDValue Callee, bool IsTailCall,
MachineBasicBlock *LandingPad = NULL);
private:
void visitRet(ReturnInst &I);
void visitBr(BranchInst &I);
void visitSwitch(SwitchInst &I);
void visitIndirectBr(IndirectBrInst &I);
void visitUnreachable(UnreachableInst &I) { }
bool handleSmallSwitchRange(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
bool handleJTSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
bool handleBTSplitSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
bool handleBitTestsSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
public:
void visitSwitchCase(CaseBlock &CB);
void visitBitTestHeader(BitTestBlock &B);
void visitBitTestCase(MachineBasicBlock* NextMBB,
unsigned Reg,
BitTestCase &B);
void visitJumpTable(JumpTable &JT);
void visitJumpTableHeader(JumpTable &JT, JumpTableHeader &JTH);
private:
void visitInvoke(InvokeInst &I);
void visitUnwind(UnwindInst &I);
void visitBinary(User &I, unsigned OpCode);
void visitShift(User &I, unsigned Opcode);
void visitAdd(User &I) { visitBinary(I, ISD::ADD); }
void visitFAdd(User &I) { visitBinary(I, ISD::FADD); }
void visitSub(User &I) { visitBinary(I, ISD::SUB); }
void visitFSub(User &I);
void visitMul(User &I) { visitBinary(I, ISD::MUL); }
void visitFMul(User &I) { visitBinary(I, ISD::FMUL); }
void visitURem(User &I) { visitBinary(I, ISD::UREM); }
void visitSRem(User &I) { visitBinary(I, ISD::SREM); }
void visitFRem(User &I) { visitBinary(I, ISD::FREM); }
void visitUDiv(User &I) { visitBinary(I, ISD::UDIV); }
void visitSDiv(User &I) { visitBinary(I, ISD::SDIV); }
void visitFDiv(User &I) { visitBinary(I, ISD::FDIV); }
void visitAnd (User &I) { visitBinary(I, ISD::AND); }
void visitOr (User &I) { visitBinary(I, ISD::OR); }
void visitXor (User &I) { visitBinary(I, ISD::XOR); }
void visitShl (User &I) { visitShift(I, ISD::SHL); }
void visitLShr(User &I) { visitShift(I, ISD::SRL); }
void visitAShr(User &I) { visitShift(I, ISD::SRA); }
void visitICmp(User &I);
void visitFCmp(User &I);
void visitTrunc(User &I);
void visitZExt(User &I);
void visitSExt(User &I);
void visitFPTrunc(User &I);
void visitFPExt(User &I);
void visitFPToUI(User &I);
void visitFPToSI(User &I);
void visitUIToFP(User &I);
void visitSIToFP(User &I);
void visitPtrToInt(User &I);
void visitIntToPtr(User &I);
void visitBitCast(User &I);
void visitExtractElement(User &I);
void visitInsertElement(User &I);
void visitShuffleVector(User &I);
void visitExtractValue(ExtractValueInst &I);
void visitInsertValue(InsertValueInst &I);
void visitGetElementPtr(User &I);
void visitSelect(User &I);
void visitAlloca(AllocaInst &I);
void visitLoad(LoadInst &I);
void visitStore(StoreInst &I);
void visitPHI(PHINode &I) { } void visitCall(CallInst &I);
bool visitMemCmpCall(CallInst &I);
void visitInlineAsm(CallSite CS);
const char *visitIntrinsicCall(CallInst &I, unsigned Intrinsic);
void visitTargetIntrinsic(CallInst &I, unsigned Intrinsic);
void visitPow(CallInst &I);
void visitExp2(CallInst &I);
void visitExp(CallInst &I);
void visitLog(CallInst &I);
void visitLog2(CallInst &I);
void visitLog10(CallInst &I);
void visitVAStart(CallInst &I);
void visitVAArg(VAArgInst &I);
void visitVAEnd(CallInst &I);
void visitVACopy(CallInst &I);
void visitUserOp1(Instruction &I) {
llvm_unreachable("UserOp1 should not exist at instruction selection time!");
}
void visitUserOp2(Instruction &I) {
llvm_unreachable("UserOp2 should not exist at instruction selection time!");
}
const char *implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op);
const char *implVisitAluOverflow(CallInst &I, ISD::NodeType Op);
void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
bool EmitFuncArgumentDbgValue(const DbgValueInst &DI,
const Value *V, MDNode *Variable,
uint64_t Offset, SDValue &N);
};
}
#endif