Index: lib/Target/Mips/Mips64r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64r6InstrInfo.td +++ lib/Target/Mips/Mips64r6InstrInfo.td @@ -88,6 +88,23 @@ list Defs = [AT]; } +class BGEC64_DESC : CMP_BC_DESC_BASE<"bgec", brtarget, GPR64Opnd>; +class BGEUC64_DESC : CMP_BC_DESC_BASE<"bgeuc", brtarget, GPR64Opnd>; +class BEQC64_DESC : CMP_BC_DESC_BASE<"beqc", brtarget, GPR64Opnd>; +class BNEC64_DESC : CMP_BC_DESC_BASE<"bnec", brtarget, GPR64Opnd>; + +class BLTC64_DESC : CMP_BC_DESC_BASE<"bltc", brtarget, GPR64Opnd>; +class BLTUC64_DESC : CMP_BC_DESC_BASE<"bltuc", brtarget, GPR64Opnd>; + +class BLTZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"bltzc", brtarget, GPR64Opnd>; +class BGEZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgezc", brtarget, GPR64Opnd>; + +class BLEZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"blezc", brtarget, GPR64Opnd>; +class BGTZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgtzc", brtarget, GPR64Opnd>; + +class BEQZC64_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21, GPR64Opnd>; +class BNEZC64_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21, GPR64Opnd>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -123,9 +140,29 @@ def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64; def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64; } + +/// Jump and Branch Instructions let isCodeGenOnly = 1 in { def JIALC64 : JIALC_ENC, JIALC64_DESC, ISA_MIPS64R6; def JIC64 : JIC_ENC, JIC64_DESC, ISA_MIPS64R6; + +def BLEZC64 : BLEZC_ENC, BLEZC64_DESC, ISA_MIPS64R6, GPR_64; +def BGEZC64 : BGEZC_ENC, BGEZC64_DESC, ISA_MIPS64R6, GPR_64; +def BGEC64 : BGEC_ENC, BGEC64_DESC, ISA_MIPS64R6, GPR_64; + +def BGTZC64 : BGTZC_ENC, BGTZC64_DESC, ISA_MIPS64R6, GPR_64; +def BLTZC64 : BLTZC_ENC, BLTZC64_DESC, ISA_MIPS64R6, GPR_64; +def BLTC64 : BLTC_ENC, BLTC64_DESC, ISA_MIPS64R6, GPR_64; + +def BGEUC64 : BGEUC_ENC, BGEUC64_DESC, ISA_MIPS64R6, GPR_64; + +def BLTUC64 : BLTUC_ENC, BLTUC64_DESC, ISA_MIPS64R6, GPR_64; + +def BEQC64 : BEQC_ENC, BEQC64_DESC, ISA_MIPS64R6, GPR_64; +def BNEC64 : BNEC_ENC, BNEC64_DESC, ISA_MIPS64R6, GPR_64; + +def BEQZC64 : BEQZC_ENC, BEQZC64_DESC, ISA_MIPS64R6, GPR_64; +def BNEZC64 : BNEZC_ENC, BNEZC64_DESC, ISA_MIPS64R6, GPR_64; } //===----------------------------------------------------------------------===// // Index: lib/Target/Mips/MipsInstrInfo.cpp =================================================================== --- lib/Target/Mips/MipsInstrInfo.cpp +++ lib/Target/Mips/MipsInstrInfo.cpp @@ -314,6 +314,18 @@ return Mips::BLTUC; case Mips::BLTZ: return Mips::BLTZC; + case Mips::BEQ64: + return Mips::BEQC64; + case Mips::BNE64: + return Mips::BNEC64; + case Mips::BGEZ64: + return Mips::BGEZC64; + case Mips::BGTZ64: + return Mips::BGTZC64; + case Mips::BLEZ64: + return Mips::BLEZC64; + case Mips::BLTZ64: + return Mips::BLTZC64; // 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: @@ -379,10 +391,7 @@ // 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. - // 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. + // Certain atomic sequences for MIPS64 generate references to Mips::ZERO. bool BranchWithZeroOperand = (I->isBranch() && !I->isPseudo() && I->getOperand(1).isReg() && (I->getOperand(1).getReg() == Mips::ZERO || @@ -402,14 +411,26 @@ case Mips::BLTC: NewOpc = Mips::BLTZC; break; - } + case Mips::BEQC64: + NewOpc = Mips::BEQZC64; + break; + case Mips::BNEC64: + NewOpc = Mips::BNEZC64; + break; + case Mips::BLTC64: + NewOpc = Mips::BLTZC64; + break; + case Mips::BGEC64: + NewOpc = Mips::BGEZC64; + break; + } } MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); // 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 - // implicit operand as copying the implicit operations of the instructio we're + // implicit operand as copying the implicit operations of the instruction we're // looking at will give us the correct flags. if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || NewOpc == Mips::JIALC64) { Index: lib/Target/Mips/MipsSEInstrInfo.cpp =================================================================== --- lib/Target/Mips/MipsSEInstrInfo.cpp +++ lib/Target/Mips/MipsSEInstrInfo.cpp @@ -428,6 +428,18 @@ case Mips::BGEZC: return Mips::BLTZC; case Mips::BLTZC: return Mips::BGEZC; case Mips::BLEZC: return Mips::BGTZC; + case Mips::BEQZC64: return Mips::BNEZC64; + case Mips::BNEZC64: return Mips::BEQZC64; + case Mips::BEQC64: return Mips::BNEC64; + case Mips::BNEC64: return Mips::BEQC64; + case Mips::BGTZC64: return Mips::BLEZC64; + case Mips::BGEZC64: return Mips::BLTZC64; + case Mips::BLTZC64: return Mips::BGEZC64; + case Mips::BLEZC64: return Mips::BGTZC64; + case Mips::BGEUC64: return Mips::BLTUC64; + case Mips::BLTUC64: return Mips::BGEUC64; + case Mips::BGEC64: return Mips::BLTC64; + case Mips::BLTC64: return Mips::BGEC64; } } @@ -506,7 +518,11 @@ Opc == Mips::BGEC || Opc == Mips::BLTUC || Opc == Mips::BGEUC || Opc == Mips::BGTZC || Opc == Mips::BLEZC || Opc == Mips::BGEZC || Opc == Mips::BLTZC || Opc == Mips::BEQZC || Opc == Mips::BNEZC || - Opc == Mips::BC) ? Opc : 0; + Opc == Mips::BEQC64 || Opc == Mips::BNEC64 || Opc == Mips::BGEZC64 || + Opc == Mips::BLTZC64 || Opc == Mips::BLEZC64 || + Opc == Mips::BGTZC64 || Opc == Mips::BLTC64 || Opc == Mips::BGEC64 || + Opc == Mips::BGEUC64 || Opc == Mips::BLTUC64 || Opc == Mips::BC) + ? Opc : 0; } void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, Index: test/CodeGen/Mips/compactbranches/compact-branches-64.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/compactbranches/compact-branches-64.ll @@ -0,0 +1,200 @@ +; RUN: llc -march=mips64el -mcpu=mips64r6 -disable-mips-delay-filler -asm-show-inst < %s | FileCheck %s + +; Function Attrs: nounwind +define void @l() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() +; CHECK: JIALC64 + %call1 = tail call i64 @j() + %cmp = icmp eq i64 %call, %call1 +; CHECK: BNEC64 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: +; CHECK: JIALC64 + tail call void @f(i64 signext -2) + br label %if.end + +if.end: ; preds = %if.then, %entry +; CHECK: JIC64 + ret void +} + +declare i64 @k() + +declare i64 @j() + +declare void @f(i64 signext) + +; Function Attrs: define void @l2() { +define void @l2() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() +; CHECK: JIALC64 + %call1 = tail call i64 @i() + %cmp = icmp eq i64 %call, %call1 +; CHECK: BEQC64 + br i1 %cmp, label %if.end, label %if.then + +if.then: ; preds = %entry: + + +; CHECK: JIALC64 + tail call void @f(i64 signext -1) + br label %if.end + +if.end: ; preds = %entry, %if.then +; CHECK: JIC64 + ret void +} + +declare i64 @i() + +; Function Attrs: nounwind +define void @l3() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() + %cmp = icmp slt i64 %call, 0 +; CHECK: BGEZC64 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: + + +; CHECK: JIALC64 + tail call void @f(i64 signext 0) + br label %if.end + +if.end: ; preds = %if.then, %entry +; CHECK: JIC64 + ret void +} + +; Function Attrs: nounwind +define void @l4() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() + %cmp = icmp slt i64 %call, 1 +; CHECK: BGTZC64 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: + + +; CHECK: JIALC64 + tail call void @f(i64 signext 1) + br label %if.end + +if.end: ; preds = %if.then, %entry +; CHECK: JIC64 + ret void +} + +; Function Attrs: nounwind +define void @l5() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() +; CHECK: BLEZC64 + %cmp = icmp sgt i64 %call, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: + + +; CHECK: JIALC64 + tail call void @f(i64 signext 2) + br label %if.end + +if.end: ; preds = %if.then, %entry +; CHECK: JIC64 + ret void +} + +; Function Attrs: nounwind +define void @l6() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() +; CHECK: BLTZC64 + %cmp = icmp sgt i64 %call, -1 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: + + +; CHECK: JIALC64 + tail call void @f(i64 signext 3) + br label %if.end + +if.end: ; preds = %if.then, %entry +; CHECK: JIC64 + ret void +} + +; Function Attrs: nounwind +define void @l7() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() + %cmp = icmp eq i64 %call, 0 +; CHECK: BNEZC64 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: + + +; CHECK: JIALC64 + tail call void @f(i64 signext 4) + br label %if.end + +if.end: ; preds = %if.then, %entry +; CHECK: JIC64 + ret void +} + +; Function Attrs: nounwind +define void @l8() { +entry: +; CHECK: JIALC64 + %call = tail call i64 @k() + %cmp = icmp eq i64 %call, 0 +; CHECK: BEQZC64 + br i1 %cmp, label %if.end, label %if.then + +if.then: ; preds = %entry: + + +; CHECK: JIALC64 + tail call void @f(i64 signext 5) + br label %if.end + +if.end: ; preds = %entry, %if.then +; CHECK: JIC64 + ret void +} + +define i64 @l9(i8* ()* %i) #0 { +entry: + %i.addr = alloca i8* ()*, align 4 + store i8* ()* %i, i8* ()** %i.addr, align 4 +; CHECK: JIALC64 + %call = call i64 @k() + %cmp = icmp ne i64 %call, 0 +; CHECK: BEQZC64 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + %0 = load i8* ()*, i8* ()** %i.addr, align 4 +; CHECK: JIALC64 + %call1 = call i8* %0() + br label %if.end + +if.end: ; preds = %if.then, %entry +; CHECK: JIC64 + ret i64 -1 +}