blob: c2d506729ea40725cae860179765a585e2914ad5 [file] [log] [blame]
Chris Lattner5930d3d2005-11-16 22:59:19 +00001//===- X86ISelDAGToDAG.cpp - A DAG pattern matching inst selector for X86 -===//
Chris Lattner655e7df2005-11-16 01:54:32 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the Evan Cheng and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a DAG pattern matching instruction selector for X86,
11// converting from a legalized dag to a X86 dag.
12//
13//===----------------------------------------------------------------------===//
14
Evan Chengb9d34bd2006-08-07 22:28:20 +000015#define DEBUG_TYPE "x86-isel"
Chris Lattner655e7df2005-11-16 01:54:32 +000016#include "X86.h"
Evan Chengbc7a0f442006-01-11 06:09:51 +000017#include "X86InstrBuilder.h"
Evan Cheng2dd2c652006-03-13 23:20:37 +000018#include "X86ISelLowering.h"
Chris Lattner7c551262006-01-11 01:15:34 +000019#include "X86RegisterInfo.h"
Chris Lattner655e7df2005-11-16 01:54:32 +000020#include "X86Subtarget.h"
Evan Cheng2dd2c652006-03-13 23:20:37 +000021#include "X86TargetMachine.h"
Chris Lattner3f0f71b2005-11-19 02:11:08 +000022#include "llvm/GlobalValue.h"
Chris Lattner7c551262006-01-11 01:15:34 +000023#include "llvm/Instructions.h"
Chris Lattner5d70a7c2006-03-25 06:47:10 +000024#include "llvm/Intrinsics.h"
Chris Lattner7c551262006-01-11 01:15:34 +000025#include "llvm/Support/CFG.h"
Chris Lattner3f0f71b2005-11-19 02:11:08 +000026#include "llvm/CodeGen/MachineConstantPool.h"
Chris Lattner655e7df2005-11-16 01:54:32 +000027#include "llvm/CodeGen/MachineFunction.h"
Evan Cheng73a1ad92006-01-10 20:26:56 +000028#include "llvm/CodeGen/MachineFrameInfo.h"
Chris Lattner7c551262006-01-11 01:15:34 +000029#include "llvm/CodeGen/MachineInstrBuilder.h"
30#include "llvm/CodeGen/SSARegMap.h"
Chris Lattner655e7df2005-11-16 01:54:32 +000031#include "llvm/CodeGen/SelectionDAGISel.h"
32#include "llvm/Target/TargetMachine.h"
33#include "llvm/Support/Debug.h"
Chris Lattner0cc59072006-06-28 23:27:49 +000034#include "llvm/Support/Visibility.h"
Chris Lattner655e7df2005-11-16 01:54:32 +000035#include "llvm/ADT/Statistic.h"
Evan Cheng2e945382006-07-28 06:05:06 +000036#include <deque>
Chris Lattnerde02d772006-01-22 23:41:00 +000037#include <iostream>
Evan Chengb9d34bd2006-08-07 22:28:20 +000038#include <queue>
Evan Cheng54cb1832006-02-05 06:46:41 +000039#include <set>
Chris Lattner655e7df2005-11-16 01:54:32 +000040using namespace llvm;
41
42//===----------------------------------------------------------------------===//
43// Pattern Matcher Implementation
44//===----------------------------------------------------------------------===//
45
46namespace {
Chris Lattner3f0f71b2005-11-19 02:11:08 +000047 /// X86ISelAddressMode - This corresponds to X86AddressMode, but uses
48 /// SDOperand's instead of register numbers for the leaves of the matched
49 /// tree.
50 struct X86ISelAddressMode {
51 enum {
52 RegBase,
Chris Lattneraa2372562006-05-24 17:04:05 +000053 FrameIndexBase
Chris Lattner3f0f71b2005-11-19 02:11:08 +000054 } BaseType;
55
56 struct { // This is really a union, discriminated by BaseType!
57 SDOperand Reg;
58 int FrameIndex;
59 } Base;
60
61 unsigned Scale;
62 SDOperand IndexReg;
63 unsigned Disp;
64 GlobalValue *GV;
Evan Cheng77d86ff2006-02-25 10:09:08 +000065 Constant *CP;
66 unsigned Align; // CP alignment.
Chris Lattner3f0f71b2005-11-19 02:11:08 +000067
68 X86ISelAddressMode()
Evan Cheng77d86ff2006-02-25 10:09:08 +000069 : BaseType(RegBase), Scale(1), IndexReg(), Disp(0), GV(0),
70 CP(0), Align(0) {
Chris Lattner3f0f71b2005-11-19 02:11:08 +000071 }
72 };
73}
74
75namespace {
Chris Lattner655e7df2005-11-16 01:54:32 +000076 Statistic<>
77 NumFPKill("x86-codegen", "Number of FP_REG_KILL instructions added");
78
79 //===--------------------------------------------------------------------===//
80 /// ISel - X86 specific code to select X86 machine instructions for
81 /// SelectionDAG operations.
82 ///
Chris Lattner0cc59072006-06-28 23:27:49 +000083 class VISIBILITY_HIDDEN X86DAGToDAGISel : public SelectionDAGISel {
Chris Lattner655e7df2005-11-16 01:54:32 +000084 /// ContainsFPCode - Every instruction we select that uses or defines a FP
85 /// register should set this to true.
86 bool ContainsFPCode;
87
88 /// X86Lowering - This object fully describes how to lower LLVM code to an
89 /// X86-specific SelectionDAG.
90 X86TargetLowering X86Lowering;
91
92 /// Subtarget - Keep a pointer to the X86Subtarget around so that we can
93 /// make the right decision when generating code for different targets.
94 const X86Subtarget *Subtarget;
Evan Cheng5588de92006-02-18 00:15:05 +000095
96 unsigned GlobalBaseReg;
Evan Cheng691a63d2006-07-27 16:44:36 +000097
Chris Lattner655e7df2005-11-16 01:54:32 +000098 public:
Evan Cheng2dd2c652006-03-13 23:20:37 +000099 X86DAGToDAGISel(X86TargetMachine &TM)
100 : SelectionDAGISel(X86Lowering),
Evan Cheng691a63d2006-07-27 16:44:36 +0000101 X86Lowering(*TM.getTargetLowering()),
102 Subtarget(&TM.getSubtarget<X86Subtarget>()),
Evan Chengb9d34bd2006-08-07 22:28:20 +0000103 ReachabilityMatrix(NULL) {}
Chris Lattner655e7df2005-11-16 01:54:32 +0000104
Evan Cheng5588de92006-02-18 00:15:05 +0000105 virtual bool runOnFunction(Function &Fn) {
106 // Make sure we re-emit a set of the global base reg if necessary
107 GlobalBaseReg = 0;
108 return SelectionDAGISel::runOnFunction(Fn);
109 }
110
Chris Lattner655e7df2005-11-16 01:54:32 +0000111 virtual const char *getPassName() const {
112 return "X86 DAG->DAG Instruction Selection";
113 }
114
115 /// InstructionSelectBasicBlock - This callback is invoked by
116 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
117 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
118
Evan Chengbc7a0f442006-01-11 06:09:51 +0000119 virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
120
Evan Chenge2a3f702006-07-28 01:03:48 +0000121 virtual bool CanBeFoldedBy(SDNode *N, SDNode *U);
Evan Cheng691a63d2006-07-27 16:44:36 +0000122
Chris Lattner655e7df2005-11-16 01:54:32 +0000123// Include the pieces autogenerated from the target description.
124#include "X86GenDAGISel.inc"
125
126 private:
Evan Chengb9d34bd2006-08-07 22:28:20 +0000127 void DetermineReachability();
Evan Cheng691a63d2006-07-27 16:44:36 +0000128
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000129 void Select(SDOperand &Result, SDOperand N);
Chris Lattner655e7df2005-11-16 01:54:32 +0000130
Evan Chenga86ba852006-02-11 02:05:36 +0000131 bool MatchAddress(SDOperand N, X86ISelAddressMode &AM, bool isRoot = true);
Evan Chengc9fab312005-12-08 02:01:35 +0000132 bool SelectAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
133 SDOperand &Index, SDOperand &Disp);
134 bool SelectLEAAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
135 SDOperand &Index, SDOperand &Disp);
Evan Chengd5f2ba02006-02-06 06:02:33 +0000136 bool TryFoldLoad(SDOperand P, SDOperand N,
137 SDOperand &Base, SDOperand &Scale,
Evan Cheng10d27902006-01-06 20:36:21 +0000138 SDOperand &Index, SDOperand &Disp);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000139
140 virtual void SelectRootInit() {
141 DAGSize = CurDAG->AssignTopologicalOrder(TopOrder);
142 unsigned NumBytes = (DAGSize + 7) / 8;
143 UnfoldableSet = new unsigned char[NumBytes];
144 memset(UnfoldableSet, 0, NumBytes);
145 unsigned RMSize = (DAGSize * DAGSize + 7) / 8;
146 ReachabilityMatrix = new unsigned char[RMSize];
147 memset(ReachabilityMatrix, 0, RMSize);
148 DetermineReachability();
149 }
150
Chris Lattnerba1ed582006-06-08 18:03:49 +0000151 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
152 /// inline asm expressions.
153 virtual bool SelectInlineAsmMemoryOperand(const SDOperand &Op,
154 char ConstraintCode,
155 std::vector<SDOperand> &OutOps,
156 SelectionDAG &DAG);
157
Evan Chenge8a42362006-06-02 22:38:37 +0000158 void EmitSpecialCodeForMain(MachineBasicBlock *BB, MachineFrameInfo *MFI);
159
Evan Cheng67ed58e2005-12-12 21:49:40 +0000160 inline void getAddressOperands(X86ISelAddressMode &AM, SDOperand &Base,
161 SDOperand &Scale, SDOperand &Index,
162 SDOperand &Disp) {
163 Base = (AM.BaseType == X86ISelAddressMode::FrameIndexBase) ?
164 CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, MVT::i32) : AM.Base.Reg;
Evan Cheng1d712482005-12-17 09:13:43 +0000165 Scale = getI8Imm(AM.Scale);
Evan Cheng67ed58e2005-12-12 21:49:40 +0000166 Index = AM.IndexReg;
167 Disp = AM.GV ? CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp)
Evan Cheng77d86ff2006-02-25 10:09:08 +0000168 : (AM.CP ?
169 CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Align, AM.Disp)
170 : getI32Imm(AM.Disp));
Evan Cheng67ed58e2005-12-12 21:49:40 +0000171 }
172
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000173 /// getI8Imm - Return a target constant with the specified value, of type
174 /// i8.
175 inline SDOperand getI8Imm(unsigned Imm) {
176 return CurDAG->getTargetConstant(Imm, MVT::i8);
177 }
178
Chris Lattner655e7df2005-11-16 01:54:32 +0000179 /// getI16Imm - Return a target constant with the specified value, of type
180 /// i16.
181 inline SDOperand getI16Imm(unsigned Imm) {
182 return CurDAG->getTargetConstant(Imm, MVT::i16);
183 }
184
185 /// getI32Imm - Return a target constant with the specified value, of type
186 /// i32.
187 inline SDOperand getI32Imm(unsigned Imm) {
188 return CurDAG->getTargetConstant(Imm, MVT::i32);
189 }
Evan Chengd49cc362006-02-10 22:24:32 +0000190
Evan Cheng5588de92006-02-18 00:15:05 +0000191 /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
192 /// base register. Return the virtual register that holds this value.
193 SDOperand getGlobalBaseReg();
194
Evan Cheng45af2872006-08-01 08:17:22 +0000195 /// ReachabilityMatrix - A N x N matrix representing all pairs reachability
Evan Cheng691a63d2006-07-27 16:44:36 +0000196 /// information. One bit per potential edge.
Evan Cheng8101dd62006-08-02 09:18:33 +0000197 unsigned char *ReachabilityMatrix;
Evan Cheng45af2872006-08-01 08:17:22 +0000198
Evan Cheng691a63d2006-07-27 16:44:36 +0000199 inline void setReachable(SDNode *f, SDNode *t) {
200 unsigned Idx = f->getNodeId() * DAGSize + t->getNodeId();
Evan Cheng8101dd62006-08-02 09:18:33 +0000201 ReachabilityMatrix[Idx / 8] |= 1 << (Idx % 8);
Evan Cheng691a63d2006-07-27 16:44:36 +0000202 }
203
204 inline bool isReachable(SDNode *f, SDNode *t) {
205 unsigned Idx = f->getNodeId() * DAGSize + t->getNodeId();
Evan Cheng8101dd62006-08-02 09:18:33 +0000206 return ReachabilityMatrix[Idx / 8] & (1 << (Idx % 8));
Evan Cheng691a63d2006-07-27 16:44:36 +0000207 }
208
Evan Cheng11a4d8c2006-07-28 00:49:31 +0000209 /// UnfoldableSet - An boolean array representing nodes which have been
210 /// folded into addressing modes and therefore should not be folded in
211 /// another operation.
Evan Cheng8101dd62006-08-02 09:18:33 +0000212 unsigned char *UnfoldableSet;
Evan Cheng11a4d8c2006-07-28 00:49:31 +0000213
214 inline void setUnfoldable(SDNode *N) {
Evan Cheng8101dd62006-08-02 09:18:33 +0000215 unsigned Id = N->getNodeId();
216 UnfoldableSet[Id / 8] |= 1 << (Id % 8);
Evan Cheng11a4d8c2006-07-28 00:49:31 +0000217 }
218
219 inline bool isUnfoldable(SDNode *N) {
Evan Cheng8101dd62006-08-02 09:18:33 +0000220 unsigned Id = N->getNodeId();
221 return UnfoldableSet[Id / 8] & (1 << (Id % 8));
Evan Cheng11a4d8c2006-07-28 00:49:31 +0000222 }
223
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000224#ifndef NDEBUG
225 unsigned Indent;
226#endif
Chris Lattner655e7df2005-11-16 01:54:32 +0000227 };
228}
229
Evan Chenge2a3f702006-07-28 01:03:48 +0000230bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U) {
Evan Cheng11a4d8c2006-07-28 00:49:31 +0000231 // Is it already folded by SelectAddr / SelectLEAAddr?
232 if (isUnfoldable(N))
233 return false;
234
Evan Cheng691a63d2006-07-27 16:44:36 +0000235 // If U use can somehow reach N through another path then U can't fold N or
236 // it will create a cycle. e.g. In the following diagram, U can reach N
Evan Chenge8071ec2006-07-28 06:33:41 +0000237 // through X. If N is folded into into U, then X is both a predecessor and
Evan Cheng691a63d2006-07-27 16:44:36 +0000238 // a successor of U.
239 //
240 // [ N ]
241 // ^ ^
242 // | |
243 // / \---
244 // / [X]
245 // | ^
246 // [U]--------|
Evan Cheng691a63d2006-07-27 16:44:36 +0000247 assert(isReachable(U, N) && "Attempting to fold a non-operand node?");
248 for (SDNode::op_iterator I = U->op_begin(), E = U->op_end(); I != E; ++I) {
249 SDNode *P = I->Val;
250 if (P != N && isReachable(P, N))
251 return false;
252 }
253 return true;
254}
255
Evan Cheng45af2872006-08-01 08:17:22 +0000256/// DetermineReachability - Determine reachability between all pairs of nodes
Evan Cheng2e945382006-07-28 06:05:06 +0000257/// between f and t in topological order.
Evan Chengb9d34bd2006-08-07 22:28:20 +0000258void X86DAGToDAGISel::DetermineReachability() {
259 for (unsigned i = 0; i < DAGSize; ++i) {
Evan Cheng691a63d2006-07-27 16:44:36 +0000260 SDNode *N = TopOrder[i];
261 setReachable(N, N);
262 // If N is a leaf node, there is nothing more to do.
263 if (N->getNumOperands() == 0)
264 continue;
265
Evan Chengb9d34bd2006-08-07 22:28:20 +0000266 for (unsigned i2 = 0; ; ++i2) {
Evan Cheng691a63d2006-07-27 16:44:36 +0000267 SDNode *M = TopOrder[i2];
268 if (isReachable(M, N)) {
Evan Cheng45af2872006-08-01 08:17:22 +0000269 // Update reachability from M to N's operands.
Evan Cheng8f585192006-08-02 22:01:32 +0000270 for (SDNode::op_iterator I = N->op_begin(),E = N->op_end(); I != E;++I){
271 SDNode *P = I->Val;
272 if (P->getNodeId() >= 0)
273 setReachable(M, P);
274 }
Evan Cheng691a63d2006-07-27 16:44:36 +0000275 }
276 if (M == N) break;
277 }
278 }
279}
280
Chris Lattner655e7df2005-11-16 01:54:32 +0000281/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
282/// when it has created a SelectionDAG for us to codegen.
283void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
284 DEBUG(BB->dump());
Chris Lattner7c551262006-01-11 01:15:34 +0000285 MachineFunction::iterator FirstMBB = BB;
Chris Lattner655e7df2005-11-16 01:54:32 +0000286
287 // Codegen the basic block.
Evan Chengd49cc362006-02-10 22:24:32 +0000288#ifndef NDEBUG
289 DEBUG(std::cerr << "===== Instruction selection begins:\n");
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000290 Indent = 0;
Evan Chengd49cc362006-02-10 22:24:32 +0000291#endif
Evan Cheng54cb1832006-02-05 06:46:41 +0000292 DAG.setRoot(SelectRoot(DAG.getRoot()));
Evan Chengd49cc362006-02-10 22:24:32 +0000293#ifndef NDEBUG
294 DEBUG(std::cerr << "===== Instruction selection ends:\n");
295#endif
Evan Cheng3b5e0ca2006-07-28 00:10:59 +0000296
Evan Cheng8101dd62006-08-02 09:18:33 +0000297 delete[] ReachabilityMatrix;
Evan Cheng8101dd62006-08-02 09:18:33 +0000298 delete[] UnfoldableSet;
299 ReachabilityMatrix = NULL;
Evan Cheng8101dd62006-08-02 09:18:33 +0000300 UnfoldableSet = NULL;
Chris Lattner655e7df2005-11-16 01:54:32 +0000301 DAG.RemoveDeadNodes();
302
303 // Emit machine code to BB.
304 ScheduleAndEmitDAG(DAG);
Chris Lattner7c551262006-01-11 01:15:34 +0000305
306 // If we are emitting FP stack code, scan the basic block to determine if this
307 // block defines any FP values. If so, put an FP_REG_KILL instruction before
308 // the terminator of the block.
Evan Chengcde9e302006-01-27 08:10:46 +0000309 if (!Subtarget->hasSSE2()) {
Chris Lattner7c551262006-01-11 01:15:34 +0000310 // Note that FP stack instructions *are* used in SSE code when returning
311 // values, but these are not live out of the basic block, so we don't need
312 // an FP_REG_KILL in this case either.
313 bool ContainsFPCode = false;
314
315 // Scan all of the machine instructions in these MBBs, checking for FP
316 // stores.
317 MachineFunction::iterator MBBI = FirstMBB;
318 do {
319 for (MachineBasicBlock::iterator I = MBBI->begin(), E = MBBI->end();
320 !ContainsFPCode && I != E; ++I) {
321 for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) {
322 if (I->getOperand(op).isRegister() && I->getOperand(op).isDef() &&
323 MRegisterInfo::isVirtualRegister(I->getOperand(op).getReg()) &&
324 RegMap->getRegClass(I->getOperand(0).getReg()) ==
325 X86::RFPRegisterClass) {
326 ContainsFPCode = true;
327 break;
328 }
329 }
330 }
331 } while (!ContainsFPCode && &*(MBBI++) != BB);
332
333 // Check PHI nodes in successor blocks. These PHI's will be lowered to have
334 // a copy of the input value in this block.
335 if (!ContainsFPCode) {
336 // Final check, check LLVM BB's that are successors to the LLVM BB
337 // corresponding to BB for FP PHI nodes.
338 const BasicBlock *LLVMBB = BB->getBasicBlock();
339 const PHINode *PN;
340 for (succ_const_iterator SI = succ_begin(LLVMBB), E = succ_end(LLVMBB);
341 !ContainsFPCode && SI != E; ++SI) {
342 for (BasicBlock::const_iterator II = SI->begin();
343 (PN = dyn_cast<PHINode>(II)); ++II) {
344 if (PN->getType()->isFloatingPoint()) {
345 ContainsFPCode = true;
346 break;
347 }
348 }
349 }
350 }
351
352 // Finally, if we found any FP code, emit the FP_REG_KILL instruction.
353 if (ContainsFPCode) {
354 BuildMI(*BB, BB->getFirstTerminator(), X86::FP_REG_KILL, 0);
355 ++NumFPKill;
356 }
357 }
Chris Lattner655e7df2005-11-16 01:54:32 +0000358}
359
Evan Chengbc7a0f442006-01-11 06:09:51 +0000360/// EmitSpecialCodeForMain - Emit any code that needs to be executed only in
361/// the main function.
Evan Chenge8a42362006-06-02 22:38:37 +0000362void X86DAGToDAGISel::EmitSpecialCodeForMain(MachineBasicBlock *BB,
363 MachineFrameInfo *MFI) {
364 if (Subtarget->TargetType == X86Subtarget::isCygwin)
365 BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("__main");
366
Evan Chengbc7a0f442006-01-11 06:09:51 +0000367 // Switch the FPU to 64-bit precision mode for better compatibility and speed.
368 int CWFrameIdx = MFI->CreateStackObject(2, 2);
369 addFrameReference(BuildMI(BB, X86::FNSTCW16m, 4), CWFrameIdx);
370
371 // Set the high part to be 64-bit precision.
372 addFrameReference(BuildMI(BB, X86::MOV8mi, 5),
373 CWFrameIdx, 1).addImm(2);
374
375 // Reload the modified control word now.
376 addFrameReference(BuildMI(BB, X86::FLDCW16m, 4), CWFrameIdx);
377}
378
379void X86DAGToDAGISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
380 // If this is main, emit special code for main.
381 MachineBasicBlock *BB = MF.begin();
382 if (Fn.hasExternalLinkage() && Fn.getName() == "main")
383 EmitSpecialCodeForMain(BB, MF.getFrameInfo());
384}
385
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000386/// MatchAddress - Add the specified node to the specified addressing mode,
387/// returning true if it cannot be done. This just pattern matches for the
388/// addressing mode
Evan Chenga86ba852006-02-11 02:05:36 +0000389bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
390 bool isRoot) {
Evan Chengb9d34bd2006-08-07 22:28:20 +0000391 int id = N.Val->getNodeId();
392 bool Available = isSelected(id);
Evan Chenga86ba852006-02-11 02:05:36 +0000393
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000394 switch (N.getOpcode()) {
395 default: break;
Evan Cheng77d86ff2006-02-25 10:09:08 +0000396 case ISD::Constant:
397 AM.Disp += cast<ConstantSDNode>(N)->getValue();
398 return false;
399
400 case X86ISD::Wrapper:
401 // If both base and index components have been picked, we can't fit
402 // the result available in the register in the addressing mode. Duplicate
403 // GlobalAddress or ConstantPool as displacement.
404 if (!Available || (AM.Base.Reg.Val && AM.IndexReg.Val)) {
405 if (ConstantPoolSDNode *CP =
406 dyn_cast<ConstantPoolSDNode>(N.getOperand(0))) {
407 if (AM.CP == 0) {
408 AM.CP = CP->get();
409 AM.Align = CP->getAlignment();
410 AM.Disp += CP->getOffset();
411 return false;
412 }
413 } else if (GlobalAddressSDNode *G =
414 dyn_cast<GlobalAddressSDNode>(N.getOperand(0))) {
415 if (AM.GV == 0) {
416 AM.GV = G->getGlobal();
417 AM.Disp += G->getOffset();
418 return false;
419 }
420 }
421 }
422 break;
423
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000424 case ISD::FrameIndex:
425 if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
426 AM.BaseType = X86ISelAddressMode::FrameIndexBase;
427 AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
428 return false;
429 }
430 break;
Evan Chengc9fab312005-12-08 02:01:35 +0000431
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000432 case ISD::SHL:
Evan Cheng77d86ff2006-02-25 10:09:08 +0000433 if (!Available && AM.IndexReg.Val == 0 && AM.Scale == 1)
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000434 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1))) {
435 unsigned Val = CN->getValue();
436 if (Val == 1 || Val == 2 || Val == 3) {
437 AM.Scale = 1 << Val;
438 SDOperand ShVal = N.Val->getOperand(0);
439
440 // Okay, we know that we have a scale by now. However, if the scaled
441 // value is an add of something and a constant, we can fold the
442 // constant into the disp field here.
443 if (ShVal.Val->getOpcode() == ISD::ADD && ShVal.hasOneUse() &&
444 isa<ConstantSDNode>(ShVal.Val->getOperand(1))) {
445 AM.IndexReg = ShVal.Val->getOperand(0);
446 ConstantSDNode *AddVal =
447 cast<ConstantSDNode>(ShVal.Val->getOperand(1));
448 AM.Disp += AddVal->getValue() << Val;
449 } else {
450 AM.IndexReg = ShVal;
451 }
452 return false;
453 }
454 }
455 break;
Evan Chengc9fab312005-12-08 02:01:35 +0000456
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000457 case ISD::MUL:
458 // X*[3,5,9] -> X+X*[2,4,8]
Evan Cheng77d86ff2006-02-25 10:09:08 +0000459 if (!Available &&
460 AM.BaseType == X86ISelAddressMode::RegBase &&
461 AM.Base.Reg.Val == 0 &&
462 AM.IndexReg.Val == 0)
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000463 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1)))
464 if (CN->getValue() == 3 || CN->getValue() == 5 || CN->getValue() == 9) {
465 AM.Scale = unsigned(CN->getValue())-1;
466
467 SDOperand MulVal = N.Val->getOperand(0);
468 SDOperand Reg;
469
470 // Okay, we know that we have a scale by now. However, if the scaled
471 // value is an add of something and a constant, we can fold the
472 // constant into the disp field here.
473 if (MulVal.Val->getOpcode() == ISD::ADD && MulVal.hasOneUse() &&
474 isa<ConstantSDNode>(MulVal.Val->getOperand(1))) {
475 Reg = MulVal.Val->getOperand(0);
476 ConstantSDNode *AddVal =
477 cast<ConstantSDNode>(MulVal.Val->getOperand(1));
478 AM.Disp += AddVal->getValue() * CN->getValue();
479 } else {
480 Reg = N.Val->getOperand(0);
481 }
482
483 AM.IndexReg = AM.Base.Reg = Reg;
484 return false;
485 }
486 break;
487
488 case ISD::ADD: {
Evan Cheng77d86ff2006-02-25 10:09:08 +0000489 if (!Available) {
Evan Chenga86ba852006-02-11 02:05:36 +0000490 X86ISelAddressMode Backup = AM;
491 if (!MatchAddress(N.Val->getOperand(0), AM, false) &&
492 !MatchAddress(N.Val->getOperand(1), AM, false))
493 return false;
494 AM = Backup;
495 if (!MatchAddress(N.Val->getOperand(1), AM, false) &&
496 !MatchAddress(N.Val->getOperand(0), AM, false))
497 return false;
498 AM = Backup;
499 }
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000500 break;
501 }
Evan Cheng734e1e22006-05-30 06:59:36 +0000502
503 case ISD::OR: {
504 if (!Available) {
505 X86ISelAddressMode Backup = AM;
506 // Look for (x << c1) | c2 where (c2 < c1)
507 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(0));
508 if (CN && !MatchAddress(N.Val->getOperand(1), AM, false)) {
509 if (AM.GV == NULL && AM.Disp == 0 && CN->getValue() < AM.Scale) {
510 AM.Disp = CN->getValue();
511 return false;
512 }
513 }
514 AM = Backup;
515 CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1));
516 if (CN && !MatchAddress(N.Val->getOperand(0), AM, false)) {
517 if (AM.GV == NULL && AM.Disp == 0 && CN->getValue() < AM.Scale) {
518 AM.Disp = CN->getValue();
519 return false;
520 }
521 }
522 AM = Backup;
523 }
524 break;
525 }
Chris Lattner3f0f71b2005-11-19 02:11:08 +0000526 }
527
528 // Is the base register already occupied?
529 if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.Val) {
530 // If so, check to see if the scale index register is set.
531 if (AM.IndexReg.Val == 0) {
532 AM.IndexReg = N;
533 AM.Scale = 1;
534 return false;
535 }
536
537 // Otherwise, we cannot select it.
538 return true;
539 }
540
541 // Default, generate it as a register.
542 AM.BaseType = X86ISelAddressMode::RegBase;
543 AM.Base.Reg = N;
544 return false;
545}
546
Evan Chengc9fab312005-12-08 02:01:35 +0000547/// SelectAddr - returns true if it is able pattern match an addressing mode.
548/// It returns the operands which make up the maximal addressing mode it can
549/// match by reference.
550bool X86DAGToDAGISel::SelectAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
551 SDOperand &Index, SDOperand &Disp) {
552 X86ISelAddressMode AM;
Evan Chengbc7a0f442006-01-11 06:09:51 +0000553 if (MatchAddress(N, AM))
554 return false;
Evan Chengc9fab312005-12-08 02:01:35 +0000555
Evan Chengbc7a0f442006-01-11 06:09:51 +0000556 if (AM.BaseType == X86ISelAddressMode::RegBase) {
Evan Chengd19d51f2006-02-05 05:25:07 +0000557 if (!AM.Base.Reg.Val)
Evan Chengbc7a0f442006-01-11 06:09:51 +0000558 AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
Evan Chengc9fab312005-12-08 02:01:35 +0000559 }
Evan Chengbc7a0f442006-01-11 06:09:51 +0000560
Evan Chengd19d51f2006-02-05 05:25:07 +0000561 if (!AM.IndexReg.Val)
Evan Chengbc7a0f442006-01-11 06:09:51 +0000562 AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
563
564 getAddressOperands(AM, Base, Scale, Index, Disp);
Evan Cheng77d86ff2006-02-25 10:09:08 +0000565
Evan Cheng11a4d8c2006-07-28 00:49:31 +0000566 int Id = Base.Val ? Base.Val->getNodeId() : -1;
567 if (Id != -1)
568 setUnfoldable(Base.Val);
569 Id = Index.Val ? Index.Val->getNodeId() : -1;
570 if (Id != -1)
571 setUnfoldable(Index.Val);
572
Evan Chengbc7a0f442006-01-11 06:09:51 +0000573 return true;
Evan Chengc9fab312005-12-08 02:01:35 +0000574}
575
Evan Cheng77d86ff2006-02-25 10:09:08 +0000576/// SelectLEAAddr - it calls SelectAddr and determines if the maximal addressing
577/// mode it matches can be cost effectively emitted as an LEA instruction.
Evan Cheng77d86ff2006-02-25 10:09:08 +0000578bool X86DAGToDAGISel::SelectLEAAddr(SDOperand N, SDOperand &Base,
579 SDOperand &Scale,
580 SDOperand &Index, SDOperand &Disp) {
581 X86ISelAddressMode AM;
582 if (MatchAddress(N, AM))
583 return false;
584
585 unsigned Complexity = 0;
586 if (AM.BaseType == X86ISelAddressMode::RegBase)
587 if (AM.Base.Reg.Val)
588 Complexity = 1;
589 else
590 AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
591 else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
592 Complexity = 4;
593
594 if (AM.IndexReg.Val)
595 Complexity++;
596 else
597 AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
598
Evan Cheng990c3602006-02-28 21:13:57 +0000599 if (AM.Scale > 2)
Evan Cheng77d86ff2006-02-25 10:09:08 +0000600 Complexity += 2;
Evan Cheng990c3602006-02-28 21:13:57 +0000601 // Don't match just leal(,%reg,2). It's cheaper to do addl %reg, %reg
602 else if (AM.Scale > 1)
603 Complexity++;
Evan Cheng77d86ff2006-02-25 10:09:08 +0000604
605 // FIXME: We are artificially lowering the criteria to turn ADD %reg, $GA
606 // to a LEA. This is determined with some expermentation but is by no means
607 // optimal (especially for code size consideration). LEA is nice because of
608 // its three-address nature. Tweak the cost function again when we can run
609 // convertToThreeAddress() at register allocation time.
610 if (AM.GV || AM.CP)
611 Complexity += 2;
612
613 if (AM.Disp && (AM.Base.Reg.Val || AM.IndexReg.Val))
614 Complexity++;
615
616 if (Complexity > 2) {
617 getAddressOperands(AM, Base, Scale, Index, Disp);
618 return true;
619 }
620
Evan Cheng11a4d8c2006-07-28 00:49:31 +0000621 int Id = Base.Val ? Base.Val->getNodeId() : -1;
622 if (Id != -1)
623 setUnfoldable(Base.Val);
624 Id = Index.Val ? Index.Val->getNodeId() : -1;
625 if (Id != -1)
626 setUnfoldable(Index.Val);
627
Evan Cheng77d86ff2006-02-25 10:09:08 +0000628 return false;
629}
630
Evan Chengd5f2ba02006-02-06 06:02:33 +0000631bool X86DAGToDAGISel::TryFoldLoad(SDOperand P, SDOperand N,
632 SDOperand &Base, SDOperand &Scale,
633 SDOperand &Index, SDOperand &Disp) {
634 if (N.getOpcode() == ISD::LOAD &&
635 N.hasOneUse() &&
Evan Chenge2a3f702006-07-28 01:03:48 +0000636 !CanBeFoldedBy(N.Val, P.Val))
Evan Cheng10d27902006-01-06 20:36:21 +0000637 return SelectAddr(N.getOperand(1), Base, Scale, Index, Disp);
638 return false;
639}
640
641static bool isRegister0(SDOperand Op) {
Evan Chengc9fab312005-12-08 02:01:35 +0000642 if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op))
643 return (R->getReg() == 0);
644 return false;
645}
646
Evan Cheng5588de92006-02-18 00:15:05 +0000647/// getGlobalBaseReg - Output the instructions required to put the
648/// base address to use for accessing globals into a register.
649///
650SDOperand X86DAGToDAGISel::getGlobalBaseReg() {
651 if (!GlobalBaseReg) {
652 // Insert the set of GlobalBaseReg into the first MBB of the function
653 MachineBasicBlock &FirstMBB = BB->getParent()->front();
654 MachineBasicBlock::iterator MBBI = FirstMBB.begin();
655 SSARegMap *RegMap = BB->getParent()->getSSARegMap();
656 // FIXME: when we get to LP64, we will need to create the appropriate
657 // type of register here.
Evan Cheng9fee4422006-05-16 07:21:53 +0000658 GlobalBaseReg = RegMap->createVirtualRegister(X86::GR32RegisterClass);
Evan Cheng5588de92006-02-18 00:15:05 +0000659 BuildMI(FirstMBB, MBBI, X86::MovePCtoStack, 0);
660 BuildMI(FirstMBB, MBBI, X86::POP32r, 1, GlobalBaseReg);
661 }
662 return CurDAG->getRegister(GlobalBaseReg, MVT::i32);
663}
664
Evan Chengf838cfc2006-05-20 01:36:52 +0000665static SDNode *FindCallStartFromCall(SDNode *Node) {
666 if (Node->getOpcode() == ISD::CALLSEQ_START) return Node;
667 assert(Node->getOperand(0).getValueType() == MVT::Other &&
668 "Node doesn't have a token chain argument!");
669 return FindCallStartFromCall(Node->getOperand(0).Val);
670}
671
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000672void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) {
Evan Cheng00fcb002005-12-15 01:02:48 +0000673 SDNode *Node = N.Val;
674 MVT::ValueType NVT = Node->getValueType(0);
Evan Cheng10d27902006-01-06 20:36:21 +0000675 unsigned Opc, MOpc;
676 unsigned Opcode = Node->getOpcode();
Chris Lattner655e7df2005-11-16 01:54:32 +0000677
Evan Chengd49cc362006-02-10 22:24:32 +0000678#ifndef NDEBUG
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000679 DEBUG(std::cerr << std::string(Indent, ' '));
Evan Chengd49cc362006-02-10 22:24:32 +0000680 DEBUG(std::cerr << "Selecting: ");
681 DEBUG(Node->dump(CurDAG));
682 DEBUG(std::cerr << "\n");
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000683 Indent += 2;
Evan Chengd49cc362006-02-10 22:24:32 +0000684#endif
685
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000686 if (Opcode >= ISD::BUILTIN_OP_END && Opcode < X86ISD::FIRST_NUMBER) {
687 Result = N;
Evan Chengd49cc362006-02-10 22:24:32 +0000688#ifndef NDEBUG
Evan Chenga86ba852006-02-11 02:05:36 +0000689 DEBUG(std::cerr << std::string(Indent-2, ' '));
Evan Chengd49cc362006-02-10 22:24:32 +0000690 DEBUG(std::cerr << "== ");
691 DEBUG(Node->dump(CurDAG));
692 DEBUG(std::cerr << "\n");
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000693 Indent -= 2;
Evan Chengd49cc362006-02-10 22:24:32 +0000694#endif
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000695 return; // Already selected.
696 }
Evan Cheng2ae799a2006-01-11 22:15:18 +0000697
Evan Cheng10d27902006-01-06 20:36:21 +0000698 switch (Opcode) {
Chris Lattner655e7df2005-11-16 01:54:32 +0000699 default: break;
Evan Chenge0ed6ec2006-02-23 20:41:18 +0000700 case X86ISD::GlobalBaseReg:
701 Result = getGlobalBaseReg();
Evan Chengb9d34bd2006-08-07 22:28:20 +0000702 ReplaceUses(N, Result);
Evan Chenge0ed6ec2006-02-23 20:41:18 +0000703 return;
704
Evan Cheng77d86ff2006-02-25 10:09:08 +0000705 case ISD::ADD: {
706 // Turn ADD X, c to MOV32ri X+c. This cannot be done with tblgen'd
707 // code and is matched first so to prevent it from being turned into
708 // LEA32r X+c.
709 SDOperand N0 = N.getOperand(0);
710 SDOperand N1 = N.getOperand(1);
711 if (N.Val->getValueType(0) == MVT::i32 &&
712 N0.getOpcode() == X86ISD::Wrapper &&
713 N1.getOpcode() == ISD::Constant) {
714 unsigned Offset = (unsigned)cast<ConstantSDNode>(N1)->getValue();
715 SDOperand C(0, 0);
716 // TODO: handle ExternalSymbolSDNode.
717 if (GlobalAddressSDNode *G =
718 dyn_cast<GlobalAddressSDNode>(N0.getOperand(0))) {
719 C = CurDAG->getTargetGlobalAddress(G->getGlobal(), MVT::i32,
720 G->getOffset() + Offset);
721 } else if (ConstantPoolSDNode *CP =
722 dyn_cast<ConstantPoolSDNode>(N0.getOperand(0))) {
723 C = CurDAG->getTargetConstantPool(CP->get(), MVT::i32,
724 CP->getAlignment(),
725 CP->getOffset()+Offset);
726 }
727
728 if (C.Val) {
729 if (N.Val->hasOneUse()) {
730 Result = CurDAG->SelectNodeTo(N.Val, X86::MOV32ri, MVT::i32, C);
731 } else {
732 SDNode *ResNode = CurDAG->getTargetNode(X86::MOV32ri, MVT::i32, C);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000733 Result = SDOperand(ResNode, 0);
734 ReplaceUses(N, Result);
Evan Cheng77d86ff2006-02-25 10:09:08 +0000735 }
736 return;
737 }
738 }
739
740 // Other cases are handled by auto-generated code.
741 break;
Evan Cheng1f342c22006-02-23 02:43:52 +0000742 }
Evan Chenge0ed6ec2006-02-23 20:41:18 +0000743
Evan Cheng10d27902006-01-06 20:36:21 +0000744 case ISD::MULHU:
745 case ISD::MULHS: {
746 if (Opcode == ISD::MULHU)
747 switch (NVT) {
748 default: assert(0 && "Unsupported VT!");
749 case MVT::i8: Opc = X86::MUL8r; MOpc = X86::MUL8m; break;
750 case MVT::i16: Opc = X86::MUL16r; MOpc = X86::MUL16m; break;
751 case MVT::i32: Opc = X86::MUL32r; MOpc = X86::MUL32m; break;
752 }
753 else
754 switch (NVT) {
755 default: assert(0 && "Unsupported VT!");
756 case MVT::i8: Opc = X86::IMUL8r; MOpc = X86::IMUL8m; break;
757 case MVT::i16: Opc = X86::IMUL16r; MOpc = X86::IMUL16m; break;
758 case MVT::i32: Opc = X86::IMUL32r; MOpc = X86::IMUL32m; break;
759 }
760
761 unsigned LoReg, HiReg;
762 switch (NVT) {
763 default: assert(0 && "Unsupported VT!");
764 case MVT::i8: LoReg = X86::AL; HiReg = X86::AH; break;
765 case MVT::i16: LoReg = X86::AX; HiReg = X86::DX; break;
766 case MVT::i32: LoReg = X86::EAX; HiReg = X86::EDX; break;
767 }
768
769 SDOperand N0 = Node->getOperand(0);
770 SDOperand N1 = Node->getOperand(1);
771
772 bool foldedLoad = false;
773 SDOperand Tmp0, Tmp1, Tmp2, Tmp3;
Evan Chengd5f2ba02006-02-06 06:02:33 +0000774 foldedLoad = TryFoldLoad(N, N1, Tmp0, Tmp1, Tmp2, Tmp3);
Evan Cheng92e27972006-01-06 23:19:29 +0000775 // MULHU and MULHS are commmutative
776 if (!foldedLoad) {
Evan Chengd5f2ba02006-02-06 06:02:33 +0000777 foldedLoad = TryFoldLoad(N, N0, Tmp0, Tmp1, Tmp2, Tmp3);
Evan Cheng92e27972006-01-06 23:19:29 +0000778 if (foldedLoad) {
779 N0 = Node->getOperand(1);
780 N1 = Node->getOperand(0);
781 }
782 }
783
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000784 SDOperand Chain;
785 if (foldedLoad)
Evan Chengb9d34bd2006-08-07 22:28:20 +0000786 AddToQueue(Chain, N1.getOperand(0));
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000787 else
788 Chain = CurDAG->getEntryNode();
Evan Cheng10d27902006-01-06 20:36:21 +0000789
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000790 SDOperand InFlag(0, 0);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000791 AddToQueue(N0, N0);
Evan Cheng10d27902006-01-06 20:36:21 +0000792 Chain = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(LoReg, NVT),
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000793 N0, InFlag);
Evan Cheng10d27902006-01-06 20:36:21 +0000794 InFlag = Chain.getValue(1);
795
796 if (foldedLoad) {
Evan Chengb9d34bd2006-08-07 22:28:20 +0000797 AddToQueue(Tmp0, Tmp0);
798 AddToQueue(Tmp1, Tmp1);
799 AddToQueue(Tmp2, Tmp2);
800 AddToQueue(Tmp3, Tmp3);
Evan Chengd1b82d82006-02-09 07:17:49 +0000801 SDNode *CNode =
802 CurDAG->getTargetNode(MOpc, MVT::Other, MVT::Flag, Tmp0, Tmp1,
803 Tmp2, Tmp3, Chain, InFlag);
804 Chain = SDOperand(CNode, 0);
805 InFlag = SDOperand(CNode, 1);
Evan Cheng10d27902006-01-06 20:36:21 +0000806 } else {
Evan Chengb9d34bd2006-08-07 22:28:20 +0000807 AddToQueue(N1, N1);
Evan Chengd1b82d82006-02-09 07:17:49 +0000808 InFlag =
809 SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
Evan Cheng10d27902006-01-06 20:36:21 +0000810 }
811
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000812 Result = CurDAG->getCopyFromReg(Chain, HiReg, NVT, InFlag);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000813 ReplaceUses(N.getValue(0), Result);
814 if (foldedLoad)
815 ReplaceUses(N1.getValue(1), Result.getValue(1));
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000816
Evan Chengd49cc362006-02-10 22:24:32 +0000817#ifndef NDEBUG
Evan Chenga86ba852006-02-11 02:05:36 +0000818 DEBUG(std::cerr << std::string(Indent-2, ' '));
Evan Chengb9d34bd2006-08-07 22:28:20 +0000819 DEBUG(std::cerr << "=> ");
Evan Chengd49cc362006-02-10 22:24:32 +0000820 DEBUG(Result.Val->dump(CurDAG));
821 DEBUG(std::cerr << "\n");
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000822 Indent -= 2;
Evan Chengd49cc362006-02-10 22:24:32 +0000823#endif
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000824 return;
Evan Cheng92e27972006-01-06 23:19:29 +0000825 }
Evan Cheng5588de92006-02-18 00:15:05 +0000826
Evan Cheng92e27972006-01-06 23:19:29 +0000827 case ISD::SDIV:
828 case ISD::UDIV:
829 case ISD::SREM:
830 case ISD::UREM: {
831 bool isSigned = Opcode == ISD::SDIV || Opcode == ISD::SREM;
832 bool isDiv = Opcode == ISD::SDIV || Opcode == ISD::UDIV;
833 if (!isSigned)
834 switch (NVT) {
835 default: assert(0 && "Unsupported VT!");
836 case MVT::i8: Opc = X86::DIV8r; MOpc = X86::DIV8m; break;
837 case MVT::i16: Opc = X86::DIV16r; MOpc = X86::DIV16m; break;
838 case MVT::i32: Opc = X86::DIV32r; MOpc = X86::DIV32m; break;
839 }
840 else
841 switch (NVT) {
842 default: assert(0 && "Unsupported VT!");
843 case MVT::i8: Opc = X86::IDIV8r; MOpc = X86::IDIV8m; break;
844 case MVT::i16: Opc = X86::IDIV16r; MOpc = X86::IDIV16m; break;
845 case MVT::i32: Opc = X86::IDIV32r; MOpc = X86::IDIV32m; break;
846 }
847
848 unsigned LoReg, HiReg;
849 unsigned ClrOpcode, SExtOpcode;
850 switch (NVT) {
851 default: assert(0 && "Unsupported VT!");
852 case MVT::i8:
853 LoReg = X86::AL; HiReg = X86::AH;
Evan Chenga2efb9f2006-06-02 21:20:34 +0000854 ClrOpcode = X86::MOV8r0;
Evan Cheng92e27972006-01-06 23:19:29 +0000855 SExtOpcode = X86::CBW;
856 break;
857 case MVT::i16:
858 LoReg = X86::AX; HiReg = X86::DX;
Evan Chenga2efb9f2006-06-02 21:20:34 +0000859 ClrOpcode = X86::MOV16r0;
Evan Cheng92e27972006-01-06 23:19:29 +0000860 SExtOpcode = X86::CWD;
861 break;
862 case MVT::i32:
863 LoReg = X86::EAX; HiReg = X86::EDX;
Evan Chenga2efb9f2006-06-02 21:20:34 +0000864 ClrOpcode = X86::MOV32r0;
Evan Cheng92e27972006-01-06 23:19:29 +0000865 SExtOpcode = X86::CDQ;
866 break;
867 }
868
869 SDOperand N0 = Node->getOperand(0);
870 SDOperand N1 = Node->getOperand(1);
871
872 bool foldedLoad = false;
873 SDOperand Tmp0, Tmp1, Tmp2, Tmp3;
Evan Chengd5f2ba02006-02-06 06:02:33 +0000874 foldedLoad = TryFoldLoad(N, N1, Tmp0, Tmp1, Tmp2, Tmp3);
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000875 SDOperand Chain;
876 if (foldedLoad)
Evan Chengb9d34bd2006-08-07 22:28:20 +0000877 AddToQueue(Chain, N1.getOperand(0));
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000878 else
879 Chain = CurDAG->getEntryNode();
Evan Cheng92e27972006-01-06 23:19:29 +0000880
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000881 SDOperand InFlag(0, 0);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000882 AddToQueue(N0, N0);
Evan Cheng92e27972006-01-06 23:19:29 +0000883 Chain = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(LoReg, NVT),
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000884 N0, InFlag);
Evan Cheng92e27972006-01-06 23:19:29 +0000885 InFlag = Chain.getValue(1);
886
887 if (isSigned) {
888 // Sign extend the low part into the high part.
Evan Chengd1b82d82006-02-09 07:17:49 +0000889 InFlag =
890 SDOperand(CurDAG->getTargetNode(SExtOpcode, MVT::Flag, InFlag), 0);
Evan Cheng92e27972006-01-06 23:19:29 +0000891 } else {
892 // Zero out the high part, effectively zero extending the input.
Evan Chenga2efb9f2006-06-02 21:20:34 +0000893 SDOperand ClrNode = SDOperand(CurDAG->getTargetNode(ClrOpcode, NVT), 0);
Evan Cheng92e27972006-01-06 23:19:29 +0000894 Chain = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(HiReg, NVT),
895 ClrNode, InFlag);
896 InFlag = Chain.getValue(1);
897 }
898
899 if (foldedLoad) {
Evan Chengb9d34bd2006-08-07 22:28:20 +0000900 AddToQueue(Tmp0, Tmp0);
901 AddToQueue(Tmp1, Tmp1);
902 AddToQueue(Tmp2, Tmp2);
903 AddToQueue(Tmp3, Tmp3);
Evan Chengd1b82d82006-02-09 07:17:49 +0000904 SDNode *CNode =
905 CurDAG->getTargetNode(MOpc, MVT::Other, MVT::Flag, Tmp0, Tmp1,
906 Tmp2, Tmp3, Chain, InFlag);
907 Chain = SDOperand(CNode, 0);
908 InFlag = SDOperand(CNode, 1);
Evan Cheng92e27972006-01-06 23:19:29 +0000909 } else {
Evan Chengb9d34bd2006-08-07 22:28:20 +0000910 AddToQueue(N1, N1);
Evan Chengd1b82d82006-02-09 07:17:49 +0000911 InFlag =
912 SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
Evan Cheng92e27972006-01-06 23:19:29 +0000913 }
914
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000915 Result = CurDAG->getCopyFromReg(Chain, isDiv ? LoReg : HiReg,
916 NVT, InFlag);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000917 ReplaceUses(N.getValue(0), Result);
918 if (foldedLoad)
919 ReplaceUses(N1.getValue(1), Result.getValue(1));
Evan Chengd49cc362006-02-10 22:24:32 +0000920
921#ifndef NDEBUG
Evan Chenga86ba852006-02-11 02:05:36 +0000922 DEBUG(std::cerr << std::string(Indent-2, ' '));
Evan Chengb9d34bd2006-08-07 22:28:20 +0000923 DEBUG(std::cerr << "=> ");
Evan Chengd49cc362006-02-10 22:24:32 +0000924 DEBUG(Result.Val->dump(CurDAG));
925 DEBUG(std::cerr << "\n");
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000926 Indent -= 2;
Evan Chengd49cc362006-02-10 22:24:32 +0000927#endif
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000928 return;
Evan Cheng10d27902006-01-06 20:36:21 +0000929 }
Evan Cheng9733bde2006-05-08 08:01:26 +0000930
931 case ISD::TRUNCATE: {
932 if (NVT == MVT::i8) {
933 unsigned Opc2;
934 MVT::ValueType VT;
935 switch (Node->getOperand(0).getValueType()) {
936 default: assert(0 && "Unknown truncate!");
937 case MVT::i16:
938 Opc = X86::MOV16to16_;
939 VT = MVT::i16;
Evan Cheng9fee4422006-05-16 07:21:53 +0000940 Opc2 = X86::TRUNC_GR16_GR8;
Evan Cheng9733bde2006-05-08 08:01:26 +0000941 break;
942 case MVT::i32:
943 Opc = X86::MOV32to32_;
944 VT = MVT::i32;
Evan Cheng9fee4422006-05-16 07:21:53 +0000945 Opc2 = X86::TRUNC_GR32_GR8;
Evan Cheng9733bde2006-05-08 08:01:26 +0000946 break;
947 }
948
949 SDOperand Tmp0, Tmp1;
Evan Chengb9d34bd2006-08-07 22:28:20 +0000950 AddToQueue(Tmp0, Node->getOperand(0));
Evan Cheng9733bde2006-05-08 08:01:26 +0000951 Tmp1 = SDOperand(CurDAG->getTargetNode(Opc, VT, Tmp0), 0);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000952 Result = SDOperand(CurDAG->getTargetNode(Opc2, NVT, Tmp1), 0);
953 ReplaceUses(N, Result);
Evan Cheng9733bde2006-05-08 08:01:26 +0000954
955#ifndef NDEBUG
956 DEBUG(std::cerr << std::string(Indent-2, ' '));
Evan Chengb9d34bd2006-08-07 22:28:20 +0000957 DEBUG(std::cerr << "=> ");
Evan Cheng9733bde2006-05-08 08:01:26 +0000958 DEBUG(Result.Val->dump(CurDAG));
959 DEBUG(std::cerr << "\n");
960 Indent -= 2;
961#endif
962 return;
963 }
Evan Chenga26c4512006-05-20 07:44:28 +0000964
965 break;
Evan Cheng9733bde2006-05-08 08:01:26 +0000966 }
Chris Lattner655e7df2005-11-16 01:54:32 +0000967 }
968
Evan Cheng6dc90ca2006-02-09 00:37:58 +0000969 SelectCode(Result, N);
Evan Chengd49cc362006-02-10 22:24:32 +0000970#ifndef NDEBUG
Evan Chenga86ba852006-02-11 02:05:36 +0000971 DEBUG(std::cerr << std::string(Indent-2, ' '));
Evan Chengd49cc362006-02-10 22:24:32 +0000972 DEBUG(std::cerr << "=> ");
973 DEBUG(Result.Val->dump(CurDAG));
974 DEBUG(std::cerr << "\n");
Evan Cheng2b6f78b2006-02-10 22:46:26 +0000975 Indent -= 2;
Evan Chengd49cc362006-02-10 22:24:32 +0000976#endif
Chris Lattner655e7df2005-11-16 01:54:32 +0000977}
978
Chris Lattnerba1ed582006-06-08 18:03:49 +0000979bool X86DAGToDAGISel::
980SelectInlineAsmMemoryOperand(const SDOperand &Op, char ConstraintCode,
981 std::vector<SDOperand> &OutOps, SelectionDAG &DAG){
982 SDOperand Op0, Op1, Op2, Op3;
983 switch (ConstraintCode) {
984 case 'o': // offsetable ??
985 case 'v': // not offsetable ??
986 default: return true;
987 case 'm': // memory
988 if (!SelectAddr(Op, Op0, Op1, Op2, Op3))
989 return true;
990 break;
991 }
992
993 OutOps.resize(4);
Evan Chengb9d34bd2006-08-07 22:28:20 +0000994 AddToQueue(OutOps[0], Op0);
995 AddToQueue(OutOps[1], Op1);
996 AddToQueue(OutOps[2], Op2);
997 AddToQueue(OutOps[3], Op3);
Chris Lattnerba1ed582006-06-08 18:03:49 +0000998 return false;
999}
1000
Chris Lattner655e7df2005-11-16 01:54:32 +00001001/// createX86ISelDag - This pass converts a legalized DAG into a
1002/// X86-specific DAG, ready for instruction scheduling.
1003///
Evan Cheng2dd2c652006-03-13 23:20:37 +00001004FunctionPass *llvm::createX86ISelDag(X86TargetMachine &TM) {
Chris Lattner655e7df2005-11-16 01:54:32 +00001005 return new X86DAGToDAGISel(TM);
1006}