[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