Generates conditional branch instead of fake ones for Select instruction in some...
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAGISel.cpp
index f6c5d90f47ae1386c1c1f91370298d903b773220..491d7ec451c0525740732541e9e0b2b0625c063a 100644 (file)
@@ -467,15 +467,50 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
 
   MF->setHasInlineAsm(false);
 
+  FuncInfo->SplitCSR = false;
+  SmallVector<MachineBasicBlock*, 4> Returns;
+
+  // We split CSR if the target supports it for the given function
+  // and the function has only return exits.
+  if (TLI->supportSplitCSR(MF)) {
+    FuncInfo->SplitCSR = true;
+
+    // Collect all the return blocks.
+    for (const BasicBlock &BB : Fn) {
+      if (!succ_empty(&BB))
+        continue;
+
+      const TerminatorInst *Term = BB.getTerminator();
+      if (isa<UnreachableInst>(Term))
+        continue;
+      if (isa<ReturnInst>(Term)) {
+        Returns.push_back(FuncInfo->MBBMap[&BB]);
+        continue;
+      }
+
+      // Bail out if the exit block is not Return nor Unreachable.
+      FuncInfo->SplitCSR = false;
+      break;
+    }
+  }
+
+  MachineBasicBlock *EntryMBB = &MF->front();
+  if (FuncInfo->SplitCSR)
+    // This performs initialization so lowering for SplitCSR will be correct.
+    TLI->initializeSplitCSR(EntryMBB);
+
   SelectAllBasicBlocks(Fn);
 
   // 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.
-  MachineBasicBlock *EntryMBB = &MF->front();
   const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
   RegInfo->EmitLiveInCopies(EntryMBB, TRI, *TII);
 
+  // Insert copies in the entry block and the return blocks.
+  if (FuncInfo->SplitCSR)
+    TLI->insertCopiesSplitCSR(EntryMBB, Returns);
+
   DenseMap<unsigned, unsigned> LiveInMap;
   if (!FuncInfo->ArgDbgValues.empty())
     for (MachineRegisterInfo::livein_iterator LI = RegInfo->livein_begin(),
@@ -598,6 +633,9 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
     MRI.replaceRegWith(From, To);
   }
 
+  if (TLI->hasCopyImplyingStackAdjustment(MF))
+    MFI->setHasCopyImplyingStackAdjustment(true);
+
   // Freeze the set of reserved registers now that MachineFrameInfo has been
   // set up. All the information required by getReservedRegs() should be
   // available now.
@@ -607,6 +645,50 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
   // at this point.
   FuncInfo->clear();
 
+  // XXX-update: Right after instruction selection, check through the
+  // intentionally added fake conditional branches and mark them as unremovable.
+  for (auto& MBB : *MF) {
+    // Check whether MBB has two successors which only contains an unconditional
+    // branch to the same destination.
+    if (MBB.succ_size() != 2 ||
+        !MBB.getLastNonDebugInstr()->isUnconditionalBranch()) {
+      continue;
+    }
+    auto MBBSuccIter = MBB.succ_begin();
+    auto* Succ1 = *MBBSuccIter;
+    MBBSuccIter++;
+    auto* Succ2 = *MBBSuccIter;
+
+    MachineBasicBlock* Succ1Succ = nullptr;
+    MachineBasicBlock* Succ2Succ = nullptr;
+    if ((Succ1->size() == 1 && Succ1->begin()->isUnconditionalBranch()) ||
+        (Succ1->size() == 0)) {
+      if (Succ1->succ_size()) {
+        Succ1Succ = *Succ1->succ_begin();
+      }
+    }
+    if ((Succ2->size() == 1 && Succ2->begin()->isUnconditionalBranch()) ||
+        (Succ2->size() == 0)) {
+      if (Succ1->succ_size()) {
+        Succ2Succ = *Succ2->succ_begin();
+      }
+    }
+
+    bool HasCommonDest = Succ1Succ && Succ1Succ == Succ2Succ;
+    if (HasCommonDest) {
+      auto MBBIter = MBB.end();
+      std::advance(MBBIter, -2);
+      assert(MBBIter->isConditionalBranch());
+      MBB.disableCanEliminateMachineBB();
+      Succ1->disableCanEliminateMachineBB();
+      Succ2->disableCanEliminateMachineBB();
+      Succ1Succ->disableCanEliminateMachineBB();
+      DEBUG(dbgs() << "Mark as unremovable machine basic block: " << MBB
+                   << "\nMark as unremovable branch instruction: " << *MBBIter
+                   << "\n");
+    }
+  }
+
   DEBUG(dbgs() << "*** MachineFunction at end of ISel ***\n");
   DEBUG(MF->print(dbgs()));