[llvm-branch-commits] [llvm-branch] r105960 - in /llvm/branches/Apple/Troughton: ./ include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/ lib/CodeGen/SelectionDAG/ lib/Target/ARM/

Evan Cheng evan.cheng at apple.com
Mon Jun 14 14:13:42 PDT 2010


Author: evancheng
Date: Mon Jun 14 16:13:41 2010
New Revision: 105960

URL: http://llvm.org/viewvc/llvm-project?rev=105960&view=rev
Log:
Merge 105669, 105677, 105745, 105774, 105775, 105862, and 105959.

Added:
    llvm/branches/Apple/Troughton/include/llvm/CodeGen/PostRAHazardRecognizer.h
      - copied unchanged from r105959, llvm/trunk/include/llvm/CodeGen/PostRAHazardRecognizer.h
    llvm/branches/Apple/Troughton/lib/CodeGen/PostRAHazardRecognizer.cpp
      - copied unchanged from r105959, llvm/trunk/lib/CodeGen/PostRAHazardRecognizer.cpp
Removed:
    llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.cpp
    llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.h
    llvm/branches/Apple/Troughton/lib/CodeGen/SimpleHazardRecognizer.h
Modified:
    llvm/branches/Apple/Troughton/   (props changed)
    llvm/branches/Apple/Troughton/include/llvm/Target/TargetInstrInfo.h
    llvm/branches/Apple/Troughton/lib/CodeGen/PostRASchedulerList.cpp
    llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
    llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
    llvm/branches/Apple/Troughton/lib/CodeGen/TargetInstrInfoImpl.cpp
    llvm/branches/Apple/Troughton/lib/CodeGen/TwoAddressInstructionPass.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARM.h
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMTargetMachine.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2ITBlockPass.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.h

Propchange: llvm/branches/Apple/Troughton/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Jun 14 16:13:41 2010
@@ -1 +1 @@
-/llvm/trunk:105358,105361,105369,105372,105399,105427,105437,105439,105441,105470,105481,105498,105541,105554,105557,105585-105586,105634,105653,105836,105845,105938
+/llvm/trunk:105358,105361,105369,105372,105399,105427,105437,105439,105441,105470,105481,105498,105541,105554,105557,105585-105586,105634,105653,105669,105677,105745,105774-105775,105836,105845,105862,105938,105959

Modified: llvm/branches/Apple/Troughton/include/llvm/Target/TargetInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/include/llvm/Target/TargetInstrInfo.h?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/include/llvm/Target/TargetInstrInfo.h (original)
+++ llvm/branches/Apple/Troughton/include/llvm/Target/TargetInstrInfo.h Mon Jun 14 16:13:41 2010
@@ -20,12 +20,14 @@
 namespace llvm {
 
 class CalleeSavedInfo;
+class InstrItineraryData;
 class LiveVariables;
 class MCAsmInfo;
 class MachineMemOperand;
 class MDNode;
 class MCInst;
 class SDNode;
+class ScheduleHazardRecognizer;
 class SelectionDAG;
 class TargetRegisterClass;
 class TargetRegisterInfo;
@@ -203,6 +205,14 @@
                              const MachineInstr *Orig,
                              const TargetRegisterInfo &TRI) const = 0;
 
+  /// scheduleTwoAddrSource - Schedule the copy / re-mat of the source of the
+  /// two-addrss instruction inserted by two-address pass.
+  virtual void scheduleTwoAddrSource(MachineInstr *SrcMI,
+                                     MachineInstr *UseMI,
+                                     const TargetRegisterInfo &TRI) const {
+    // Do nothing.
+  }
+
   /// duplicate - Create a duplicate of the Orig instruction in MF. This is like
   /// MachineFunction::CloneMachineInstr(), but the target may update operands
   /// that are required to be unique.
@@ -567,6 +577,12 @@
   /// length.
   virtual unsigned getInlineAsmLength(const char *Str,
                                       const MCAsmInfo &MAI) const;
+
+  /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer
+  /// to use for this target when scheduling the machine instructions after
+  /// register allocation.
+  virtual ScheduleHazardRecognizer*
+  CreateTargetPostRAHazardRecognizer(const InstrItineraryData&) const = 0;
 };
 
 /// TargetInstrInfoImpl - This is the default implementation of
@@ -594,6 +610,9 @@
   virtual bool produceSameValue(const MachineInstr *MI0,
                                 const MachineInstr *MI1) const;
   virtual unsigned GetFunctionSizeInBytes(const MachineFunction &MF) const;
+
+  virtual ScheduleHazardRecognizer *
+  CreateTargetPostRAHazardRecognizer(const InstrItineraryData&) const;
 };
 
 } // End llvm namespace

Removed: llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.cpp?rev=105959&view=auto
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.cpp (removed)
@@ -1,180 +0,0 @@
-//===----- ExactHazardRecognizer.cpp - hazard recognizer -------- ---------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This implements a hazard recognizer using the instructions itineraries
-// defined for the current target.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "post-RA-sched"
-#include "ExactHazardRecognizer.h"
-#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrItineraries.h"
-
-using namespace llvm;
-
-ExactHazardRecognizer::
-ExactHazardRecognizer(const InstrItineraryData &LItinData) :
-  ScheduleHazardRecognizer(), ItinData(LItinData) 
-{
-  // Determine the maximum depth of any itinerary. This determines the
-  // depth of the scoreboard. We always make the scoreboard at least 1
-  // cycle deep to avoid dealing with the boundary condition.
-  unsigned ScoreboardDepth = 1;
-  if (!ItinData.isEmpty()) {
-    for (unsigned idx = 0; ; ++idx) {
-      if (ItinData.isEndMarker(idx))
-        break;
-
-      const InstrStage *IS = ItinData.beginStage(idx);
-      const InstrStage *E = ItinData.endStage(idx);
-      unsigned ItinDepth = 0;
-      for (; IS != E; ++IS)
-        ItinDepth += IS->getCycles();
-
-      ScoreboardDepth = std::max(ScoreboardDepth, ItinDepth);
-    }
-  }
-
-  ReservedScoreboard.reset(ScoreboardDepth);
-  RequiredScoreboard.reset(ScoreboardDepth);
-
-  DEBUG(dbgs() << "Using exact hazard recognizer: ScoreboardDepth = " 
-               << ScoreboardDepth << '\n');
-}
-
-void ExactHazardRecognizer::Reset() {
-  RequiredScoreboard.reset();
-  ReservedScoreboard.reset();
-}
-
-void ExactHazardRecognizer::ScoreBoard::dump() const {
-  dbgs() << "Scoreboard:\n";
-
-  unsigned last = Depth - 1;
-  while ((last > 0) && ((*this)[last] == 0))
-    last--;
-
-  for (unsigned i = 0; i <= last; i++) {
-    unsigned FUs = (*this)[i];
-    dbgs() << "\t";
-    for (int j = 31; j >= 0; j--)
-      dbgs() << ((FUs & (1 << j)) ? '1' : '0');
-    dbgs() << '\n';
-  }
-}
-
-ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU) {
-  if (ItinData.isEmpty())
-    return NoHazard;
-
-  unsigned cycle = 0;
-
-  // Use the itinerary for the underlying instruction to check for
-  // free FU's in the scoreboard at the appropriate future cycles.
-  unsigned idx = SU->getInstr()->getDesc().getSchedClass();
-  for (const InstrStage *IS = ItinData.beginStage(idx),
-         *E = ItinData.endStage(idx); IS != E; ++IS) {
-    // We must find one of the stage's units free for every cycle the
-    // stage is occupied. FIXME it would be more accurate to find the
-    // same unit free in all the cycles.
-    for (unsigned int i = 0; i < IS->getCycles(); ++i) {
-      assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
-             "Scoreboard depth exceeded!");
-
-      unsigned freeUnits = IS->getUnits();
-      switch (IS->getReservationKind()) {
-      default:
-       assert(0 && "Invalid FU reservation");
-      case InstrStage::Required:
-        // Required FUs conflict with both reserved and required ones
-        freeUnits &= ~ReservedScoreboard[cycle + i];
-        // FALLTHROUGH
-      case InstrStage::Reserved:
-        // Reserved FUs can conflict only with required ones.
-        freeUnits &= ~RequiredScoreboard[cycle + i];
-        break;
-      }
-
-      if (!freeUnits) {
-        DEBUG(dbgs() << "*** Hazard in cycle " << (cycle + i) << ", ");
-        DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
-        DEBUG(SU->getInstr()->dump());
-        return Hazard;
-      }
-    }
-
-    // Advance the cycle to the next stage.
-    cycle += IS->getNextCycles();
-  }
-
-  return NoHazard;
-}
-
-void ExactHazardRecognizer::EmitInstruction(SUnit *SU) {
-  if (ItinData.isEmpty())
-    return;
-
-  unsigned cycle = 0;
-
-  // Use the itinerary for the underlying instruction to reserve FU's
-  // in the scoreboard at the appropriate future cycles.
-  unsigned idx = SU->getInstr()->getDesc().getSchedClass();
-  for (const InstrStage *IS = ItinData.beginStage(idx),
-         *E = ItinData.endStage(idx); IS != E; ++IS) {
-    // We must reserve one of the stage's units for every cycle the
-    // stage is occupied. FIXME it would be more accurate to reserve
-    // the same unit free in all the cycles.
-    for (unsigned int i = 0; i < IS->getCycles(); ++i) {
-      assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
-             "Scoreboard depth exceeded!");
-
-      unsigned freeUnits = IS->getUnits();
-      switch (IS->getReservationKind()) {
-      default:
-       assert(0 && "Invalid FU reservation");
-      case InstrStage::Required:
-        // Required FUs conflict with both reserved and required ones
-        freeUnits &= ~ReservedScoreboard[cycle + i];
-        // FALLTHROUGH
-      case InstrStage::Reserved:
-        // Reserved FUs can conflict only with required ones.
-        freeUnits &= ~RequiredScoreboard[cycle + i];
-        break;
-      }
-
-      // reduce to a single unit
-      unsigned freeUnit = 0;
-      do {
-        freeUnit = freeUnits;
-        freeUnits = freeUnit & (freeUnit - 1);
-      } while (freeUnits);
-
-      assert(freeUnit && "No function unit available!");
-      if (IS->getReservationKind() == InstrStage::Required)
-        RequiredScoreboard[cycle + i] |= freeUnit;
-      else
-        ReservedScoreboard[cycle + i] |= freeUnit;
-    }
-
-    // Advance the cycle to the next stage.
-    cycle += IS->getNextCycles();
-  }
-
-  DEBUG(ReservedScoreboard.dump());
-  DEBUG(RequiredScoreboard.dump());
-}
-
-void ExactHazardRecognizer::AdvanceCycle() {
-  ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
-  RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
-}

Removed: llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.h?rev=105959&view=auto
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.h (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/ExactHazardRecognizer.h (removed)
@@ -1,86 +0,0 @@
-//=- llvm/CodeGen/ExactHazardRecognizer.h - Scheduling Support -*- C++ -*-=//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the ExactHazardRecognizer class, which
-// implements hazard-avoidance heuristics for scheduling, based on the
-// scheduling itineraries specified for the target.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H
-#define LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H
-
-#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
-#include "llvm/CodeGen/ScheduleDAG.h"
-#include "llvm/Target/TargetInstrItineraries.h"
-
-namespace llvm {
-  class ExactHazardRecognizer : public ScheduleHazardRecognizer {
-    // ScoreBoard to track function unit usage. ScoreBoard[0] is a
-    // mask of the FUs in use in the cycle currently being
-    // schedule. ScoreBoard[1] is a mask for the next cycle. The
-    // ScoreBoard is used as a circular buffer with the current cycle
-    // indicated by Head.
-    class ScoreBoard {
-      unsigned *Data;
-
-      // The maximum number of cycles monitored by the Scoreboard. This
-      // value is determined based on the target itineraries to ensure
-      // that all hazards can be tracked.
-      size_t Depth;
-      // Indices into the Scoreboard that represent the current cycle.
-      size_t Head;
-    public:
-      ScoreBoard():Data(NULL), Depth(0), Head(0) { }
-      ~ScoreBoard() {
-        delete[] Data;
-      }
-
-      size_t getDepth() const { return Depth; }
-      unsigned& operator[](size_t idx) const {
-        assert(Depth && "ScoreBoard was not initialized properly!");
-
-        return Data[(Head + idx) % Depth];
-      }
-
-      void reset(size_t d = 1) {
-        if (Data == NULL) {
-          Depth = d;
-          Data = new unsigned[Depth];
-        }
-
-        memset(Data, 0, Depth * sizeof(Data[0]));
-        Head = 0;
-      }
-
-      void advance() {
-        Head = (Head + 1) % Depth;
-      }
-
-      // Print the scoreboard.
-      void dump() const;
-    };
-
-    // Itinerary data for the target.
-    const InstrItineraryData &ItinData;
-
-    ScoreBoard ReservedScoreboard;
-    ScoreBoard RequiredScoreboard;
-
-  public:
-    ExactHazardRecognizer(const InstrItineraryData &ItinData);
-
-    virtual HazardType getHazardType(SUnit *SU);
-    virtual void Reset();
-    virtual void EmitInstruction(SUnit *SU);
-    virtual void AdvanceCycle();
-  };
-}
-
-#endif

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/PostRASchedulerList.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/PostRASchedulerList.cpp?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/PostRASchedulerList.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/PostRASchedulerList.cpp Mon Jun 14 16:13:41 2010
@@ -22,8 +22,6 @@
 #include "AntiDepBreaker.h"
 #include "AggressiveAntiDepBreaker.h"
 #include "CriticalAntiDepBreaker.h"
-#include "ExactHazardRecognizer.h"
-#include "SimpleHazardRecognizer.h"
 #include "ScheduleDAGInstrs.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/LatencyPriorityQueue.h"
@@ -65,10 +63,6 @@
                       cl::desc("Break post-RA scheduling anti-dependencies: "
                                "\"critical\", \"all\", or \"none\""),
                       cl::init("none"), cl::Hidden);
-static cl::opt<bool>
-EnablePostRAHazardAvoidance("avoid-hazards",
-                      cl::desc("Enable exact hazard avoidance"),
-                      cl::init(true), cl::Hidden);
 
 // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
 static cl::opt<int>
@@ -237,10 +231,10 @@
 
   const MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
   const MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
-  const InstrItineraryData &InstrItins = Fn.getTarget().getInstrItineraryData();
-  ScheduleHazardRecognizer *HR = EnablePostRAHazardAvoidance ?
-    (ScheduleHazardRecognizer *)new ExactHazardRecognizer(InstrItins) :
-    (ScheduleHazardRecognizer *)new SimpleHazardRecognizer();
+  const TargetMachine &TM = Fn.getTarget();
+  const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
+  ScheduleHazardRecognizer *HR =
+    TM.getInstrInfo()->CreateTargetPostRAHazardRecognizer(InstrItins);
   AntiDepBreaker *ADB =
     ((AntiDepMode == TargetSubtarget::ANTIDEP_ALL) ?
      (AntiDepBreaker *)new AggressiveAntiDepBreaker(Fn, CriticalPathRCs) :
@@ -680,15 +674,6 @@
       ScheduleNodeTopDown(FoundSUnit, CurCycle);
       HazardRec->EmitInstruction(FoundSUnit);
       CycleHasInsts = true;
-
-      // If we are using the target-specific hazards, then don't
-      // advance the cycle time just because we schedule a node. If
-      // the target allows it we can schedule multiple nodes in the
-      // same cycle.
-      if (!EnablePostRAHazardAvoidance) {
-        if (FoundSUnit->Latency)  // Don't increment CurCycle for pseudo-ops!
-          ++CurCycle;
-      }
     } else {
       if (CycleHasInsts) {
         DEBUG(dbgs() << "*** Finished cycle " << CurCycle << '\n');

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Mon Jun 14 16:13:41 2010
@@ -128,98 +128,99 @@
 /// offsets are not far apart (target specific), it add MVT::Flag inputs and
 /// outputs to ensure they are scheduled together and in order. This
 /// optimization may benefit some targets by improving cache locality.
-void ScheduleDAGSDNodes::ClusterNeighboringLoads() {
+void ScheduleDAGSDNodes::ClusterNeighboringLoads(SDNode *Node) {
+  SDNode *Chain = 0;
+  unsigned NumOps = Node->getNumOperands();
+  if (Node->getOperand(NumOps-1).getValueType() == MVT::Other)
+    Chain = Node->getOperand(NumOps-1).getNode();
+  if (!Chain)
+    return;
+
+  // Look for other loads of the same chain. Find loads that are loading from
+  // the same base pointer and different offsets.
   SmallPtrSet<SDNode*, 16> Visited;
   SmallVector<int64_t, 4> Offsets;
   DenseMap<long long, SDNode*> O2SMap;  // Map from offset to SDNode.
-  for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
-       E = DAG->allnodes_end(); NI != E; ++NI) {
-    SDNode *Node = &*NI;
-    if (!Node || !Node->isMachineOpcode())
+  bool Cluster = false;
+  SDNode *Base = Node;
+  int64_t BaseOffset;
+  for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end();
+       I != E; ++I) {
+    SDNode *User = *I;
+    if (User == Node || !Visited.insert(User))
       continue;
-
-    unsigned Opc = Node->getMachineOpcode();
-    const TargetInstrDesc &TID = TII->get(Opc);
-    if (!TID.mayLoad())
+    int64_t Offset1, Offset2;
+    if (!TII->areLoadsFromSameBasePtr(Base, User, Offset1, Offset2) ||
+        Offset1 == Offset2)
+      // FIXME: Should be ok if they addresses are identical. But earlier
+      // optimizations really should have eliminated one of the loads.
       continue;
+    if (O2SMap.insert(std::make_pair(Offset1, Base)).second)
+      Offsets.push_back(Offset1);
+    O2SMap.insert(std::make_pair(Offset2, User));
+    Offsets.push_back(Offset2);
+    if (Offset2 < Offset1) {
+      Base = User;
+      BaseOffset = Offset2;
+    } else {
+      BaseOffset = Offset1;
+    }
+    Cluster = true;
+  }
 
-    SDNode *Chain = 0;
-    unsigned NumOps = Node->getNumOperands();
-    if (Node->getOperand(NumOps-1).getValueType() == MVT::Other)
-      Chain = Node->getOperand(NumOps-1).getNode();
-    if (!Chain)
-      continue;
+  if (!Cluster)
+    return;
 
-    // Look for other loads of the same chain. Find loads that are loading from
-    // the same base pointer and different offsets.
-    Visited.clear();
-    Offsets.clear();
-    O2SMap.clear();
-    bool Cluster = false;
-    SDNode *Base = Node;
-    int64_t BaseOffset;
-    for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end();
-         I != E; ++I) {
-      SDNode *User = *I;
-      if (User == Node || !Visited.insert(User))
-        continue;
-      int64_t Offset1, Offset2;
-      if (!TII->areLoadsFromSameBasePtr(Base, User, Offset1, Offset2) ||
-          Offset1 == Offset2)
-        // FIXME: Should be ok if they addresses are identical. But earlier
-        // optimizations really should have eliminated one of the loads.
-        continue;
-      if (O2SMap.insert(std::make_pair(Offset1, Base)).second)
-        Offsets.push_back(Offset1);
-      O2SMap.insert(std::make_pair(Offset2, User));
-      Offsets.push_back(Offset2);
-      if (Offset2 < Offset1) {
-        Base = User;
-        BaseOffset = Offset2;
-      } else {
-        BaseOffset = Offset1;
-      }
-      Cluster = true;
-    }
+  // Sort them in increasing order.
+  std::sort(Offsets.begin(), Offsets.end());
 
-    if (!Cluster)
-      continue;
+  // Check if the loads are close enough.
+  SmallVector<SDNode*, 4> Loads;
+  unsigned NumLoads = 0;
+  int64_t BaseOff = Offsets[0];
+  SDNode *BaseLoad = O2SMap[BaseOff];
+  Loads.push_back(BaseLoad);
+  for (unsigned i = 1, e = Offsets.size(); i != e; ++i) {
+    int64_t Offset = Offsets[i];
+    SDNode *Load = O2SMap[Offset];
+    if (!TII->shouldScheduleLoadsNear(BaseLoad, Load, BaseOff, Offset,NumLoads))
+      break; // Stop right here. Ignore loads that are further away.
+    Loads.push_back(Load);
+    ++NumLoads;
+  }
 
-    // Sort them in increasing order.
-    std::sort(Offsets.begin(), Offsets.end());
+  if (NumLoads == 0)
+    return;
 
-    // Check if the loads are close enough.
-    SmallVector<SDNode*, 4> Loads;
-    unsigned NumLoads = 0;
-    int64_t BaseOff = Offsets[0];
-    SDNode *BaseLoad = O2SMap[BaseOff];
-    Loads.push_back(BaseLoad);
-    for (unsigned i = 1, e = Offsets.size(); i != e; ++i) {
-      int64_t Offset = Offsets[i];
-      SDNode *Load = O2SMap[Offset];
-      if (!TII->shouldScheduleLoadsNear(BaseLoad, Load, BaseOff, Offset,
-                                        NumLoads))
-        break; // Stop right here. Ignore loads that are further away.
-      Loads.push_back(Load);
-      ++NumLoads;
-    }
+  // Cluster loads by adding MVT::Flag outputs and inputs. This also
+  // ensure they are scheduled in order of increasing addresses.
+  SDNode *Lead = Loads[0];
+  AddFlags(Lead, SDValue(0,0), true, DAG);
+  SDValue InFlag = SDValue(Lead, Lead->getNumValues()-1);
+  for (unsigned i = 1, e = Loads.size(); i != e; ++i) {
+    bool OutFlag = i < e-1;
+    SDNode *Load = Loads[i];
+    AddFlags(Load, InFlag, OutFlag, DAG);
+    if (OutFlag)
+      InFlag = SDValue(Load, Load->getNumValues()-1);
+    ++LoadsClustered;
+  }
+}
 
-    if (NumLoads == 0)
+/// ClusterNodes - Cluster certain nodes which should be scheduled together.
+///
+void ScheduleDAGSDNodes::ClusterNodes() {
+  for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
+       E = DAG->allnodes_end(); NI != E; ++NI) {
+    SDNode *Node = &*NI;
+    if (!Node || !Node->isMachineOpcode())
       continue;
 
-    // Cluster loads by adding MVT::Flag outputs and inputs. This also
-    // ensure they are scheduled in order of increasing addresses.
-    SDNode *Lead = Loads[0];
-    AddFlags(Lead, SDValue(0,0), true, DAG);
-    SDValue InFlag = SDValue(Lead, Lead->getNumValues()-1);
-    for (unsigned i = 1, e = Loads.size(); i != e; ++i) {
-      bool OutFlag = i < e-1;
-      SDNode *Load = Loads[i];
-      AddFlags(Load, InFlag, OutFlag, DAG);
-      if (OutFlag)
-        InFlag = SDValue(Load, Load->getNumValues()-1);
-      ++LoadsClustered;
-    }
+    unsigned Opc = Node->getMachineOpcode();
+    const TargetInstrDesc &TID = TII->get(Opc);
+    if (TID.mayLoad())
+      // Cluster loads from "near" addresses into combined SUnits.
+      ClusterNeighboringLoads(Node);
   }
 }
 
@@ -388,8 +389,8 @@
 /// excludes nodes that aren't interesting to scheduling, and represents
 /// flagged together nodes with a single SUnit.
 void ScheduleDAGSDNodes::BuildSchedGraph(AliasAnalysis *AA) {
-  // Cluster loads from "near" addresses into combined SUnits.
-  ClusterNeighboringLoads();
+  // Cluster certain nodes which should be scheduled together.
+  ClusterNodes();
   // Populate the SUnits array.
   BuildSchedUnits();
   // Compute all the scheduling dependencies between nodes.

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h Mon Jun 14 16:13:41 2010
@@ -108,7 +108,10 @@
   private:
     /// ClusterNeighboringLoads - Cluster loads from "near" addresses into
     /// combined SUnits.
-    void ClusterNeighboringLoads();
+    void ClusterNeighboringLoads(SDNode *Node);
+    /// ClusterNodes - Cluster certain nodes which should be scheduled together.
+    ///
+    void ClusterNodes();
 
     /// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph.
     void BuildSchedUnits();

Removed: llvm/branches/Apple/Troughton/lib/CodeGen/SimpleHazardRecognizer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/SimpleHazardRecognizer.h?rev=105959&view=auto
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/SimpleHazardRecognizer.h (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/SimpleHazardRecognizer.h (removed)
@@ -1,89 +0,0 @@
-//=- llvm/CodeGen/SimpleHazardRecognizer.h - Scheduling Support -*- C++ -*-=//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SimpleHazardRecognizer class, which
-// implements hazard-avoidance heuristics for scheduling, based on the
-// scheduling itineraries specified for the target.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_SIMPLEHAZARDRECOGNIZER_H
-#define LLVM_CODEGEN_SIMPLEHAZARDRECOGNIZER_H
-
-#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
-#include "llvm/CodeGen/ScheduleDAG.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetInstrInfo.h"
-
-namespace llvm {
-  /// SimpleHazardRecognizer - A *very* simple hazard recognizer. It uses
-  /// a coarse classification and attempts to avoid that instructions of
-  /// a given class aren't grouped too densely together.
-  class SimpleHazardRecognizer : public ScheduleHazardRecognizer {
-    /// Class - A simple classification for SUnits.
-    enum Class {
-      Other, Load, Store
-    };
-
-    /// Window - The Class values of the most recently issued
-    /// instructions.
-    Class Window[8];
-
-    /// getClass - Classify the given SUnit.
-    Class getClass(const SUnit *SU) {
-      const MachineInstr *MI = SU->getInstr();
-      const TargetInstrDesc &TID = MI->getDesc();
-      if (TID.mayLoad())
-        return Load;
-      if (TID.mayStore())
-        return Store;
-      return Other;
-    }
-
-    /// Step - Rotate the existing entries in Window and insert the
-    /// given class value in position as the most recent.
-    void Step(Class C) {
-      std::copy(Window+1, array_endof(Window), Window);
-      Window[array_lengthof(Window)-1] = C;
-    }
-
-  public:
-    SimpleHazardRecognizer() : Window() {
-      Reset();
-    }
-
-    virtual HazardType getHazardType(SUnit *SU) {
-      Class C = getClass(SU);
-      if (C == Other)
-        return NoHazard;
-      unsigned Score = 0;
-      for (unsigned i = 0; i != array_lengthof(Window); ++i)
-        if (Window[i] == C)
-          Score += i + 1;
-      if (Score > array_lengthof(Window) * 2)
-        return Hazard;
-      return NoHazard;
-    }
-
-    virtual void Reset() {
-      for (unsigned i = 0; i != array_lengthof(Window); ++i)
-        Window[i] = Other;
-    }
-
-    virtual void EmitInstruction(SUnit *SU) {
-      Step(getClass(SU));
-    }
-
-    virtual void AdvanceCycle() {
-      Step(Other);
-    }
-  };
-}
-
-#endif

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/TargetInstrInfoImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/TargetInstrInfoImpl.cpp?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/TargetInstrInfoImpl.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/TargetInstrInfoImpl.cpp Mon Jun 14 16:13:41 2010
@@ -21,6 +21,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineMemOperand.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/PostRAHazardRecognizer.h"
 #include "llvm/CodeGen/PseudoSourceValue.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
@@ -316,3 +317,9 @@
   // Everything checked out.
   return true;
 }
+
+// Default implementation of CreateTargetPostRAHazardRecognizer.
+ScheduleHazardRecognizer *TargetInstrInfoImpl::
+CreateTargetPostRAHazardRecognizer(const InstrItineraryData &II) const {
+  return (ScheduleHazardRecognizer *)new PostRAHazardRecognizer(II);
+}

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/TwoAddressInstructionPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/TwoAddressInstructionPass.cpp?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/TwoAddressInstructionPass.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/TwoAddressInstructionPass.cpp Mon Jun 14 16:13:41 2010
@@ -1104,7 +1104,12 @@
             }
           }
         }
-          
+
+        // Schedule the source copy / remat inserted to form two-address
+        // instruction. FIXME: Does it matter the distance map may not be
+        // accurate after it's scheduled?
+        TII->scheduleTwoAddrSource(prior(mi), mi, *TRI);
+
         MadeChange = true;
 
         DEBUG(dbgs() << "\t\trewrite to:\t" << *mi);

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARM.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARM.h?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARM.h (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARM.h Mon Jun 14 16:13:41 2010
@@ -105,7 +105,7 @@
 FunctionPass *createARMConstantIslandPass();
 FunctionPass *createNEONPreAllocPass();
 FunctionPass *createNEONMoveFixPass();
-FunctionPass *createThumb2ITBlockPass();
+FunctionPass *createThumb2ITBlockPass(bool PreAlloc = false);
 FunctionPass *createThumb2SizeReductionPass();
 
 extern Target TheARMTarget, TheThumbTarget;

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMTargetMachine.cpp?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMTargetMachine.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMTargetMachine.cpp Mon Jun 14 16:13:41 2010
@@ -16,11 +16,17 @@
 #include "ARM.h"
 #include "llvm/PassManager.h"
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/Target/TargetRegistry.h"
 using namespace llvm;
 
+static cl::opt<bool>
+EarlyITBlockFormation("thumb2-early-it-blocks", cl::Hidden,
+  cl::desc("Form IT blocks early before register allocation"),
+  cl::init(false));
+
 static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
   Triple TheTriple(TT);
   switch (TheTriple.getOS()) {
@@ -98,6 +104,10 @@
   // FIXME: temporarily disabling load / store optimization pass for Thumb1.
   if (OptLevel != CodeGenOpt::None && !Subtarget.isThumb1Only())
     PM.add(createARMLoadStoreOptimizationPass(true));
+
+  if (OptLevel != CodeGenOpt::None && Subtarget.isThumb2() &&
+      EarlyITBlockFormation)
+    PM.add(createThumb2ITBlockPass(true));
   return true;
 }
 

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2ITBlockPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2ITBlockPass.cpp?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2ITBlockPass.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2ITBlockPass.cpp Mon Jun 14 16:13:41 2010
@@ -14,15 +14,21 @@
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/Statistic.h"
 using namespace llvm;
 
-STATISTIC(NumITs,     "Number of IT blocks inserted");
+STATISTIC(NumITs,        "Number of IT blocks inserted");
+STATISTIC(NumMovedInsts, "Number of predicated instructions moved");
 
 namespace {
-  struct Thumb2ITBlockPass : public MachineFunctionPass {
+  class Thumb2ITBlockPass : public MachineFunctionPass {
+    bool PreRegAlloc;
+
+  public:
     static char ID;
-    Thumb2ITBlockPass() : MachineFunctionPass(&ID) {}
+    Thumb2ITBlockPass(bool PreRA) :
+      MachineFunctionPass(&ID), PreRegAlloc(PreRA) {}
 
     const Thumb2InstrInfo *TII;
     ARMFunctionInfo *AFI;
@@ -34,7 +40,19 @@
     }
 
   private:
+    bool MoveCPSRUseUp(MachineBasicBlock &MBB,
+                       MachineBasicBlock::iterator MBBI,
+                       MachineBasicBlock::iterator E,
+                       unsigned PredReg,
+                       ARMCC::CondCodes CC, ARMCC::CondCodes OCC,
+                       bool &Done);
+
+    void FindITBlockRanges(MachineBasicBlock &MBB,
+                           SmallVector<MachineInstr*,4> &FirstUses,
+                           SmallVector<MachineInstr*,4> &LastUses);
+    bool InsertITBlock(MachineInstr *First, MachineInstr *Last);
     bool InsertITBlocks(MachineBasicBlock &MBB);
+    bool InsertITInstructions(MachineBasicBlock &MBB);
   };
   char Thumb2ITBlockPass::ID = 0;
 }
@@ -46,24 +64,231 @@
   return llvm::getInstrPredicate(MI, PredReg);
 }
 
+bool
+Thumb2ITBlockPass::MoveCPSRUseUp(MachineBasicBlock &MBB,
+                                 MachineBasicBlock::iterator MBBI,
+                                 MachineBasicBlock::iterator E,
+                                 unsigned PredReg,
+                                 ARMCC::CondCodes CC, ARMCC::CondCodes OCC,
+                                 bool &Done) {
+  SmallSet<unsigned, 4> Defs, Uses;
+  MachineBasicBlock::iterator I = MBBI;
+  // Look for next CPSR use by scanning up to 4 instructions.
+  for (unsigned i = 0; i < 4; ++i) {
+    MachineInstr *MI = &*I;
+    unsigned MPredReg = 0;
+    ARMCC::CondCodes MCC = getPredicate(MI, MPredReg);
+    if (MCC != ARMCC::AL) {
+      if (MPredReg != PredReg || (MCC != CC && MCC != OCC))
+        return false;
+
+      // Check if the instruction is using any register that's defined
+      // below the previous predicated instruction. Also return false if
+      // it defines any register which is used in between.
+      for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+        const MachineOperand &MO = MI->getOperand(i);
+        if (!MO.isReg())
+          continue;
+        unsigned Reg = MO.getReg();
+        if (!Reg)
+          continue;
+        if (MO.isDef()) {
+          if (Reg == PredReg || Uses.count(Reg))
+            return false;
+        } else {
+          if (Defs.count(Reg))
+            return false;
+        }
+      }
+
+      Done = (I == E);
+      MBB.remove(MI);
+      MBB.insert(MBBI, MI);
+      ++NumMovedInsts;
+      return true;
+    }
+
+    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+      const MachineOperand &MO = MI->getOperand(i);
+      if (!MO.isReg())
+        continue;
+      unsigned Reg = MO.getReg();
+      if (!Reg)
+        continue;
+      if (MO.isDef()) {
+        if (Reg == PredReg)
+          return false;
+        Defs.insert(Reg);
+      } else
+        Uses.insert(Reg);
+    }
+
+    if (I == E)
+      break;
+    ++I;
+  }
+  return false;
+}
+
+static bool isCPSRLiveout(MachineBasicBlock &MBB) {
+  for (MachineBasicBlock::succ_iterator I = MBB.succ_begin(),
+         E = MBB.succ_end(); I != E; ++I) {
+    if ((*I)->isLiveIn(ARM::CPSR))
+      return true;
+  }
+  return false;
+}
+
+void Thumb2ITBlockPass::FindITBlockRanges(MachineBasicBlock &MBB,
+                                       SmallVector<MachineInstr*,4> &FirstUses,
+                                       SmallVector<MachineInstr*,4> &LastUses) {
+  bool SeenUse = false;
+  MachineOperand *LastDef = 0;
+  MachineOperand *LastUse = 0;
+  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
+  while (MBBI != E) {
+    MachineInstr *MI = &*MBBI;
+    ++MBBI;
+
+    MachineOperand *Def = 0;
+    MachineOperand *Use = 0;
+    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+      MachineOperand &MO = MI->getOperand(i);
+      if (!MO.isReg() || MO.getReg() != ARM::CPSR)
+        continue;
+      if (MO.isDef()) {
+        assert(Def == 0 && "Multiple defs of CPSR?");
+        Def = &MO;
+      } else {
+        assert(Use == 0 && "Multiple uses of CPSR?");
+        Use = &MO;
+      }
+    }
+
+    if (Use) {
+      LastUse = Use;
+      if (!SeenUse) {
+        FirstUses.push_back(MI);
+        SeenUse = true;
+      }
+    }
+    if (Def) {
+      if (LastUse) {
+        LastUses.push_back(LastUse->getParent());
+        LastUse = 0;
+      }
+      LastDef = Def;
+      SeenUse = false;
+    }
+  }
+
+  if (LastUse) {
+    // Is the last use a kill?
+    if (isCPSRLiveout(MBB))
+      LastUses.push_back(0);
+    else
+      LastUses.push_back(LastUse->getParent());
+  }
+}
+
+bool Thumb2ITBlockPass::InsertITBlock(MachineInstr *First, MachineInstr *Last) {
+  if (First == Last)
+    return false;
+
+  bool Modified = false;
+  MachineBasicBlock *MBB = First->getParent();
+  MachineBasicBlock::iterator MBBI = First;
+  MachineBasicBlock::iterator E = Last;
+
+  if (First->getDesc().isBranch() || First->getDesc().isReturn())
+    return false;
+
+  unsigned PredReg = 0;
+  ARMCC::CondCodes CC = getPredicate(First, PredReg);
+  if (CC == ARMCC::AL)
+    return Modified;
+
+  // Move uses of the CPSR together if possible.
+  ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
+
+  do {
+    ++MBBI;
+    if (MBBI->getDesc().isBranch() || MBBI->getDesc().isReturn())
+      return Modified;
+    MachineInstr *NMI = &*MBBI;
+    unsigned NPredReg = 0;
+    ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
+    if (NCC != CC && NCC != OCC) {
+      if (NCC != ARMCC::AL)
+        return Modified;
+      assert(MBBI != E);
+      bool Done = false;
+      if (!MoveCPSRUseUp(*MBB, MBBI, E, PredReg, CC, OCC, Done))
+        return Modified;
+      Modified = true;
+      if (Done)
+        MBBI = E;
+    }
+  } while (MBBI != E);
+  return true;
+}
+
 bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
+  SmallVector<MachineInstr*, 4> FirstUses;
+  SmallVector<MachineInstr*, 4> LastUses;
+  FindITBlockRanges(MBB, FirstUses, LastUses);
+  assert(FirstUses.size() == LastUses.size() && "Incorrect range information!");
+
+  bool Modified = false;
+  for (unsigned i = 0, e = FirstUses.size(); i != e; ++i) {
+    if (LastUses[i] == 0)
+      // Must be the last pair where CPSR is live out of the block.
+      return Modified;
+    Modified |= InsertITBlock(FirstUses[i], LastUses[i]);
+  }
+  return Modified;
+}
+
+static void TrackDefUses(MachineInstr *MI, SmallSet<unsigned, 4> &Defs,
+                         SmallSet<unsigned, 4> &Uses) {
+  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+    MachineOperand &MO = MI->getOperand(i);
+    if (!MO.isReg())
+      continue;
+    unsigned Reg = MO.getReg();
+    if (!Reg)
+      continue;
+    if (MO.isDef())
+      Defs.insert(Reg);
+    else
+      Uses.insert(Reg);
+  }
+}
+
+bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
   bool Modified = false;
 
+  SmallSet<unsigned, 4> Defs;
+  SmallSet<unsigned, 4> Uses;
   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
   while (MBBI != E) {
     MachineInstr *MI = &*MBBI;
     DebugLoc dl = MI->getDebugLoc();
     unsigned PredReg = 0;
     ARMCC::CondCodes CC = getPredicate(MI, PredReg);
-
     if (CC == ARMCC::AL) {
       ++MBBI;
       continue;
     }
 
+    Defs.clear();
+    Uses.clear();
+    TrackDefUses(MI, Defs, Uses);
+
     // Insert an IT instruction.
     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
       .addImm(CC);
+    MachineBasicBlock::iterator InsertPos = MIB;
     ++MBBI;
 
     // Finalize IT mask.
@@ -75,17 +300,37 @@
            (!MI->getDesc().isBranch() && !MI->getDesc().isReturn()) ; ++MBBI) {
       if (MBBI->isDebugValue())
         continue;
+
       MachineInstr *NMI = &*MBBI;
       MI = NMI;
-      DebugLoc ndl = NMI->getDebugLoc();
+
       unsigned NPredReg = 0;
       ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
       if (NCC == CC || NCC == OCC)
         Mask |= (NCC & 1) << Pos;
-      else
+      else {
+        unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
+        if (NCC == ARMCC::AL &&
+            TII->isMoveInstr(*NMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) {
+          assert(SrcSubIdx == 0 && DstSubIdx == 0 &&
+                 "Sub-register indices still around?");
+          // llvm models select's as two-address instructions. That means a copy
+          // is inserted before a t2MOVccr, etc. If the copy is scheduled in
+          // between selects we would end up creating multiple IT blocks.
+          if (!Uses.count(DstReg) && !Defs.count(SrcReg)) {
+            --MBBI;
+            MBB.remove(NMI);
+            MBB.insert(InsertPos, NMI);
+            ++NumMovedInsts;
+            continue;
+          }
+        }
         break;
+      }
+      TrackDefUses(NMI, Defs, Uses);
       --Pos;
     }
+
     Mask |= (1 << Pos);
     // Tag along (firstcond[0] << 4) with the mask.
     Mask |= (CC & 1) << 4;
@@ -106,10 +351,13 @@
     return false;
 
   bool Modified = false;
-  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
-       ++MFI) {
+  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) {
     MachineBasicBlock &MBB = *MFI;
-    Modified |= InsertITBlocks(MBB);
+    ++MFI;
+    if (PreRegAlloc)
+      Modified |= InsertITBlocks(MBB);
+    else
+      Modified |= InsertITInstructions(MBB);
   }
 
   return Modified;
@@ -117,6 +365,6 @@
 
 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
 /// insertion pass.
-FunctionPass *llvm::createThumb2ITBlockPass() {
-  return new Thumb2ITBlockPass();
+FunctionPass *llvm::createThumb2ITBlockPass(bool PreAlloc) {
+  return new Thumb2ITBlockPass(PreAlloc);
 }

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp Mon Jun 14 16:13:41 2010
@@ -503,3 +503,46 @@
   Offset = (isSub) ? -Offset : Offset;
   return Offset == 0;
 }
+
+/// scheduleTwoAddrSource - Schedule the copy / re-mat of the source of the
+/// two-addrss instruction inserted by two-address pass.
+void
+Thumb2InstrInfo::scheduleTwoAddrSource(MachineInstr *SrcMI,
+                                       MachineInstr *UseMI,
+                                       const TargetRegisterInfo &TRI) const {
+  if (SrcMI->getOpcode() != ARM::tMOVgpr2gpr ||
+      SrcMI->getOperand(1).isKill())
+    return;
+
+  unsigned PredReg = 0;
+  ARMCC::CondCodes CC = llvm::getInstrPredicate(UseMI, PredReg);
+  if (CC == ARMCC::AL || PredReg != ARM::CPSR)
+    return;
+
+  // Schedule the copy so it doesn't come between previous instructions
+  // and UseMI which can form an IT block.
+  unsigned SrcReg = SrcMI->getOperand(1).getReg();
+  ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
+  MachineBasicBlock *MBB = UseMI->getParent();
+  MachineBasicBlock::iterator MBBI = SrcMI;
+  unsigned NumInsts = 0;
+  while (--MBBI != MBB->begin()) {
+    if (MBBI->isDebugValue())
+      continue;
+
+    MachineInstr *NMI = &*MBBI;
+    ARMCC::CondCodes NCC = llvm::getInstrPredicate(NMI, PredReg);
+    if (!(NCC == CC || NCC == OCC) ||
+        NMI->modifiesRegister(SrcReg, &TRI) ||
+        NMI->definesRegister(ARM::CPSR))
+      break;
+    if (++NumInsts == 4)
+      // Too many in a row!
+      return;
+  }
+
+  if (NumInsts) {
+    MBB->remove(SrcMI);
+    MBB->insert(++MBBI, SrcMI);
+  }
+}

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.h?rev=105960&r1=105959&r2=105960&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.h (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.h Mon Jun 14 16:13:41 2010
@@ -50,6 +50,11 @@
                             const TargetRegisterClass *RC,
                             const TargetRegisterInfo *TRI) const;
 
+  /// scheduleTwoAddrSource - Schedule the copy / re-mat of the source of the
+  /// two-addrss instruction inserted by two-address pass.
+  void scheduleTwoAddrSource(MachineInstr *SrcMI, MachineInstr *UseMI,
+                             const TargetRegisterInfo &TRI) const;
+
   /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info.  As
   /// such, whenever a client has an instance of instruction info, it should
   /// always be able to get register info as well (through this method).





More information about the llvm-branch-commits mailing list