17c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner//===-- DelaySlotFiller.cpp - SPARC delay slot filler ---------------------===//
2b5f662fa0314f7e7e690aae8ebff7136cc3a5ab0Misha Brukman//
320117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke//                     The LLVM Compiler Infrastructure
420117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7b5f662fa0314f7e7e690aae8ebff7136cc3a5ab0Misha Brukman//
820117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke//===----------------------------------------------------------------------===//
920117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke//
1071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju// This is a simple local pass that attempts to fill delay slots with useful
1171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju// instructions. If no instructions can be moved into the delay slot, then a
1271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju// NOP is placed.
1320117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke//===----------------------------------------------------------------------===//
1420117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
157c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner#include "Sparc.h"
1679c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju#include "SparcSubtarget.h"
17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallSet.h"
18d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/Statistic.h"
1920117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke#include "llvm/CodeGen/MachineFunctionPass.h"
2020117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke#include "llvm/CodeGen/MachineInstrBuilder.h"
2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/CodeGen/MachineRegisterInfo.h"
2271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju#include "llvm/Support/CommandLine.h"
23870248b16491c9a9a604494b4e7aa94035af2158Brian Gaeke#include "llvm/Target/TargetInstrInfo.h"
24d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetMachine.h"
2571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju#include "llvm/Target/TargetRegisterInfo.h"
2671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
2720117102c2e10fa2c0fa74965894e28751a3df34Brian Gaekeusing namespace llvm;
2820117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
29dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "delay-slot-filler"
30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
3195b2c7da5e83670881270c1cd231a240be0556d9Chris LattnerSTATISTIC(FilledSlots, "Number of delay slots filled");
3220117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
3371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindarajustatic cl::opt<bool> DisableDelaySlotFiller(
3471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  "disable-sparc-delay-filler",
3571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  cl::init(false),
3671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  cl::desc("Disable the Sparc delay slot filler."),
3771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  cl::Hidden);
3871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
3995b2c7da5e83670881270c1cd231a240be0556d9Chris Lattnernamespace {
4020117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke  struct Filler : public MachineFunctionPass {
4120117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke    /// Target machine description which we query for reg. names, data
4220117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke    /// layout, etc.
4320117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke    ///
4420117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke    TargetMachine &TM;
4579c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju    const SparcSubtarget *Subtarget;
4620117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
471997473cf72957d0e70322e2fe6fe2ab141c58a6Devang Patel    static char ID;
481e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju    Filler(TargetMachine &tm)
4979c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju      : MachineFunctionPass(ID), TM(tm),
5079c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju        Subtarget(&TM.getSubtarget<SparcSubtarget>()) {
5179c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju    }
5220117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const char *getPassName() const override {
547c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner      return "SPARC Delay Slot Filler";
5520117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke    }
5620117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
577c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner    bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
58dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    bool runOnMachineFunction(MachineFunction &F) override {
5920117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke      bool Changed = false;
6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // This pass invalidates liveness information when it reorders
6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // instructions to fill delay slot.
6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      F.getRegInfo().invalidateLiveness();
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
657c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner      for (MachineFunction::iterator FI = F.begin(), FE = F.end();
6620117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke           FI != FE; ++FI)
677c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner        Changed |= runOnMachineBasicBlock(*FI);
6820117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke      return Changed;
6920117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke    }
7020117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
71d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindaraju    void insertCallDefsUses(MachineBasicBlock::iterator MI,
72d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindaraju                            SmallSet<unsigned, 32>& RegDefs,
73d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindaraju                            SmallSet<unsigned, 32>& RegUses);
7471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
7571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    void insertDefsUses(MachineBasicBlock::iterator MI,
7671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                        SmallSet<unsigned, 32>& RegDefs,
7771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                        SmallSet<unsigned, 32>& RegUses);
7871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
7971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    bool IsRegInSet(SmallSet<unsigned, 32>& RegSet,
8071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                    unsigned Reg);
8171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
8271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    bool delayHasHazard(MachineBasicBlock::iterator candidate,
8371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                        bool &sawLoad, bool &sawStore,
8471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                        SmallSet<unsigned, 32> &RegDefs,
8571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                        SmallSet<unsigned, 32> &RegUses);
8671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
8771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    MachineBasicBlock::iterator
8871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot);
8971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
9058269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju    bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize);
9171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
9265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    bool tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
9365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                                       MachineBasicBlock::iterator MBBI);
9465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
9520117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke  };
961997473cf72957d0e70322e2fe6fe2ab141c58a6Devang Patel  char Filler::ID = 0;
9720117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke} // end of anonymous namespace
9820117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
997c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner/// createSparcDelaySlotFillerPass - Returns a pass that fills in delay
1007c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner/// slots in Sparc MachineFunctions
10120117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke///
1027c90f73a1b06040d971a3dd95a491031ae6238d5Chris LattnerFunctionPass *llvm::createSparcDelaySlotFillerPass(TargetMachine &tm) {
1037c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattner  return new Filler(tm);
10420117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke}
10520117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke
10658269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju
10720117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
10871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju/// We assume there is only one delay slot per delayed instruction.
10920117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke///
1107c90f73a1b06040d971a3dd95a491031ae6238d5Chris Lattnerbool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
1110f51cc1759e2162485b5f9ee57b3b5bc8f5c6759Brian Gaeke  bool Changed = false;
11271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
11379c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju  const TargetInstrInfo *TII = TM.getInstrInfo();
11479c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju
11565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
11665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    MachineBasicBlock::iterator MI = I;
11765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    ++I;
11865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
1191e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju    // If MI is restore, try combining it with previous inst.
12065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    if (!DisableDelaySlotFiller &&
12165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju        (MI->getOpcode() == SP::RESTORErr
12265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju         || MI->getOpcode() == SP::RESTOREri)) {
12365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      Changed |= tryCombineRestoreWithPrevInst(MBB, MI);
12465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      continue;
12565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    }
12665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
12779c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju    if (!Subtarget->isV9() &&
12879c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju        (MI->getOpcode() == SP::FCMPS || MI->getOpcode() == SP::FCMPD
12979c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju         || MI->getOpcode() == SP::FCMPQ)) {
13079c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju      BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP));
13179c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju      Changed = true;
13279c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju      continue;
13379c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju    }
13479c5e0c5ca85454da568dfafc0bedb84af6c2a68Venkatraman Govindaraju
1351e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju    // If MI has no delay slot, skip.
13665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    if (!MI->hasDelaySlot())
13765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      continue;
13865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
13965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    MachineBasicBlock::iterator D = MBB.end();
14065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
14165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    if (!DisableDelaySlotFiller)
14265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      D = findDelayInstr(MBB, MI);
14365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
14465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    ++FilledSlots;
14565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    Changed = true;
14665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
14765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    if (D == MBB.end())
14865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP));
14965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    else
15065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      MBB.splice(I, &MBB, D);
15165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
15265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    unsigned structSize = 0;
15365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    if (needsUnimp(MI, structSize)) {
15465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      MachineBasicBlock::iterator J = MI;
1551e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju      ++J; // skip the delay filler.
15665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      assert (J != MBB.end() && "MI needs a delay instruction.");
15780cdaf35abc528ee00bd49486d455436ec049581Venkatraman Govindaraju      BuildMI(MBB, ++J, MI->getDebugLoc(),
15865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju              TII->get(SP::UNIMP)).addImm(structSize);
15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Bundle the delay filler and unimp with the instruction.
16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), J);
16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else {
16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), I);
16320117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke    }
16465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  }
1650f51cc1759e2162485b5f9ee57b3b5bc8f5c6759Brian Gaeke  return Changed;
16620117102c2e10fa2c0fa74965894e28751a3df34Brian Gaeke}
16771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
16871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman GovindarajuMachineBasicBlock::iterator
16971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman GovindarajuFiller::findDelayInstr(MachineBasicBlock &MBB,
17071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                       MachineBasicBlock::iterator slot)
17171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju{
17271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  SmallSet<unsigned, 32> RegDefs;
17371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  SmallSet<unsigned, 32> RegUses;
17471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  bool sawLoad = false;
17571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  bool sawStore = false;
17671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
177530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju  if (slot == MBB.begin())
178530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju    return MBB.end();
17971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
1803bd3419e86867ba88e7ece12c9184a01759ed917Venkatraman Govindaraju  if (slot->getOpcode() == SP::RET || slot->getOpcode() == SP::TLS_CALL)
18171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    return MBB.end();
18271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
18371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  if (slot->getOpcode() == SP::RETL) {
184530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju    MachineBasicBlock::iterator J = slot;
185530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju    --J;
186530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju
187530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju    if (J->getOpcode() == SP::RESTORErr
188530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju        || J->getOpcode() == SP::RESTOREri) {
1891e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju      // change retl to ret.
190c1dcb8d654d4468d63224269ee3c92480bf2385bBill Wendling      slot->setDesc(TM.getInstrInfo()->get(SP::RET));
191530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju      return J;
192530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju    }
19371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  }
19471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
1951e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Call's delay filler can def some of call's uses.
1965a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (slot->isCall())
197d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindaraju    insertCallDefsUses(slot, RegDefs, RegUses);
19871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  else
19971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    insertDefsUses(slot, RegDefs, RegUses);
20071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
20171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  bool done = false;
20271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
203530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju  MachineBasicBlock::iterator I = slot;
204530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju
20571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  while (!done) {
20671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    done = (I == MBB.begin());
20771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
20871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (!done)
20971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      --I;
21071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
21171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    // skip debug value
21271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (I->isDebugValue())
21371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      continue;
21471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() ||
21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        I->hasDelaySlot() || I->isBundledWithSucc())
21771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      break;
21871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
21971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) {
22071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      insertDefsUses(I, RegDefs, RegUses);
22171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      continue;
22271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    }
22371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
22471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    return I;
22571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  }
22671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  return MBB.end();
22771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju}
22871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
22971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindarajubool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
23071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                            bool &sawLoad,
23171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                            bool &sawStore,
23271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                            SmallSet<unsigned, 32> &RegDefs,
23371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                            SmallSet<unsigned, 32> &RegUses)
23471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju{
23571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
236cc5bd4a56140f8c7381afa686f28b361fd540436Venkatraman Govindaraju  if (candidate->isImplicitDef() || candidate->isKill())
237cc5bd4a56140f8c7381afa686f28b361fd540436Venkatraman Govindaraju    return true;
238cc5bd4a56140f8c7381afa686f28b361fd540436Venkatraman Govindaraju
2395a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (candidate->mayLoad()) {
24071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    sawLoad = true;
24171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (sawStore)
24271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      return true;
24371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  }
24471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
2455a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (candidate->mayStore()) {
24671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (sawStore)
24771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      return true;
24871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    sawStore = true;
24971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (sawLoad)
25071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      return true;
25171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  }
25271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
25371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
25471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    const MachineOperand &MO = candidate->getOperand(i);
25571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (!MO.isReg())
25671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      continue; // skip
25771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
25871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    unsigned Reg = MO.getReg();
25971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
26071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (MO.isDef()) {
2611e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju      // check whether Reg is defined or used before delay slot.
26271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))
26371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju        return true;
26471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    }
26571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (MO.isUse()) {
2661e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju      // check whether Reg is defined before delay slot.
26771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      if (IsRegInSet(RegDefs, Reg))
26871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju        return true;
26971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    }
27071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  }
27171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  return false;
27271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju}
27371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
27471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
275d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindarajuvoid Filler::insertCallDefsUses(MachineBasicBlock::iterator MI,
276d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindaraju                                SmallSet<unsigned, 32>& RegDefs,
277d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindaraju                                SmallSet<unsigned, 32>& RegUses)
27871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju{
2791e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Call defines o7, which is visible to the instruction in delay slot.
280d6b4caf291aa8c3cd4bcb5f3b55b72621b506278Venkatraman Govindaraju  RegDefs.insert(SP::O7);
28171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
28271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  switch(MI->getOpcode()) {
28371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  default: llvm_unreachable("Unknown opcode.");
28471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  case SP::CALL: break;
28536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case SP::CALLrr:
28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case SP::CALLri:
28771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    assert(MI->getNumOperands() >= 2);
28871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    const MachineOperand &Reg = MI->getOperand(0);
28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert(Reg.isReg() && "CALL first operand is not a register.");
29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert(Reg.isUse() && "CALL first operand is not a use.");
29171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    RegUses.insert(Reg.getReg());
29271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
29371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    const MachineOperand &RegOrImm = MI->getOperand(1);
29471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (RegOrImm.isImm())
29571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju        break;
29636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert(RegOrImm.isReg() && "CALLrr second operand is not a register.");
29736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert(RegOrImm.isUse() && "CALLrr second operand is not a use.");
29871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    RegUses.insert(RegOrImm.getReg());
29971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    break;
30071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  }
30171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju}
30271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
3031e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
30471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindarajuvoid Filler::insertDefsUses(MachineBasicBlock::iterator MI,
30571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                            SmallSet<unsigned, 32>& RegDefs,
30671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju                            SmallSet<unsigned, 32>& RegUses)
30771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju{
30871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
30971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    const MachineOperand &MO = MI->getOperand(i);
31071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (!MO.isReg())
31171e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      continue;
31271e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
31371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    unsigned Reg = MO.getReg();
31471e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (Reg == 0)
31571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      continue;
31671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju    if (MO.isDef())
31771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      RegDefs.insert(Reg);
318530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju    if (MO.isUse()) {
3191e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju      // Implicit register uses of retl are return values and
3201e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju      // retl does not use them.
321530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju      if (MO.isImplicit() && MI->getOpcode() == SP::RETL)
322530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju        continue;
32371e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      RegUses.insert(Reg);
324530086925695f074b0e1e38a0d88ee6a4c91c54cVenkatraman Govindaraju    }
32571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  }
32671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju}
32771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
3281e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju// returns true if the Reg or its alias is in the RegSet.
32971e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindarajubool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg)
33071e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju{
331f152fe8d487c46873bbdd4abab43200f783e978bJakob Stoklund Olesen  // Check Reg and all aliased Registers.
332f152fe8d487c46873bbdd4abab43200f783e978bJakob Stoklund Olesen  for (MCRegAliasIterator AI(Reg, TM.getRegisterInfo(), true);
333f152fe8d487c46873bbdd4abab43200f783e978bJakob Stoklund Olesen       AI.isValid(); ++AI)
334f152fe8d487c46873bbdd4abab43200f783e978bJakob Stoklund Olesen    if (RegSet.count(*AI))
33571e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju      return true;
33671e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju  return false;
33771e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju}
33871e39dac0ce9676dd3d0a92164167e18499d40faVenkatraman Govindaraju
33958269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindarajubool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
34058269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju{
3415a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (!I->isCall())
34258269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju    return false;
34358269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju
34458269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  unsigned structSizeOpNum = 0;
34558269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  switch (I->getOpcode()) {
34658269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  default: llvm_unreachable("Unknown call opcode.");
34758269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  case SP::CALL: structSizeOpNum = 1; break;
34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case SP::CALLrr:
34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case SP::CALLri: structSizeOpNum = 2; break;
3503bd3419e86867ba88e7ece12c9184a01759ed917Venkatraman Govindaraju  case SP::TLS_CALL: return false;
35158269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  }
35258269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju
35358269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  const MachineOperand &MO = I->getOperand(structSizeOpNum);
35458269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  if (!MO.isImm())
35558269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju    return false;
35658269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  StructSize = MO.getImm();
35758269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju  return true;
35858269b973256bf2436cac0f047aa277fe4bc01ddVenkatraman Govindaraju}
35965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
36065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindarajustatic bool combineRestoreADD(MachineBasicBlock::iterator RestoreMI,
36165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                              MachineBasicBlock::iterator AddMI,
36265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                              const TargetInstrInfo *TII)
36365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju{
3641e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Before:  add  <op0>, <op1>, %i[0-7]
3651e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  //          restore %g0, %g0, %i[0-7]
36665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  //
3671e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // After :  restore <op0>, <op1>, %o[0-7]
36865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
36965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  unsigned reg = AddMI->getOperand(0).getReg();
37065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (reg < SP::I0 || reg > SP::I7)
37165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
37265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
3731e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Erase RESTORE.
37465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  RestoreMI->eraseFromParent();
37565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
3761e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Change ADD to RESTORE.
37765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  AddMI->setDesc(TII->get((AddMI->getOpcode() == SP::ADDrr)
37865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                          ? SP::RESTORErr
37965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                          : SP::RESTOREri));
38065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
3811e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Map the destination register.
38265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
38365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
38465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  return true;
38565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju}
38665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
38765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindarajustatic bool combineRestoreOR(MachineBasicBlock::iterator RestoreMI,
38865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                             MachineBasicBlock::iterator OrMI,
38965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                             const TargetInstrInfo *TII)
39065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju{
3911e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Before:  or  <op0>, <op1>, %i[0-7]
3921e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  //          restore %g0, %g0, %i[0-7]
3931e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  //    and <op0> or <op1> is zero,
39465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  //
3951e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // After :  restore <op0>, <op1>, %o[0-7]
39665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
39765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  unsigned reg = OrMI->getOperand(0).getReg();
39865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (reg < SP::I0 || reg > SP::I7)
39965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
40065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4011e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // check whether it is a copy.
40265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (OrMI->getOpcode() == SP::ORrr
40365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      && OrMI->getOperand(1).getReg() != SP::G0
40465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      && OrMI->getOperand(2).getReg() != SP::G0)
40565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
40665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
40765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (OrMI->getOpcode() == SP::ORri
40865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      && OrMI->getOperand(1).getReg() != SP::G0
40965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju      && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
41065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
41165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4121e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Erase RESTORE.
41365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  RestoreMI->eraseFromParent();
41465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4151e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Change OR to RESTORE.
41665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  OrMI->setDesc(TII->get((OrMI->getOpcode() == SP::ORrr)
41765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                         ? SP::RESTORErr
41865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                         : SP::RESTOREri));
41965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4201e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Map the destination register.
42165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
42265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
42365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  return true;
42465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju}
42565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
42665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindarajustatic bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI,
42765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                                 MachineBasicBlock::iterator SetHiMI,
42865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                                 const TargetInstrInfo *TII)
42965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju{
4301e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Before:  sethi imm3, %i[0-7]
4311e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  //          restore %g0, %g0, %g0
43265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  //
4331e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // After :  restore %g0, (imm3<<10), %o[0-7]
43465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
43565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  unsigned reg = SetHiMI->getOperand(0).getReg();
43665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (reg < SP::I0 || reg > SP::I7)
43765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
43865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
43965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (!SetHiMI->getOperand(1).isImm())
44065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
44165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
44265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  int64_t imm = SetHiMI->getOperand(1).getImm();
44365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4441e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Is it a 3 bit immediate?
44565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (!isInt<3>(imm))
44665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
44765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4481e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Make it a 13 bit immediate.
44965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  imm = (imm << 10) & 0x1FFF;
45065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
45165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  assert(RestoreMI->getOpcode() == SP::RESTORErr);
45265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
45365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  RestoreMI->setDesc(TII->get(SP::RESTOREri));
45465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
45565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
45665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  RestoreMI->getOperand(1).setReg(SP::G0);
45765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  RestoreMI->getOperand(2).ChangeToImmediate(imm);
45865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
45965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4601e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // Erase the original SETHI.
46165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  SetHiMI->eraseFromParent();
46265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
46365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  return true;
46465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju}
46565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
46665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindarajubool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
46765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju                                        MachineBasicBlock::iterator MBBI)
46865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju{
4691e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // No previous instruction.
47065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  if (MBBI == MBB.begin())
47165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
47265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
4731e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // assert that MBBI is a "restore %g0, %g0, %g0".
47465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  assert(MBBI->getOpcode() == SP::RESTORErr
47565ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju         && MBBI->getOperand(0).getReg() == SP::G0
47665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju         && MBBI->getOperand(1).getReg() == SP::G0
47765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju         && MBBI->getOperand(2).getReg() == SP::G0);
47865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
47936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineBasicBlock::iterator PrevInst = std::prev(MBBI);
48065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
48136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // It cannot be combined with a bundled instruction.
48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (PrevInst->isBundledWithSucc())
48365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju    return false;
48465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju
485c1dcb8d654d4468d63224269ee3c92480bf2385bBill Wendling  const TargetInstrInfo *TII = TM.getInstrInfo();
486c1dcb8d654d4468d63224269ee3c92480bf2385bBill Wendling
48765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  switch (PrevInst->getOpcode()) {
48865ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  default: break;
48965ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  case SP::ADDrr:
49065ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  case SP::ADDri: return combineRestoreADD(MBBI, PrevInst, TII); break;
49165ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  case SP::ORrr:
49265ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  case SP::ORri:  return combineRestoreOR(MBBI, PrevInst, TII); break;
49365ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  case SP::SETHIi: return combineRestoreSETHIi(MBBI, PrevInst, TII); break;
49465ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  }
4951e06bcbd633175d75d13aaa5695ca0633ba86068Venkatraman Govindaraju  // It cannot combine with the previous instruction.
49665ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju  return false;
49765ca7aa57d5e9b391f02a5686e7622deaac146f9Venkatraman Govindaraju}
498