For inline asm output operand that matches an input. Encode the input operand index...
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAGISel.cpp
index fb5619cc49ccaec8da3f14534096af857e8eb678..fdabd4cb25e61d36d6abdaadd7e90e550a408878 100644 (file)
@@ -12,9 +12,9 @@
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "isel"
-#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "ScheduleDAGSDNodes.h"
 #include "SelectionDAGBuild.h"
-#include "llvm/ADT/BitVector.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Constants.h"
 #include "llvm/CallingConv.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
 #include "llvm/CodeGen/SchedulerRegistry.h"
 #include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/DwarfWriter.h"
 #include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetFrameInfo.h"
 using namespace llvm;
 
 static cl::opt<bool>
-EnableValueProp("enable-value-prop", cl::Hidden);
-static cl::opt<bool>
-EnableLegalizeTypes("enable-legalize-types", cl::Hidden);
+DisableLegalizeTypes("disable-legalize-types", cl::Hidden);
+#ifndef NDEBUG
 static cl::opt<bool>
 EnableFastISelVerbose("fast-isel-verbose", cl::Hidden,
-          cl::desc("Enable verbose messages in the experimental \"fast\" "
+          cl::desc("Enable verbose messages in the \"fast\" "
                    "instruction selector"));
 static cl::opt<bool>
 EnableFastISelAbort("fast-isel-abort", cl::Hidden,
           cl::desc("Enable abort calls when \"fast\" instruction fails"));
+#else
+static const bool EnableFastISelVerbose = false,
+                  EnableFastISelAbort = false;
+#endif
 static cl::opt<bool>
 SchedLiveInCopies("schedule-livein-copies",
                   cl::desc("Schedule copies of livein registers"),
@@ -83,6 +87,10 @@ ViewDAGCombine2("view-dag-combine2-dags", cl::Hidden,
           cl::desc("Pop up a window to show dags before the second "
                    "dag combine pass"));
 static cl::opt<bool>
+ViewDAGCombineLT("view-dag-combine-lt-dags", cl::Hidden,
+          cl::desc("Pop up a window to show dags before the post legalize types"
+                   " dag combine pass"));
+static cl::opt<bool>
 ViewISelDAGs("view-isel-dags", cl::Hidden,
           cl::desc("Pop up a window to show isel dags as they are selected"));
 static cl::opt<bool>
@@ -95,6 +103,7 @@ ViewSUnitDAGs("view-sunit-dags", cl::Hidden,
 static const bool ViewDAGCombine1 = false,
                   ViewLegalizeTypesDAGs = false, ViewLegalizeDAGs = false,
                   ViewDAGCombine2 = false,
+                  ViewDAGCombineLT = false,
                   ViewISelDAGs = false, ViewSchedDAGs = false,
                   ViewSUnitDAGs = false;
 #endif
@@ -126,19 +135,17 @@ namespace llvm {
   //===--------------------------------------------------------------------===//
   /// createDefaultScheduler - This creates an instruction scheduler appropriate
   /// for the target.
-  ScheduleDAG* createDefaultScheduler(SelectionDAGISel *IS,
-                                      SelectionDAG *DAG,
-                                      MachineBasicBlock *BB,
-                                      bool Fast) {
-    TargetLowering &TLI = IS->getTargetLowering();
-    
-    if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency) {
-      return createTDListDAGScheduler(IS, DAG, BB, Fast);
-    } else {
-      assert(TLI.getSchedulingPreference() ==
-           TargetLowering::SchedulingForRegPressure && "Unknown sched type!");
-      return createBURRListDAGScheduler(IS, DAG, BB, Fast);
-    }
+  ScheduleDAGSDNodes* createDefaultScheduler(SelectionDAGISel *IS,
+                                             bool Fast) {
+    const TargetLowering &TLI = IS->getTargetLowering();
+
+    if (Fast)
+      return createFastDAGScheduler(IS, Fast);
+    if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency)
+      return createTDListDAGScheduler(IS, Fast);
+    assert(TLI.getSchedulingPreference() ==
+         TargetLowering::SchedulingForRegPressure && "Unknown sched type!");
+    return createBURRListDAGScheduler(IS, Fast);
   }
 }
 
@@ -148,7 +155,7 @@ namespace llvm {
 // insert.  The specified MachineInstr is created but not inserted into any
 // basic blocks, and the scheduler passes ownership of it to this method.
 MachineBasicBlock *TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
-                                                       MachineBasicBlock *MBB) {
+                                                 MachineBasicBlock *MBB) const {
   cerr << "If a target marks an instruction with "
        << "'usesCustomDAGSchedInserter', it must implement "
        << "TargetLowering::EmitInstrWithCustomInserter!\n";
@@ -180,9 +187,9 @@ static void EmitLiveInCopy(MachineBasicBlock *MBB,
   // don't coalesce. Also, only coalesce away a virtual register to virtual
   // register copy.
   bool Coalesced = false;
-  unsigned SrcReg, DstReg;
+  unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
   if (NumUses == 1 &&
-      TII.isMoveInstr(*UseMI, SrcReg, DstReg) &&
+      TII.isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
       TargetRegisterInfo::isVirtualRegister(DstReg)) {
     VirtReg = DstReg;
     Coalesced = true;
@@ -255,11 +262,11 @@ static void EmitLiveInCopies(MachineBasicBlock *EntryMBB,
 // SelectionDAGISel code
 //===----------------------------------------------------------------------===//
 
-SelectionDAGISel::SelectionDAGISel(TargetLowering &tli, bool fast) :
-  FunctionPass(&ID), TLI(tli),
+SelectionDAGISel::SelectionDAGISel(TargetMachine &tm, bool fast) :
+  FunctionPass(&ID), TM(tm), TLI(*tm.getTargetLowering()),
   FuncInfo(new FunctionLoweringInfo(TLI)),
   CurDAG(new SelectionDAG(TLI, *FuncInfo)),
-  SDL(new SelectionDAGLowering(*CurDAG, TLI, *FuncInfo)),
+  SDL(new SelectionDAGLowering(*CurDAG, TLI, *FuncInfo, fast)),
   GFI(),
   Fast(fast),
   DAGSize(0)
@@ -278,6 +285,7 @@ unsigned SelectionDAGISel::MakeReg(MVT VT) {
 void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequired<AliasAnalysis>();
   AU.addRequired<GCModuleInfo>();
+  AU.addRequired<DwarfWriter>();
   AU.setPreservesAll();
 }
 
@@ -292,21 +300,21 @@ bool SelectionDAGISel::runOnFunction(Function &Fn) {
   AA = &getAnalysis<AliasAnalysis>();
 
   TargetMachine &TM = TLI.getTargetMachine();
-  MachineFunction &MF = MachineFunction::construct(&Fn, TM);
-  const MachineRegisterInfo &MRI = MF.getRegInfo();
+  MF = &MachineFunction::construct(&Fn, TM);
   const TargetInstrInfo &TII = *TM.getInstrInfo();
   const TargetRegisterInfo &TRI = *TM.getRegisterInfo();
 
-  if (MF.getFunction()->hasGC())
-    GFI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF.getFunction());
+  if (MF->getFunction()->hasGC())
+    GFI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF->getFunction());
   else
     GFI = 0;
-  RegInfo = &MF.getRegInfo();
+  RegInfo = &MF->getRegInfo();
   DOUT << "\n\n\n=== " << Fn.getName() << "\n";
 
-  FuncInfo->set(Fn, MF, EnableFastISel);
-  MachineModuleInfo *MMI = getAnalysisToUpdate<MachineModuleInfo>();
-  CurDAG->init(MF, MMI);
+  MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
+  DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
+  CurDAG->init(*MF, MMI, DW);
+  FuncInfo->set(Fn, *MF, *CurDAG, EnableFastISel);
   SDL->init(GFI, *AA);
 
   for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
@@ -314,17 +322,17 @@ bool SelectionDAGISel::runOnFunction(Function &Fn) {
       // Mark landing pad.
       FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
 
-  SelectAllBasicBlocks(Fn, MF, MMI, TII);
+  SelectAllBasicBlocks(Fn, *MF, MMI, DW, TII);
 
   // If the first basic block in the function has live ins that need to be
   // copied into vregs, emit the copies into the top of the block before
   // emitting the code for the block.
-  EmitLiveInCopies(MF.begin(), MRI, TRI, TII);
+  EmitLiveInCopies(MF->begin(), *RegInfo, TRI, TII);
 
   // Add function live-ins to entry block live-in set.
   for (MachineRegisterInfo::livein_iterator I = RegInfo->livein_begin(),
          E = RegInfo->livein_end(); I != E; ++I)
-    MF.begin()->addLiveIn(I->first);
+    MF->begin()->addLiveIn(I->first);
 
 #ifndef NDEBUG
   assert(FuncInfo->CatchInfoFound.size() == FuncInfo->CatchInfoLost.size() &&
@@ -352,7 +360,7 @@ static void copyCatchInfo(BasicBlock *SrcBB, BasicBlock *DestBB,
 /// IsFixedFrameObjectWithPosOffset - Check if object is a fixed frame object and
 /// whether object offset >= 0.
 static bool
-IsFixedFrameObjectWithPosOffset(MachineFrameInfo * MFI, SDValue Op) {
+IsFixedFrameObjectWithPosOffset(MachineFrameInfo *MFI, SDValue Op) {
   if (!isa<FrameIndexSDNode>(Op)) return false;
 
   FrameIndexSDNode * FrameIdxNode = dyn_cast<FrameIndexSDNode>(Op);
@@ -367,7 +375,7 @@ IsFixedFrameObjectWithPosOffset(MachineFrameInfo * MFI, SDValue Op) {
 /// assumes all arguments sourcing from FORMAL_ARGUMENTS or a CopyFromReg with
 /// virtual registers would be overwritten by direct lowering.
 static bool IsPossiblyOverwrittenArgumentOfTailCall(SDValue Op,
-                                                    MachineFrameInfo * MFI) {
+                                                    MachineFrameInfo *MFI) {
   RegisterSDNode * OpReg = NULL;
   if (Op.getOpcode() == ISD::FORMAL_ARGUMENTS ||
       (Op.getOpcode()== ISD::CopyFromReg &&
@@ -386,7 +394,7 @@ static bool IsPossiblyOverwrittenArgumentOfTailCall(SDValue Op,
 /// CheckDAGForTailCallsAndFixThem - This Function looks for CALL nodes in the
 /// DAG and fixes their tailcall attribute operand.
 static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG, 
-                                           TargetLowering& TLI) {
+                                           const TargetLowering& TLI) {
   SDNode * Ret = NULL;
   SDValue Terminator = DAG.getRoot();
 
@@ -430,9 +438,11 @@ static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
             MVT VT = Arg.getValueType();
             unsigned VReg = MF.getRegInfo().
               createVirtualRegister(TLI.getRegClassFor(VT));
-            Chain = DAG.getCopyToReg(Chain, VReg, Arg, InFlag);
+            Chain = DAG.getCopyToReg(Chain, Arg.getDebugLoc(),
+                                     VReg, Arg, InFlag);
             InFlag = Chain.getValue(1);
-            Arg = DAG.getCopyFromReg(Chain, VReg, VT, InFlag);
+            Arg = DAG.getCopyFromReg(Chain, Arg.getDebugLoc(),
+                                     VReg, VT, InFlag);
             Chain = Arg.getValue(1);
             InFlag = Arg.getValue(2);
           }
@@ -550,7 +560,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
     GroupName = "Instruction Selection and Scheduling";
   std::string BlockName;
   if (ViewDAGCombine1 || ViewLegalizeTypesDAGs || ViewLegalizeDAGs ||
-      ViewDAGCombine2 || ViewISelDAGs || ViewSchedDAGs || ViewSUnitDAGs)
+      ViewDAGCombine2 || ViewDAGCombineLT || ViewISelDAGs || ViewSchedDAGs ||
+      ViewSUnitDAGs)
     BlockName = CurDAG->getMachineFunction().getFunction()->getName() + ':' +
                 BB->getBasicBlock()->getName();
 
@@ -562,9 +573,9 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
   // Run the DAG combiner in pre-legalize mode.
   if (TimePassesIsEnabled) {
     NamedRegionTimer T("DAG Combining 1", GroupName);
-    CurDAG->Combine(false, *AA, Fast);
+    CurDAG->Combine(Unrestricted, *AA, Fast);
   } else {
-    CurDAG->Combine(false, *AA, Fast);
+    CurDAG->Combine(Unrestricted, *AA, Fast);
   }
   
   DOUT << "Optimized lowered selection DAG:\n";
@@ -572,30 +583,45 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
   
   // Second step, hack on the DAG until it only uses operations and types that
   // the target supports.
-  if (EnableLegalizeTypes) {// Enable this some day.
+  if (!DisableLegalizeTypes) {
     if (ViewLegalizeTypesDAGs) CurDAG->viewGraph("legalize-types input for " +
                                                  BlockName);
 
+    bool Changed;
     if (TimePassesIsEnabled) {
       NamedRegionTimer T("Type Legalization", GroupName);
-      CurDAG->LegalizeTypes();
+      Changed = CurDAG->LegalizeTypes();
     } else {
-      CurDAG->LegalizeTypes();
+      Changed = CurDAG->LegalizeTypes();
     }
 
     DOUT << "Type-legalized selection DAG:\n";
     DEBUG(CurDAG->dump());
 
-    // TODO: enable a dag combine pass here.
+    if (Changed) {
+      if (ViewDAGCombineLT)
+        CurDAG->viewGraph("dag-combine-lt input for " + BlockName);
+
+      // Run the DAG combiner in post-type-legalize mode.
+      if (TimePassesIsEnabled) {
+        NamedRegionTimer T("DAG Combining after legalize types", GroupName);
+        CurDAG->Combine(NoIllegalTypes, *AA, Fast);
+      } else {
+        CurDAG->Combine(NoIllegalTypes, *AA, Fast);
+      }
+
+      DOUT << "Optimized type-legalized selection DAG:\n";
+      DEBUG(CurDAG->dump());
+    }
   }
   
   if (ViewLegalizeDAGs) CurDAG->viewGraph("legalize input for " + BlockName);
 
   if (TimePassesIsEnabled) {
     NamedRegionTimer T("DAG Legalization", GroupName);
-    CurDAG->Legalize();
+    CurDAG->Legalize(DisableLegalizeTypes, Fast);
   } else {
-    CurDAG->Legalize();
+    CurDAG->Legalize(DisableLegalizeTypes, Fast);
   }
   
   DOUT << "Legalized selection DAG:\n";
@@ -606,9 +632,9 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
   // Run the DAG combiner in post-legalize mode.
   if (TimePassesIsEnabled) {
     NamedRegionTimer T("DAG Combining 2", GroupName);
-    CurDAG->Combine(true, *AA, Fast);
+    CurDAG->Combine(NoIllegalOperations, *AA, Fast);
   } else {
-    CurDAG->Combine(true, *AA, Fast);
+    CurDAG->Combine(NoIllegalOperations, *AA, Fast);
   }
   
   DOUT << "Optimized legalized selection DAG:\n";
@@ -616,7 +642,7 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
 
   if (ViewISelDAGs) CurDAG->viewGraph("isel input for " + BlockName);
   
-  if (!Fast && EnableValueProp)
+  if (!Fast)
     ComputeLiveOutVRegInfo();
 
   // Third, instruction select all of the operations to machine code, adding the
@@ -634,12 +660,12 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
   if (ViewSchedDAGs) CurDAG->viewGraph("scheduler input for " + BlockName);
 
   // Schedule machine code.
-  ScheduleDAG *Scheduler;
+  ScheduleDAGSDNodes *Scheduler = CreateScheduler();
   if (TimePassesIsEnabled) {
     NamedRegionTimer T("Instruction Scheduling", GroupName);
-    Scheduler = Schedule();
+    Scheduler->Run(CurDAG, BB, BB->end());
   } else {
-    Scheduler = Schedule();
+    Scheduler->Run(CurDAG, BB, BB->end());
   }
 
   if (ViewSUnitDAGs) Scheduler->viewGraph();
@@ -665,13 +691,15 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
   DEBUG(BB->dump());
 }  
 
-void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
+void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn,
+                                            MachineFunction &MF,
                                             MachineModuleInfo *MMI,
+                                            DwarfWriter *DW,
                                             const TargetInstrInfo &TII) {
   // Initialize the Fast-ISel state, if needed.
   FastISel *FastIS = 0;
   if (EnableFastISel)
-    FastIS = TLI.createFastISel(*FuncInfo->MF, MMI,
+    FastIS = TLI.createFastISel(MF, MMI, DW,
                                 FuncInfo->ValueMap,
                                 FuncInfo->MBBMap,
                                 FuncInfo->StaticAllocaMap
@@ -715,7 +743,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
       unsigned LabelID = MMI->addLandingPad(BB);
 
       const TargetInstrDesc &II = TII.get(TargetInstrInfo::EH_LABEL);
-      BuildMI(BB, II).addImm(LabelID);
+      BuildMI(BB, SDL->getCurDebugLoc(), II).addImm(LabelID);
 
       // Mark exception register as live in.
       unsigned Reg = TLI.getExceptionAddressRegister();
@@ -834,9 +862,6 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
 void
 SelectionDAGISel::FinishBasicBlock() {
 
-  // Perform target specific isel post processing.
-  InstructionSelectPostProcessing();
-  
   DOUT << "Target-post-processed machine code:\n";
   DEBUG(BB->dump());
 
@@ -1037,10 +1062,11 @@ SelectionDAGISel::FinishBasicBlock() {
 }
 
 
-/// Schedule - Pick a safe ordering for instructions for each
-/// target node in the graph.
+/// Create the scheduler. If a specific scheduler was specified
+/// via the SchedulerRegistry, use it, otherwise select the
+/// one preferred by the target.
 ///
-ScheduleDAG *SelectionDAGISel::Schedule() {
+ScheduleDAGSDNodes *SelectionDAGISel::CreateScheduler() {
   RegisterScheduler::FunctionPassCtor Ctor = RegisterScheduler::getDefault();
   
   if (!Ctor) {
@@ -1048,15 +1074,11 @@ ScheduleDAG *SelectionDAGISel::Schedule() {
     RegisterScheduler::setDefault(Ctor);
   }
   
-  ScheduleDAG *Scheduler = Ctor(this, CurDAG, BB, Fast);
-  Scheduler->Run();
-
-  return Scheduler;
+  return Ctor(this, Fast);
 }
 
-
-HazardRecognizer *SelectionDAGISel::CreateTargetHazardRecognizer() {
-  return new HazardRecognizer();
+ScheduleHazardRecognizer *SelectionDAGISel::CreateTargetHazardRecognizer() {
+  return new ScheduleHazardRecognizer();
 }
 
 //===----------------------------------------------------------------------===//
@@ -1146,10 +1168,12 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
     unsigned Flags = cast<ConstantSDNode>(InOps[i])->getZExtValue();
     if ((Flags & 7) != 4 /*MEM*/) {
       // Just skip over this operand, copying the operands verbatim.
-      Ops.insert(Ops.end(), InOps.begin()+i, InOps.begin()+i+(Flags >> 3) + 1);
-      i += (Flags >> 3) + 1;
+      Ops.insert(Ops.end(), InOps.begin()+i,
+                 InOps.begin()+i+InlineAsm::getNumOperandRegisters(Flags) + 1);
+      i += InlineAsm::getNumOperandRegisters(Flags) + 1;
     } else {
-      assert((Flags >> 3) == 1 && "Memory operand with multiple values?");
+      assert(InlineAsm::getNumOperandRegisters(Flags) == 1 &&
+             "Memory operand with multiple values?");
       // Otherwise, this is a memory operand.  Ask the target to select it.
       std::vector<SDValue> SelOps;
       if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) {