ARM backend contribution from Apple.
[oota-llvm.git] / lib / Target / ARM / ARMISelDAGToDAG.cpp
1 //===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines an instruction selector for the ARM target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARM.h"
15 #include "ARMISelLowering.h"
16 #include "ARMTargetMachine.h"
17 #include "ARMAddressingModes.h"
18 #include "llvm/CallingConv.h"
19 #include "llvm/Constants.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Function.h"
22 #include "llvm/Intrinsics.h"
23 #include "llvm/CodeGen/MachineFrameInfo.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/CodeGen/SelectionDAG.h"
27 #include "llvm/CodeGen/SelectionDAGISel.h"
28 #include "llvm/CodeGen/SSARegMap.h"
29 #include "llvm/Target/TargetLowering.h"
30 #include "llvm/Support/Debug.h"
31 #include <iostream>
32 using namespace llvm;
33
34 //===--------------------------------------------------------------------===//
35 /// ARMDAGToDAGISel - ARM specific code to select ARM machine
36 /// instructions for SelectionDAG operations.
37 ///
38 namespace {
39 class ARMDAGToDAGISel : public SelectionDAGISel {
40   ARMTargetLowering Lowering;
41
42   /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
43   /// make the right decision when generating code for different targets.
44   const ARMSubtarget *Subtarget;
45
46 public:
47   ARMDAGToDAGISel(ARMTargetMachine &TM)
48     : SelectionDAGISel(Lowering), Lowering(TM),
49     Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
50   }
51
52   virtual const char *getPassName() const {
53     return "ARM Instruction Selection";
54   } 
55   
56   SDNode *Select(SDOperand Op);
57   virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
58   bool SelectAddrMode2(SDOperand Op, SDOperand N, SDOperand &Base,
59                        SDOperand &Offset, SDOperand &Opc);
60   bool SelectAddrMode2Offset(SDOperand Op, SDOperand N,
61                              SDOperand &Offset, SDOperand &Opc);
62   bool SelectAddrMode3(SDOperand Op, SDOperand N, SDOperand &Base,
63                        SDOperand &Offset, SDOperand &Opc);
64   bool SelectAddrMode3Offset(SDOperand Op, SDOperand N,
65                              SDOperand &Offset, SDOperand &Opc);
66   bool SelectAddrMode5(SDOperand Op, SDOperand N, SDOperand &Base,
67                        SDOperand &Offset);
68
69   bool SelectAddrModePC(SDOperand Op, SDOperand N, SDOperand &Offset,
70                          SDOperand &Label);
71
72   bool SelectThumbAddrModeRR(SDOperand Op, SDOperand N, SDOperand &Base,
73                              SDOperand &Offset);
74   bool SelectThumbAddrModeRI5_1(SDOperand Op, SDOperand N, SDOperand &Base,
75                                 SDOperand &Offset);
76   bool SelectThumbAddrModeRI5_2(SDOperand Op, SDOperand N, SDOperand &Base,
77                                 SDOperand &Offset);
78   bool SelectThumbAddrModeRI5_4(SDOperand Op, SDOperand N, SDOperand &Base,
79                                 SDOperand &Offset);
80   bool SelectThumbAddrModeSP(SDOperand Op, SDOperand N, SDOperand &Base,
81                              SDOperand &Offset);
82
83   bool SelectShifterOperandReg(SDOperand Op, SDOperand N, SDOperand &A,
84                                SDOperand &B, SDOperand &C);
85   
86   // Include the pieces autogenerated from the target description.
87 #include "ARMGenDAGISel.inc"
88 };
89 }
90
91 void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
92   DEBUG(BB->dump());
93
94   DAG.setRoot(SelectRoot(DAG.getRoot()));
95   DAG.RemoveDeadNodes();
96
97   ScheduleAndEmitDAG(DAG);
98 }
99
100 bool ARMDAGToDAGISel::SelectAddrMode2(SDOperand Op, SDOperand N,
101                                       SDOperand &Base, SDOperand &Offset,
102                                       SDOperand &Opc) {
103   if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
104     Base = N;
105     if (N.getOpcode() == ISD::FrameIndex) {
106       int FI = cast<FrameIndexSDNode>(N)->getIndex();
107       Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
108     } else if (N.getOpcode() == ARMISD::Wrapper) {
109       Base = N.getOperand(0);
110     }
111     Offset = CurDAG->getRegister(0, MVT::i32);
112     Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
113                                                       ARM_AM::no_shift),
114                                     MVT::i32);
115     return true;
116   }
117   
118   // Match simple R +/- imm12 operands.
119   if (N.getOpcode() == ISD::ADD)
120     if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
121       int RHSC = (int)RHS->getValue();
122       if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits.
123         Base = N.getOperand(0);
124         Offset = CurDAG->getRegister(0, MVT::i32);
125         Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, RHSC,
126                                                           ARM_AM::no_shift),
127                                         MVT::i32);
128         return true;
129       } else if (RHSC < 0 && RHSC > -0x1000) {
130         Base = N.getOperand(0);
131         Offset = CurDAG->getRegister(0, MVT::i32);
132         Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::sub, -RHSC,
133                                                           ARM_AM::no_shift),
134                                         MVT::i32);
135         return true;
136       }
137     }
138   
139   // Otherwise this is R +/- [possibly shifted] R
140   ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub;
141   ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1));
142   unsigned ShAmt = 0;
143   
144   Base   = N.getOperand(0);
145   Offset = N.getOperand(1);
146   
147   if (ShOpcVal != ARM_AM::no_shift) {
148     // Check to see if the RHS of the shift is a constant, if not, we can't fold
149     // it.
150     if (ConstantSDNode *Sh =
151            dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
152       ShAmt = Sh->getValue();
153       Offset = N.getOperand(1).getOperand(0);
154     } else {
155       ShOpcVal = ARM_AM::no_shift;
156     }
157   }
158   
159   // Try matching (R shl C) + (R).
160   if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) {
161     ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0));
162     if (ShOpcVal != ARM_AM::no_shift) {
163       // Check to see if the RHS of the shift is a constant, if not, we can't
164       // fold it.
165       if (ConstantSDNode *Sh =
166           dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
167         ShAmt = Sh->getValue();
168         Offset = N.getOperand(0).getOperand(0);
169         Base = N.getOperand(1);
170       } else {
171         ShOpcVal = ARM_AM::no_shift;
172       }
173     }
174   }
175   
176   Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
177                                   MVT::i32);
178   return true;
179 }
180
181 bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDOperand Op, SDOperand N,
182                                             SDOperand &Offset, SDOperand &Opc) {
183   unsigned Opcode = Op.getOpcode();
184   ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
185     ? cast<LoadSDNode>(Op)->getAddressingMode()
186     : cast<StoreSDNode>(Op)->getAddressingMode();
187   ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
188     ? ARM_AM::add : ARM_AM::sub;
189   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
190     int Val = (int)C->getValue();
191     if (Val >= 0 && Val < 0x1000) { // 12 bits.
192       Offset = CurDAG->getRegister(0, MVT::i32);
193       Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
194                                                         ARM_AM::no_shift),
195                                       MVT::i32);
196       return true;
197     }
198   }
199
200   Offset = N;
201   ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
202   unsigned ShAmt = 0;
203   if (ShOpcVal != ARM_AM::no_shift) {
204     // Check to see if the RHS of the shift is a constant, if not, we can't fold
205     // it.
206     if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
207       ShAmt = Sh->getValue();
208       Offset = N.getOperand(0);
209     } else {
210       ShOpcVal = ARM_AM::no_shift;
211     }
212   }
213
214   Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
215                                   MVT::i32);
216   return true;
217 }
218
219
220 bool ARMDAGToDAGISel::SelectAddrMode3(SDOperand Op, SDOperand N,
221                                       SDOperand &Base, SDOperand &Offset,
222                                       SDOperand &Opc) {
223   if (N.getOpcode() == ISD::SUB) {
224     // X - C  is canonicalize to X + -C, no need to handle it here.
225     Base = N.getOperand(0);
226     Offset = N.getOperand(1);
227     Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
228     return true;
229   }
230   
231   if (N.getOpcode() != ISD::ADD) {
232     Base = N;
233     if (N.getOpcode() == ISD::FrameIndex) {
234       int FI = cast<FrameIndexSDNode>(N)->getIndex();
235       Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
236     }
237     Offset = CurDAG->getRegister(0, MVT::i32);
238     Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
239     return true;
240   }
241   
242   // If the RHS is +/- imm8, fold into addr mode.
243   if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
244     int RHSC = (int)RHS->getValue();
245     if (RHSC >= 0 && RHSC < 256) {
246       Base = N.getOperand(0);
247       Offset = CurDAG->getRegister(0, MVT::i32);
248       Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, RHSC),
249                                       MVT::i32);
250       return true;
251     } else if (RHSC < 0 && RHSC > -256) { // note -256 itself isn't allowed.
252       Base = N.getOperand(0);
253       Offset = CurDAG->getRegister(0, MVT::i32);
254       Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, -RHSC),
255                                       MVT::i32);
256       return true;
257     }
258   }
259   
260   Base = N.getOperand(0);
261   Offset = N.getOperand(1);
262   Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
263   return true;
264 }
265
266 bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDOperand Op, SDOperand N,
267                                             SDOperand &Offset, SDOperand &Opc) {
268   unsigned Opcode = Op.getOpcode();
269   ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
270     ? cast<LoadSDNode>(Op)->getAddressingMode()
271     : cast<StoreSDNode>(Op)->getAddressingMode();
272   ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
273     ? ARM_AM::add : ARM_AM::sub;
274   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
275     int Val = (int)C->getValue();
276     if (Val >= 0 && Val < 256) {
277       Offset = CurDAG->getRegister(0, MVT::i32);
278       Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
279       return true;
280     }
281   }
282
283   Offset = N;
284   Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
285   return true;
286 }
287
288
289 bool ARMDAGToDAGISel::SelectAddrMode5(SDOperand Op, SDOperand N,
290                                       SDOperand &Base, SDOperand &Offset) {
291   if (N.getOpcode() != ISD::ADD) {
292     Base = N;
293     if (N.getOpcode() == ISD::FrameIndex) {
294       int FI = cast<FrameIndexSDNode>(N)->getIndex();
295       Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
296     } else if (N.getOpcode() == ARMISD::Wrapper) {
297       Base = N.getOperand(0);
298     }
299     Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
300                                        MVT::i32);
301     return true;
302   }
303   
304   // If the RHS is +/- imm8, fold into addr mode.
305   if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
306     int RHSC = (int)RHS->getValue();
307     if ((RHSC & 3) == 0) {  // The constant is implicitly multiplied by 4.
308       RHSC >>= 2;
309       if (RHSC >= 0 && RHSC < 256) {
310         Base = N.getOperand(0);
311         Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, RHSC),
312                                            MVT::i32);
313         return true;
314       } else if (RHSC < 0 && RHSC > -256) { // note -256 itself isn't allowed.
315         Base = N.getOperand(0);
316         Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::sub,-RHSC),
317                                            MVT::i32);
318         return true;
319       }
320     }
321   }
322   
323   Base = N;
324   Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
325                                      MVT::i32);
326   return true;
327 }
328
329 bool ARMDAGToDAGISel::SelectAddrModePC(SDOperand Op, SDOperand N,
330                                         SDOperand &Offset, SDOperand &Label) {
331   if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
332     Offset = N.getOperand(0);
333     SDOperand N1 = N.getOperand(1);
334     Label  = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getValue(),
335                                        MVT::i32);
336     return true;
337   }
338   return false;
339 }
340
341 bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDOperand Op, SDOperand N,
342                                             SDOperand &Base, SDOperand &Offset){
343   if (N.getOpcode() != ISD::ADD)
344     return false;
345   Base = N.getOperand(0);
346   Offset = N.getOperand(1);
347   return true;
348 }
349
350 static bool SelectThumbAddrModeRI5(SDOperand N, unsigned Scale,
351                                    TargetLowering &TLI, SelectionDAG *CurDAG,
352                                    SDOperand &Base, SDOperand &Offset) {
353   if (N.getOpcode() == ISD::FrameIndex)
354     return false;
355     
356   if (N.getOpcode() != ISD::ADD) {
357     Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N;
358     Offset = CurDAG->getTargetConstant(0, MVT::i32);
359     return true;
360   }
361
362   // If the RHS is + imm5 * scale, fold into addr mode.
363   if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
364     int RHSC = (int)RHS->getValue();
365     if ((RHSC & (Scale-1)) == 0) {  // The constant is implicitly multiplied.
366       RHSC /= Scale;
367       if (RHSC >= 0 && RHSC < 32) {
368         Base = N.getOperand(0);
369         Offset = CurDAG->getTargetConstant(RHSC, MVT::i32);
370         return true;
371       }
372     }
373   }
374
375   return false;
376 }
377
378 bool ARMDAGToDAGISel::SelectThumbAddrModeRI5_1(SDOperand Op, SDOperand N,
379                                             SDOperand &Base, SDOperand &Offset){
380   return SelectThumbAddrModeRI5(N, 1, TLI, CurDAG, Base, Offset);
381 }
382
383 bool ARMDAGToDAGISel::SelectThumbAddrModeRI5_2(SDOperand Op, SDOperand N,
384                                             SDOperand &Base, SDOperand &Offset){
385   return SelectThumbAddrModeRI5(N, 2, TLI, CurDAG, Base, Offset);
386 }
387
388 bool ARMDAGToDAGISel::SelectThumbAddrModeRI5_4(SDOperand Op, SDOperand N,
389                                             SDOperand &Base, SDOperand &Offset){
390   return SelectThumbAddrModeRI5(N, 4, TLI, CurDAG, Base, Offset);
391 }
392
393 bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDOperand Op, SDOperand N,
394                                            SDOperand &Base, SDOperand &Offset) {
395   if (N.getOpcode() == ISD::FrameIndex) {
396     int FI = cast<FrameIndexSDNode>(N)->getIndex();
397     Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
398     Offset = CurDAG->getTargetConstant(0, MVT::i32);
399     return true;
400   }
401   
402   return false;
403 }
404
405 bool ARMDAGToDAGISel::SelectShifterOperandReg(SDOperand Op,
406                                               SDOperand N, 
407                                               SDOperand &BaseReg,
408                                               SDOperand &ShReg,
409                                               SDOperand &Opc) {
410   ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
411
412   // Don't match base register only case. That is matched to a separate
413   // lower complexity pattern with explicit register operand.
414   if (ShOpcVal == ARM_AM::no_shift) return false;
415   
416   BaseReg = N.getOperand(0);
417   unsigned ShImmVal = 0;
418   if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
419     ShReg = CurDAG->getRegister(0, MVT::i32);
420     ShImmVal = RHS->getValue() & 31;
421   } else {
422     ShReg = N.getOperand(1);
423   }
424   Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
425                                   MVT::i32);
426   return true;
427 }
428
429
430 SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
431   SDNode *N = Op.Val;
432   unsigned Opcode = N->getOpcode();
433
434   if (Opcode >= ISD::BUILTIN_OP_END && Opcode < ARMISD::FIRST_NUMBER)
435     return NULL;   // Already selected.
436
437   switch (N->getOpcode()) {
438   default: break;
439   case ISD::Constant: {
440     unsigned Val = cast<ConstantSDNode>(N)->getValue();
441     bool UseCP = true;
442     if (Subtarget->isThumb())
443       UseCP = (Val > 255 &&                          // MOV
444                ~Val > 255 &&                         // MOV + MVN
445                !ARM_AM::isThumbImmShiftedVal(Val));  // MOV + LSL
446     else
447       UseCP = (ARM_AM::getSOImmVal(Val) == -1 &&     // MOV
448                ARM_AM::getSOImmVal(~Val) == -1 &&    // MVN
449                !ARM_AM::isSOImmTwoPartVal(Val));     // two instrs.
450     if (UseCP) {
451       SDOperand CPIdx =
452         CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val),
453                                       TLI.getPointerTy());
454       SDOperand Ops[] = {
455         CPIdx, 
456         CurDAG->getRegister(0, MVT::i32),
457         CurDAG->getTargetConstant(0, MVT::i32),
458         CurDAG->getEntryNode()
459       };
460       SDNode *ResNode = 
461         CurDAG->getTargetNode(ARM::LDR, MVT::i32, MVT::Other, Ops, 4);
462       ReplaceUses(Op, SDOperand(ResNode, 0));
463       return NULL;
464     }
465       
466     // Other cases are autogenerated.
467     break;
468   }
469   case ISD::FrameIndex: {
470     // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
471     int FI = cast<FrameIndexSDNode>(N)->getIndex();
472     unsigned Opc = Subtarget->isThumb() ? ARM::tADDrSPi : ARM::ADDri;
473     SDOperand TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
474     return CurDAG->SelectNodeTo(N, Opc, MVT::i32, TFI,
475                                 CurDAG->getTargetConstant(0, MVT::i32));
476   }
477   case ISD::MUL:
478     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
479       unsigned RHSV = C->getValue();
480       if (!RHSV) break;
481       if (isPowerOf2_32(RHSV-1)) {  // 2^n+1?
482         SDOperand V = Op.getOperand(0);
483         AddToISelQueue(V);
484         unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1));
485         SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
486           CurDAG->getTargetConstant(ShImm, MVT::i32)
487         };
488         return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 4);
489       }
490       if (isPowerOf2_32(RHSV+1)) {  // 2^n-1?
491         SDOperand V = Op.getOperand(0);
492         AddToISelQueue(V);
493         unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1));
494         SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
495           CurDAG->getTargetConstant(ShImm, MVT::i32)
496         };
497         return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 4);
498       }
499     }
500     break;
501   case ARMISD::FMRRD:
502     AddToISelQueue(Op.getOperand(0));
503     return CurDAG->getTargetNode(ARM::FMRRD, MVT::i32, MVT::i32,
504                                  Op.getOperand(0));
505   case ARMISD::MULHILOU:
506     AddToISelQueue(Op.getOperand(0));
507     AddToISelQueue(Op.getOperand(1));
508     return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32,
509                                  Op.getOperand(0), Op.getOperand(1));
510   case ARMISD::MULHILOS:
511     AddToISelQueue(Op.getOperand(0));
512     AddToISelQueue(Op.getOperand(1));
513     return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32,
514                                  Op.getOperand(0), Op.getOperand(1));
515   case ISD::LOAD: {
516     LoadSDNode *LD = cast<LoadSDNode>(Op);
517     ISD::MemIndexedMode AM = LD->getAddressingMode();
518     MVT::ValueType LoadedVT = LD->getLoadedVT();
519     if (AM != ISD::UNINDEXED) {
520       SDOperand Offset, AMOpc;
521       bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
522       unsigned Opcode = 0;
523       bool Match = false;
524       if (LoadedVT == MVT::i32 &&
525           SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) {
526         Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST;
527         Match = true;
528       } else if (LoadedVT == MVT::i16 &&
529                  SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) {
530         Match = true;
531         Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
532           ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
533           : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
534       } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
535         if (LD->getExtensionType() == ISD::SEXTLOAD) {
536           if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) {
537             Match = true;
538             Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
539           }
540         } else {
541           if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) {
542             Match = true;
543             Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST;
544           }
545         }
546       }
547
548       if (Match) {
549         SDOperand Chain = LD->getChain();
550         SDOperand Base = LD->getBasePtr();
551         AddToISelQueue(Chain);
552         AddToISelQueue(Base);
553         AddToISelQueue(Offset);
554         SDOperand Ops[] = { Base, Offset, AMOpc, Chain };
555         return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32,
556                                      MVT::Other, Ops, 4);
557       }
558     }
559     // Other cases are autogenerated.
560     break;
561   }
562   }
563
564   return SelectCode(Op);
565 }
566
567 /// createARMISelDag - This pass converts a legalized DAG into a
568 /// ARM-specific DAG, ready for instruction scheduling.
569 ///
570 FunctionPass *llvm::createARMISelDag(ARMTargetMachine &TM) {
571   return new ARMDAGToDAGISel(TM);
572 }