<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" id="owaParaStyle"></style>
</head>
<body fpstyle="1" ocsi="0">
<div style="direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;">I see there are some more thumb references in the comments.
<div>I had searched for ARM but did not search for thumb so I missed those references.<br>
<div><br>
</div>
<div>I will take them out in the morning.</div>
<div><br>
</div>
<div>My home ubuntu machine is updating with the new ubuntu so I can't do it right now.</div>
<div><br>
</div>
<div>If my ubuntu machine finishes updating in the next half hour then I'll do it tonight.</div>
<div><br>
</div>
<div>These ARM references in my opinion should have been left in the code in places where</div>
<div>work was to be done.</div>
<div><br>
</div>
<div>I have totally removed them already from places where the port is basically done.</div>
<div><br>
</div>
<div>Those references were my reminders of what the issues are at various places.</div>
<div><br>
</div>
<div>Now I have go through the code side by side with the original version to finish things.</div>
<div><br>
</div>
<div>Reed</div>
<div><br>
<div style="font-family: Times New Roman; color: #000000; font-size: 16px">
<hr tabindex="-1">
<div id="divRpF362627" style="direction: ltr;"><font face="Tahoma" size="2" color="#000000"><b>From:</b> Eric Christopher [echristo@gmail.com]<br>
<b>Sent:</b> Tuesday, November 05, 2013 1:00 AM<br>
<b>To:</b> Reed Kotler<br>
<b>Cc:</b> llvm-commits@cs.uiuc.edu<br>
<b>Subject:</b> Re: [llvm] r194053 - Fix r194019 as requested by Eric Christopher.<br>
</font><br>
</div>
<div></div>
<div>
<div dir="ltr">Please revert this and remove all of the arm/thumb references and before you reapply again. This is pretty sloppy work and unacceptable for inclusion in mainline. There's a big difference between incremental work and this.
<div><br>
</div>
<div>-eric</div>
</div>
<div class="gmail_extra"><br>
<br>
<div class="gmail_quote">On Tue, Nov 5, 2013 at 12:14 AM, Reed Kotler <span dir="ltr">
<<a href="mailto:rkotler@mips.com" target="_blank">rkotler@mips.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex; border-left:1px #ccc solid; padding-left:1ex">
Author: rkotler<br>
Date: Tue Nov 5 02:14:14 2013<br>
New Revision: 194053<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=194053&view=rev" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=194053&view=rev</a><br>
Log:<br>
Fix r194019 as requested by Eric Christopher.<br>
Submit the basic port of the rest of ARM constant islands code to Mips.<br>
Two test cases are added which reflect the next level of functionality:<br>
constants getting moved to water areas that are out of range from the<br>
initial placement at the end of the function and basic blocks being split to<br>
create water when none exists that can be used. There is a bunch of this<br>
code that is not complete and has been marked with IN_PROGRESS. I will<br>
finish cleaning this all up during the next week or two and submit the<br>
rest of the test cases. I have elminated some code for dealing with<br>
inline assembly because to me it unecessarily complicates things and<br>
some of the newer features of llvm like function attributies and builtin<br>
assembler give me better tools to solve the alignment issues created<br>
there. Also, for Mips16 I even have the option of not doing constant<br>
islands in the present of inline assembler if I chose. When everything<br>
has been completed I will summarize the port and notify people that<br>
are knowledgable regarding the ARM Constant Islands code so they can<br>
review it in it's entirety if they wish.<br>
<br>
<br>
Added:<br>
llvm/trunk/test/CodeGen/Mips/const4.ll<br>
Modified:<br>
llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td<br>
llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp<br>
<br>
Modified: llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td?rev=194053&r1=194052&r2=194053&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td?rev=194053&r1=194052&r2=194053&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td (original)<br>
+++ llvm/trunk/lib/Target/Mips/Mips16InstrInfo.td Tue Nov 5 02:14:14 2013<br>
@@ -60,6 +60,11 @@ class FRI16_ins<bits<5> op, string asmst<br>
InstrItinClass itin>:<br>
FRI16_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>;<br>
<br>
+class FRI16_TCP_ins<bits<5> _op, string asmstr,<br>
+ InstrItinClass itin>:<br>
+ FRI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size),<br>
+ !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin>;<br>
+<br>
class FRI16R_ins_base<bits<5> op, string asmstr, string asmstr2,<br>
InstrItinClass itin>:<br>
FRI16<op, (outs), (ins CPU16Regs:$rx, simm16:$imm),<br>
@@ -174,7 +179,7 @@ class FEXT_RI16_B_ins<bits<5> _op, strin<br>
<br>
class FEXT_RI16_TCP_ins<bits<5> _op, string asmstr,<br>
InstrItinClass itin>:<br>
- FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm),<br>
+ FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size),<br>
!strconcat(asmstr, "\t$rx, $imm"), [], itin>;<br>
<br>
class FEXT_2RI16_ins<bits<5> _op, string asmstr,<br>
@@ -802,6 +807,8 @@ def LwRxSpImmX16: FEXT_RI16_SP_explicit_<br>
let Uses = [SP];<br>
}<br>
<br>
+def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad;<br>
+<br>
def LwRxPcTcpX16: FEXT_RI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad;<br>
//<br>
// Format: MOVE r32, rz MIPS16e<br>
@@ -1869,3 +1876,4 @@ let neverHasSideEffects = 1, isNotDuplic<br>
def CONSTPOOL_ENTRY :<br>
MipsPseudo16<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx,<br>
i32imm:$size), "foo", []>;<br>
+<br>
<br>
Modified: llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp?rev=194053&r1=194052&r2=194053&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp?rev=194053&r1=194052&r2=194053&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp (original)<br>
+++ llvm/trunk/lib/Target/Mips/MipsConstantIslandPass.cpp Tue Nov 5 02:14:14 2013<br>
@@ -27,6 +27,7 @@<br>
<br>
#include "Mips.h"<br>
#include "MCTargetDesc/MipsBaseInfo.h"<br>
+#include "MipsMachineFunction.h"<br>
#include "MipsTargetMachine.h"<br>
#include "llvm/ADT/Statistic.h"<br>
#include "llvm/CodeGen/MachineBasicBlock.h"<br>
@@ -42,30 +43,197 @@<br>
#include "llvm/Target/TargetInstrInfo.h"<br>
#include "llvm/Target/TargetMachine.h"<br>
#include "llvm/Target/TargetRegisterInfo.h"<br>
+#include "llvm/Support/Format.h"<br>
#include <algorithm><br>
<br>
using namespace llvm;<br>
<br>
STATISTIC(NumCPEs, "Number of constpool entries");<br>
+STATISTIC(NumSplit, "Number of uncond branches inserted");<br>
+STATISTIC(NumCBrFixed, "Number of cond branches fixed");<br>
+STATISTIC(NumUBrFixed, "Number of uncond branches fixed");<br>
<br>
// FIXME: This option should be removed once it has received sufficient testing.<br>
static cl::opt<bool><br>
AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true),<br>
cl::desc("Align constant islands in code"));<br>
<br>
+<br>
+// Rather than do make check tests with huge amounts of code, we force<br>
+// the test to use this amount.<br>
+//<br>
+static cl::opt<int> ConstantIslandsSmallOffset(<br>
+ "mips-constant-islands-small-offset",<br>
+ cl::init(0),<br>
+ cl::desc("Make small offsets be this amount for testing purposes"),<br>
+ cl::Hidden);<br>
+<br>
+/// UnknownPadding - Return the worst case padding that could result from<br>
+/// unknown offset bits. This does not include alignment padding caused by<br>
+/// known offset bits.<br>
+///<br>
+/// @param LogAlign log2(alignment)<br>
+/// @param KnownBits Number of known low offset bits.<br>
+static inline unsigned UnknownPadding(unsigned LogAlign, unsigned KnownBits) {<br>
+ if (KnownBits < LogAlign)<br>
+ return (1u << LogAlign) - (1u << KnownBits);<br>
+ return 0;<br>
+}<br>
+<br>
namespace {<br>
+<br>
+<br>
typedef MachineBasicBlock::iterator Iter;<br>
typedef MachineBasicBlock::reverse_iterator ReverseIter;<br>
<br>
+ /// MipsConstantIslands - Due to limited PC-relative displacements, Mips<br>
+ /// requires constant pool entries to be scattered among the instructions<br>
+ /// inside a function. To do this, it completely ignores the normal LLVM<br>
+ /// constant pool; instead, it places constants wherever it feels like with<br>
+ /// special instructions.<br>
+ ///<br>
+ /// The terminology used in this pass includes:<br>
+ /// Islands - Clumps of constants placed in the function.<br>
+ /// Water - Potential places where an island could be formed.<br>
+ /// CPE - A constant pool entry that has been placed somewhere, which<br>
+ /// tracks a list of users.<br>
+<br>
class MipsConstantIslands : public MachineFunctionPass {<br>
<br>
- const TargetMachine &TM;<br>
- bool IsPIC;<br>
- unsigned ABI;<br>
- const MipsSubtarget *STI;<br>
- const MipsInstrInfo *TII;<br>
- MachineFunction *MF;<br>
- MachineConstantPool *MCP;<br>
+ /// BasicBlockInfo - Information about the offset and size of a single<br>
+ /// basic block.<br>
+ struct BasicBlockInfo {<br>
+ /// Offset - Distance from the beginning of the function to the beginning<br>
+ /// of this basic block.<br>
+ ///<br>
+ /// Offsets are computed assuming worst case padding before an aligned<br>
+ /// block. This means that subtracting basic block offsets always gives a<br>
+ /// conservative estimate of the real distance which may be smaller.<br>
+ ///<br>
+ /// Because worst case padding is used, the computed offset of an aligned<br>
+ /// block may not actually be aligned.<br>
+ unsigned Offset;<br>
+<br>
+ /// Size - Size of the basic block in bytes. If the block contains<br>
+ /// inline assembly, this is a worst case estimate.<br>
+ ///<br>
+ /// The size does not include any alignment padding whether from the<br>
+ /// beginning of the block, or from an aligned jump table at the end.<br>
+ unsigned Size;<br>
+<br>
+ /// KnownBits - The number of low bits in Offset that are known to be<br>
+ /// exact. The remaining bits of Offset are an upper bound.<br>
+ uint8_t KnownBits;<br>
+<br>
+ /// Unalign - When non-zero, the block contains instructions (inline asm)<br>
+ /// of unknown size. The real size may be smaller than Size bytes by a<br>
+ /// multiple of 1 << Unalign.<br>
+ uint8_t Unalign;<br>
+<br>
+ /// PostAlign - When non-zero, the block terminator contains a .align<br>
+ /// directive, so the end of the block is aligned to 1 << PostAlign<br>
+ /// bytes.<br>
+ uint8_t PostAlign;<br>
+<br>
+ BasicBlockInfo() : Offset(0), Size(0), KnownBits(0), Unalign(0),<br>
+ PostAlign(0) {}<br>
+<br>
+ /// Compute the number of known offset bits internally to this block.<br>
+ /// This number should be used to predict worst case padding when<br>
+ /// splitting the block.<br>
+ unsigned internalKnownBits() const {<br>
+ unsigned Bits = Unalign ? Unalign : KnownBits;<br>
+ // If the block size isn't a multiple of the known bits, assume the<br>
+ // worst case padding.<br>
+ if (Size & ((1u << Bits) - 1))<br>
+ Bits = countTrailingZeros(Size);<br>
+ return Bits;<br>
+ }<br>
+<br>
+ /// Compute the offset immediately following this block. If LogAlign is<br>
+ /// specified, return the offset the successor block will get if it has<br>
+ /// this alignment.<br>
+ unsigned postOffset(unsigned LogAlign = 0) const {<br>
+ unsigned PO = Offset + Size;<br>
+ return PO;<br>
+ }<br>
+<br>
+ /// Compute the number of known low bits of postOffset. If this block<br>
+ /// contains inline asm, the number of known bits drops to the<br>
+ /// instruction alignment. An aligned terminator may increase the number<br>
+ /// of know bits.<br>
+ /// If LogAlign is given, also consider the alignment of the next block.<br>
+ unsigned postKnownBits(unsigned LogAlign = 0) const {<br>
+ return std::max(std::max(unsigned(PostAlign), LogAlign),<br>
+ internalKnownBits());<br>
+ }<br>
+ };<br>
+<br>
+ std::vector<BasicBlockInfo> BBInfo;<br>
+<br>
+ /// WaterList - A sorted list of basic blocks where islands could be placed<br>
+ /// (i.e. blocks that don't fall through to the following block, due<br>
+ /// to a return, unreachable, or unconditional branch).<br>
+ std::vector<MachineBasicBlock*> WaterList;<br>
+<br>
+ /// NewWaterList - The subset of WaterList that was created since the<br>
+ /// previous iteration by inserting unconditional branches.<br>
+ SmallSet<MachineBasicBlock*, 4> NewWaterList;<br>
+<br>
+ typedef std::vector<MachineBasicBlock*>::iterator water_iterator;<br>
+<br>
+ /// CPUser - One user of a constant pool, keeping the machine instruction<br>
+ /// pointer, the constant pool being referenced, and the max displacement<br>
+ /// allowed from the instruction to the CP. The HighWaterMark records the<br>
+ /// highest basic block where a new CPEntry can be placed. To ensure this<br>
+ /// pass terminates, the CP entries are initially placed at the end of the<br>
+ /// function and then move monotonically to lower addresses. The<br>
+ /// exception to this rule is when the current CP entry for a particular<br>
+ /// CPUser is out of range, but there is another CP entry for the same<br>
+ /// constant value in range. We want to use the existing in-range CP<br>
+ /// entry, but if it later moves out of range, the search for new water<br>
+ /// should resume where it left off. The HighWaterMark is used to record<br>
+ /// that point.<br>
+ struct CPUser {<br>
+ MachineInstr *MI;<br>
+ MachineInstr *CPEMI;<br>
+ MachineBasicBlock *HighWaterMark;<br>
+ private:<br>
+ unsigned MaxDisp;<br>
+ unsigned LongFormMaxDisp; // mips16 has 16/32 bit instructions<br>
+ // with different displacements<br>
+ unsigned LongFormOpcode;<br>
+ public:<br>
+ bool NegOk;<br>
+ bool IsSoImm;<br>
+ bool KnownAlignment;<br>
+ CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,<br>
+ bool neg, bool soimm,<br>
+ unsigned longformmaxdisp, unsigned longformopcode)<br>
+ : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp),<br>
+ LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode),<br>
+ NegOk(neg), IsSoImm(soimm), KnownAlignment(false) {<br>
+ HighWaterMark = CPEMI->getParent();<br>
+ }<br>
+ /// getMaxDisp - Returns the maximum displacement supported by MI.<br>
+ /// Correct for unknown alignment.<br>
+ /// Conservatively subtract 2 bytes to handle weird alignment effects.<br>
+ unsigned getMaxDisp() const {<br>
+ unsigned xMaxDisp = ConstantIslandsSmallOffset?<br>
+ ConstantIslandsSmallOffset: MaxDisp;<br>
+ return (KnownAlignment ? xMaxDisp : xMaxDisp - 2) - 2;<br>
+ }<br>
+ unsigned getLongFormMaxDisp() const {<br>
+ return (KnownAlignment ? LongFormMaxDisp : LongFormMaxDisp - 2) - 2;<br>
+ }<br>
+ unsigned getLongFormOpcode() const {<br>
+ return LongFormOpcode;<br>
+ }<br>
+ };<br>
+<br>
+ /// CPUsers - Keep track of all of the machine instructions that use various<br>
+ /// constant pools and their max displacement.<br>
+ std::vector<CPUser> CPUsers;<br>
<br>
/// CPEntry - One per constant pool entry, keeping the machine instruction<br>
/// pointer, the constpool index, and the number of CPUser's which<br>
@@ -85,13 +253,56 @@ namespace {<br>
/// put in the vector of the original element, but have distinct CPIs.<br>
std::vector<std::vector<CPEntry> > CPEntries;<br>
<br>
+ /// ImmBranch - One per immediate branch, keeping the machine instruction<br>
+ /// pointer, conditional or unconditional, the max displacement,<br>
+ /// and (if isCond is true) the corresponding unconditional branch<br>
+ /// opcode.<br>
+ struct ImmBranch {<br>
+ MachineInstr *MI;<br>
+ unsigned MaxDisp : 31;<br>
+ bool isCond : 1;<br>
+ int UncondBr;<br>
+ ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr)<br>
+ : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}<br>
+ };<br>
+<br>
+ /// ImmBranches - Keep track of all the immediate branch instructions.<br>
+ ///<br>
+ std::vector<ImmBranch> ImmBranches;<br>
+<br>
+ /// HasFarJump - True if any far jump instruction has been emitted during<br>
+ /// the branch fix up pass.<br>
+ bool HasFarJump;<br>
+<br>
+ const TargetMachine &TM;<br>
+ bool IsPIC;<br>
+ unsigned ABI;<br>
+ const MipsSubtarget *STI;<br>
+ const MipsInstrInfo *TII;<br>
+ MipsFunctionInfo *MFI;<br>
+ MachineFunction *MF;<br>
+ MachineConstantPool *MCP;<br>
+<br>
+ unsigned PICLabelUId;<br>
+ bool PrescannedForConstants;<br>
+<br>
+ void initPICLabelUId(unsigned UId) {<br>
+ PICLabelUId = UId;<br>
+ }<br>
+<br>
+<br>
+ unsigned createPICLabelUId() {<br>
+ return PICLabelUId++;<br>
+ }<br>
+<br>
public:<br>
static char ID;<br>
MipsConstantIslands(TargetMachine &tm)<br>
: MachineFunctionPass(ID), TM(tm),<br>
IsPIC(TM.getRelocationModel() == Reloc::PIC_),<br>
ABI(TM.getSubtarget<MipsSubtarget>().getTargetABI()),<br>
- STI(&TM.getSubtarget<MipsSubtarget>()), MF(0), MCP(0){}<br>
+ STI(&TM.getSubtarget<MipsSubtarget>()), MF(0), MCP(0),<br>
+ PrescannedForConstants(false){}<br>
<br>
virtual const char *getPassName() const {<br>
return "Mips Constant Islands";<br>
@@ -100,6 +311,45 @@ namespace {<br>
bool runOnMachineFunction(MachineFunction &F);<br>
<br>
void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);<br>
+ CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);<br>
+ unsigned getCPELogAlign(const MachineInstr *CPEMI);<br>
+ void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs);<br>
+ unsigned getOffsetOf(MachineInstr *MI) const;<br>
+ unsigned getUserOffset(CPUser&) const;<br>
+ void dumpBBs();<br>
+ void verify();<br>
+<br>
+ bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,<br>
+ unsigned Disp, bool NegativeOK, bool IsSoImm = false);<br>
+ bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,<br>
+ const CPUser &U);<br>
+<br>
+ bool isLongFormOffsetInRange(unsigned UserOffset, unsigned TrialOffset,<br>
+ const CPUser &U);<br>
+<br>
+ void computeBlockSize(MachineBasicBlock *MBB);<br>
+ MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);<br>
+ void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);<br>
+ void adjustBBOffsetsAfter(MachineBasicBlock *BB);<br>
+ bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);<br>
+ int findInRangeCPEntry(CPUser& U, unsigned UserOffset);<br>
+ int findLongFormInRangeCPEntry(CPUser& U, unsigned UserOffset);<br>
+ bool findAvailableWater(CPUser&U, unsigned UserOffset,<br>
+ water_iterator &WaterIter);<br>
+ void createNewWater(unsigned CPUserIndex, unsigned UserOffset,<br>
+ MachineBasicBlock *&NewMBB);<br>
+ bool handleConstantPoolUser(unsigned CPUserIndex);<br>
+ void removeDeadCPEMI(MachineInstr *CPEMI);<br>
+ bool removeUnusedCPEntries();<br>
+ bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,<br>
+ MachineInstr *CPEMI, unsigned Disp, bool NegOk,<br>
+ bool DoDump = false);<br>
+ bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water,<br>
+ CPUser &U, unsigned &Growth);<br>
+ bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);<br>
+ bool fixupImmediateBr(ImmBranch &Br);<br>
+ bool fixupConditionalBr(ImmBranch &Br);<br>
+ bool fixupUnconditionalBr(ImmBranch &Br);<br>
<br>
void prescanForConstants();<br>
<br>
@@ -110,6 +360,33 @@ namespace {<br>
char MipsConstantIslands::ID = 0;<br>
} // end of anonymous namespace<br>
<br>
+<br>
+bool MipsConstantIslands::isLongFormOffsetInRange<br>
+ (unsigned UserOffset, unsigned TrialOffset,<br>
+ const CPUser &U) {<br>
+ return isOffsetInRange(UserOffset, TrialOffset,<br>
+ U.getLongFormMaxDisp(), U.NegOk, U.IsSoImm);<br>
+}<br>
+<br>
+bool MipsConstantIslands::isOffsetInRange<br>
+ (unsigned UserOffset, unsigned TrialOffset,<br>
+ const CPUser &U) {<br>
+ return isOffsetInRange(UserOffset, TrialOffset,<br>
+ U.getMaxDisp(), U.NegOk, U.IsSoImm);<br>
+}<br>
+/// print block size and offset information - debugging<br>
+void MipsConstantIslands::dumpBBs() {<br>
+ DEBUG({<br>
+ for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {<br>
+ const BasicBlockInfo &BBI = BBInfo[J];<br>
+ dbgs() << format("%08x BB#%u\t", BBI.Offset, J)<br>
+ << " kb=" << unsigned(BBI.KnownBits)<br>
+ << " ua=" << unsigned(BBI.Unalign)<br>
+ << " pa=" << unsigned(BBI.PostAlign)<br>
+ << format(" size=%#x\n", BBInfo[J].Size);<br>
+ }<br>
+ });<br>
+}<br>
/// createMipsLongBranchPass - Returns a pass that converts branches to long<br>
/// branches.<br>
FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) {<br>
@@ -127,13 +404,15 @@ bool MipsConstantIslands::runOnMachineFu<br>
return false;<br>
}<br>
TII = (const MipsInstrInfo*)MF->getTarget().getInstrInfo();<br>
+ MFI = MF->getInfo<MipsFunctionInfo>();<br>
DEBUG(dbgs() << "constant island processing " << "\n");<br>
//<br>
// will need to make predermination if there is any constants we need to<br>
// put in constant islands. TBD.<br>
//<br>
- prescanForConstants();<br>
+ if (!PrescannedForConstants) prescanForConstants();<br>
<br>
+ HasFarJump = false;<br>
// This pass invalidates liveness information when it splits basic blocks.<br>
MF->getRegInfo().invalidateLiveness();<br>
<br>
@@ -141,13 +420,66 @@ bool MipsConstantIslands::runOnMachineFu<br>
// the numbers agree with the position of the block in the function.<br>
MF->RenumberBlocks();<br>
<br>
+ bool MadeChange = false;<br>
+<br>
// Perform the initial placement of the constant pool entries. To start with,<br>
// we put them all at the end of the function.<br>
std::vector<MachineInstr*> CPEMIs;<br>
if (!MCP->isEmpty())<br>
doInitialPlacement(CPEMIs);<br>
<br>
- return true;<br>
+ /// The next UID to take is the first unused one.<br>
+ initPICLabelUId(CPEMIs.size());<br>
+<br>
+ // Do the initial scan of the function, building up information about the<br>
+ // sizes of each block, the location of all the water, and finding all of the<br>
+ // constant pool users.<br>
+ initializeFunctionInfo(CPEMIs);<br>
+ CPEMIs.clear();<br>
+ DEBUG(dumpBBs());<br>
+<br>
+ /// Remove dead constant pool entries.<br>
+ MadeChange |= removeUnusedCPEntries();<br>
+<br>
+ // Iteratively place constant pool entries and fix up branches until there<br>
+ // is no change.<br>
+ unsigned NoCPIters = 0, NoBRIters = 0;<br>
+ (void)NoBRIters;<br>
+ while (true) {<br>
+ DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n');<br>
+ bool CPChange = false;<br>
+ for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)<br>
+ CPChange |= handleConstantPoolUser(i);<br>
+ if (CPChange && ++NoCPIters > 30)<br>
+ report_fatal_error("Constant Island pass failed to converge!");<br>
+ DEBUG(dumpBBs());<br>
+<br>
+ // Clear NewWaterList now. If we split a block for branches, it should<br>
+ // appear as "new water" for the next iteration of constant pool placement.<br>
+ NewWaterList.clear();<br>
+<br>
+ DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n');<br>
+ bool BRChange = false;<br>
+#ifdef IN_PROGRESS<br>
+ for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)<br>
+ BRChange |= fixupImmediateBr(ImmBranches[i]);<br>
+ if (BRChange && ++NoBRIters > 30)<br>
+ report_fatal_error("Branch Fix Up pass failed to converge!");<br>
+ DEBUG(dumpBBs());<br>
+#endif<br>
+ if (!CPChange && !BRChange)<br>
+ break;<br>
+ MadeChange = true;<br>
+ }<br>
+<br>
+ DEBUG(dbgs() << '\n'; dumpBBs());<br>
+<br>
+ BBInfo.clear();<br>
+ WaterList.clear();<br>
+ CPUsers.clear();<br>
+ CPEntries.clear();<br>
+ ImmBranches.clear();<br>
+ return MadeChange;<br>
}<br>
<br>
/// doInitialPlacement - Perform the initial placement of the constant pool<br>
@@ -216,9 +548,1034 @@ MipsConstantIslands::doInitialPlacement(<br>
DEBUG(BB->dump());<br>
}<br>
<br>
+/// BBHasFallthrough - Return true if the specified basic block can fallthrough<br>
+/// into the block immediately after it.<br>
+static bool BBHasFallthrough(MachineBasicBlock *MBB) {<br>
+ // Get the next machine basic block in the function.<br>
+ MachineFunction::iterator MBBI = MBB;<br>
+ // Can't fall off end of function.<br>
+ if (llvm::next(MBBI) == MBB->getParent()->end())<br>
+ return false;<br>
+<br>
+ MachineBasicBlock *NextBB = llvm::next(MBBI);<br>
+ for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(),<br>
+ E = MBB->succ_end(); I != E; ++I)<br>
+ if (*I == NextBB)<br>
+ return true;<br>
+<br>
+ return false;<br>
+}<br>
+<br>
+/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI,<br>
+/// look up the corresponding CPEntry.<br>
+MipsConstantIslands::CPEntry<br>
+*MipsConstantIslands::findConstPoolEntry(unsigned CPI,<br>
+ const MachineInstr *CPEMI) {<br>
+ std::vector<CPEntry> &CPEs = CPEntries[CPI];<br>
+ // Number of entries per constpool index should be small, just do a<br>
+ // linear search.<br>
+ for (unsigned i = 0, e = CPEs.size(); i != e; ++i) {<br>
+ if (CPEs[i].CPEMI == CPEMI)<br>
+ return &CPEs[i];<br>
+ }<br>
+ return NULL;<br>
+}<br>
+<br>
+/// getCPELogAlign - Returns the required alignment of the constant pool entry<br>
+/// represented by CPEMI. Alignment is measured in log2(bytes) units.<br>
+unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr *CPEMI) {<br>
+ assert(CPEMI && CPEMI->getOpcode() == Mips::CONSTPOOL_ENTRY);<br>
+<br>
+ // Everything is 4-byte aligned unless AlignConstantIslands is set.<br>
+ if (!AlignConstantIslands)<br>
+ return 2;<br>
+<br>
+ unsigned CPI = CPEMI->getOperand(1).getIndex();<br>
+ assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");<br>
+ unsigned Align = MCP->getConstants()[CPI].getAlignment();<br>
+ assert(isPowerOf2_32(Align) && "Invalid CPE alignment");<br>
+ return Log2_32(Align);<br>
+}<br>
+<br>
+/// initializeFunctionInfo - Do the initial scan of the function, building up<br>
+/// information about the sizes of each block, the location of all the water,<br>
+/// and finding all of the constant pool users.<br>
+void MipsConstantIslands::<br>
+initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {<br>
+ BBInfo.clear();<br>
+ BBInfo.resize(MF->getNumBlockIDs());<br>
+<br>
+ // First thing, compute the size of all basic blocks, and see if the function<br>
+ // has any inline assembly in it. If so, we have to be conservative about<br>
+ // alignment assumptions, as we don't know for sure the size of any<br>
+ // instructions in the inline assembly.<br>
+ for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I)<br>
+ computeBlockSize(I);<br>
+<br>
+ // The known bits of the entry block offset are determined by the function<br>
+ // alignment.<br>
+ BBInfo.front().KnownBits = MF->getAlignment();<br>
+<br>
+ // Compute block offsets.<br>
+ adjustBBOffsetsAfter(MF->begin());<br>
+<br>
+ // Now go back through the instructions and build up our data structures.<br>
+ for (MachineFunction::iterator MBBI = MF->begin(), E = MF->end();<br>
+ MBBI != E; ++MBBI) {<br>
+ MachineBasicBlock &MBB = *MBBI;<br>
+<br>
+ // If this block doesn't fall through into the next MBB, then this is<br>
+ // 'water' that a constant pool island could be placed.<br>
+ if (!BBHasFallthrough(&MBB))<br>
+ WaterList.push_back(&MBB);<br>
+ for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();<br>
+ I != E; ++I) {<br>
+ if (I->isDebugValue())<br>
+ continue;<br>
+<br>
+ int Opc = I->getOpcode();<br>
+ if (I->isBranch()) {<br>
+ bool isCond = false;<br>
+ unsigned Bits = 0;<br>
+ unsigned Scale = 1;<br>
+ int UOpc = Opc;<br>
+<br>
+ switch (Opc) {<br>
+ default:<br>
+ continue; // Ignore other JT branches<br>
+ }<br>
+ // Record this immediate branch.<br>
+ unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;<br>
+ ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc));<br>
+<br>
+ }<br>
+<br>
+<br>
+ if (Opc == Mips::CONSTPOOL_ENTRY)<br>
+ continue;<br>
+<br>
+<br>
+ // Scan the instructions for constant pool operands.<br>
+ for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)<br>
+ if (I->getOperand(op).isCPI()) {<br>
+<br>
+ // We found one. The addressing mode tells us the max displacement<br>
+ // from the PC that this instruction permits.<br>
+<br>
+ // Basic size info comes from the TSFlags field.<br>
+ unsigned Bits = 0;<br>
+ unsigned Scale = 1;<br>
+ bool NegOk = false;<br>
+ bool IsSoImm = false;<br>
+ unsigned LongFormBits = 0;<br>
+ unsigned LongFormScale = 0;<br>
+ unsigned LongFormOpcode = 0;<br>
+ switch (Opc) {<br>
+ default:<br>
+ llvm_unreachable("Unknown addressing mode for CP reference!");<br>
+ case Mips::LwRxPcTcp16:<br>
+ Bits = 8;<br>
+ Scale = 2;<br>
+ LongFormOpcode = Mips::LwRxPcTcpX16;<br>
+ break;<br>
+ case Mips::LwRxPcTcpX16:<br>
+ Bits = 16;<br>
+ Scale = 2;<br>
+ break;<br>
+ }<br>
+ // Remember that this is a user of a CP entry.<br>
+ unsigned CPI = I->getOperand(op).getIndex();<br>
+ MachineInstr *CPEMI = CPEMIs[CPI];<br>
+ unsigned MaxOffs = ((1 << Bits)-1) * Scale;<br>
+ unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;<br>
+ CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk,<br>
+ IsSoImm, LongFormMaxOffs,<br>
+ LongFormOpcode));<br>
+<br>
+ // Increment corresponding CPEntry reference count.<br>
+ CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);<br>
+ assert(CPE && "Cannot find a corresponding CPEntry!");<br>
+ CPE->RefCount++;<br>
+<br>
+ // Instructions can only use one CP entry, don't bother scanning the<br>
+ // rest of the operands.<br>
+ break;<br>
+<br>
+ }<br>
+<br>
+ }<br>
+ }<br>
+<br>
+}<br>
+<br>
+/// computeBlockSize - Compute the size and some alignment information for MBB.<br>
+/// This function updates BBInfo directly.<br>
+void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) {<br>
+ BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];<br>
+ BBI.Size = 0;<br>
+ BBI.Unalign = 0;<br>
+ BBI.PostAlign = 0;<br>
+<br>
+ for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;<br>
+ ++I)<br>
+ BBI.Size += TII->GetInstSizeInBytes(I);<br>
+<br>
+}<br>
+<br>
+/// getOffsetOf - Return the current offset of the specified machine instruction<br>
+/// from the start of the function. This offset changes as stuff is moved<br>
+/// around inside the function.<br>
+unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const {<br>
+ MachineBasicBlock *MBB = MI->getParent();<br>
+<br>
+ // The offset is composed of two things: the sum of the sizes of all MBB's<br>
+ // before this instruction's block, and the offset from the start of the block<br>
+ // it is in.<br>
+ unsigned Offset = BBInfo[MBB->getNumber()].Offset;<br>
+<br>
+ // Sum instructions before MI in MBB.<br>
+ for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) {<br>
+ assert(I != MBB->end() && "Didn't find MI in its own basic block?");<br>
+ Offset += TII->GetInstSizeInBytes(I);<br>
+ }<br>
+ return Offset;<br>
+}<br>
+<br>
+/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB<br>
+/// ID.<br>
+static bool CompareMBBNumbers(const MachineBasicBlock *LHS,<br>
+ const MachineBasicBlock *RHS) {<br>
+ return LHS->getNumber() < RHS->getNumber();<br>
+}<br>
+<br>
+/// updateForInsertedWaterBlock - When a block is newly inserted into the<br>
+/// machine function, it upsets all of the block numbers. Renumber the blocks<br>
+/// and update the arrays that parallel this numbering.<br>
+void MipsConstantIslands::updateForInsertedWaterBlock<br>
+ (MachineBasicBlock *NewBB) {<br>
+ // Renumber the MBB's to keep them consecutive.<br>
+ NewBB->getParent()->RenumberBlocks(NewBB);<br>
+<br>
+ // Insert an entry into BBInfo to align it properly with the (newly<br>
+ // renumbered) block numbers.<br>
+ BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());<br>
+<br>
+ // Next, update WaterList. Specifically, we need to add NewMBB as having<br>
+ // available water after it.<br>
+ water_iterator IP =<br>
+ std::lower_bound(WaterList.begin(), WaterList.end(), NewBB,<br>
+ CompareMBBNumbers);<br>
+ WaterList.insert(IP, NewBB);<br>
+}<br>
+<br>
+/// getUserOffset - Compute the offset of U.MI as seen by the hardware<br>
+/// displacement computation. Update U.KnownAlignment to match its current<br>
+/// basic block location.<br>
+unsigned MipsConstantIslands::getUserOffset(CPUser &U) const {<br>
+ unsigned UserOffset = getOffsetOf(U.MI);<br>
+ const BasicBlockInfo &BBI = BBInfo[U.MI->getParent()->getNumber()];<br>
+ unsigned KnownBits = BBI.internalKnownBits();<br>
+<br>
+ // The value read from PC is offset from the actual instruction address.<br>
+<br>
+<br>
+ // Because of inline assembly, we may not know the alignment (mod 4) of U.MI.<br>
+ // Make sure U.getMaxDisp() returns a constrained range.<br>
+ U.KnownAlignment = (KnownBits >= 2);<br>
+<br>
+ // On Thumb, offsets==2 mod 4 are rounded down by the hardware for<br>
+ // purposes of the displacement computation; compensate for that here.<br>
+ // For unknown alignments, getMaxDisp() constrains the range instead.<br>
+<br>
+<br>
+ return UserOffset;<br>
+}<br>
+<br>
+/// Split the basic block containing MI into two blocks, which are joined by<br>
+/// an unconditional branch. Update data structures and renumber blocks to<br>
+/// account for this change and returns the newly created block.<br>
+MachineBasicBlock *MipsConstantIslands::splitBlockBeforeInstr<br>
+ (MachineInstr *MI) {<br>
+ MachineBasicBlock *OrigBB = MI->getParent();<br>
+<br>
+ // Create a new MBB for the code after the OrigBB.<br>
+ MachineBasicBlock *NewBB =<br>
+ MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());<br>
+ MachineFunction::iterator MBBI = OrigBB; ++MBBI;<br>
+ MF->insert(MBBI, NewBB);<br>
+<br>
+ // Splice the instructions starting with MI over to NewBB.<br>
+ NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());<br>
+<br>
+ // Add an unconditional branch from OrigBB to NewBB.<br>
+ // Note the new unconditional branch is not being recorded.<br>
+ // There doesn't seem to be meaningful DebugInfo available; this doesn't<br>
+ // correspond to anything in the source.<br>
+ BuildMI(OrigBB, DebugLoc(), TII->get(Mips::BimmX16)).addMBB(NewBB);<br>
+ ++NumSplit;<br>
+<br>
+ // Update the CFG. All succs of OrigBB are now succs of NewBB.<br>
+ NewBB->transferSuccessors(OrigBB);<br>
+<br>
+ // OrigBB branches to NewBB.<br>
+ OrigBB->addSuccessor(NewBB);<br>
+<br>
+ // Update internal data structures to account for the newly inserted MBB.<br>
+ // This is almost the same as updateForInsertedWaterBlock, except that<br>
+ // the Water goes after OrigBB, not NewBB.<br>
+ MF->RenumberBlocks(NewBB);<br>
+<br>
+ // Insert an entry into BBInfo to align it properly with the (newly<br>
+ // renumbered) block numbers.<br>
+ BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());<br>
+<br>
+ // Next, update WaterList. Specifically, we need to add OrigMBB as having<br>
+ // available water after it (but not if it's already there, which happens<br>
+ // when splitting before a conditional branch that is followed by an<br>
+ // unconditional branch - in that case we want to insert NewBB).<br>
+ water_iterator IP =<br>
+ std::lower_bound(WaterList.begin(), WaterList.end(), OrigBB,<br>
+ CompareMBBNumbers);<br>
+ MachineBasicBlock* WaterBB = *IP;<br>
+ if (WaterBB == OrigBB)<br>
+ WaterList.insert(llvm::next(IP), NewBB);<br>
+ else<br>
+ WaterList.insert(IP, OrigBB);<br>
+ NewWaterList.insert(OrigBB);<br>
+<br>
+ // Figure out how large the OrigBB is. As the first half of the original<br>
+ // block, it cannot contain a tablejump. The size includes<br>
+ // the new jump we added. (It should be possible to do this without<br>
+ // recounting everything, but it's very confusing, and this is rarely<br>
+ // executed.)<br>
+ computeBlockSize(OrigBB);<br>
+<br>
+ // Figure out how large the NewMBB is. As the second half of the original<br>
+ // block, it may contain a tablejump.<br>
+ computeBlockSize(NewBB);<br>
+<br>
+ // All BBOffsets following these blocks must be modified.<br>
+ adjustBBOffsetsAfter(OrigBB);<br>
+<br>
+ return NewBB;<br>
+}<br>
+<br>
+<br>
+<br>
+/// isOffsetInRange - Checks whether UserOffset (the location of a constant pool<br>
+/// reference) is within MaxDisp of TrialOffset (a proposed location of a<br>
+/// constant pool entry).<br>
+/// UserOffset is computed by getUserOffset above to include PC adjustments. If<br>
+/// the mod 4 alignment of UserOffset is not known, the uncertainty must be<br>
+/// subtracted from MaxDisp instead. CPUser::getMaxDisp() does that.<br>
+bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset,<br>
+ unsigned TrialOffset, unsigned MaxDisp,<br>
+ bool NegativeOK, bool IsSoImm) {<br>
+ if (UserOffset <= TrialOffset) {<br>
+ // User before the Trial.<br>
+ if (TrialOffset - UserOffset <= MaxDisp)<br>
+ return true;<br>
+ // FIXME: Make use full range of soimm values.<br>
+ } else if (NegativeOK) {<br>
+ if (UserOffset - TrialOffset <= MaxDisp)<br>
+ return true;<br>
+ // FIXME: Make use full range of soimm values.<br>
+ }<br>
+ return false;<br>
+}<br>
+<br>
+/// isWaterInRange - Returns true if a CPE placed after the specified<br>
+/// Water (a basic block) will be in range for the specific MI.<br>
+///<br>
+/// Compute how much the function will grow by inserting a CPE after Water.<br>
+bool MipsConstantIslands::isWaterInRange(unsigned UserOffset,<br>
+ MachineBasicBlock* Water, CPUser &U,<br>
+ unsigned &Growth) {<br>
+ unsigned CPELogAlign = getCPELogAlign(U.CPEMI);<br>
+ unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPELogAlign);<br>
+ unsigned NextBlockOffset, NextBlockAlignment;<br>
+ MachineFunction::const_iterator NextBlock = Water;<br>
+ if (++NextBlock == MF->end()) {<br>
+ NextBlockOffset = BBInfo[Water->getNumber()].postOffset();<br>
+ NextBlockAlignment = 0;<br>
+ } else {<br>
+ NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;<br>
+ NextBlockAlignment = NextBlock->getAlignment();<br>
+ }<br>
+ unsigned Size = U.CPEMI->getOperand(2).getImm();<br>
+ unsigned CPEEnd = CPEOffset + Size;<br>
+<br>
+ // The CPE may be able to hide in the alignment padding before the next<br>
+ // block. It may also cause more padding to be required if it is more aligned<br>
+ // that the next block.<br>
+ if (CPEEnd > NextBlockOffset) {<br>
+ Growth = CPEEnd - NextBlockOffset;<br>
+ // Compute the padding that would go at the end of the CPE to align the next<br>
+ // block.<br>
+ Growth += OffsetToAlignment(CPEEnd, 1u << NextBlockAlignment);<br>
+<br>
+ // If the CPE is to be inserted before the instruction, that will raise<br>
+ // the offset of the instruction. Also account for unknown alignment padding<br>
+ // in blocks between CPE and the user.<br>
+ if (CPEOffset < UserOffset)<br>
+ UserOffset += Growth + UnknownPadding(MF->getAlignment(), CPELogAlign);<br>
+ } else<br>
+ // CPE fits in existing padding.<br>
+ Growth = 0;<br>
+<br>
+ return isOffsetInRange(UserOffset, CPEOffset, U);<br>
+}<br>
+<br>
+/// isCPEntryInRange - Returns true if the distance between specific MI and<br>
+/// specific ConstPool entry instruction can fit in MI's displacement field.<br>
+bool MipsConstantIslands::isCPEntryInRange<br>
+ (MachineInstr *MI, unsigned UserOffset,<br>
+ MachineInstr *CPEMI, unsigned MaxDisp,<br>
+ bool NegOk, bool DoDump) {<br>
+ unsigned CPEOffset = getOffsetOf(CPEMI);<br>
+<br>
+ if (DoDump) {<br>
+ DEBUG({<br>
+ unsigned Block = MI->getParent()->getNumber();<br>
+ const BasicBlockInfo &BBI = BBInfo[Block];<br>
+ dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm()<br>
+ << " max delta=" << MaxDisp<br>
+ << format(" insn address=%#x", UserOffset)<br>
+ << " in BB#" << Block << ": "<br>
+ << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI<br>
+ << format("CPE address=%#x offset=%+d: ", CPEOffset,<br>
+ int(CPEOffset-UserOffset));<br>
+ });<br>
+ }<br>
+<br>
+ return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);<br>
+}<br>
+<br>
+#ifndef NDEBUG<br>
+/// BBIsJumpedOver - Return true of the specified basic block's only predecessor<br>
+/// unconditionally branches to its only successor.<br>
+static bool BBIsJumpedOver(MachineBasicBlock *MBB) {<br>
+ if (MBB->pred_size() != 1 || MBB->succ_size() != 1)<br>
+ return false;<br>
+ MachineBasicBlock *Succ = *MBB->succ_begin();<br>
+ MachineBasicBlock *Pred = *MBB->pred_begin();<br>
+ MachineInstr *PredMI = &Pred->back();<br>
+ if (PredMI->getOpcode() == Mips::BimmX16)<br>
+ return PredMI->getOperand(0).getMBB() == Succ;<br>
+ return false;<br>
+}<br>
+#endif<br>
+<br>
+void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) {<br>
+ unsigned BBNum = BB->getNumber();<br>
+ for(unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {<br>
+ // Get the offset and known bits at the end of the layout predecessor.<br>
+ // Include the alignment of the current block.<br>
+ unsigned Offset = BBInfo[i - 1].postOffset();<br>
+ BBInfo[i].Offset = Offset;<br>
+ }<br>
+}<br>
+<br>
+/// decrementCPEReferenceCount - find the constant pool entry with index CPI<br>
+/// and instruction CPEMI, and decrement its refcount. If the refcount<br>
+/// becomes 0 remove the entry and instruction. Returns true if we removed<br>
+/// the entry, false if we didn't.<br>
+<br>
+bool MipsConstantIslands::decrementCPEReferenceCount(unsigned CPI,<br>
+ MachineInstr *CPEMI) {<br>
+ // Find the old entry. Eliminate it if it is no longer used.<br>
+ CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);<br>
+ assert(CPE && "Unexpected!");<br>
+ if (--CPE->RefCount == 0) {<br>
+ removeDeadCPEMI(CPEMI);<br>
+ CPE->CPEMI = NULL;<br>
+ --NumCPEs;<br>
+ return true;<br>
+ }<br>
+ return false;<br>
+}<br>
+<br>
+/// LookForCPEntryInRange - see if the currently referenced CPE is in range;<br>
+/// if not, see if an in-range clone of the CPE is in range, and if so,<br>
+/// change the data structures so the user references the clone. Returns:<br>
+/// 0 = no existing entry found<br>
+/// 1 = entry found, and there were no code insertions or deletions<br>
+/// 2 = entry found, and there were code insertions or deletions<br>
+int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset)<br>
+{<br>
+ MachineInstr *UserMI = U.MI;<br>
+ MachineInstr *CPEMI = U.CPEMI;<br>
+<br>
+ // Check to see if the CPE is already in-range.<br>
+ if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,<br>
+ true)) {<br>
+ DEBUG(dbgs() << "In range\n");<br>
+ return 1;<br>
+ }<br>
+<br>
+ // No. Look for previously created clones of the CPE that are in range.<br>
+ unsigned CPI = CPEMI->getOperand(1).getIndex();<br>
+ std::vector<CPEntry> &CPEs = CPEntries[CPI];<br>
+ for (unsigned i = 0, e = CPEs.size(); i != e; ++i) {<br>
+ // We already tried this one<br>
+ if (CPEs[i].CPEMI == CPEMI)<br>
+ continue;<br>
+ // Removing CPEs can leave empty entries, skip<br>
+ if (CPEs[i].CPEMI == NULL)<br>
+ continue;<br>
+ if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getMaxDisp(),<br>
+ U.NegOk)) {<br>
+ DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#"<br>
+ << CPEs[i].CPI << "\n");<br>
+ // Point the CPUser node to the replacement<br>
+ U.CPEMI = CPEs[i].CPEMI;<br>
+ // Change the CPI in the instruction operand to refer to the clone.<br>
+ for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j)<br>
+ if (UserMI->getOperand(j).isCPI()) {<br>
+ UserMI->getOperand(j).setIndex(CPEs[i].CPI);<br>
+ break;<br>
+ }<br>
+ // Adjust the refcount of the clone...<br>
+ CPEs[i].RefCount++;<br>
+ // ...and the original. If we didn't remove the old entry, none of the<br>
+ // addresses changed, so we don't need another pass.<br>
+ return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;<br>
+ }<br>
+ }<br>
+ return 0;<br>
+}<br>
+<br>
+/// LookForCPEntryInRange - see if the currently referenced CPE is in range;<br>
+/// This version checks if the longer form of the instruction can be used to<br>
+/// to satisfy things.<br>
+/// if not, see if an in-range clone of the CPE is in range, and if so,<br>
+/// change the data structures so the user references the clone. Returns:<br>
+/// 0 = no existing entry found<br>
+/// 1 = entry found, and there were no code insertions or deletions<br>
+/// 2 = entry found, and there were code insertions or deletions<br>
+int MipsConstantIslands::findLongFormInRangeCPEntry<br>
+ (CPUser& U, unsigned UserOffset)<br>
+{<br>
+ MachineInstr *UserMI = U.MI;<br>
+ MachineInstr *CPEMI = U.CPEMI;<br>
+<br>
+ // Check to see if the CPE is already in-range.<br>
+ if (isCPEntryInRange(UserMI, UserOffset, CPEMI,<br>
+ U.getLongFormMaxDisp(), U.NegOk,<br>
+ true)) {<br>
+ DEBUG(dbgs() << "In range\n");<br>
+ UserMI->setDesc(TII->get(U.getLongFormOpcode()));<br>
+ return 2; // instruction is longer length now<br>
+ }<br>
+<br>
+ // No. Look for previously created clones of the CPE that are in range.<br>
+ unsigned CPI = CPEMI->getOperand(1).getIndex();<br>
+ std::vector<CPEntry> &CPEs = CPEntries[CPI];<br>
+ for (unsigned i = 0, e = CPEs.size(); i != e; ++i) {<br>
+ // We already tried this one<br>
+ if (CPEs[i].CPEMI == CPEMI)<br>
+ continue;<br>
+ // Removing CPEs can leave empty entries, skip<br>
+ if (CPEs[i].CPEMI == NULL)<br>
+ continue;<br>
+ if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI,<br>
+ U.getLongFormMaxDisp(), U.NegOk)) {<br>
+ DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#"<br>
+ << CPEs[i].CPI << "\n");<br>
+ // Point the CPUser node to the replacement<br>
+ U.CPEMI = CPEs[i].CPEMI;<br>
+ // Change the CPI in the instruction operand to refer to the clone.<br>
+ for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j)<br>
+ if (UserMI->getOperand(j).isCPI()) {<br>
+ UserMI->getOperand(j).setIndex(CPEs[i].CPI);<br>
+ break;<br>
+ }<br>
+ // Adjust the refcount of the clone...<br>
+ CPEs[i].RefCount++;<br>
+ // ...and the original. If we didn't remove the old entry, none of the<br>
+ // addresses changed, so we don't need another pass.<br>
+ return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;<br>
+ }<br>
+ }<br>
+ return 0;<br>
+}<br>
+<br>
+/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in<br>
+/// the specific unconditional branch instruction.<br>
+static inline unsigned getUnconditionalBrDisp(int Opc) {<br>
+ switch (Opc) {<br>
+ case Mips::BimmX16:<br>
+ return ((1<<16)-1)*2;<br>
+ default:<br>
+ break;<br>
+ }<br>
+ return ((1<<16)-1)*2;<br>
+}<br>
+<br>
+/// findAvailableWater - Look for an existing entry in the WaterList in which<br>
+/// we can place the CPE referenced from U so it's within range of U's MI.<br>
+/// Returns true if found, false if not. If it returns true, WaterIter<br>
+/// is set to the WaterList entry. For Thumb, prefer water that will not<br>
+/// introduce padding to water that will. To ensure that this pass<br>
+/// terminates, the CPE location for a particular CPUser is only allowed to<br>
+/// move to a lower address, so search backward from the end of the list and<br>
+/// prefer the first water that is in range.<br>
+bool MipsConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,<br>
+ water_iterator &WaterIter) {<br>
+ if (WaterList.empty())<br>
+ return false;<br>
+<br>
+ unsigned BestGrowth = ~0u;<br>
+ for (water_iterator IP = prior(WaterList.end()), B = WaterList.begin();;<br>
+ --IP) {<br>
+ MachineBasicBlock* WaterBB = *IP;<br>
+ // Check if water is in range and is either at a lower address than the<br>
+ // current "high water mark" or a new water block that was created since<br>
+ // the previous iteration by inserting an unconditional branch. In the<br>
+ // latter case, we want to allow resetting the high water mark back to<br>
+ // this new water since we haven't seen it before. Inserting branches<br>
+ // should be relatively uncommon and when it does happen, we want to be<br>
+ // sure to take advantage of it for all the CPEs near that block, so that<br>
+ // we don't insert more branches than necessary.<br>
+ unsigned Growth;<br>
+ if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&<br>
+ (WaterBB->getNumber() < U.HighWaterMark->getNumber() ||<br>
+ NewWaterList.count(WaterBB)) && Growth < BestGrowth) {<br>
+ // This is the least amount of required padding seen so far.<br>
+ BestGrowth = Growth;<br>
+ WaterIter = IP;<br>
+ DEBUG(dbgs() << "Found water after BB#" << WaterBB->getNumber()<br>
+ << " Growth=" << Growth << '\n');<br>
+<br>
+ // Keep looking unless it is perfect.<br>
+ if (BestGrowth == 0)<br>
+ return true;<br>
+ }<br>
+ if (IP == B)<br>
+ break;<br>
+ }<br>
+ return BestGrowth != ~0u;<br>
+}<br>
+<br>
+/// createNewWater - No existing WaterList entry will work for<br>
+/// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the<br>
+/// block is used if in range, and the conditional branch munged so control<br>
+/// flow is correct. Otherwise the block is split to create a hole with an<br>
+/// unconditional branch around it. In either case NewMBB is set to a<br>
+/// block following which the new island can be inserted (the WaterList<br>
+/// is not adjusted).<br>
+void MipsConstantIslands::createNewWater(unsigned CPUserIndex,<br>
+ unsigned UserOffset,<br>
+ MachineBasicBlock *&NewMBB) {<br>
+ CPUser &U = CPUsers[CPUserIndex];<br>
+ MachineInstr *UserMI = U.MI;<br>
+ MachineInstr *CPEMI = U.CPEMI;<br>
+ unsigned CPELogAlign = getCPELogAlign(CPEMI);<br>
+ MachineBasicBlock *UserMBB = UserMI->getParent();<br>
+ const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];<br>
+<br>
+ // If the block does not end in an unconditional branch already, and if the<br>
+ // end of the block is within range, make new water there. (The addition<br>
+ // below is for the unconditional branch we will be adding: 4 bytes on ARM +<br>
+ // Thumb2, 2 on Thumb1.<br>
+ if (BBHasFallthrough(UserMBB)) {<br>
+ // Size of branch to insert.<br>
+ unsigned Delta = 2;<br>
+ // Compute the offset where the CPE will begin.<br>
+ unsigned CPEOffset = UserBBI.postOffset(CPELogAlign) + Delta;<br>
+<br>
+ if (isOffsetInRange(UserOffset, CPEOffset, U)) {<br>
+ DEBUG(dbgs() << "Split at end of BB#" << UserMBB->getNumber()<br>
+ << format(", expected CPE offset %#x\n", CPEOffset));<br>
+ NewMBB = llvm::next(MachineFunction::iterator(UserMBB));<br>
+ // Add an unconditional branch from UserMBB to fallthrough block. Record<br>
+ // it for branch lengthening; this new branch will not get out of range,<br>
+ // but if the preceding conditional branch is out of range, the targets<br>
+ // will be exchanged, and the altered branch may be out of range, so the<br>
+ // machinery has to know about it.<br>
+ int UncondBr = Mips::BimmX16;<br>
+ BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);<br>
+ unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);<br>
+ ImmBranches.push_back(ImmBranch(&UserMBB->back(),<br>
+ MaxDisp, false, UncondBr));<br>
+ BBInfo[UserMBB->getNumber()].Size += Delta;<br>
+ adjustBBOffsetsAfter(UserMBB);<br>
+ return;<br>
+ }<br>
+ }<br>
+<br>
+ // What a big block. Find a place within the block to split it. This is a<br>
+ // little tricky on Thumb1 since instructions are 2 bytes and constant pool<br>
+ // entries are 4 bytes: if instruction I references island CPE, and<br>
+ // instruction I+1 references CPE', it will not work well to put CPE as far<br>
+ // forward as possible, since then CPE' cannot immediately follow it (that<br>
+ // location is 2 bytes farther away from I+1 than CPE was from I) and we'd<br>
+ // need to create a new island. So, we make a first guess, then walk through<br>
+ // the instructions between the one currently being looked at and the<br>
+ // possible insertion point, and make sure any other instructions that<br>
+ // reference CPEs will be able to use the same island area; if not, we back<br>
+ // up the insertion point.<br>
+<br>
+ // Try to split the block so it's fully aligned. Compute the latest split<br>
+ // point where we can add a 4-byte branch instruction, and then align to<br>
+ // LogAlign which is the largest possible alignment in the function.<br>
+ unsigned LogAlign = MF->getAlignment();<br>
+ assert(LogAlign >= CPELogAlign && "Over-aligned constant pool entry");<br>
+ unsigned KnownBits = UserBBI.internalKnownBits();<br>
+ unsigned UPad = UnknownPadding(LogAlign, KnownBits);<br>
+ unsigned BaseInsertOffset = UserOffset + U.getMaxDisp() - UPad;<br>
+ DEBUG(dbgs() << format("Split in middle of big block before %#x",<br>
+ BaseInsertOffset));<br>
+<br>
+ // The 4 in the following is for the unconditional branch we'll be inserting<br>
+ // (allows for long branch on Thumb1). Alignment of the island is handled<br>
+ // inside isOffsetInRange.<br>
+ BaseInsertOffset -= 4;<br>
+<br>
+ DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset)<br>
+ << " la=" << LogAlign<br>
+ << " kb=" << KnownBits<br>
+ << " up=" << UPad << '\n');<br>
+<br>
+ // This could point off the end of the block if we've already got constant<br>
+ // pool entries following this block; only the last one is in the water list.<br>
+ // Back past any possible branches (allow for a conditional and a maximally<br>
+ // long unconditional).<br>
+ if (BaseInsertOffset + 8 >= UserBBI.postOffset()) {<br>
+ BaseInsertOffset = UserBBI.postOffset() - UPad - 8;<br>
+ DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset));<br>
+ }<br>
+ unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +<br>
+ CPEMI->getOperand(2).getImm();<br>
+ MachineBasicBlock::iterator MI = UserMI;<br>
+ ++MI;<br>
+ unsigned CPUIndex = CPUserIndex+1;<br>
+ unsigned NumCPUsers = CPUsers.size();<br>
+ //MachineInstr *LastIT = 0;<br>
+ for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI);<br>
+ Offset < BaseInsertOffset;<br>
+ Offset += TII->GetInstSizeInBytes(MI),<br>
+ MI = llvm::next(MI)) {<br>
+ assert(MI != UserMBB->end() && "Fell off end of block");<br>
+ if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) {<br>
+ CPUser &U = CPUsers[CPUIndex];<br>
+ if (!isOffsetInRange(Offset, EndInsertOffset, U)) {<br>
+ // Shift intertion point by one unit of alignment so it is within reach.<br>
+ BaseInsertOffset -= 1u << LogAlign;<br>
+ EndInsertOffset -= 1u << LogAlign;<br>
+ }<br>
+ // This is overly conservative, as we don't account for CPEMIs being<br>
+ // reused within the block, but it doesn't matter much. Also assume CPEs<br>
+ // are added in order with alignment padding. We may eventually be able<br>
+ // to pack the aligned CPEs better.<br>
+ EndInsertOffset += U.CPEMI->getOperand(2).getImm();<br>
+ CPUIndex++;<br>
+ }<br>
+ }<br>
+<br>
+ --MI;<br>
+ NewMBB = splitBlockBeforeInstr(MI);<br>
+}<br>
+<br>
+/// handleConstantPoolUser - Analyze the specified user, checking to see if it<br>
+/// is out-of-range. If so, pick up the constant pool value and move it some<br>
+/// place in-range. Return true if we changed any addresses (thus must run<br>
+/// another pass of branch lengthening), false otherwise.<br>
+bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {<br>
+ CPUser &U = CPUsers[CPUserIndex];<br>
+ MachineInstr *UserMI = U.MI;<br>
+ MachineInstr *CPEMI = U.CPEMI;<br>
+ unsigned CPI = CPEMI->getOperand(1).getIndex();<br>
+ unsigned Size = CPEMI->getOperand(2).getImm();<br>
+ // Compute this only once, it's expensive.<br>
+ unsigned UserOffset = getUserOffset(U);<br>
+<br>
+ // See if the current entry is within range, or there is a clone of it<br>
+ // in range.<br>
+ int result = findInRangeCPEntry(U, UserOffset);<br>
+ if (result==1) return false;<br>
+ else if (result==2) return true;<br>
+<br>
+<br>
+ // Look for water where we can place this CPE.<br>
+ MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();<br>
+ MachineBasicBlock *NewMBB;<br>
+ water_iterator IP;<br>
+ if (findAvailableWater(U, UserOffset, IP)) {<br>
+ DEBUG(dbgs() << "Found water in range\n");<br>
+ MachineBasicBlock *WaterBB = *IP;<br>
+<br>
+ // If the original WaterList entry was "new water" on this iteration,<br>
+ // propagate that to the new island. This is just keeping NewWaterList<br>
+ // updated to match the WaterList, which will be updated below.<br>
+ if (NewWaterList.erase(WaterBB))<br>
+ NewWaterList.insert(NewIsland);<br>
+<br>
+ // The new CPE goes before the following block (NewMBB).<br>
+ NewMBB = llvm::next(MachineFunction::iterator(WaterBB));<br>
+<br>
+ } else {<br>
+ // No water found.<br>
+ // we first see if a longer form of the instrucion could have reached<br>
+ // the constant. in that case we won't bother to split<br>
+#ifdef IN_PROGRESS<br>
+ result = findLongFormInRangeCPEntry(U, UserOffset);<br>
+#endif<br>
+ DEBUG(dbgs() << "No water found\n");<br>
+ createNewWater(CPUserIndex, UserOffset, NewMBB);<br>
+<br>
+ // splitBlockBeforeInstr adds to WaterList, which is important when it is<br>
+ // called while handling branches so that the water will be seen on the<br>
+ // next iteration for constant pools, but in this context, we don't want<br>
+ // it. Check for this so it will be removed from the WaterList.<br>
+ // Also remove any entry from NewWaterList.<br>
+ MachineBasicBlock *WaterBB = prior(MachineFunction::iterator(NewMBB));<br>
+ IP = std::find(WaterList.begin(), WaterList.end(), WaterBB);<br>
+ if (IP != WaterList.end())<br>
+ NewWaterList.erase(WaterBB);<br>
+<br>
+ // We are adding new water. Update NewWaterList.<br>
+ NewWaterList.insert(NewIsland);<br>
+ }<br>
+<br>
+ // Remove the original WaterList entry; we want subsequent insertions in<br>
+ // this vicinity to go after the one we're about to insert. This<br>
+ // considerably reduces the number of times we have to move the same CPE<br>
+ // more than once and is also important to ensure the algorithm terminates.<br>
+ if (IP != WaterList.end())<br>
+ WaterList.erase(IP);<br>
+<br>
+ // Okay, we know we can put an island before NewMBB now, do it!<br>
+ MF->insert(NewMBB, NewIsland);<br>
+<br>
+ // Update internal data structures to account for the newly inserted MBB.<br>
+ updateForInsertedWaterBlock(NewIsland);<br>
+<br>
+ // Decrement the old entry, and remove it if refcount becomes 0.<br>
+ decrementCPEReferenceCount(CPI, CPEMI);<br>
+<br>
+ // Now that we have an island to add the CPE to, clone the original CPE and<br>
+ // add it to the island.<br>
+ U.HighWaterMark = NewIsland;<br>
+ U.CPEMI = BuildMI(NewIsland, DebugLoc(), TII->get(Mips::CONSTPOOL_ENTRY))<br>
+ .addImm(ID).addConstantPoolIndex(CPI).addImm(Size);<br>
+ CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));<br>
+ ++NumCPEs;<br>
+<br>
+ // Mark the basic block as aligned as required by the const-pool entry.<br>
+ NewIsland->setAlignment(getCPELogAlign(U.CPEMI));<br>
+<br>
+ // Increase the size of the island block to account for the new entry.<br>
+ BBInfo[NewIsland->getNumber()].Size += Size;<br>
+ adjustBBOffsetsAfter(llvm::prior(MachineFunction::iterator(NewIsland)));<br>
+<br>
+ // No existing clone of this CPE is within range.<br>
+ // We will be generating a new clone. Get a UID for it.<br>
+ unsigned ID = createPICLabelUId();<br>
+<br>
+ // Finally, change the CPI in the instruction operand to be ID.<br>
+ for (unsigned i = 0, e = UserMI->getNumOperands(); i != e; ++i)<br>
+ if (UserMI->getOperand(i).isCPI()) {<br>
+ UserMI->getOperand(i).setIndex(ID);<br>
+ break;<br>
+ }<br>
+<br>
+ DEBUG(dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI<br>
+ << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset));<br>
+<br>
+ return true;<br>
+}<br>
+<br>
+/// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update<br>
+/// sizes and offsets of impacted basic blocks.<br>
+void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {<br>
+ MachineBasicBlock *CPEBB = CPEMI->getParent();<br>
+ unsigned Size = CPEMI->getOperand(2).getImm();<br>
+ CPEMI->eraseFromParent();<br>
+ BBInfo[CPEBB->getNumber()].Size -= Size;<br>
+ // All succeeding offsets have the current size value added in, fix this.<br>
+ if (CPEBB->empty()) {<br>
+ BBInfo[CPEBB->getNumber()].Size = 0;<br>
+<br>
+ // This block no longer needs to be aligned.<br>
+ CPEBB->setAlignment(0);<br>
+ } else<br>
+ // Entries are sorted by descending alignment, so realign from the front.<br>
+ CPEBB->setAlignment(getCPELogAlign(CPEBB->begin()));<br>
+<br>
+ adjustBBOffsetsAfter(CPEBB);<br>
+ // An island has only one predecessor BB and one successor BB. Check if<br>
+ // this BB's predecessor jumps directly to this BB's successor. This<br>
+ // shouldn't happen currently.<br>
+ assert(!BBIsJumpedOver(CPEBB) && "How did this happen?");<br>
+ // FIXME: remove the empty blocks after all the work is done?<br>
+}<br>
+<br>
+/// removeUnusedCPEntries - Remove constant pool entries whose refcounts<br>
+/// are zero.<br>
+bool MipsConstantIslands::removeUnusedCPEntries() {<br>
+ unsigned MadeChange = false;<br>
+ for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) {<br>
+ std::vector<CPEntry> &CPEs = CPEntries[i];<br>
+ for (unsigned j = 0, ee = CPEs.size(); j != ee; ++j) {<br>
+ if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) {<br>
+ removeDeadCPEMI(CPEs[j].CPEMI);<br>
+ CPEs[j].CPEMI = NULL;<br>
+ MadeChange = true;<br>
+ }<br>
+ }<br>
+ }<br>
+ return MadeChange;<br>
+}<br>
+<br>
+/// isBBInRange - Returns true if the distance between specific MI and<br>
+/// specific BB can fit in MI's displacement field.<br>
+bool MipsConstantIslands::isBBInRange<br>
+ (MachineInstr *MI,MachineBasicBlock *DestBB, unsigned MaxDisp) {<br>
+<br>
+unsigned PCAdj = 4;<br>
+<br>
+ unsigned BrOffset = getOffsetOf(MI) + PCAdj;<br>
+ unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;<br>
+<br>
+ DEBUG(dbgs() << "Branch of destination BB#" << DestBB->getNumber()<br>
+ << " from BB#" << MI->getParent()->getNumber()<br>
+ << " max delta=" << MaxDisp<br>
+ << " from " << getOffsetOf(MI) << " to " << DestOffset<br>
+ << " offset " << int(DestOffset-BrOffset) << "\t" << *MI);<br>
+<br>
+ if (BrOffset <= DestOffset) {<br>
+ // Branch before the Dest.<br>
+ if (DestOffset-BrOffset <= MaxDisp)<br>
+ return true;<br>
+ } else {<br>
+ if (BrOffset-DestOffset <= MaxDisp)<br>
+ return true;<br>
+ }<br>
+ return false;<br>
+}<br>
+<br>
+/// fixupImmediateBr - Fix up an immediate branch whose destination is too far<br>
+/// away to fit in its displacement field.<br>
+bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) {<br>
+ MachineInstr *MI = Br.MI;<br>
+ MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();<br>
+<br>
+ // Check to see if the DestBB is already in-range.<br>
+ if (isBBInRange(MI, DestBB, Br.MaxDisp))<br>
+ return false;<br>
+<br>
+ if (!Br.isCond)<br>
+ return fixupUnconditionalBr(Br);<br>
+ return fixupConditionalBr(Br);<br>
+}<br>
+<br>
+/// fixupUnconditionalBr - Fix up an unconditional branch whose destination is<br>
+/// too far away to fit in its displacement field. If the LR register has been<br>
+/// spilled in the epilogue, then we can use BL to implement a far jump.<br>
+/// Otherwise, add an intermediate branch instruction to a branch.<br>
+bool<br>
+MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {<br>
+ MachineInstr *MI = Br.MI;<br>
+ MachineBasicBlock *MBB = MI->getParent();<br>
+ // Use BL to implement far jump.<br>
+ Br.MaxDisp = ((1 << 16)-1) * 2;<br>
+ MI->setDesc(TII->get(Mips::BimmX16));<br>
+ BBInfo[MBB->getNumber()].Size += 2;<br>
+ adjustBBOffsetsAfter(MBB);<br>
+ HasFarJump = true;<br>
+ ++NumUBrFixed;<br>
+<br>
+ DEBUG(dbgs() << " Changed B to long jump " << *MI);<br>
+<br>
+ return true;<br>
+}<br>
+<br>
+/// fixupConditionalBr - Fix up a conditional branch whose destination is too<br>
+/// far away to fit in its displacement field. It is converted to an inverse<br>
+/// conditional branch + an unconditional branch to the destination.<br>
+bool<br>
+MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {<br>
+ MachineInstr *MI = Br.MI;<br>
+ MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();<br>
+<br>
+ // Add an unconditional branch to the destination and invert the branch<br>
+ // condition to jump over it:<br>
+ // blt L1<br>
+ // =><br>
+ // bge L2<br>
+ // b L1<br>
+ // L2:<br>
+ unsigned CCReg = 0; // FIXME<br>
+ unsigned CC=0; //FIXME<br>
+<br>
+ // If the branch is at the end of its MBB and that has a fall-through block,<br>
+ // direct the updated conditional branch to the fall-through block. Otherwise,<br>
+ // split the MBB before the next instruction.<br>
+ MachineBasicBlock *MBB = MI->getParent();<br>
+ MachineInstr *BMI = &MBB->back();<br>
+ bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB);<br>
+<br>
+ ++NumCBrFixed;<br>
+ if (BMI != MI) {<br>
+ if (llvm::next(MachineBasicBlock::iterator(MI)) == prior(MBB->end()) &&<br>
+ BMI->getOpcode() == Br.UncondBr) {<br>
+ // Last MI in the BB is an unconditional branch. Can we simply invert the<br>
+ // condition and swap destinations:<br>
+ // beq L1<br>
+ // b L2<br>
+ // =><br>
+ // bne L2<br>
+ // b L1<br>
+ MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB();<br>
+ if (isBBInRange(MI, NewDest, Br.MaxDisp)) {<br>
+ DEBUG(dbgs() << " Invert Bcc condition and swap its destination with "<br>
+ << *BMI);<br>
+ BMI->getOperand(0).setMBB(DestBB);<br>
+ MI->getOperand(0).setMBB(NewDest);<br>
+ return true;<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ if (NeedSplit) {<br>
+ splitBlockBeforeInstr(MI);<br>
+ // No need for the branch to the next block. We're adding an unconditional<br>
+ // branch to the destination.<br>
+ int delta = TII->GetInstSizeInBytes(&MBB->back());<br>
+ BBInfo[MBB->getNumber()].Size -= delta;<br>
+ MBB->back().eraseFromParent();<br>
+ // BBInfo[SplitBB].Offset is wrong temporarily, fixed below<br>
+ }<br>
+ MachineBasicBlock *NextBB = llvm::next(MachineFunction::iterator(MBB));<br>
+<br>
+ DEBUG(dbgs() << " Insert B to BB#" << DestBB->getNumber()<br>
+ << " also invert condition and change dest. to BB#"<br>
+ << NextBB->getNumber() << "\n");<br>
+<br>
+ // Insert a new conditional branch and a new unconditional branch.<br>
+ // Also update the ImmBranch as well as adding a new entry for the new branch.<br>
+ BuildMI(MBB, DebugLoc(), TII->get(MI->getOpcode()))<br>
+ .addMBB(NextBB).addImm(CC).addReg(CCReg);<br>
+ Br.MI = &MBB->back();<br>
+ BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back());<br>
+ BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB);<br>
+ BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back());<br>
+ unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr);<br>
+ ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr));<br>
+<br>
+ // Remove the old conditional branch. It may or may not still be in MBB.<br>
+ BBInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(MI);<br>
+ MI->eraseFromParent();<br>
+ adjustBBOffsetsAfter(MBB);<br>
+ return true;<br>
+}<br>
+<br>
<br>
void MipsConstantIslands::prescanForConstants() {<br>
- unsigned int J;<br>
+ unsigned J = 0;<br>
+ (void)J;<br>
+ PrescannedForConstants = true;<br>
for (MachineFunction::iterator B =<br>
MF->begin(), E = MF->end(); B != E; ++B) {<br>
for (MachineBasicBlock::instr_iterator I =<br>
@@ -238,10 +1595,11 @@ void MipsConstantIslands::prescanForCons<br>
unsigned index = MCP->getConstantPoolIndex(C, 4);<br>
I->getOperand(2).ChangeToImmediate(index);<br>
DEBUG(dbgs() << "constant island constant " << *I << "\n");<br>
- I->setDesc(TII->get(Mips::LwRxPcTcpX16));<br>
+ I->setDesc(TII->get(Mips::LwRxPcTcp16));<br>
I->RemoveOperand(1);<br>
I->RemoveOperand(1);<br>
I->addOperand(MachineOperand::CreateCPI(index, 0));<br>
+ I->addOperand(MachineOperand::CreateImm(4));<br>
}<br>
break;<br>
}<br>
@@ -251,3 +1609,4 @@ void MipsConstantIslands::prescanForCons<br>
}<br>
}<br>
}<br>
+<br>
<br>
Added: llvm/trunk/test/CodeGen/Mips/const4.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/const4.ll?rev=194053&view=auto" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/const4.ll?rev=194053&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/Mips/const4.ll (added)<br>
+++ llvm/trunk/test/CodeGen/Mips/const4.ll Tue Nov 5 02:14:14 2013<br>
@@ -0,0 +1,64 @@<br>
+; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static -mips16-constant-islands -mips-constant-islands-small-offset=20 < %s | FileCheck %s -check-prefix=offset20<br>
+<br>
+; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static -mips16-constant-islands -mips-constant-islands-small-offset=40 < %s | FileCheck %s -check-prefix=offset40<br>
+<br>
+<br>
+@i = common global i32 0, align 4<br>
+@b = common global i32 0, align 4<br>
+<br>
+; Function Attrs: nounwind<br>
+define void @t() #0 {<br>
+entry:<br>
+ store i32 -559023410, i32* @i, align 4<br>
+ %0 = load i32* @b, align 4<br>
+ %tobool = icmp ne i32 %0, 0<br>
+ br i1 %tobool, label %if.then, label %if.else<br>
+; offset20: lw ${{[0-9]+}}, $CPI0_1 # 16 bit inst<br>
+; offset20: b $BB0_2<br>
+; offset20: .align 2<br>
+; offset20: $CPI0_0:<br>
+; offset20: .4byte 3735943886<br>
+; offset20: $BB0_2:<br>
+<br>
+; offset40: beqz ${{[0-9]+}}, $BB0_3<br>
+; offset40: jal foo<br>
+; offset40: nop<br>
+; offset40: b $BB0_4<br>
+; offset40: .align 2<br>
+; offset40: $CPI0_0:<br>
+; offset40: .4byte 3735943886<br>
+; offset40: $BB0_3:<br>
+; offset40: jal goo<br>
+<br>
+if.then: ; preds = %entry<br>
+ call void bitcast (void (...)* @foo to void ()*)()<br>
+ br label %if.end<br>
+<br>
+if.else: ; preds = %entry<br>
+ call void bitcast (void (...)* @goo to void ()*)()<br>
+ br label %if.end<br>
+<br>
+if.end: ; preds = %if.else, %if.then<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ call void bitcast (void (...)* @hoo to void ()*)()<br>
+ ret void<br>
+}<br>
+<br>
+declare void @foo(...) #1<br>
+<br>
+declare void @goo(...) #1<br>
+<br>
+declare void @hoo(...) #1<br>
+<br>
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" }<br>
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" }<br>
+<br>
+!llvm.ident = !{!0}<br>
+<br>
+!0 = metadata !{metadata !"clang version 3.4 (gitosis@dmz-portal.mips.com:clang.git 3a50d847e098f36e3bf8bc14eea07a6cc35f7803) (gitosis@dmz-portal.mips.com:llvm.git f52db0b69f0c888bdc98bb2f13aaecc1e83288a9)"}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>