[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