[llvm] r194053 - Fix r194019 as requested by Eric Christopher.

Reed Kotler Reed.Kotler at imgtec.com
Thu Nov 7 02:45:17 PST 2013


Hi,

I was at the LLVM conference yesterday and did not see this.

This whole pass is not turned on by default at this time.
You have to use a hidden option to enable it. It's part of a port in progress.
I will fix this section that is causing warnings for you and remove the parts
that don't need to be there at this time.

Reed

________________________________________
From: aaron.ballman at gmail.com [aaron.ballman at gmail.com] on behalf of Aaron Ballman [aaron at aaronballman.com]
Sent: Wednesday, November 06, 2013 10:01 AM
To: Reed Kotler
Cc: llvm-commits
Subject: Re: [llvm] r194053 - Fix r194019 as requested by Eric Christopher.

On Tue, Nov 5, 2013 at 3:14 AM, Reed Kotler <rkotler at mips.com> wrote:
> Author: rkotler
> Date: Tue Nov  5 02:14:14 2013
> New Revision: 194053
>
> URL: http://llvm.org/viewvc/llvm-project?rev=194053&view=rev
> Log:
> Fix r194019 as requested by Eric Christopher.
> Submit the basic port of the rest of ARM constant islands code to Mips.
> Two test cases are added which reflect the next level of functionality:
> constants getting moved to water areas that are out of range from the
> initial placement at the end of the function and basic blocks being split to
> create water when none exists that can be used. There is a bunch of this
> code that is not complete and has been marked with IN_PROGRESS. I will
> finish cleaning this all up during the next week or two and submit the
> rest of the test cases. I have elminated some code for dealing with
> inline assembly because to me it unecessarily complicates things and
> some of the newer features of llvm like function attributies and builtin
> assembler give me better tools to solve the alignment issues created
> there. Also, for Mips16 I even have the option of not doing constant
> islands in the present of inline assembler if I chose. When everything
> has been completed I will summarize the port and notify people that
> are knowledgable regarding the ARM Constant Islands code so they can
> review it in it's entirety if they wish.
>
>
> Added:
>     llvm/trunk/test/CodeGen/Mips/const4.ll
> Modified:
>     llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td
>     llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp
>
> Modified: llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td?rev=194053&r1=194052&r2=194053&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td (original)
> +++ llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td Tue Nov  5 02:14:14 2013
> @@ -60,6 +60,11 @@ class FRI16_ins<bits<5> op, string asmst
>                  InstrItinClass itin>:
>    FRI16_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>;
>
> +class FRI16_TCP_ins<bits<5> _op, string asmstr,
> +                    InstrItinClass itin>:
> +  FRI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size),
> +            !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin>;
> +
>  class FRI16R_ins_base<bits<5> op, string asmstr, string asmstr2,
>                       InstrItinClass itin>:
>    FRI16<op, (outs), (ins CPU16Regs:$rx, simm16:$imm),
> @@ -174,7 +179,7 @@ class FEXT_RI16_B_ins<bits<5> _op, strin
>
>  class FEXT_RI16_TCP_ins<bits<5> _op, string asmstr,
>                          InstrItinClass itin>:
> -  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm),
> +  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size),
>              !strconcat(asmstr, "\t$rx, $imm"), [], itin>;
>
>  class FEXT_2RI16_ins<bits<5> _op, string asmstr,
> @@ -802,6 +807,8 @@ def LwRxSpImmX16: FEXT_RI16_SP_explicit_
>    let Uses = [SP];
>  }
>
> +def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad;
> +
>  def LwRxPcTcpX16: FEXT_RI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad;
>  //
>  // Format: MOVE r32, rz MIPS16e
> @@ -1869,3 +1876,4 @@ let neverHasSideEffects = 1, isNotDuplic
>  def CONSTPOOL_ENTRY :
>  MipsPseudo16<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx,
>                        i32imm:$size), "foo", []>;
> +
>
> Modified: llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp?rev=194053&r1=194052&r2=194053&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp (original)
> +++ llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp Tue Nov  5 02:14:14 2013
> @@ -27,6 +27,7 @@
>
>  #include "Mips.h"
>  #include "MCTargetDesc/MipsBaseInfo.h"
> +#include "MipsMachineFunction.h"
>  #include "MipsTargetMachine.h"
>  #include "llvm/ADT/Statistic.h"
>  #include "llvm/CodeGen/MachineBasicBlock.h"
> @@ -42,30 +43,197 @@
>  #include "llvm/Target/TargetInstrInfo.h"
>  #include "llvm/Target/TargetMachine.h"
>  #include "llvm/Target/TargetRegisterInfo.h"
> +#include "llvm/Support/Format.h"
>  #include <algorithm>
>
>  using namespace llvm;
>
>  STATISTIC(NumCPEs,       "Number of constpool entries");
> +STATISTIC(NumSplit,      "Number of uncond branches inserted");
> +STATISTIC(NumCBrFixed,   "Number of cond branches fixed");
> +STATISTIC(NumUBrFixed,   "Number of uncond branches fixed");
>
>  // FIXME: This option should be removed once it has received sufficient testing.
>  static cl::opt<bool>
>  AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true),
>            cl::desc("Align constant islands in code"));
>
> +
> +// Rather than do make check tests with huge amounts of code, we force
> +// the test to use this amount.
> +//
> +static cl::opt<int> ConstantIslandsSmallOffset(
> +  "mips-constant-islands-small-offset",
> +  cl::init(0),
> +  cl::desc("Make small offsets be this amount for testing purposes"),
> +  cl::Hidden);
> +
> +/// UnknownPadding - Return the worst case padding that could result from
> +/// unknown offset bits.  This does not include alignment padding caused by
> +/// known offset bits.
> +///
> +/// @param LogAlign log2(alignment)
> +/// @param KnownBits Number of known low offset bits.
> +static inline unsigned UnknownPadding(unsigned LogAlign, unsigned KnownBits) {
> +  if (KnownBits < LogAlign)
> +    return (1u << LogAlign) - (1u << KnownBits);
> +  return 0;
> +}
> +
>  namespace {
> +
> +
>    typedef MachineBasicBlock::iterator Iter;
>    typedef MachineBasicBlock::reverse_iterator ReverseIter;
>
> +  /// MipsConstantIslands - Due to limited PC-relative displacements, Mips
> +  /// requires constant pool entries to be scattered among the instructions
> +  /// inside a function.  To do this, it completely ignores the normal LLVM
> +  /// constant pool; instead, it places constants wherever it feels like with
> +  /// special instructions.
> +  ///
> +  /// The terminology used in this pass includes:
> +  ///   Islands - Clumps of constants placed in the function.
> +  ///   Water   - Potential places where an island could be formed.
> +  ///   CPE     - A constant pool entry that has been placed somewhere, which
> +  ///             tracks a list of users.
> +
>    class MipsConstantIslands : public MachineFunctionPass {
>
> -  const TargetMachine &TM;
> -  bool IsPIC;
> -  unsigned ABI;
> -  const MipsSubtarget *STI;
> -  const MipsInstrInfo *TII;
> -  MachineFunction *MF;
> -  MachineConstantPool *MCP;
> +    /// BasicBlockInfo - Information about the offset and size of a single
> +    /// basic block.
> +    struct BasicBlockInfo {
> +      /// Offset - Distance from the beginning of the function to the beginning
> +      /// of this basic block.
> +      ///
> +      /// Offsets are computed assuming worst case padding before an aligned
> +      /// block. This means that subtracting basic block offsets always gives a
> +      /// conservative estimate of the real distance which may be smaller.
> +      ///
> +      /// Because worst case padding is used, the computed offset of an aligned
> +      /// block may not actually be aligned.
> +      unsigned Offset;
> +
> +      /// Size - Size of the basic block in bytes.  If the block contains
> +      /// inline assembly, this is a worst case estimate.
> +      ///
> +      /// The size does not include any alignment padding whether from the
> +      /// beginning of the block, or from an aligned jump table at the end.
> +      unsigned Size;
> +
> +      /// KnownBits - The number of low bits in Offset that are known to be
> +      /// exact.  The remaining bits of Offset are an upper bound.
> +      uint8_t KnownBits;
> +
> +      /// Unalign - When non-zero, the block contains instructions (inline asm)
> +      /// of unknown size.  The real size may be smaller than Size bytes by a
> +      /// multiple of 1 << Unalign.
> +      uint8_t Unalign;
> +
> +      /// PostAlign - When non-zero, the block terminator contains a .align
> +      /// directive, so the end of the block is aligned to 1 << PostAlign
> +      /// bytes.
> +      uint8_t PostAlign;
> +
> +      BasicBlockInfo() : Offset(0), Size(0), KnownBits(0), Unalign(0),
> +        PostAlign(0) {}
> +
> +      /// Compute the number of known offset bits internally to this block.
> +      /// This number should be used to predict worst case padding when
> +      /// splitting the block.
> +      unsigned internalKnownBits() const {
> +        unsigned Bits = Unalign ? Unalign : KnownBits;
> +        // If the block size isn't a multiple of the known bits, assume the
> +        // worst case padding.
> +        if (Size & ((1u << Bits) - 1))
> +          Bits = countTrailingZeros(Size);
> +        return Bits;
> +      }
> +
> +      /// Compute the offset immediately following this block.  If LogAlign is
> +      /// specified, return the offset the successor block will get if it has
> +      /// this alignment.
> +      unsigned postOffset(unsigned LogAlign = 0) const {
> +        unsigned PO = Offset + Size;
> +        return PO;
> +      }
> +
> +      /// Compute the number of known low bits of postOffset.  If this block
> +      /// contains inline asm, the number of known bits drops to the
> +      /// instruction alignment.  An aligned terminator may increase the number
> +      /// of know bits.
> +      /// If LogAlign is given, also consider the alignment of the next block.
> +      unsigned postKnownBits(unsigned LogAlign = 0) const {
> +        return std::max(std::max(unsigned(PostAlign), LogAlign),
> +                        internalKnownBits());
> +      }
> +    };
> +
> +    std::vector<BasicBlockInfo> BBInfo;
> +
> +    /// WaterList - A sorted list of basic blocks where islands could be placed
> +    /// (i.e. blocks that don't fall through to the following block, due
> +    /// to a return, unreachable, or unconditional branch).
> +    std::vector<MachineBasicBlock*> WaterList;
> +
> +    /// NewWaterList - The subset of WaterList that was created since the
> +    /// previous iteration by inserting unconditional branches.
> +    SmallSet<MachineBasicBlock*, 4> NewWaterList;
> +
> +    typedef std::vector<MachineBasicBlock*>::iterator water_iterator;
> +
> +    /// CPUser - One user of a constant pool, keeping the machine instruction
> +    /// pointer, the constant pool being referenced, and the max displacement
> +    /// allowed from the instruction to the CP.  The HighWaterMark records the
> +    /// highest basic block where a new CPEntry can be placed.  To ensure this
> +    /// pass terminates, the CP entries are initially placed at the end of the
> +    /// function and then move monotonically to lower addresses.  The
> +    /// exception to this rule is when the current CP entry for a particular
> +    /// CPUser is out of range, but there is another CP entry for the same
> +    /// constant value in range.  We want to use the existing in-range CP
> +    /// entry, but if it later moves out of range, the search for new water
> +    /// should resume where it left off.  The HighWaterMark is used to record
> +    /// that point.
> +    struct CPUser {
> +      MachineInstr *MI;
> +      MachineInstr *CPEMI;
> +      MachineBasicBlock *HighWaterMark;
> +    private:
> +      unsigned MaxDisp;
> +      unsigned LongFormMaxDisp; // mips16 has 16/32 bit instructions
> +                                // with different displacements
> +      unsigned LongFormOpcode;
> +    public:
> +      bool NegOk;
> +      bool IsSoImm;
> +      bool KnownAlignment;
> +      CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
> +             bool neg, bool soimm,
> +             unsigned longformmaxdisp, unsigned longformopcode)
> +        : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp),
> +          LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode),
> +          NegOk(neg), IsSoImm(soimm), KnownAlignment(false)  {
> +        HighWaterMark = CPEMI->getParent();
> +      }
> +      /// getMaxDisp - Returns the maximum displacement supported by MI.
> +      /// Correct for unknown alignment.
> +      /// Conservatively subtract 2 bytes to handle weird alignment effects.
> +      unsigned getMaxDisp() const {
> +        unsigned xMaxDisp = ConstantIslandsSmallOffset?
> +                            ConstantIslandsSmallOffset: MaxDisp;
> +        return (KnownAlignment ? xMaxDisp : xMaxDisp - 2) - 2;
> +      }
> +      unsigned getLongFormMaxDisp() const {
> +        return (KnownAlignment ? LongFormMaxDisp : LongFormMaxDisp - 2) - 2;
> +      }
> +      unsigned getLongFormOpcode() const {
> +          return LongFormOpcode;
> +      }
> +    };
> +
> +    /// CPUsers - Keep track of all of the machine instructions that use various
> +    /// constant pools and their max displacement.
> +    std::vector<CPUser> CPUsers;
>
>    /// CPEntry - One per constant pool entry, keeping the machine instruction
>    /// pointer, the constpool index, and the number of CPUser's which
> @@ -85,13 +253,56 @@ namespace {
>    /// put in the vector of the original element, but have distinct CPIs.
>    std::vector<std::vector<CPEntry> > CPEntries;
>
> +  /// ImmBranch - One per immediate branch, keeping the machine instruction
> +  /// pointer, conditional or unconditional, the max displacement,
> +  /// and (if isCond is true) the corresponding unconditional branch
> +  /// opcode.
> +  struct ImmBranch {
> +    MachineInstr *MI;
> +    unsigned MaxDisp : 31;
> +    bool isCond : 1;
> +    int UncondBr;
> +    ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr)
> +      : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
> +  };
> +
> +  /// ImmBranches - Keep track of all the immediate branch instructions.
> +  ///
> +  std::vector<ImmBranch> ImmBranches;
> +
> +  /// HasFarJump - True if any far jump instruction has been emitted during
> +  /// the branch fix up pass.
> +  bool HasFarJump;
> +
> +  const TargetMachine &TM;
> +  bool IsPIC;
> +  unsigned ABI;
> +  const MipsSubtarget *STI;
> +  const MipsInstrInfo *TII;
> +  MipsFunctionInfo *MFI;
> +  MachineFunction *MF;
> +  MachineConstantPool *MCP;
> +
> +  unsigned PICLabelUId;
> +  bool PrescannedForConstants;
> +
> +  void initPICLabelUId(unsigned UId) {
> +    PICLabelUId = UId;
> +  }
> +
> +
> +  unsigned createPICLabelUId() {
> +    return PICLabelUId++;
> +  }
> +
>    public:
>      static char ID;
>      MipsConstantIslands(TargetMachine &tm)
>        : MachineFunctionPass(ID), TM(tm),
>          IsPIC(TM.getRelocationModel() == Reloc::PIC_),
>          ABI(TM.getSubtarget<MipsSubtarget>().getTargetABI()),
> -        STI(&TM.getSubtarget<MipsSubtarget>()), MF(0), MCP(0){}
> +        STI(&TM.getSubtarget<MipsSubtarget>()), MF(0), MCP(0),
> +        PrescannedForConstants(false){}
>
>      virtual const char *getPassName() const {
>        return "Mips Constant Islands";
> @@ -100,6 +311,45 @@ namespace {
>      bool runOnMachineFunction(MachineFunction &F);
>
>      void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
> +    CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
> +    unsigned getCPELogAlign(const MachineInstr *CPEMI);
> +    void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs);
> +    unsigned getOffsetOf(MachineInstr *MI) const;
> +    unsigned getUserOffset(CPUser&) const;
> +    void dumpBBs();
> +    void verify();
> +
> +    bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
> +                         unsigned Disp, bool NegativeOK, bool IsSoImm = false);
> +    bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
> +                         const CPUser &U);
> +
> +    bool isLongFormOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
> +                                const CPUser &U);
> +
> +    void computeBlockSize(MachineBasicBlock *MBB);
> +    MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);
> +    void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
> +    void adjustBBOffsetsAfter(MachineBasicBlock *BB);
> +    bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);
> +    int findInRangeCPEntry(CPUser& U, unsigned UserOffset);
> +    int findLongFormInRangeCPEntry(CPUser& U, unsigned UserOffset);
> +    bool findAvailableWater(CPUser&U, unsigned UserOffset,
> +                            water_iterator &WaterIter);
> +    void createNewWater(unsigned CPUserIndex, unsigned UserOffset,
> +                        MachineBasicBlock *&NewMBB);
> +    bool handleConstantPoolUser(unsigned CPUserIndex);
> +    void removeDeadCPEMI(MachineInstr *CPEMI);
> +    bool removeUnusedCPEntries();
> +    bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
> +                          MachineInstr *CPEMI, unsigned Disp, bool NegOk,
> +                          bool DoDump = false);
> +    bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water,
> +                        CPUser &U, unsigned &Growth);
> +    bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
> +    bool fixupImmediateBr(ImmBranch &Br);
> +    bool fixupConditionalBr(ImmBranch &Br);
> +    bool fixupUnconditionalBr(ImmBranch &Br);
>
>      void prescanForConstants();
>
> @@ -110,6 +360,33 @@ namespace {
>    char MipsConstantIslands::ID = 0;
>  } // end of anonymous namespace
>
> +
> +bool MipsConstantIslands::isLongFormOffsetInRange
> +  (unsigned UserOffset, unsigned TrialOffset,
> +   const CPUser &U) {
> +  return isOffsetInRange(UserOffset, TrialOffset,
> +                         U.getLongFormMaxDisp(), U.NegOk, U.IsSoImm);
> +}
> +
> +bool MipsConstantIslands::isOffsetInRange
> +  (unsigned UserOffset, unsigned TrialOffset,
> +   const CPUser &U) {
> +  return isOffsetInRange(UserOffset, TrialOffset,
> +                         U.getMaxDisp(), U.NegOk, U.IsSoImm);
> +}
> +/// print block size and offset information - debugging
> +void MipsConstantIslands::dumpBBs() {
> +  DEBUG({
> +    for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {
> +      const BasicBlockInfo &BBI = BBInfo[J];
> +      dbgs() << format("%08x BB#%u\t", BBI.Offset, J)
> +             << " kb=" << unsigned(BBI.KnownBits)
> +             << " ua=" << unsigned(BBI.Unalign)
> +             << " pa=" << unsigned(BBI.PostAlign)
> +             << format(" size=%#x\n", BBInfo[J].Size);
> +    }
> +  });
> +}
>  /// createMipsLongBranchPass - Returns a pass that converts branches to long
>  /// branches.
>  FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) {
> @@ -127,13 +404,15 @@ bool MipsConstantIslands::runOnMachineFu
>      return false;
>    }
>    TII = (const MipsInstrInfo*)MF->getTarget().getInstrInfo();
> +  MFI = MF->getInfo<MipsFunctionInfo>();
>    DEBUG(dbgs() << "constant island processing " << "\n");
>    //
>    // will need to make predermination if there is any constants we need to
>    // put in constant islands. TBD.
>    //
> -  prescanForConstants();
> +  if (!PrescannedForConstants) prescanForConstants();
>
> +  HasFarJump = false;
>    // This pass invalidates liveness information when it splits basic blocks.
>    MF->getRegInfo().invalidateLiveness();
>
> @@ -141,13 +420,66 @@ bool MipsConstantIslands::runOnMachineFu
>    // the numbers agree with the position of the block in the function.
>    MF->RenumberBlocks();
>
> +  bool MadeChange = false;
> +
>    // Perform the initial placement of the constant pool entries.  To start with,
>    // we put them all at the end of the function.
>    std::vector<MachineInstr*> CPEMIs;
>    if (!MCP->isEmpty())
>      doInitialPlacement(CPEMIs);
>
> -  return true;
> +  /// The next UID to take is the first unused one.
> +  initPICLabelUId(CPEMIs.size());
> +
> +  // Do the initial scan of the function, building up information about the
> +  // sizes of each block, the location of all the water, and finding all of the
> +  // constant pool users.
> +  initializeFunctionInfo(CPEMIs);
> +  CPEMIs.clear();
> +  DEBUG(dumpBBs());
> +
> +  /// Remove dead constant pool entries.
> +  MadeChange |= removeUnusedCPEntries();
> +
> +  // Iteratively place constant pool entries and fix up branches until there
> +  // is no change.
> +  unsigned NoCPIters = 0, NoBRIters = 0;
> +  (void)NoBRIters;
> +  while (true) {
> +    DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n');
> +    bool CPChange = false;
> +    for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
> +      CPChange |= handleConstantPoolUser(i);
> +    if (CPChange && ++NoCPIters > 30)
> +      report_fatal_error("Constant Island pass failed to converge!");
> +    DEBUG(dumpBBs());
> +
> +    // Clear NewWaterList now.  If we split a block for branches, it should
> +    // appear as "new water" for the next iteration of constant pool placement.
> +    NewWaterList.clear();
> +
> +    DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n');
> +    bool BRChange = false;
> +#ifdef IN_PROGRESS
> +    for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
> +      BRChange |= fixupImmediateBr(ImmBranches[i]);
> +    if (BRChange && ++NoBRIters > 30)
> +      report_fatal_error("Branch Fix Up pass failed to converge!");
> +    DEBUG(dumpBBs());
> +#endif
> +    if (!CPChange && !BRChange)
> +      break;
> +    MadeChange = true;
> +  }
> +
> +  DEBUG(dbgs() << '\n'; dumpBBs());
> +
> +  BBInfo.clear();
> +  WaterList.clear();
> +  CPUsers.clear();
> +  CPEntries.clear();
> +  ImmBranches.clear();
> +  return MadeChange;
>  }
>
>  /// doInitialPlacement - Perform the initial placement of the constant pool
> @@ -216,9 +548,1034 @@ MipsConstantIslands::doInitialPlacement(
>    DEBUG(BB->dump());
>  }
>
> +/// BBHasFallthrough - Return true if the specified basic block can fallthrough
> +/// into the block immediately after it.
> +static bool BBHasFallthrough(MachineBasicBlock *MBB) {
> +  // Get the next machine basic block in the function.
> +  MachineFunction::iterator MBBI = MBB;
> +  // Can't fall off end of function.
> +  if (llvm::next(MBBI) == MBB->getParent()->end())
> +    return false;
> +
> +  MachineBasicBlock *NextBB = llvm::next(MBBI);
> +  for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(),
> +       E = MBB->succ_end(); I != E; ++I)
> +    if (*I == NextBB)
> +      return true;
> +
> +  return false;
> +}
> +
> +/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI,
> +/// look up the corresponding CPEntry.
> +MipsConstantIslands::CPEntry
> +*MipsConstantIslands::findConstPoolEntry(unsigned CPI,
> +                                        const MachineInstr *CPEMI) {
> +  std::vector<CPEntry> &CPEs = CPEntries[CPI];
> +  // Number of entries per constpool index should be small, just do a
> +  // linear search.
> +  for (unsigned i = 0, e = CPEs.size(); i != e; ++i) {
> +    if (CPEs[i].CPEMI == CPEMI)
> +      return &CPEs[i];
> +  }
> +  return NULL;
> +}
> +
> +/// getCPELogAlign - Returns the required alignment of the constant pool entry
> +/// represented by CPEMI.  Alignment is measured in log2(bytes) units.
> +unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr *CPEMI) {
> +  assert(CPEMI && CPEMI->getOpcode() == Mips::CONSTPOOL_ENTRY);
> +
> +  // Everything is 4-byte aligned unless AlignConstantIslands is set.
> +  if (!AlignConstantIslands)
> +    return 2;
> +
> +  unsigned CPI = CPEMI->getOperand(1).getIndex();
> +  assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
> +  unsigned Align = MCP->getConstants()[CPI].getAlignment();
> +  assert(isPowerOf2_32(Align) && "Invalid CPE alignment");
> +  return Log2_32(Align);
> +}
> +
> +/// initializeFunctionInfo - Do the initial scan of the function, building up
> +/// information about the sizes of each block, the location of all the water,
> +/// and finding all of the constant pool users.
> +void MipsConstantIslands::
> +initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
> +  BBInfo.clear();
> +  BBInfo.resize(MF->getNumBlockIDs());
> +
> +  // First thing, compute the size of all basic blocks, and see if the function
> +  // has any inline assembly in it. If so, we have to be conservative about
> +  // alignment assumptions, as we don't know for sure the size of any
> +  // instructions in the inline assembly.
> +  for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I)
> +    computeBlockSize(I);
> +
> +  // The known bits of the entry block offset are determined by the function
> +  // alignment.
> +  BBInfo.front().KnownBits = MF->getAlignment();
> +
> +  // Compute block offsets.
> +  adjustBBOffsetsAfter(MF->begin());
> +
> +  // Now go back through the instructions and build up our data structures.
> +  for (MachineFunction::iterator MBBI = MF->begin(), E = MF->end();
> +       MBBI != E; ++MBBI) {
> +    MachineBasicBlock &MBB = *MBBI;
> +
> +    // If this block doesn't fall through into the next MBB, then this is
> +    // 'water' that a constant pool island could be placed.
> +    if (!BBHasFallthrough(&MBB))
> +      WaterList.push_back(&MBB);
> +    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
> +         I != E; ++I) {
> +      if (I->isDebugValue())
> +        continue;
> +
> +      int Opc = I->getOpcode();
> +      if (I->isBranch()) {
> +        bool isCond = false;
> +        unsigned Bits = 0;
> +        unsigned Scale = 1;
> +        int UOpc = Opc;
> +
> +        switch (Opc) {
> +        default:
> +          continue;  // Ignore other JT branches
> +        }

This smells like a bug, and it causes new warnings to boot.  This
continue will fire every time, yet there's code following the switch.
Can you please rectify this, and remove the switch statement
containing only a default with no cases?

> +        // Record this immediate branch.
> +        unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
> +        ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc));
> +
> +      }

~Aaron





More information about the llvm-commits mailing list