Fix Mips long branch pass.
authorAkira Hatanaka <ahatanaka@mips.com>
Sat, 21 Jul 2012 03:30:44 +0000 (03:30 +0000)
committerAkira Hatanaka <ahatanaka@mips.com>
Sat, 21 Jul 2012 03:30:44 +0000 (03:30 +0000)
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
lib/Target/Mips/MipsLongBranch.cpp
test/CodeGen/Mips/longbranch.ll

index c47f0cbf4bf0e0b89ecc043ebbfca48f1c665764..f1aada49fb256ef05538207f77aa1a68d6c15e30 100644 (file)
@@ -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>;
index 7be353f1901243e60e578abc2485b8681057e02c..70ecbc13612759899d4a4d316de7a13f61292123 100644 (file)
@@ -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<MipsFunctionInfo>()->setEmitNOAT();
-  bool IsPIC = (TM.getRelocationModel() == Reloc::PIC_);
-  unsigned ABI = TM.getSubtarget<MipsSubtarget>().getTargetABI();
-  bool N64 = (ABI == MipsSubtarget::N64);
-  unsigned NumInstrs;
-
-  if (IsPIC || N64) {
-    bool HasMips64 = TM.getSubtarget<MipsSubtarget>().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<const MipsRegisterInfo*>(TM.getRegisterInfo());
-    unsigned SP = MRI->getFrameRegister(*MF);
-    unsigned GlobalRegFI = MF->getInfo<MipsFunctionInfo>()->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<MipsFunctionInfo>()->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<MipsSubtarget>().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);
+
+  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
+    //
+    //  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<MipsFunctionInfo>()->setEmitNOAT();
+    MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB);
+    MF->insert(FallThroughMBB, BalTgtMBB);
+    LongBrMBB->addSuccessor(BalTgtMBB);
+    BalTgtMBB->addSuccessor(TgtMBB);
 
-  if (I.Br->isUnconditionalBranch()) {
-    // Unconditional branch before transformation:
-    //   b $tgt
-    //   delay-slot-instr
+    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:
     //
-    // 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;
-
-    // Remove branch and clear InsideBundle bit of the next instruction.
-    llvm::next(MachineBasicBlock::instr_iterator(I.Br))
-      ->setIsInsideBundle(false);
-    I.Br->eraseFromParent();
-    return;
+    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<MBBInfo, 16>::iterator I, E = MBBInfos.end();
   bool EverMadeChange = false, MadeChange = true;
 
@@ -393,17 +401,10 @@ 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))
-          continue;
-
-        // Check if offset fits into 26-bit immediate field of jumps (J).
-        if (I->Br->isUnconditionalBranch() && !IsPIC && isInt<26>(Offset / 4))
+        if (isInt<16>(computeOffset(I->Br) / 4))
           continue;
-      }
 
       expandToLongBranch(*I);
       ++LongBranches;
index ef95d0011c978d835ecb4ece64523b42633a48d0..0227b88fbc86863895ff98b7cca72cf7124b09c3 100644 (file)
@@ -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