summaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/DAGBuilder.cpp
blob: 03bf14bc28fb72773b6ec54551bbcbb703840aa2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
//===-- DAGBuilder.cpp - Turn an LLVM BasicBlock into a DAG for selection -===//
//
// This file turns an LLVM BasicBlock into a target independent SelectionDAG in
// preparation for target specific optimizations and instruction selection.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/InstVisitor.h"

struct SelectionDAGBuilder : public InstVisitor<SelectionDAGBuilder> {
  // DAG - the current dag we are building.
  SelectionDAG &DAG;

  // SDTB - The target-specific builder interface, which indicates how to expand
  // extremely target-specific aspects of the representation, such as function
  // calls and arguments.
  SelectionDAGTargetBuilder &SDTB;

  // BB - The current machine basic block we are working on.
  MachineBasicBlock *BB;

  // CurRoot - The root built for the current basic block.
  SelectionDAGNode *CurRoot;

  SelectionDAGBuilder(SelectionDAG &dag, SelectionDAGTargetBuilder &sdtb)
    : DAG(dag), SDTB(sdtb), BB(0), CurRoot(0) {}

  void visitBB(BasicBlock &bb);

  // Visitation methods for instructions: Create the appropriate DAG nodes for
  // the instruction.
  void visitAdd(BinaryOperator &BO);
  void visitSub(BinaryOperator &BO);
  void visitMul(BinaryOperator &BO);

  void visitAnd(BinaryOperator &BO);
  void visitOr (BinaryOperator &BO);
  void visitXor(BinaryOperator &BO);

  void visitSetEQ(BinaryOperator &BO);

  void visitLoad(LoadInst &LI);
  void visitCall(CallInst &CI);

  void visitBr(BranchInst &BI);
  void visitRet(ReturnInst &RI);

  void visitInstruction(Instruction &I) {
    std::cerr << "DAGBuilder: Cannot instruction select: " << I;
    abort();
  }

private:
  SelectionDAGNode *getNodeFor(Value *V);
  SelectionDAGNode *getNodeFor(Value &V) { return getNodeFor(&V); }
  
  SelectionDAGNode *addSeqNode(SelectionDAGNode *N);
};

/// addSeqNode - The same as addNode, but the node is also included in the
/// sequence nodes for this block.  This method should be called for any
/// instructions which have a specified sequence they must be evaluated in.
///
SelectionDAGNode *SelectionDAGBuilder::addSeqNode(SelectionDAGNode *N) {
  DAG.addNode(N);   // First, add the node to the selection DAG
  
  if (!CurRoot)
    CurRoot = N;
  else {
    // Create and add a new chain node for the existing root and this node...
    CurRoot = DAG.addNode(new SelectionDAGNode(ISD::ChainNode, MVT::isVoid,
                                               BB, CurRoot, N));
  }
  return N;
}

/// getNodeFor - This method returns the SelectionDAGNode for the specified LLVM
/// value, creating a node as necessary.
///
SelectionDAGNode *SelectionDAGBuilder::getNodeFor(Value *V) {
  // If we already have the entry, return it.
  SelectionDAGNode*& Entry = DAG.ValueMap[V];
  if (Entry) return Entry;
  
  // Otherwise, we need to create a node to return now... start by figuring out
  // which type the node will be...
  MVT::ValueType ValueType = DAG.getValueType(V->getType());

  if (Instruction *I = dyn_cast<Instruction>(V))
    // Instructions will be filled in later.  For now, just create and return a
    // dummy node.
    return Entry = new SelectionDAGNode(ISD::ProtoNode, ValueType);

  if (Constant *C = dyn_cast<Constant>(V)) {
    if (ConstantBool *CB = dyn_cast<ConstantBool>(C)) {
      Entry = new SelectionDAGNode(ISD::Constant, ValueType);
      Entry->addValue(new ReducedValue_Constant_i1(CB->getValue()));
    } else if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
      Entry = new SelectionDAGNode(ISD::Constant, ValueType);
      switch (ValueType) {
      case MVT::i8:
        Entry->addValue(new ReducedValue_Constant_i8(CI->getRawValue()));
        break;
      case MVT::i16:
        Entry->addValue(new ReducedValue_Constant_i16(CI->getRawValue()));
        break;
      case MVT::i32:
        Entry->addValue(new ReducedValue_Constant_i32(CI->getRawValue()));
        break;
      case MVT::i64:
        Entry->addValue(new ReducedValue_Constant_i64(CI->getRawValue()));
        break;
      default:
        assert(0 && "Invalid ValueType for an integer constant!");
      }

    } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
      Entry = new SelectionDAGNode(ISD::Constant, ValueType);
      if (ValueType == MVT::f32)
        Entry->addValue(new ReducedValue_Constant_f32(CFP->getValue()));
      else
        Entry->addValue(new ReducedValue_Constant_f64(CFP->getValue()));
    }
    if (Entry) return Entry;
  } else if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) {
    Entry = new SelectionDAGNode(ISD::BasicBlock, ValueType);
    Entry->addValue(new ReducedValue_BasicBlock_i32(DAG.BlockMap[BB]));
    return Entry;
  }

  std::cerr << "Unhandled LLVM value in DAG Builder!: " << *V << "\n";
  abort();
  return 0;
}


// visitBB - This method is used to visit a basic block in the program.  It
// manages the CurRoot instance variable so that all of the visit(Instruction)
// methods can be written to assume that there is only one basic block being
// constructed.
//
void SelectionDAGBuilder::visitBB(BasicBlock &bb) {
  BB = DAG.BlockMap[&bb];       // Update BB instance var
  
  // Save the current global DAG...
  SelectionDAGNode *OldRoot = CurRoot;
  CurRoot = 0;
  
  visit(bb.begin(), bb.end());  // Visit all of the instructions...
  
  if (OldRoot) {
    if (!CurRoot)
      CurRoot = OldRoot;   // This block had no root of its own..
    else {
      // The previous basic block AND this basic block had roots, insert a
      // block chain node now...
      CurRoot = DAG.addNode(new SelectionDAGNode(ISD::BlockChainNode,
                                                 MVT::isVoid,
                                                 BB, OldRoot, CurRoot));
    }
  }
}

//===----------------------------------------------------------------------===//
//                         ...Visitation Methods...
//===----------------------------------------------------------------------===//

void SelectionDAGBuilder::visitAdd(BinaryOperator &BO) {
  getNodeFor(BO)->setNode(ISD::Plus, BB, getNodeFor(BO.getOperand(0)),
                          getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitSub(BinaryOperator &BO) {
  getNodeFor(BO)->setNode(ISD::Minus, BB, getNodeFor(BO.getOperand(0)),
                          getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitMul(BinaryOperator &BO) {
  getNodeFor(BO)->setNode(ISD::Times, BB, getNodeFor(BO.getOperand(0)),
                          getNodeFor(BO.getOperand(1)));
}

void SelectionDAGBuilder::visitAnd(BinaryOperator &BO) {
  getNodeFor(BO)->setNode(ISD::And, BB, getNodeFor(BO.getOperand(0)),
                          getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitOr(BinaryOperator &BO) {
  getNodeFor(BO)->setNode(ISD::Or, BB, getNodeFor(BO.getOperand(0)),
                          getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitXor(BinaryOperator &BO) {
  getNodeFor(BO)->setNode(ISD::Xor, BB, getNodeFor(BO.getOperand(0)),
                          getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitSetEQ(BinaryOperator &BO) {
  getNodeFor(BO)->setNode(ISD::SetEQ, BB, getNodeFor(BO.getOperand(0)),
                          getNodeFor(BO.getOperand(1)));
}


void SelectionDAGBuilder::visitRet(ReturnInst &RI) {
  if (RI.getNumOperands()) {         // Value return
    addSeqNode(new SelectionDAGNode(ISD::Ret, MVT::isVoid, BB,
                                    getNodeFor(RI.getOperand(0))));
  } else {                           // Void return
    addSeqNode(new SelectionDAGNode(ISD::RetVoid, MVT::isVoid, BB));
  }
}


void SelectionDAGBuilder::visitBr(BranchInst &BI) {
  if (BI.isUnconditional())
    addSeqNode(new SelectionDAGNode(ISD::Br, MVT::isVoid, BB,
                                    getNodeFor(BI.getOperand(0))));
  else
    addSeqNode(new SelectionDAGNode(ISD::BrCond, MVT::isVoid, BB,
                                    getNodeFor(BI.getCondition()),
                                    getNodeFor(BI.getSuccessor(0)),
                                    getNodeFor(BI.getSuccessor(1))));
}


void SelectionDAGBuilder::visitLoad(LoadInst &LI) {
  // FIXME: this won't prevent reordering of loads!
  getNodeFor(LI)->setNode(ISD::Load, BB, getNodeFor(LI.getOperand(0)));  
}

void SelectionDAGBuilder::visitCall(CallInst &CI) {
  SDTB.expandCall(DAG, CI);
}



// SelectionDAG constructor - Just use the SelectionDAGBuilder to do all of the
// dirty work...
SelectionDAG::SelectionDAG(MachineFunction &f, const TargetMachine &tm,
                           SelectionDAGTargetBuilder &SDTB)
  : F(f), TM(tm) {

  switch (TM.getTargetData().getPointerSize()) {
  default: assert(0 && "Unknown pointer size!"); abort();
  case 8:  PointerType = MVT::i8; break;
  case 16: PointerType = MVT::i16; break;
  case 32: PointerType = MVT::i32; break;
  case 64: PointerType = MVT::i64; break;
  }

  // Create all of the machine basic blocks for the function... building the
  // BlockMap.  This map is used for PHI node conversion.
  const Function &Fn = *F.getFunction();
  for (Function::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
    F.getBasicBlockList().push_back(BlockMap[I] = new MachineBasicBlock(I));

  SDTB.expandArguments(*this);

  SelectionDAGBuilder SDB(*this, SDTB);
  for (Function::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
    SDB.visitBB(const_cast<BasicBlock&>(*I));
  Root = SDB.CurRoot;
}