[PATCH] Optimize long branch for MIPS64 by removing calculation of %higher and %highest

Sasa Stankovic Sasa.Stankovic at imgtec.com
Wed Apr 16 10:26:15 PDT 2014



================
Comment at: lib/Target/Mips/MipsLongBranch.cpp:328
@@ -330,2 +327,3 @@
+      //  daddiu $at, $zero, 0
       //  daddiu $at, $at, %hi($tgt - $baltgt)
       //  bal $baltgt
----------------
Daniel Sanders wrote:
> Sasa Stankovic wrote:
> > Mark Seaborn wrote:
> > > Does 64-bit MIPS not have an instruction for setting bits 16-31 of a register while zeroing the others (as 32-bit MIPS' "lui" instruction does)?
> > > 
> > > What does lui64 do?
> > > 
> > > This part looks OK to me, but I'm not familiar with 64-bit MIPS, so you might want to get someone who is sign off on the change too.
> > There is no lui64 (I fixed that comment), there is only a lui instruction (you can see it in .td file lib/Target/Mips/Mips64InstrInfo.td - mnemonic for MIPS64 LUi64 instruction is just "lui"). lui on MIPS64 sets bits 16-31 of a register, zeroes bits 15-0, and sign-extends bit 31 into higher part of the 64-bit register.  MIPS64 supports all (or almost all) MIPS32 instructions, and they all operate like this - they change low 32 bits just like they do on MIPS32, and they sign-extend bit 31 into high 32 bits. MIPS64 also has instructions that operate on all 64 bits (their mnemonics start with d (from double)), but there is no instruction that sets bits 16-31 while clearing the others.
> > Does 64-bit MIPS not have an instruction for setting bits 16-31 of a register while 
> > zeroing the others (as 32-bit MIPS' "lui" instruction does)?
> 
> Not while zeroing the other bits but 32-bit results are generally sign-extended to 64-bit. lui is nearly the right operation but sign-extends instead of zero extending.
> 
> > What does lui64 do?
> 
> lui64 doesn't exist in the assembler or the ISA spec so we ought to avoid using that term when writing assembly examples. It's the same as the 32-bit lui instruction but sign-extended to 64-bits.
> 
> ----
> 
> It looks like you should be able to remove another insn by replacing:
>     daddiu $at, $zero, 0
>     daddiu $at, $at, %hi($tgt - $baltgt)
> with:
>     daddiu $at, $zero, %hi($tgt - $baltgt)
You are right, I'll implement this.

================
Comment at: lib/Target/Mips/MipsLongBranch.cpp:350-364
@@ -346,1 +349,17 @@
+      //
+      // It's safe to do this because %highest and %higher can have non-zero
+      // values only when the offset is greater than 4GB, which is highly
+      // unlikely, if not impossible when compiling a single function.
+      //
+      // Note that this will work even if the offset is negative, because
+      // of the +1 modification that's added in that case.  For example, if the
+      // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is
+      //
+      // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000
+      //
+      // and the bits [47:32] are zero.  For %highest
+      //
+      // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000
+      //
+      // and the bits [63:48] are zero.
 
----------------
Daniel Sanders wrote:
> This logic makes sense to me but I didn't notice a guarantee that $tgt and $baltgt are in the same function. Have I missed it?
Do you want that I add the assert that that $tgt and $baltgt are in the current function? $baltgt is always in the current function because it is part of the long branch. As for $tgt, it is the target operand of the original branch that is expanded into long branch. I suppose that branches always jump to the blocks in the same function, but I may be wrong.


http://reviews.llvm.org/D3281






More information about the llvm-commits mailing list