[llvm-commits] [llvm] r93554 - in /llvm/trunk/lib/Target/MSP430: MSP430.h MSP430BranchSelector.cpp MSP430InstrInfo.cpp MSP430InstrInfo.h MSP430InstrInfo.td MSP430TargetMachine.cpp MSP430TargetMachine.h

Anton Korobeynikov asl at math.spbu.ru
Fri Jan 15 13:19:05 PST 2010


Author: asl
Date: Fri Jan 15 15:19:05 2010
New Revision: 93554

URL: http://llvm.org/viewvc/llvm-project?rev=93554&view=rev
Log:
Add branch relaxation pass (shamelessly stolen from PPC).

Added:
    llvm/trunk/lib/Target/MSP430/MSP430BranchSelector.cpp
Modified:
    llvm/trunk/lib/Target/MSP430/MSP430.h
    llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.cpp
    llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.h
    llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.td
    llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.cpp
    llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.h

Modified: llvm/trunk/lib/Target/MSP430/MSP430.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430.h?rev=93554&r1=93553&r2=93554&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430.h (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430.h Fri Jan 15 15:19:05 2010
@@ -39,6 +39,8 @@
   FunctionPass *createMSP430ISelDag(MSP430TargetMachine &TM,
                                     CodeGenOpt::Level OptLevel);
 
+  FunctionPass *createMSP430BranchSelectionPass();
+
   extern Target TheMSP430Target;
 
 } // end namespace llvm;

Added: llvm/trunk/lib/Target/MSP430/MSP430BranchSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430BranchSelector.cpp?rev=93554&view=auto

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430BranchSelector.cpp (added)
+++ llvm/trunk/lib/Target/MSP430/MSP430BranchSelector.cpp Fri Jan 15 15:19:05 2010
@@ -0,0 +1,179 @@
+//===-- MSP430BranchSelector.cpp - Emit long conditional branches--*- C++ -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that scans a machine function to determine which
+// conditional branches need more than 10 bits of displacement to reach their
+// target basic block.  It does this in two passes; a calculation of basic block
+// positions pass, and a branch psuedo op to machine branch opcode pass.  This
+// pass should be run last, just before the assembly printer.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "msp430-branch-select"
+#include "MSP430.h"
+#include "MSP430InstrInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MathExtras.h"
+using namespace llvm;
+
+STATISTIC(NumExpanded, "Number of branches expanded to long format");
+
+namespace {
+  struct MSP430BSel : public MachineFunctionPass {
+    static char ID;
+    MSP430BSel() : MachineFunctionPass(&ID) {}
+
+    /// BlockSizes - The sizes of the basic blocks in the function.
+    std::vector<unsigned> BlockSizes;
+
+    virtual bool runOnMachineFunction(MachineFunction &Fn);
+
+    virtual const char *getPassName() const {
+      return "MSP430 Branch Selector";
+    }
+  };
+  char MSP430BSel::ID = 0;
+}
+
+/// createMSP430BranchSelectionPass - returns an instance of the Branch
+/// Selection Pass
+///
+FunctionPass *llvm::createMSP430BranchSelectionPass() {
+  return new MSP430BSel();
+}
+
+bool MSP430BSel::runOnMachineFunction(MachineFunction &Fn) {
+  const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
+  // Give the blocks of the function a dense, in-order, numbering.
+  Fn.RenumberBlocks();
+  BlockSizes.resize(Fn.getNumBlockIDs());
+
+  // Measure each MBB and compute a size for the entire function.
+  unsigned FuncSize = 0;
+  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
+       ++MFI) {
+    MachineBasicBlock *MBB = MFI;
+
+    unsigned BlockSize = 0;
+    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
+         MBBI != EE; ++MBBI)
+      BlockSize += TII->GetInstSizeInBytes(MBBI);
+
+    BlockSizes[MBB->getNumber()] = BlockSize;
+    FuncSize += BlockSize;
+  }
+
+  // If the entire function is smaller than the displacement of a branch field,
+  // we know we don't need to shrink any branches in this function.  This is a
+  // common case.
+  if (FuncSize < (1 << 9)) {
+    BlockSizes.clear();
+    return false;
+  }
+
+  // For each conditional branch, if the offset to its destination is larger
+  // than the offset field allows, transform it into a long branch sequence
+  // like this:
+  //   short branch:
+  //     bCC MBB
+  //   long branch:
+  //     b!CC $PC+6
+  //     b MBB
+  //
+  bool MadeChange = true;
+  bool EverMadeChange = false;
+  while (MadeChange) {
+    // Iteratively expand branches until we reach a fixed point.
+    MadeChange = false;
+
+    for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
+         ++MFI) {
+      MachineBasicBlock &MBB = *MFI;
+      unsigned MBBStartOffset = 0;
+      for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
+           I != E; ++I) {
+        if ((I->getOpcode() != MSP430::JCC || I->getOperand(0).isImm()) &&
+            I->getOpcode() != MSP430::JMP) {
+          MBBStartOffset += TII->GetInstSizeInBytes(I);
+          continue;
+        }
+
+        // Determine the offset from the current branch to the destination
+        // block.
+        MachineBasicBlock *Dest = I->getOperand(0).getMBB();
+
+        int BranchSize;
+        if (Dest->getNumber() <= MBB.getNumber()) {
+          // If this is a backwards branch, the delta is the offset from the
+          // start of this block to this branch, plus the sizes of all blocks
+          // from this block to the dest.
+          BranchSize = MBBStartOffset;
+
+          for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i)
+            BranchSize += BlockSizes[i];
+        } else {
+          // Otherwise, add the size of the blocks between this block and the
+          // dest to the number of bytes left in this block.
+          BranchSize = -MBBStartOffset;
+
+          for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i)
+            BranchSize += BlockSizes[i];
+        }
+
+        // If this branch is in range, ignore it.
+        if (isInt<10>(BranchSize)) {
+          MBBStartOffset += 2;
+          continue;
+        }
+
+        // Otherwise, we have to expand it to a long branch.
+        unsigned NewSize;
+        MachineInstr *OldBranch = I;
+        DebugLoc dl = OldBranch->getDebugLoc();
+
+        if (I->getOpcode() == MSP430::JMP) {
+          NewSize = 4;
+        } else {
+          // The BCC operands are:
+          // 0. MSP430 branch predicate
+          // 1. Target MBB
+          SmallVector<MachineOperand, 1> Cond;
+          Cond.push_back(I->getOperand(1));
+
+          // Jump over the uncond branch inst (i.e. $+6) on opposite condition.
+          TII->ReverseBranchCondition(Cond);
+          BuildMI(MBB, I, dl, TII->get(MSP430::JCC))
+            .addImm(4).addOperand(Cond[0]);
+
+          NewSize = 6;
+        }
+        // Uncond branch to the real destination.
+        I = BuildMI(MBB, I, dl, TII->get(MSP430::B)).addMBB(Dest);
+
+        // Remove the old branch from the function.
+        OldBranch->eraseFromParent();
+
+        // Remember that this instruction is NewSize bytes, increase the size of the
+        // block by NewSize-2, remember to iterate.
+        BlockSizes[MBB.getNumber()] += NewSize-2;
+        MBBStartOffset += NewSize;
+
+        ++NumExpanded;
+        MadeChange = true;
+      }
+    }
+    EverMadeChange |= MadeChange;
+  }
+
+  BlockSizes.clear();
+  return true;
+}

Modified: llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.cpp?rev=93554&r1=93553&r2=93554&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.cpp Fri Jan 15 15:19:05 2010
@@ -344,3 +344,45 @@
   }
   return Count;
 }
+
+/// GetInstSize - Return the number of bytes of code the specified
+/// instruction may be.  This returns the maximum number of bytes.
+///
+unsigned MSP430InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
+  const TargetInstrDesc &Desc = MI->getDesc();
+
+  switch (Desc.TSFlags & MSP430II::SizeMask) {
+  default:
+    switch (Desc.getOpcode()) {
+    default:
+      assert(0 && "Unknown instruction size!");
+    case TargetInstrInfo::DBG_LABEL:
+    case TargetInstrInfo::EH_LABEL:
+    case TargetInstrInfo::IMPLICIT_DEF:
+    case TargetInstrInfo::KILL:
+      return 0;
+    case TargetInstrInfo::INLINEASM: {
+      const MachineFunction *MF = MI->getParent()->getParent();
+      const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
+      return TII.getInlineAsmLength(MI->getOperand(0).getSymbolName(),
+                                    *MF->getTarget().getMCAsmInfo());
+    }
+    }
+  case MSP430II::SizeSpecial:
+    switch (MI->getOpcode()) {
+    default:
+      assert(0 && "Unknown instruction size!");
+    case MSP430::SAR8r1c:
+    case MSP430::SAR16r1c:
+      return 4;
+    }
+  case MSP430II::Size2Bytes:
+    return 2;
+  case MSP430II::Size4Bytes:
+    return 4;
+  case MSP430II::Size6Bytes:
+    return 6;
+  }
+
+  return 6;
+}

Modified: llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.h?rev=93554&r1=93553&r2=93554&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.h (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.h Fri Jan 15 15:19:05 2010
@@ -21,6 +21,22 @@
 
 class MSP430TargetMachine;
 
+/// MSP430II - This namespace holds all of the target specific flags that
+/// instruction info tracks.
+///
+namespace MSP430II {
+  enum {
+    SizeShift   = 2,
+    SizeMask    = 7 << SizeShift,
+
+    SizeUnknown = 0 << SizeShift,
+    SizeSpecial = 1 << SizeShift,
+    Size2Bytes  = 2 << SizeShift,
+    Size4Bytes  = 3 << SizeShift,
+    Size6Bytes  = 4 << SizeShift
+  };
+}
+
 class MSP430InstrInfo : public TargetInstrInfoImpl {
   const MSP430RegisterInfo RI;
   MSP430TargetMachine &TM;
@@ -59,6 +75,8 @@
                                            MachineBasicBlock::iterator MI,
                                  const std::vector<CalleeSavedInfo> &CSI) const;
 
+  unsigned GetInstSizeInBytes(const MachineInstr *MI) const;
+
   // Branch folding goodness
   bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
   bool isUnpredicatedTerminator(const MachineInstr *MI) const;

Modified: llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.td?rev=93554&r1=93553&r2=93554&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.td (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430InstrInfo.td Fri Jan 15 15:19:05 2010
@@ -167,11 +167,18 @@
 // FIXME: expand opcode & cond field for branches!
 
 // Direct branch
-let isBarrier = 1 in
+let isBarrier = 1 in {
+  // Short branch
   def JMP : CJForm<0, 0,
                    (outs), (ins brtarget:$dst),
                    "jmp\t$dst",
                    [(br bb:$dst)]>;
+  // Long branch
+  def B   : I16ri<0,
+                  (outs), (ins brtarget:$dst),
+                  "br\t$dst",
+                  []>;
+}
 
 // Conditional branches
 let Uses = [SRW] in

Modified: llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.cpp?rev=93554&r1=93553&r2=93554&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.cpp Fri Jan 15 15:19:05 2010
@@ -44,3 +44,9 @@
   return false;
 }
 
+bool MSP430TargetMachine::addPreEmitPass(PassManagerBase &PM,
+                                         CodeGenOpt::Level OptLevel) {
+  // Must run branch selection immediately preceding the asm printer.
+  PM.add(createMSP430BranchSelectionPass());
+  return false;
+}

Modified: llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.h?rev=93554&r1=93553&r2=93554&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.h (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430TargetMachine.h Fri Jan 15 15:19:05 2010
@@ -55,6 +55,7 @@
   }
 
   virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
+  virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
 }; // MSP430TargetMachine.
 
 } // end namespace llvm





More information about the llvm-commits mailing list