From 60287963c7505180500d63b1c1b90f0f4b337430 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Sat, 21 Jul 2012 03:30:44 +0000 Subject: [PATCH] Fix Mips long branch pass. This pass no longer requires that the global pointer value be saved to the stack or register since it uses bal instruction to compute branch distance. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160601 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsInstrInfo.td | 4 + lib/Target/Mips/MipsLongBranch.cpp | 261 +++++++++++++++-------------- test/CodeGen/Mips/longbranch.ll | 10 +- 3 files changed, 141 insertions(+), 134 deletions(-) diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index c47f0cbf4bf..f1aada49fb2 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -1005,6 +1005,10 @@ def BGTZ : CBranchZero<0x07, 0, "bgtz", setgt, CPURegs>; def BLEZ : CBranchZero<0x06, 0, "blez", setle, CPURegs>; def BLTZ : CBranchZero<0x01, 0, "bltz", setlt, CPURegs>; +let rt = 0, rs = 0, isBranch = 1, isTerminator = 1, isBarrier = 1, + hasDelaySlot = 1, Defs = [RA] in +def BAL_BR: FI<0x1, (outs), (ins brtarget:$imm16), "bal\t$imm16", [], IIBranch>; + def JAL : JumpLink<0x03, "jal">; def JALR : JumpLinkReg<0x00, 0x09, "jalr", CPURegs>; def BGEZAL : BranchLink<"bgezal", 0x11, CPURegs>; diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index 7be353f1901..70ecbc13612 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -73,9 +73,6 @@ namespace { void splitMBB(MachineBasicBlock *MBB); void initMBBInfo(); int64_t computeOffset(const MachineInstr *Br); - bool offsetFitsIntoField(const MachineInstr *Br); - unsigned addLongBranch(MachineBasicBlock &MBB, Iter Pos, - MachineBasicBlock *Tgt, DebugLoc DL, bool Nop); void replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL, MachineBasicBlock *MBBOpnd); void expandToLongBranch(MBBInfo &Info); @@ -178,7 +175,9 @@ void MipsLongBranch::initMBBInfo() { ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End); if ((Br != End) && !Br->isIndirectBranch() && - (Br->isConditionalBranch() || Br->isUnconditionalBranch())) + (Br->isConditionalBranch() || + (Br->isUnconditionalBranch() && + TM.getRelocationModel() == Reloc::PIC_))) MBBInfos[I].Br = (++Br).base(); } } @@ -204,77 +203,6 @@ int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) { return -Offset + 4; } -// Insert the following sequence: -// (pic or N64) -// lw $at, global_reg_slot -// lw $at, got($L1)($at) -// addiu $at, $at, lo($L1) -// jr $at -// noop -// (static and !N64) -// lui $at, hi($L1) -// addiu $at, $at, lo($L1) -// jr $at -// noop -unsigned MipsLongBranch::addLongBranch(MachineBasicBlock &MBB, Iter Pos, - MachineBasicBlock *Tgt, DebugLoc DL, - bool Nop) { - MF->getInfo()->setEmitNOAT(); - bool IsPIC = (TM.getRelocationModel() == Reloc::PIC_); - unsigned ABI = TM.getSubtarget().getTargetABI(); - bool N64 = (ABI == MipsSubtarget::N64); - unsigned NumInstrs; - - if (IsPIC || N64) { - bool HasMips64 = TM.getSubtarget().hasMips64(); - unsigned AT = N64 ? Mips::AT_64 : Mips::AT; - unsigned Load = N64 ? Mips::LD_P8 : Mips::LW; - unsigned ADDiu = N64 ? Mips::DADDiu : Mips::ADDiu; - unsigned JR = N64 ? Mips::JR64 : Mips::JR; - unsigned GOTFlag = HasMips64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; - unsigned OFSTFlag = HasMips64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; - const MipsRegisterInfo *MRI = - static_cast(TM.getRegisterInfo()); - unsigned SP = MRI->getFrameRegister(*MF); - unsigned GlobalRegFI = MF->getInfo()->getGlobalRegFI(); - int64_t Offset = MF->getFrameInfo()->getObjectOffset(GlobalRegFI); - - if (isInt<16>(Offset)) { - BuildMI(MBB, Pos, DL, TII->get(Load), AT).addReg(SP).addImm(Offset); - NumInstrs = 1; - } else { - unsigned ADDu = N64 ? Mips::DADDu : Mips::ADDu; - MipsAnalyzeImmediate::Inst LastInst(0, 0); - - MF->getInfo()->setEmitNOAT(); - NumInstrs = Mips::loadImmediate(Offset, N64, *TII, MBB, Pos, DL, true, - &LastInst) + 2; - BuildMI(MBB, Pos, DL, TII->get(ADDu), AT).addReg(SP).addReg(AT); - BuildMI(MBB, Pos, DL, TII->get(Load), AT).addReg(AT) - .addImm(SignExtend64<16>(LastInst.ImmOpnd)); - } - - BuildMI(MBB, Pos, DL, TII->get(Load), AT).addReg(AT).addMBB(Tgt, GOTFlag); - BuildMI(MBB, Pos, DL, TII->get(ADDiu), AT).addReg(AT).addMBB(Tgt, OFSTFlag); - BuildMI(MBB, Pos, DL, TII->get(JR)).addReg(Mips::AT, RegState::Kill); - NumInstrs += 3; - } else { - BuildMI(MBB, Pos, DL, TII->get(Mips::LUi), Mips::AT) - .addMBB(Tgt, MipsII::MO_ABS_HI); - BuildMI(MBB, Pos, DL, TII->get(Mips::ADDiu), Mips::AT) - .addReg(Mips::AT).addMBB(Tgt, MipsII::MO_ABS_LO); - BuildMI(MBB, Pos, DL, TII->get(Mips::JR)).addReg(Mips::AT, RegState::Kill); - NumInstrs = 3; - } - - if (Nop) { - BuildMI(MBB, Pos, DL, TII->get(Mips::NOP))->setIsInsideBundle(); - ++NumInstrs; - } - - return NumInstrs; -} - // Replace Br with a branch which has the opposite condition code and a // MachineBasicBlock operand MBBOpnd. void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, @@ -304,57 +232,138 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, void MipsLongBranch::expandToLongBranch(MBBInfo &I) { I.HasLongBranch = true; - MachineBasicBlock *MBB = I.Br->getParent(), *Tgt = getTargetMBB(*I.Br); + bool IsPIC = TM.getRelocationModel() == Reloc::PIC_; + unsigned ABI = TM.getSubtarget().getTargetABI(); + bool N64 = ABI == MipsSubtarget::N64; + + MachineBasicBlock::iterator Pos; + MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); DebugLoc DL = I.Br->getDebugLoc(); + const BasicBlock *BB = MBB->getBasicBlock(); + MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); + MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); - if (I.Br->isUnconditionalBranch()) { - // Unconditional branch before transformation: - // b $tgt - // delay-slot-instr + MF->insert(FallThroughMBB, LongBrMBB); + MBB->removeSuccessor(TgtMBB); + MBB->addSuccessor(LongBrMBB); + + if (IsPIC) { + // $longbr: + // addiu $sp, $sp, -regsize * 2 + // sw $ra, 0($sp) + // bal $baltgt + // sw $a3, regsize($sp) + // $baltgt: + // lui $a3, %hi($baltgt) + // lui $at, %hi($tgt) + // addiu $a3, $a3, %lo($baltgt) + // addiu $at, $at, %lo($tgt) + // subu $at, $at, $a3 + // addu $at, $ra, $at // - // after transformation: - // delay-slot-instr - // lw $at, global_reg_slot - // lw $at, %got($tgt)($at) - // addiu $at, $at, %lo($tgt) - // jr $at - // nop - I.Size += (addLongBranch(*MBB, llvm::next(Iter(I.Br)), Tgt, DL, true) - - 1) * 4; + // if n64: + // lui $a3, %highest($baltgt) + // lui $ra, %highest($tgt) + // addiu $a3, $a3, %higher($baltgt) + // addiu $ra, $ra, %higher($tgt) + // dsll $a3, $a3, 32 + // dsll $ra, $ra, 32 + // subu $at, $at, $a3 + // addu $at, $at, $ra + // + // lw $ra, 0($sp) + // lw $a3, regsize($sp) + // jr $at + // addiu $sp, $sp, regsize * 2 + // $fallthrough: + // + MF->getInfo()->setEmitNOAT(); + MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); + MF->insert(FallThroughMBB, BalTgtMBB); + LongBrMBB->addSuccessor(BalTgtMBB); + BalTgtMBB->addSuccessor(TgtMBB); - // Remove branch and clear InsideBundle bit of the next instruction. - llvm::next(MachineBasicBlock::instr_iterator(I.Br)) - ->setIsInsideBundle(false); - I.Br->eraseFromParent(); - return; + int RegSize = N64 ? 8 : 4; + unsigned AT = N64 ? Mips::AT_64 : Mips::AT; + unsigned A3 = N64 ? Mips::A3_64 : Mips::A3; + unsigned SP = N64 ? Mips::SP_64 : Mips::SP; + unsigned RA = N64 ? Mips::RA_64 : Mips::RA; + unsigned Load = N64 ? Mips::LD_P8 : Mips::LW; + unsigned Store = N64 ? Mips::SD_P8 : Mips::SW; + unsigned LUi = N64 ? Mips::LUi64 : Mips::LUi; + unsigned ADDiu = N64 ? Mips::DADDiu : Mips::ADDiu; + unsigned ADDu = N64 ? Mips::DADDu : Mips::ADDu; + unsigned SUBu = N64 ? Mips::SUBu : Mips::SUBu; + unsigned JR = N64 ? Mips::JR64 : Mips::JR; + + Pos = LongBrMBB->begin(); + + BuildMI(*LongBrMBB, Pos, DL, TII->get(ADDiu), SP).addReg(SP) + .addImm(-RegSize * 2); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Store)).addReg(RA).addReg(SP) + .addImm(0); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Store)).addReg(A3).addReg(SP) + .addImm(RegSize)->setIsInsideBundle(); + + Pos = BalTgtMBB->begin(); + + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), A3) + .addMBB(BalTgtMBB, MipsII::MO_ABS_HI); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), AT) + .addMBB(TgtMBB, MipsII::MO_ABS_HI); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), A3).addReg(A3) + .addMBB(BalTgtMBB, MipsII::MO_ABS_LO); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), AT).addReg(AT) + .addMBB(TgtMBB, MipsII::MO_ABS_LO); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(SUBu), AT).addReg(AT).addReg(A3); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDu), AT).addReg(RA).addReg(AT); + + if (N64) { + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), A3) + .addMBB(BalTgtMBB, MipsII::MO_HIGHEST); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), RA) + .addMBB(TgtMBB, MipsII::MO_HIGHEST); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), A3).addReg(A3) + .addMBB(BalTgtMBB, MipsII::MO_HIGHER); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), RA).addReg(RA) + .addMBB(TgtMBB, MipsII::MO_HIGHER); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DSLL), A3).addReg(A3) + .addImm(32); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DSLL), RA).addReg(RA) + .addImm(32); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(SUBu), AT).addReg(AT).addReg(A3); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDu), AT).addReg(AT).addReg(RA); + I.Size += 4 * 8; + } + + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Load), RA).addReg(SP).addImm(0); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Load), A3).addReg(SP).addImm(RegSize); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(JR)).addReg(AT); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), SP).addReg(SP) + .addImm(RegSize * 2)->setIsInsideBundle(); + I.Size += 4 * 14; + } else { + // $longbr: + // j $tgt + // nop + // $fallthrough: + // + Pos = LongBrMBB->begin(); + LongBrMBB->addSuccessor(TgtMBB); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::J)).addMBB(TgtMBB); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::NOP))->setIsInsideBundle(); + I.Size += 4 * 2; } - assert(I.Br->isConditionalBranch() && "Conditional branch expected."); - - // Conditional branch before transformation: - // b cc, $tgt - // delay-slot-instr - // FallThrough: - // - // after transformation: - // b !cc, FallThrough - // delay-slot-instr - // NewMBB: - // lw $at, global_reg_slot - // lw $at, %got($tgt)($at) - // addiu $at, $at, %lo($tgt) - // jr $at - // noop - // FallThrough: - - MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB->getBasicBlock()); - MF->insert(llvm::next(MachineFunction::iterator(MBB)), NewMBB); - MBB->removeSuccessor(Tgt); - MBB->addSuccessor(NewMBB); - NewMBB->addSuccessor(Tgt); - - I.Size += addLongBranch(*NewMBB, NewMBB->begin(), Tgt, DL, true) * 4; - replaceBranch(*MBB, I.Br, DL, *MBB->succ_begin()); + if (I.Br->isUnconditionalBranch()) { + // Change branch destination. + assert(I.Br->getDesc().getNumOperands() == 1); + I.Br->RemoveOperand(0); + I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); + } else + // Change branch destination and reverse condition. + replaceBranch(*MBB, I.Br, DL, FallThroughMBB); } static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { @@ -380,7 +389,6 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { MF = &F; initMBBInfo(); - bool IsPIC = (TM.getRelocationModel() == Reloc::PIC_); SmallVector::iterator I, E = MBBInfos.end(); bool EverMadeChange = false, MadeChange = true; @@ -393,18 +401,11 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { if (!I->Br || I->HasLongBranch) continue; - if (!ForceLongBranch) { - int64_t Offset = computeOffset(I->Br); - + if (!ForceLongBranch) // Check if offset fits into 16-bit immediate field of branches. - if ((I->Br->isConditionalBranch() || IsPIC) && isInt<16>(Offset / 4)) + if (isInt<16>(computeOffset(I->Br) / 4)) continue; - // Check if offset fits into 26-bit immediate field of jumps (J). - if (I->Br->isUnconditionalBranch() && !IsPIC && isInt<26>(Offset / 4)) - continue; - } - expandToLongBranch(*I); ++LongBranches; EverMadeChange = MadeChange = true; diff --git a/test/CodeGen/Mips/longbranch.ll b/test/CodeGen/Mips/longbranch.ll index ef95d0011c9..0227b88fbc8 100644 --- a/test/CodeGen/Mips/longbranch.ll +++ b/test/CodeGen/Mips/longbranch.ll @@ -1,12 +1,14 @@ -; RUN: llc -march=mipsel -force-mips-long-branch < %s | FileCheck %s +; RUN: llc -march=mipsel -force-mips-long-branch < %s | FileCheck %s -check-prefix=O32 +; RUN: llc -march=mips64el -mcpu=mips64 -mattr=n64 -force-mips-long-branch < %s | FileCheck %s -check-prefix=N64 @g0 = external global i32 define void @foo1(i32 %s) nounwind { entry: -; CHECK: lw $[[R0:[a-z0-9]+]], %got($BB0_3)(${{[a-z0-9]+}}) -; CHECK: addiu $[[R1:[a-z0-9]+]], $[[R0]], %lo($BB0_3) -; CHECK: jr $[[R1]] +; O32: bal +; N64: bal +; N64: highest +; N64: higher %tobool = icmp eq i32 %s, 0 br i1 %tobool, label %if.end, label %if.then