diff options
| -rw-r--r-- | llvm/lib/Target/Mips/Mips32r6InstrInfo.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Mips64r6InstrInfo.td | 17 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 49 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.cpp | 106 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Mips/compactbranches/compact-branches.ll | 85 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Mips/llvm-ir/call.ll | 61 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Mips/llvm-ir/indirectbr.ll | 7 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Mips/llvm-ir/ret.ll | 15 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Mips/mips64-f128.ll | 59 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/mips32r6/valid.s | 2 | 
10 files changed, 263 insertions, 142 deletions
diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index f3bd2bf275f..3e2c8293c26 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -412,10 +412,11 @@ class JMP_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd,    dag InOperandList = (ins GPROpnd:$rt, opnd:$offset);    string AsmString = !strconcat(opstr, "\t$rt, $offset");    list<dag> Pattern = []; -  bit isTerminator = 1;    bit hasDelaySlot = 0;    InstrItinClass Itinerary = itin;    bit isCTI = 1; +  bit isBranch = 1; +  bit isIndirectBranch = 1;  }  class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, @@ -427,6 +428,7 @@ class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16,  class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16,                                             GPR32Opnd, II_JIALC> {    bit isBarrier = 1; +  bit isTerminator = 1;    list<Register> Defs = [AT];  } diff --git a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td index b2fc9111170..d11f2a2890a 100644 --- a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td @@ -76,6 +76,18 @@ class SCD_R6_DESC   : SC_R6_DESC_BASE<"scd", GPR64Opnd, II_SCD>;  class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>;  class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>; +class JIALC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, +                                             GPR64Opnd> { +  bit isCall = 1; +  list<Register> Defs = [RA]; +} + +class JIC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR64Opnd> { +  bit isBarrier = 1; +  bit isTerminator = 1; +  list<Register> Defs = [AT]; +} +  //===----------------------------------------------------------------------===//  //  // Instruction Definitions @@ -107,7 +119,10 @@ let DecoderNamespace = "Mips32r6_64r6_GP64" in {    def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64;    def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64;  } - +let isCodeGenOnly = 1 in { +def JIALC64 : JIALC_ENC, JIALC64_DESC, ISA_MIPS64R6; +def JIC64 : JIC_ENC, JIC64_DESC, ISA_MIPS64R6; +}  //===----------------------------------------------------------------------===//  //  // Instruction Aliases diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index a40b51cb19f..0a7ffb10153 100644 --- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -205,9 +205,6 @@ namespace {      Iter replaceWithCompactBranch(MachineBasicBlock &MBB,                                    Iter Branch, DebugLoc DL); -    Iter replaceWithCompactJump(MachineBasicBlock &MBB, -                                Iter Jump, DebugLoc DL); -      /// This function checks if it is valid to move Candidate to the delay slot      /// and returns true if it isn't. It also updates memory and register      /// dependence information. @@ -522,24 +519,6 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB,    return Branch;  } -// Replace Jumps with the compact jump instruction. -Iter Filler::replaceWithCompactJump(MachineBasicBlock &MBB, -                                    Iter Jump, DebugLoc DL) { -  const MipsInstrInfo *TII = -      MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); - -  const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM); -  MachineInstrBuilder MIB = BuildMI(MBB, Jump, DL, NewDesc); - -  MIB.addReg(Jump->getOperand(0).getReg()); - -  Iter tmpIter = Jump; -  Jump = std::prev(Jump); -  MBB.erase(tmpIter); - -  return Jump; -} -  // For given opcode returns opcode of corresponding instruction with short  // delay slot.  static int getEquivalentCallShort(int Opcode) { @@ -604,31 +583,21 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {            // corresponding instruction with short delay slot.            DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode())));          } -          continue;        }      } -    // If instruction is BEQ or BNE with one ZERO register, then instead of -    // adding NOP replace this instruction with the corresponding compact -    // branch instruction, i.e. BEQZC or BNEZC. -    if (InMicroMipsMode) { -      if (TII->getEquivalentCompactForm(I)) { -        I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); -        continue; -      } - -      if (I->isIndirectBranch() || I->isReturn()) { -        // For microMIPS the PseudoReturn and PseudoIndirectBranch are always -        // expanded to JR_MM, so they can be replaced with JRC16_MM. -        I = replaceWithCompactJump(MBB, I, I->getDebugLoc()); -        continue; -      } -    } +    // For microMIPS if instruction is BEQ or BNE with one ZERO register, then +    // instead of adding NOP replace this instruction with the corresponding +    // compact branch instruction, i.e. BEQZC or BNEZC. Additionally +    // PseudoReturn and PseudoIndirectBranch are expanded to JR_MM, so they can +    // be replaced with JRC16_MM.      // For MIPSR6 attempt to produce the corresponding compact (no delay slot) -    // form of the branch. This should save putting in a NOP. -    if ((STI.hasMips32r6()) && TII->getEquivalentCompactForm(I)) { +    // form of the CTI. For indirect jumps this will not require inserting a +    // NOP and for branches will hopefully avoid requiring a NOP. +    if ((InMicroMipsMode || STI.hasMips32r6()) && +         TII->getEquivalentCompactForm(I)) {        I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());        continue;      } diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp index 84368d7b80f..0f4e820fb00 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp @@ -261,24 +261,40 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(  unsigned MipsInstrInfo::getEquivalentCompactForm(      const MachineBasicBlock::iterator I) const {    unsigned Opcode = I->getOpcode(); -  bool canUseShortMMBranches = -      Subtarget.inMicroMipsMode() && -      (Opcode == Mips::BNE || Opcode == Mips::BEQ) && -      I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg(); +  bool canUseShortMicroMipsCTI = false; -  if (Subtarget.hasMips32r6() || canUseShortMMBranches) { +  if (Subtarget.inMicroMipsMode()) { +    switch (Opcode) { +    case Mips::BNE: +    case Mips::BEQ: +    // microMIPS has NE,EQ branches that do not have delay slots provided one +    // of the operands is zero. +      if (I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg()) +        canUseShortMicroMipsCTI = true; +      break; +    // For microMIPS the PseudoReturn and PseudoIndirectBranch are always +    // expanded to JR_MM, so they can be replaced with JRC16_MM. +    case Mips::JR: +    case Mips::PseudoReturn: +    case Mips::PseudoIndirectBranch: +      canUseShortMicroMipsCTI = true; +      break; +    } +  } + +  if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) {      switch (Opcode) {      case Mips::B:        return Mips::BC;      case Mips::BAL:        return Mips::BALC;      case Mips::BEQ: -      if (canUseShortMMBranches) +      if (canUseShortMicroMipsCTI)          return Mips::BEQZC_MM;        else          return Mips::BEQC;      case Mips::BNE: -      if (canUseShortMMBranches) +      if (canUseShortMicroMipsCTI)          return Mips::BNEZC_MM;        else          return Mips::BNEC; @@ -298,7 +314,23 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(        return Mips::BLTUC;      case Mips::BLTZ:        return Mips::BLTZC; -    default: +    // For MIPSR6, the instruction 'jic' can be used for these cases. Some +    // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'. +    case Mips::JR: +    case Mips::PseudoReturn: +    case Mips::PseudoIndirectBranch: +      if (canUseShortMicroMipsCTI) +        return Mips::JRC16_MM; +      return Mips::JIC; +    case Mips::JALRPseudo: +      return Mips::JIALC; +    case Mips::JR64: +    case Mips::PseudoReturn64: +    case Mips::PseudoIndirectBranch64: +      return Mips::JIC64; +    case Mips::JALR64Pseudo: +      return Mips::JIALC64; +     default:        return 0;      }    } @@ -343,19 +375,20 @@ MachineInstrBuilder  MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,                                    MachineBasicBlock::iterator I) const {    MachineInstrBuilder MIB; -  bool BranchWithZeroOperand = false;    // Certain branches have two forms: e.g beq $1, $zero, dst vs beqz $1, dest    // Pick the zero form of the branch for readable assembly and for greater    // branch distance in non-microMIPS mode. -  if (I->isBranch() && I->getOperand(1).isReg() && -      // FIXME: Certain atomic sequences on mips64 generate 32bit references to -      // Mips::ZERO, which is incorrect. This test should be updated to use -      // Subtarget.getABI().GetZeroReg() when those atomic sequences and others -      // are fixed. -      (I->getOperand(1).getReg() == Mips::ZERO || -       I->getOperand(1).getReg() == Mips::ZERO_64)) { -    BranchWithZeroOperand = true; +  // FIXME: Certain atomic sequences on mips64 generate 32bit references to +  // Mips::ZERO, which is incorrect. This test should be updated to use +  // Subtarget.getABI().GetZeroReg() when those atomic sequences and others +  // are fixed. +  bool BranchWithZeroOperand = +      (I->isBranch() && !I->isPseudo() && I->getOperand(1).isReg() && +       (I->getOperand(1).getReg() == Mips::ZERO || +        I->getOperand(1).getReg() == Mips::ZERO_64)); + +  if (BranchWithZeroOperand) {      switch (NewOpc) {      case Mips::BEQC:        NewOpc = Mips::BEQZC; @@ -369,20 +402,43 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,      case Mips::BLTC:        NewOpc = Mips::BLTZC;        break; -    case Mips::BNEZC_MM: -    case Mips::BEQZC_MM: -      break; -    default: -      BranchWithZeroOperand = false; -      break;      }    }    MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); -  for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) -    if (!(BranchWithZeroOperand && (J == 1))) +  // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an +  // immediate 0 as an operand and requires the removal of it's %RA<imp-def> +  // implicit operand as copying the implicit operations of the instructio we're +  // looking at will give us the correct flags. +  if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || +      NewOpc == Mips::JIALC64) { + +    if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64) +      MIB->RemoveOperand(0); + +    for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { +      MIB.addOperand(I->getOperand(J)); +    } + +    MIB.addImm(0); + + } else if (BranchWithZeroOperand) { +    // For MIPSR6 and microMIPS branches with an explicit zero operand, copy +    // everything after the zero. +     MIB.addOperand(I->getOperand(0)); + +    for (unsigned J = 2, E = I->getDesc().getNumOperands(); J < E; ++J) {        MIB.addOperand(I->getOperand(J)); +    } +  } else { +    // All other cases copy all other operands. +    for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { +      MIB.addOperand(I->getOperand(J)); +    } +  } + +  MIB.copyImplicitOps(*I);    MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end());    return MIB; diff --git a/llvm/test/CodeGen/Mips/compactbranches/compact-branches.ll b/llvm/test/CodeGen/Mips/compactbranches/compact-branches.ll index e863c740943..b489a23f69e 100644 --- a/llvm/test/CodeGen/Mips/compactbranches/compact-branches.ll +++ b/llvm/test/CodeGen/Mips/compactbranches/compact-branches.ll @@ -1,21 +1,26 @@ -; RUN: llc -march=mipsel -mcpu=mips32r6 -relocation-model=static < %s | FileCheck %s +; RUN: llc -march=mipsel -mcpu=mips32r6 -relocation-model=static -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=STATIC32 +; RUN: llc -march=mipsel -mcpu=mips64r6 -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=PIC  ; Function Attrs: nounwind  define void @l()  {  entry: +; PIC: jialc $25, 0    %call = tail call i32 @k() +; PIC: jialc $25, 0    %call1 = tail call i32 @j()    %cmp = icmp eq i32 %call, %call1  ; CHECK: bnec    br i1 %cmp, label %if.then, label %if.end  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal +; PIC: jialc $25, 0    tail call void @f(i32 signext -2)    br label %if.end  if.end:                                           ; preds = %if.then, %entry +; CHECK: jic $ra, 0    ret void  } @@ -28,19 +33,23 @@ declare void @f(i32 signext)  ; Function Attrs: define void @l2()  {  define void @l2()  {  entry: +; PIC: jialc $25, 0    %call = tail call i32 @k() +; PIC: jialc $25, 0    %call1 = tail call i32 @i()    %cmp = icmp eq i32 %call, %call1  ; CHECK beqc    br i1 %cmp, label %if.end, label %if.then  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal +; PIC: jialc $25, 0    tail call void @f(i32 signext -1)    br label %if.end  if.end:                                           ; preds = %entry, %if.then +; CHECK: jic $ra, 0    ret void  } @@ -49,18 +58,21 @@ declare i32 @i()  ; Function Attrs: nounwind  define void @l3()  {  entry: +; PIC: jialc $25, 0    %call = tail call i32 @k()    %cmp = icmp slt i32 %call, 0  ; CHECK : bgez    br i1 %cmp, label %if.then, label %if.end  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal +; PIC: jialc $25, 0    tail call void @f(i32 signext 0)    br label %if.end  if.end:                                           ; preds = %if.then, %entry +; CHECK: jic $ra, 0    ret void  } @@ -73,83 +85,122 @@ entry:    br i1 %cmp, label %if.then, label %if.end  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal    tail call void @f(i32 signext 1)    br label %if.end  if.end:                                           ; preds = %if.then, %entry +; CHECK: jic $ra, 0    ret void  }  ; Function Attrs: nounwind  define void @l5()  {  entry: +; PIC: jialc $25, 0    %call = tail call i32 @k() +; PIC: jialc $25, 0    %cmp = icmp sgt i32 %call, 0  ; CHECK: blezc    br i1 %cmp, label %if.then, label %if.end  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal +; PIC: jialc $25, 0    tail call void @f(i32 signext 2)     br label %if.end  if.end:                                           ; preds = %if.then, %entry +; CHECK: jic $ra, 0    ret void  }  ; Function Attrs: nounwind  define void @l6()  {  entry: +; PIC: jialc $25, 0    %call = tail call i32 @k() +; PIC: jialc $25, 0    %cmp = icmp sgt i32 %call, -1  ; CHECK: bltzc    br i1 %cmp, label %if.then, label %if.end  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal +; PIC: jialc $25, 0    tail call void @f(i32 signext 3)    br label %if.end  if.end:                                           ; preds = %if.then, %entry +; CHECK: jic $ra, 0    ret void  }  ; Function Attrs: nounwind  define void @l7()  {  entry: +; PIC: jialc $25, 0    %call = tail call i32 @k()    %cmp = icmp eq i32 %call, 0  ; CHECK: bnezc    br i1 %cmp, label %if.then, label %if.end  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal +; PIC: jialc $25, 0    tail call void @f(i32 signext 4)    br label %if.end  if.end:                                           ; preds = %if.then, %entry +; CHECK: jic $ra, 0    ret void  }  ; Function Attrs: nounwind  define void @l8()  {  entry: +; PIC: jialc $25, 0    %call = tail call i32 @k()    %cmp = icmp eq i32 %call, 0  ; CHECK: beqzc    br i1 %cmp, label %if.end, label %if.then  if.then:                                          ; preds = %entry: -; CHECK: nop -; CHECK: jal +; STATIC: nop +; STATIC: jal +; PIC: jialc $25, 0    tail call void @f(i32 signext 5)    br label %if.end  if.end:                                           ; preds = %entry, %if.then +; CHECK: jic $ra, 0    ret void  } + +define i32 @l9(i8* ()* %i) #0 { +entry: +  %i.addr = alloca i8* ()*, align 4 +  store i8* ()* %i, i8* ()** %i.addr, align 4 +; STATIC32: jal +; STATIC32: nop +; PIC: jialc $25, 0 +  %call = call i32 @k() +; PIC: jialc $25, 0 +  %cmp = icmp ne i32 %call, 0 +; CHECK: beqzc +  br i1 %cmp, label %if.then, label %if.end + +if.then:                                          ; preds = %entry +  %0 = load i8* ()*, i8* ()** %i.addr, align 4 +; CHECK: jialc $25, 0 +  %call1 = call i8* %0() +  br label %if.end + +if.end:                                           ; preds = %if.then, %entry +; CHECK: jic $ra, 0 +  ret i32 -1 +} diff --git a/llvm/test/CodeGen/Mips/llvm-ir/call.ll b/llvm/test/CodeGen/Mips/llvm-ir/call.ll index a4b03405f72..9b46d3b0960 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/call.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/call.ll @@ -1,18 +1,18 @@  ; Test the 'call' instruction and the tailcall variant.  ; FIXME: We should remove the need for -enable-mips-tail-calls -; RUN: llc -march=mips   -mcpu=mips32   -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -; RUN: llc -march=mips   -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -; RUN: llc -march=mips   -mcpu=mips32r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -; RUN: llc -march=mips   -mcpu=mips32r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -; RUN: llc -march=mips   -mcpu=mips32r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -; RUN: llc -march=mips   -mcpu=mips32r6 -mattr=+fp64,+nooddspreg -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -; RUN: llc -march=mips64 -mcpu=mips4    -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -; RUN: llc -march=mips64 -mcpu=mips64   -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -; RUN: llc -march=mips64 -mcpu=mips64r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -; RUN: llc -march=mips64 -mcpu=mips64r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -; RUN: llc -march=mips64 -mcpu=mips64r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 +; RUN: llc -march=mips   -mcpu=mips32 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C +; RUN: llc -march=mips   -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C +; RUN: llc -march=mips   -mcpu=mips32r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C +; RUN: llc -march=mips   -mcpu=mips32r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C +; RUN: llc -march=mips   -mcpu=mips32r6 -disable-mips-delay-filler -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C +; RUN: llc -march=mips   -mcpu=mips32r6 -mattr=+fp64,+nooddspreg -disable-mips-delay-filler -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C +; RUN: llc -march=mips64 -mcpu=mips4    -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C +; RUN: llc -march=mips64 -mcpu=mips64   -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C +; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C +; RUN: llc -march=mips64 -mcpu=mips64r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C +; RUN: llc -march=mips64 -mcpu=mips64r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C +; RUN: llc -march=mips64 -mcpu=mips64r6 -disable-mips-delay-filler -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=R6C  declare void @extern_void_void()  declare i32 @extern_i32_void() @@ -25,7 +25,8 @@ define i32 @call_void_void() {  ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) -; ALL:           jalr $[[TGT]] +; NOT-R6C:       jalr $[[TGT]] +; R6C:           jialc $[[TGT]], 0    call void @extern_void_void()    ret i32 0 @@ -38,7 +39,8 @@ define i32 @call_i32_void() {  ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) -; ALL:           jalr $[[TGT]] +; NOT-R6C:       jalr $[[TGT]] +; R6C:           jialc $[[TGT]], 0    %1 = call i32 @extern_i32_void()    %2 = add i32 %1, 1 @@ -55,9 +57,9 @@ define float @call_float_void() {  ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp) -; ALL:           jalr $[[TGT]] +; NOT-R6C:       jalr $[[TGT]] +; R6C:           jialc $[[TGT]], 0 -; O32:           move $gp, $[[GP]]    %1 = call float @extern_float_void()    %2 = fadd float %1, 1.0 @@ -71,8 +73,7 @@ define void @musttail_call_void_void() {  ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) -; NOT-R6:        jr $[[TGT]] -; R6:            r6.jr $[[TGT]] +; ALL:           jr $[[TGT]]    musttail call void @extern_void_void()    ret void @@ -85,8 +86,7 @@ define i32 @musttail_call_i32_void() {  ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) -; NOT-R6:        jr $[[TGT]] -; R6:            r6.jr $[[TGT]] +; ALL:           jr $[[TGT]]    %1 = musttail call i32 @extern_i32_void()    ret i32 %1 @@ -99,8 +99,7 @@ define float @musttail_call_float_void() {  ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp) -; NOT-R6:        jr $[[TGT]] -; R6:            r6.jr $[[TGT]] +; ALL:           jr $[[TGT]]    %1 = musttail call float @extern_float_void()    ret float %1 @@ -110,7 +109,9 @@ define i32 @indirect_call_void_void(void ()* %addr) {  ; ALL-LABEL: indirect_call_void_void:  ; ALL:           move $25, $4 -; ALL:           jalr $25 +; NOT-R6C:       jalr $25 +; R6C:           jialc $25, 0 +    call void %addr()    ret i32 0 @@ -120,7 +121,9 @@ define i32 @indirect_call_i32_void(i32 ()* %addr) {  ; ALL-LABEL: indirect_call_i32_void:  ; ALL:           move $25, $4 -; ALL:           jalr $25 +; NOT-R6C:       jalr $25 +; R6C:           jialc $25, 0 +    %1 = call i32 %addr()    %2 = add i32 %1, 1 @@ -131,7 +134,9 @@ define float @indirect_call_float_void(float ()* %addr) {  ; ALL-LABEL: indirect_call_float_void:  ; ALL:           move $25, $4 -; ALL:           jalr $25 +; NOT-R6C:       jalr $25 +; R6C:           jialc $25, 0 +    %1 = call float %addr()    %2 = fadd float %1, 1.0 @@ -178,7 +183,8 @@ define hidden void @thunk_undef_double(i32 %this, double %volume) unnamed_addr a  ; ALL-LABEL: thunk_undef_double:  ; O32: # implicit-def: %A2  ; O32: # implicit-def: %A3 -; ALL: jr $25 +; ALL:        jr $25 +    tail call void @undef_double(i32 undef, double undef) #8    ret void  } @@ -190,7 +196,8 @@ define i32 @jal_only_allows_symbols() {  ; ALL-NOT:       {{jal }}  ; ALL:           addiu $[[TGT:[0-9]+]], $zero, 1234  ; ALL-NOT:       {{jal }} -; ALL:           jalr $[[TGT]] +; NOT-R6C:       jalr $[[TGT]] +; R6C:           jialc $[[TGT]], 0  ; ALL-NOT:       {{jal }}    call void () inttoptr (i32 1234 to void ()*)() diff --git a/llvm/test/CodeGen/Mips/llvm-ir/indirectbr.ll b/llvm/test/CodeGen/Mips/llvm-ir/indirectbr.ll index debfeb35b21..4fdce5a0490 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/indirectbr.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/indirectbr.ll @@ -4,7 +4,7 @@  ; RUN: llc -march=mips   -mcpu=mips32r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6  ; RUN: llc -march=mips   -mcpu=mips32r3 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6  ; RUN: llc -march=mips   -mcpu=mips32r5 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6 -; RUN: llc -march=mips   -mcpu=mips32r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=R6 +; RUN: llc -march=mips   -mcpu=mips32r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=R6C  ; RUN: llc -march=mips64 -mcpu=mips4    -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6  ; RUN: llc -march=mips64 -mcpu=mips64   -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6  ; RUN: llc -march=mips64 -mcpu=mips64r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6 @@ -15,16 +15,19 @@  define i32 @br(i8 *%addr) {  ; ALL-LABEL: br:  ; NOT-R6:        jr $4 # <MCInst #{{[0-9]+}} JR -; R6:            jr $4 # <MCInst #{{[0-9]+}} JALR +; R6C:           jic $4, 0 # <MCInst #{{[0-9]+}} JIC +  ; ALL: $BB0_1: # %L1  ; NOT-R6:        jr $ra # <MCInst #{{[0-9]+}} JR  ; R6:            jr $ra # <MCInst #{{[0-9]+}} JALR +; R6C:           jr $ra # <MCInst #{{[0-9]+}} JALR  ; ALL:           addiu $2, $zero, 0  ; ALL: $BB0_2: # %L2  ; NOT-R6:        jr $ra # <MCInst #{{[0-9]+}} JR  ; R6:            jr $ra # <MCInst #{{[0-9]+}} JALR +; R6C:           jr $ra # <MCInst #{{[0-9]+}} JALR  ; ALL:           addiu $2, $zero, 1  entry: diff --git a/llvm/test/CodeGen/Mips/llvm-ir/ret.ll b/llvm/test/CodeGen/Mips/llvm-ir/ret.ll index 0561c24219c..de104f97551 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/ret.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/ret.ll @@ -11,19 +11,27 @@  ; RUN: llc -march=mips   -mcpu=mips32r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1 -check-prefix=NOT-R6  ; RUN: llc -march=mips   -mcpu=mips32r3 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1 -check-prefix=NOT-R6  ; RUN: llc -march=mips   -mcpu=mips32r5 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1 -check-prefix=NOT-R6 -; RUN: llc -march=mips   -mcpu=mips32r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1 -check-prefix=R6 +; RUN: llc -march=mips   -mcpu=mips32r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1 -check-prefix=R6C  ; RUN: llc -march=mips64 -mcpu=mips4    -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6  ; RUN: llc -march=mips64 -mcpu=mips64   -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6  ; RUN: llc -march=mips64 -mcpu=mips64r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6  ; RUN: llc -march=mips64 -mcpu=mips64r3 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6  ; RUN: llc -march=mips64 -mcpu=mips64r5 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6 -; RUN: llc -march=mips64 -mcpu=mips64r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=R6 + +; FIXME: for the test ret_double_0x0, the delay slot of jr cannot be filled +;        as mthc1 has unmodeled side effects. This is an artifact of our backend. +;        Force the delay slot filler off to check that the sequence jr $ra; nop is +;        turned into jic 0, $ra. + +; RUN: llc -march=mips64 -mcpu=mips64r6 -asm-show-inst -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 \ +; RUN:     -check-prefix=R6C  define void @ret_void() {  ; ALL-LABEL: ret_void:  ; NOT-R6-DAG:    jr $ra # <MCInst #{{[0-9]+}} JR  ; R6-DAG:        jr $ra # <MCInst #{{[0-9]+}} JALR +; R6C-DAG:       jic $ra, 0 # <MCInst #{{[0-9]+}} JIC    ret void  } @@ -173,6 +181,7 @@ define float @ret_float_0x3() {  ; NOT-R6-DAG:    jr $ra # <MCInst #{{[0-9]+}} JR  ; R6-DAG:        jr $ra # <MCInst #{{[0-9]+}} JALR +; R6C-DAG:       jic $ra, 0 # <MCInst #{{[0-9]+}} JIC  ; float constants are written as double constants    ret float 0x36b8000000000000 @@ -191,6 +200,7 @@ define double @ret_double_0x0() {  ; NOT-R6-DAG:    jr $ra # <MCInst #{{[0-9]+}} JR  ; R6-DAG:        jr $ra # <MCInst #{{[0-9]+}} JALR +; R6C-DAG:       jic $ra, 0 # <MCInst #{{[0-9]+}} JIC    ret double 0x0000000000000000  } @@ -204,6 +214,7 @@ define double @ret_double_0x3() {  ; NOT-R6-DAG:    jr $ra # <MCInst #{{[0-9]+}} JR  ; R6-DAG:        jr $ra # <MCInst #{{[0-9]+}} JALR +; R6C-DAG:       jic $ra, 0 # <MCInst #{{[0-9]+}} JIC    ret double 0x0000000000000003  } diff --git a/llvm/test/CodeGen/Mips/mips64-f128.ll b/llvm/test/CodeGen/Mips/mips64-f128.ll index d9c93810438..66a2f95cde2 100644 --- a/llvm/test/CodeGen/Mips/mips64-f128.ll +++ b/llvm/test/CodeGen/Mips/mips64-f128.ll @@ -1,11 +1,11 @@  ; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips4 -mattr=+soft-float -O1 \ -; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=C_CC_FMT +; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=C_CC_FMT -check-prefix=PRER6  ; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips64 -mattr=+soft-float -O1 \ -; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=C_CC_FMT +; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=C_CC_FMT -check-prefix=PRER6  ; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips64r2 -mattr=+soft-float -O1 \ -; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=C_CC_FMT +; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=C_CC_FMT -check-prefix=PRER6  ; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips64r6 -mattr=+soft-float -O1 \ -; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=CMP_CC_FMT +; RUN:     -disable-mips-delay-filler < %s | FileCheck %s -check-prefix=ALL -check-prefix=CMP_CC_FMT -check-prefix=R6  @gld0 = external global fp128  @gld1 = external global fp128 @@ -544,10 +544,11 @@ entry:  }  ; ALL-LABEL: load_LD_float: -; ALL: ld   $[[R0:[0-9]+]], %got_disp(gf1) -; ALL: lw   $4, 0($[[R0]]) -; ALL: ld   $25, %call16(__extendsftf2) -; ALL: jalr $25 +; ALL:   ld   $[[R0:[0-9]+]], %got_disp(gf1) +; ALL:   lw   $4, 0($[[R0]]) +; ALL:   ld   $25, %call16(__extendsftf2) +; PRER6: jalr $25 +; R6:    jialc $25, 0  define fp128 @load_LD_float() {  entry: @@ -557,10 +558,11 @@ entry:  }  ; ALL-LABEL: load_LD_double: -; ALL: ld   $[[R0:[0-9]+]], %got_disp(gd1) -; ALL: ld   $4, 0($[[R0]]) -; ALL: ld   $25, %call16(__extenddftf2) -; ALL: jalr $25 +; ALL:   ld   $[[R0:[0-9]+]], %got_disp(gd1) +; ALL:   ld   $4, 0($[[R0]]) +; ALL:   ld   $25, %call16(__extenddftf2) +; PRER6: jalr $25 +; R6:    jialc $25, 0  define fp128 @load_LD_double() {  entry: @@ -585,13 +587,14 @@ entry:  }  ; ALL-LABEL: store_LD_float: -; ALL: ld   $[[R0:[0-9]+]], %got_disp(gld1) -; ALL: ld   $4, 0($[[R0]]) -; ALL: ld   $5, 8($[[R0]]) -; ALL: ld   $25, %call16(__trunctfsf2) -; ALL: jalr $25 -; ALL: ld   $[[R1:[0-9]+]], %got_disp(gf1) -; ALL: sw   $2, 0($[[R1]]) +; ALL:   ld   $[[R0:[0-9]+]], %got_disp(gld1) +; ALL:   ld   $4, 0($[[R0]]) +; ALL:   ld   $5, 8($[[R0]]) +; ALL:   ld   $25, %call16(__trunctfsf2) +; PRER6: jalr $25 +; R6:    jialc $25, 0 +; ALL:   ld   $[[R1:[0-9]+]], %got_disp(gf1) +; ALL:   sw   $2, 0($[[R1]])  define void @store_LD_float() {  entry: @@ -602,13 +605,14 @@ entry:  }  ; ALL-LABEL: store_LD_double: -; ALL: ld   $[[R0:[0-9]+]], %got_disp(gld1) -; ALL: ld   $4, 0($[[R0]]) -; ALL: ld   $5, 8($[[R0]]) -; ALL: ld   $25, %call16(__trunctfdf2) -; ALL: jalr $25 -; ALL: ld   $[[R1:[0-9]+]], %got_disp(gd1) -; ALL: sd   $2, 0($[[R1]]) +; ALL:   ld   $[[R0:[0-9]+]], %got_disp(gld1) +; ALL:   ld   $4, 0($[[R0]]) +; ALL:   ld   $5, 8($[[R0]]) +; ALL:   ld   $25, %call16(__trunctfdf2) +; PRER6: jalr $25 +; R6:    jialc $25, 0 +; ALL:   ld   $[[R1:[0-9]+]], %got_disp(gd1) +; ALL:   sd   $2, 0($[[R1]])  define void @store_LD_double() {  entry: @@ -648,7 +652,8 @@ entry:  ; ALL:           move $[[R2:[0-9]+]], $9  ; ALL:           move $[[R3:[0-9]+]], $8  ; ALL:           ld   $25, %call16(__gttf2)($gp) -; ALL:           jalr $25 +; PRER6:         jalr $25 +; R6:            jialc $25, 0  ; C_CC_FMT:      slti $[[CC:[0-9]+]], $2, 1  ; C_CC_FMT:      movz $[[R1]], $[[R3]], $[[CC]] diff --git a/llvm/test/MC/Mips/mips32r6/valid.s b/llvm/test/MC/Mips/mips32r6/valid.s index 0cc8d4d91a3..8e759a0ee6b 100644 --- a/llvm/test/MC/Mips/mips32r6/valid.s +++ b/llvm/test/MC/Mips/mips32r6/valid.s @@ -165,6 +165,8 @@ a:          jr      $25              # CHECK: jr $25                 # encoding: [0x03,0x20,0x00,0x09]          jalr.hb $4               # CHECK: jalr.hb $4             # encoding: [0x00,0x80,0xfc,0x09]          jalr.hb $4, $5           # CHECK: jalr.hb $4, $5         # encoding: [0x00,0xa0,0x24,0x09] +        jialc   $15, 16161       # CHECK: jialc $15, 16161       # encoding: [0xf8,0x0f,0x3f,0x21] +        jic     $12, -3920       # CHECK: jic $12, -3920         # encoding: [0xd8,0x0c,0xf0,0xb0]          ldc2    $8, -701($at)    # CHECK: ldc2 $8, -701($1)      # encoding: [0x49,0xc8,0x0d,0x43]          lwc2    $18,-841($a2)    # CHECK: lwc2 $18, -841($6)     # encoding: [0x49,0x52,0x34,0xb7]          sdc2    $20,629($s2)     # CHECK: sdc2 $20, 629($18)     # encoding: [0x49,0xf4,0x92,0x75]  | 

