[llvm] c30c291 - [SPARC] Lower BR_CC to BPr on 64-bit target whenever possible

Brad Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 26 15:56:12 PDT 2023


Author: Brad Smith
Date: 2023-04-26T18:56:00-04:00
New Revision: c30c29188770d2981a3dca826768319e1138b124

URL: https://github.com/llvm/llvm-project/commit/c30c29188770d2981a3dca826768319e1138b124
DIFF: https://github.com/llvm/llvm-project/commit/c30c29188770d2981a3dca826768319e1138b124.diff

LOG: [SPARC] Lower BR_CC to BPr on 64-bit target whenever possible

On 64-bit target, when doing i64 BR_CC where one of the comparison operands is a
constant zero, try to fold the compare and BPcc into a BPr instruction.

For all integers, EQ and NE comparison are available, additionally for signed
integers, GT, GE, LT, and LE is also available.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D142461

Added: 
    

Modified: 
    llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
    llvm/lib/Target/Sparc/SparcISelLowering.cpp
    llvm/lib/Target/Sparc/SparcISelLowering.h
    llvm/lib/Target/Sparc/SparcInstr64Bit.td
    llvm/lib/Target/Sparc/SparcInstrAliases.td
    llvm/lib/Target/Sparc/SparcInstrFormats.td
    llvm/lib/Target/Sparc/SparcInstrInfo.cpp
    llvm/lib/Target/Sparc/SparcInstrInfo.td
    llvm/test/CodeGen/SPARC/branches-relax.ll
    llvm/test/CodeGen/SPARC/branches-v9.ll
    llvm/test/CodeGen/SPARC/missinglabel.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
index b2e784a0c2545..51a6732d05c6d 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
@@ -197,6 +197,10 @@ void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
     // Make sure CC is a cp conditional flag.
     CC = (CC < SPCC::CPCC_BEGIN) ? (CC + SPCC::CPCC_BEGIN) : CC;
     break;
+  case SP::BPR:
+  case SP::BPRA:
+  case SP::BPRNT:
+  case SP::BPRANT:
   case SP::MOVRri:
   case SP::MOVRrr:
   case SP::FMOVRS:

diff  --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 660c141369364..13e18734c9179 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1977,6 +1977,8 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case SPISD::BRFCC:           return "SPISD::BRFCC";
   case SPISD::BRFCC_V9:
     return "SPISD::BRFCC_V9";
+  case SPISD::BR_REG:
+    return "SPISD::BR_REG";
   case SPISD::SELECT_ICC:      return "SPISD::SELECT_ICC";
   case SPISD::SELECT_XCC:      return "SPISD::SELECT_XCC";
   case SPISD::SELECT_FCC:      return "SPISD::SELECT_FCC";
@@ -2582,7 +2584,7 @@ static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG,
 
 static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
                           const SparcTargetLowering &TLI, bool hasHardQuad,
-                          bool isV9) {
+                          bool isV9, bool is64Bit) {
   SDValue Chain = Op.getOperand(0);
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
   SDValue LHS = Op.getOperand(2);
@@ -2599,6 +2601,15 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
   // Get the condition flag.
   SDValue CompareFlag;
   if (LHS.getValueType().isInteger()) {
+    // On V9 processors running in 64-bit mode, if CC compares two `i64`s
+    // and the RHS is zero we might be able to use a specialized branch.
+    const ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS);
+    if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 && RHSC &&
+        RHSC->isZero() && !ISD::isUnsignedIntSetCC(CC))
+      return DAG.getNode(SPISD::BR_REG, dl, MVT::Other, Chain, Dest,
+                         DAG.getConstant(intCondCCodeToRcond(CC), dl, MVT::i32),
+                         LHS);
+
     CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
     if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
     if (isV9)
@@ -3213,7 +3224,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::UINT_TO_FP:         return LowerUINT_TO_FP(Op, DAG, *this,
                                                        hasHardQuad);
   case ISD::BR_CC:
-    return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9);
+    return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit);
   case ISD::SELECT_CC:
     return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit);
   case ISD::VASTART:            return LowerVASTART(Op, DAG, *this);

diff  --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index 0af20271f1b23..5504dcd464fb2 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -31,6 +31,7 @@ namespace llvm {
     BPXCC,    // Branch to dest on xcc condition, with prediction (64-bit only).
     BRFCC,    // Branch to dest on fcc condition
     BRFCC_V9, // Branch to dest on fcc condition (v9 variant).
+    BR_REG,   // Branch to dest using the comparison of a register with zero.
     SELECT_ICC, // Select between two values using the current ICC flags.
     SELECT_XCC, // Select between two values using the current XCC flags.
     SELECT_FCC, // Select between two values using the current FCC flags.

diff  --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
index 77f203fd0d680..0a64794874188 100644
--- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
@@ -356,15 +356,15 @@ def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
 
 // Branch On integer register with Prediction (BPr).
 let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in
-multiclass BranchOnReg<bits<3> cond, string OpcStr> {
-  def napt : F2_4<cond, 0, 1, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
-             !strconcat(OpcStr, " $rs1, $imm16"), []>;
-  def apt  : F2_4<cond, 1, 1, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
-             !strconcat(OpcStr, ",a $rs1, $imm16"), []>;
-  def napn  : F2_4<cond, 0, 0, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
-             !strconcat(OpcStr, ",pn $rs1, $imm16"), []>;
-  def apn : F2_4<cond, 1, 0, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
-             !strconcat(OpcStr, ",a,pn $rs1, $imm16"), []>;
+multiclass BranchOnReg<list<dag> CCPattern> {
+  def R    : F2_4<0, 1, (outs), (ins bprtarget16:$imm16, RegCCOp:$rcond, I64Regs:$rs1),
+             "br$rcond $rs1, $imm16", CCPattern>;
+  def RA   : F2_4<1, 1, (outs), (ins bprtarget16:$imm16, RegCCOp:$rcond, I64Regs:$rs1),
+             "br$rcond,a $rs1, $imm16", []>;
+  def RNT  : F2_4<0, 0, (outs), (ins bprtarget16:$imm16, RegCCOp:$rcond, I64Regs:$rs1),
+             "br$rcond,pn $rs1, $imm16", []>;
+  def RANT : F2_4<1, 0, (outs), (ins bprtarget16:$imm16, RegCCOp:$rcond, I64Regs:$rs1),
+             "br$rcond,a,pn $rs1, $imm16", []>;
 }
 
 multiclass bpr_alias<string OpcStr, Instruction NAPT, Instruction APT> {
@@ -374,19 +374,8 @@ multiclass bpr_alias<string OpcStr, Instruction NAPT, Instruction APT> {
                   (APT I64Regs:$rs1, bprtarget16:$imm16), 0>;
 }
 
-defm BPZ   : BranchOnReg<0b001, "brz">;
-defm BPLEZ : BranchOnReg<0b010, "brlez">;
-defm BPLZ  : BranchOnReg<0b011, "brlz">;
-defm BPNZ  : BranchOnReg<0b101, "brnz">;
-defm BPGZ  : BranchOnReg<0b110, "brgz">;
-defm BPGEZ : BranchOnReg<0b111, "brgez">;
-
-defm : bpr_alias<"brz",   BPZnapt,   BPZapt  >;
-defm : bpr_alias<"brlez", BPLEZnapt, BPLEZapt>;
-defm : bpr_alias<"brlz",  BPLZnapt,  BPLZapt >;
-defm : bpr_alias<"brnz",  BPNZnapt,  BPNZapt >;
-defm : bpr_alias<"brgz",  BPGZnapt,  BPGZapt >;
-defm : bpr_alias<"brgez", BPGEZnapt, BPGEZapt>;
+let Predicates = [Is64Bit] in
+  defm BP : BranchOnReg<[(SPbrreg bb:$imm16, imm:$rcond, i64:$rs1)]>;
 
 // Move integer register on register condition (MOVr).
 let Predicates = [Is64Bit], Constraints = "$f = $rd" in {

diff  --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td
index f10021321406c..01c3696cc7bca 100644
--- a/llvm/lib/Target/Sparc/SparcInstrAliases.td
+++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td
@@ -295,6 +295,36 @@ multiclass cp_cond_alias<string cond, int condVal> {
 
 // Instruction aliases for register conditional branches and moves.
 multiclass reg_cond_alias<string rcond, int condVal> {
+  // br<rcond> $rs1, $imm
+  def : InstAlias<!strconcat(!strconcat("br", rcond), " $rs1, $imm"),
+                  (BPR bprtarget16:$imm, condVal, I64Regs:$rs1)>,
+                  Requires<[Is64Bit]>;
+
+  // br<rcond>,pt $rs1, $imm
+  def : InstAlias<!strconcat(!strconcat("br", rcond), ",pt $rs1, $imm"),
+                  (BPR bprtarget16:$imm, condVal, I64Regs:$rs1)>,
+                  Requires<[Is64Bit]>;
+
+  // br<rcond>,pn $rs1, $imm
+  def : InstAlias<!strconcat(!strconcat("br", rcond), ",pn $rs1, $imm"),
+                  (BPRNT bprtarget16:$imm, condVal, I64Regs:$rs1)>,
+                  Requires<[Is64Bit]>;
+
+  // br<rcond>,a $rs1, $imm
+  def : InstAlias<!strconcat(!strconcat("br", rcond), ",a $rs1, $imm"),
+                  (BPRA bprtarget16:$imm, condVal, I64Regs:$rs1)>,
+                  Requires<[Is64Bit]>;
+
+  // br<rcond>,a,pt $rs1, $imm
+  def : InstAlias<!strconcat(!strconcat("br", rcond), ",a,pt $rs1, $imm"),
+                  (BPRA bprtarget16:$imm, condVal, I64Regs:$rs1)>,
+                  Requires<[Is64Bit]>;
+
+  // br<rcond>,a,pn $rs1, $imm
+  def : InstAlias<!strconcat(!strconcat("br", rcond), ",a,pn $rs1, $imm"),
+                  (BPRANT bprtarget16:$imm, condVal, I64Regs:$rs1)>,
+                  Requires<[Is64Bit]>;
+
   defm : regcond_mov_alias<rcond, condVal,
                             MOVRrr, MOVRri,
                             FMOVRS, FMOVRD, FMOVRQ>,

diff  --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td
index 522dcd96a1125..c67b591ab98ac 100644
--- a/llvm/lib/Target/Sparc/SparcInstrFormats.td
+++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td
@@ -83,17 +83,18 @@ class F2_3<bits<3> op2Val, bit annul, bit pred,
   let Inst{18-0}  = imm19;
 }
 
-class F2_4<bits<3> cond, bit annul, bit pred, dag outs, dag ins,
+class F2_4<bit annul, bit pred, dag outs, dag ins,
            string asmstr, list<dag> pattern, InstrItinClass itin = NoItinerary>
    : InstSP<outs, ins, asmstr, pattern, itin> {
   bits<16> imm16;
   bits<5>  rs1;
+  bits<3>  rcond;
 
   let op          = 0;    // op = 0
 
   let Inst{29}    = annul;
   let Inst{28}    = 0;
-  let Inst{27-25} = cond;
+  let Inst{27-25} = rcond;
   let Inst{24-22} = 0b011;
   let Inst{21-20} = imm16{15-14};
   let Inst{19}    = pred;

diff  --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index a3a09a36f1dd4..90662cd87dcf1 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -32,6 +32,10 @@ static cl::opt<unsigned> BPccDisplacementBits(
     "sparc-bpcc-offset-bits", cl::Hidden, cl::init(19),
     cl::desc("Restrict range of BPcc/FBPfcc instructions (DEBUG)"));
 
+static cl::opt<unsigned>
+    BPrDisplacementBits("sparc-bpr-offset-bits", cl::Hidden, cl::init(16),
+                        cl::desc("Restrict range of BPr instructions (DEBUG)"));
+
 // Pin the vtable to this file.
 void SparcInstrInfo::anchor() {}
 
@@ -166,6 +170,11 @@ static bool isI64CondBranchOpcode(int Opc) {
          Opc == SP::BPXCCANT;
 }
 
+static bool isRegCondBranchOpcode(int Opc) {
+  return Opc == SP::BPR || Opc == SP::BPRA || Opc == SP::BPRNT ||
+         Opc == SP::BPRANT;
+}
+
 static bool isFCondBranchOpcode(int Opc) {
   return Opc == SP::FBCOND || Opc == SP::FBCONDA || Opc == SP::FBCOND_V9 ||
          Opc == SP::FBCONDA_V9;
@@ -173,7 +182,7 @@ static bool isFCondBranchOpcode(int Opc) {
 
 static bool isCondBranchOpcode(int Opc) {
   return isI32CondBranchOpcode(Opc) || isI64CondBranchOpcode(Opc) ||
-         isFCondBranchOpcode(Opc);
+         isRegCondBranchOpcode(Opc) || isFCondBranchOpcode(Opc);
 }
 
 static bool isIndirectBranchOpcode(int Opc) {
@@ -190,6 +199,13 @@ static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,
   Cond.push_back(MachineOperand::CreateImm(Opc));
   Cond.push_back(MachineOperand::CreateImm(CC));
 
+  // Branch on register contents need another argument to indicate
+  // the register it branches on.
+  if (isRegCondBranchOpcode(Opc)) {
+      Register Reg = LastInst->getOperand(2).getReg();
+      Cond.push_back(MachineOperand::CreateReg(Reg, false));
+  }
+
   Target = LastInst->getOperand(0).getMBB();
 }
 
@@ -217,6 +233,10 @@ SparcInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
   case SP::BPFCCANT:
   case SP::FBCOND_V9:
   case SP::FBCONDA_V9:
+  case SP::BPR:
+  case SP::BPRA:
+  case SP::BPRNT:
+  case SP::BPRANT:
       return MI.getOperand(0).getMBB();
   }
 }
@@ -311,8 +331,8 @@ unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB,
                                       const DebugLoc &DL,
                                       int *BytesAdded) const {
   assert(TBB && "insertBranch must not be told to insert a fallthrough");
-  assert((Cond.size() <= 2) &&
-         "Sparc branch conditions should have at most two components!");
+  assert((Cond.size() <= 3) &&
+         "Sparc branch conditions should have at most three components!");
 
   if (Cond.empty()) {
     assert(!FBB && "Unconditional branch with multiple successors!");
@@ -325,7 +345,12 @@ unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB,
   // Conditional branch
   unsigned Opc = Cond[0].getImm();
   unsigned CC = Cond[1].getImm();
-  BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);
+  if (isRegCondBranchOpcode(Opc)) {
+    Register Reg = Cond[2].getReg();
+    BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC).addReg(Reg);
+  } else {
+    BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);
+  }
 
   if (!FBB) {
     if (BytesAdded)
@@ -367,7 +392,7 @@ unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,
 
 bool SparcInstrInfo::reverseBranchCondition(
     SmallVectorImpl<MachineOperand> &Cond) const {
-  assert(Cond.size() <= 2);
+  assert(Cond.size() <= 3);
   SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[1].getImm());
   Cond[1].setImm(GetOppositeBranchCondition(CC));
   return false;
@@ -399,6 +424,12 @@ bool SparcInstrInfo::isBranchOffsetInRange(unsigned BranchOpc,
   case SP::FBCOND_V9:
   case SP::FBCONDA_V9:
     return isIntN(BPccDisplacementBits, Offset >> 2);
+
+  case SP::BPR:
+  case SP::BPRA:
+  case SP::BPRNT:
+  case SP::BPRANT:
+    return isIntN(BPrDisplacementBits, Offset >> 2);
   }
 
   llvm_unreachable("Unknown branch instruction!");

diff  --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index c10e4a0efa339..a55b7c3f5f18b 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -224,6 +224,8 @@ def SDTSPcmpfcc :
 SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisSameAs<0, 1>]>;
 def SDTSPbrcc :
 SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>;
+def SDTSPbrreg :
+SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>, SDTCisVT<2, i64>]>;
 def SDTSPselectcc :
 SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>]>;
 def SDTSPselectreg :
@@ -253,6 +255,7 @@ def SPbpicc : SDNode<"SPISD::BPICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
 def SPbpxcc : SDNode<"SPISD::BPXCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
 def SPbrfcc : SDNode<"SPISD::BRFCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
 def SPbrfccv9 : SDNode<"SPISD::BRFCC_V9", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
+def SPbrreg : SDNode<"SPISD::BR_REG", SDTSPbrreg, [SDNPHasChain, SDNPInGlue]>;
 
 def SPhi    : SDNode<"SPISD::Hi", SDTIntUnaryOp>;
 def SPlo    : SDNode<"SPISD::Lo", SDTIntUnaryOp>;

diff  --git a/llvm/test/CodeGen/SPARC/branches-relax.ll b/llvm/test/CodeGen/SPARC/branches-relax.ll
index 11324faf1146f..334a7ebfb6739 100644
--- a/llvm/test/CodeGen/SPARC/branches-relax.ll
+++ b/llvm/test/CodeGen/SPARC/branches-relax.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=sparc64 -sparc-bpcc-offset-bits=4 | FileCheck --check-prefix=SPARC64 %s
+; RUN: llc < %s -mtriple=sparc64 -sparc-bpcc-offset-bits=4 -sparc-bpr-offset-bits=4 | FileCheck --check-prefix=SPARC64 %s
 
 define i32 @branch_relax_int(i32 %in) {
 ; SPARC64-LABEL: branch_relax_int:
@@ -53,6 +53,57 @@ false:
   ret i32 0
 }
 
+define i64 @branch_relax_reg(i64 %in) {
+; SPARC64-LABEL: branch_relax_reg:
+; SPARC64:         .cfi_startproc
+; SPARC64-NEXT:  ! %bb.0:
+; SPARC64-NEXT:    save %sp, -128, %sp
+; SPARC64-NEXT:    .cfi_def_cfa_register %fp
+; SPARC64-NEXT:    .cfi_window_save
+; SPARC64-NEXT:    .cfi_register %o7, %i7
+; SPARC64-NEXT:    brnz %i0, .LBB1_1
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    ba .LBB1_2
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:  .LBB1_1: ! %false
+; SPARC64-NEXT:    !APP
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    !NO_APP
+; SPARC64-NEXT:    ret
+; SPARC64-NEXT:    restore %g0, %g0, %o0
+; SPARC64-NEXT:  .LBB1_2: ! %true
+; SPARC64-NEXT:    mov 4, %i0
+; SPARC64-NEXT:    !APP
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    nop
+; SPARC64-NEXT:    !NO_APP
+; SPARC64-NEXT:    ret
+; SPARC64-NEXT:    restore
+  %tst = icmp eq i64 %in, 0
+  br i1 %tst, label %true, label %false
+
+true:
+  call void asm sideeffect "nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop", ""()
+  ret i64 4
+
+false:
+  call void asm sideeffect "nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop\0A\09nop", ""()
+  ret i64 0
+}
+
 define float @branch_relax_float(float %in) {
 ; SPARC64-LABEL: branch_relax_float:
 ; SPARC64:         .cfi_startproc
@@ -61,20 +112,20 @@ define float @branch_relax_float(float %in) {
 ; SPARC64-NEXT:    .cfi_def_cfa_register %fp
 ; SPARC64-NEXT:    .cfi_window_save
 ; SPARC64-NEXT:    .cfi_register %o7, %i7
-; SPARC64-NEXT:    sethi %h44(.LCPI1_0), %i0
-; SPARC64-NEXT:    add %i0, %m44(.LCPI1_0), %i0
+; SPARC64-NEXT:    sethi %h44(.LCPI2_0), %i0
+; SPARC64-NEXT:    add %i0, %m44(.LCPI2_0), %i0
 ; SPARC64-NEXT:    sllx %i0, 12, %i0
-; SPARC64-NEXT:    ld [%i0+%l44(.LCPI1_0)], %f0
+; SPARC64-NEXT:    ld [%i0+%l44(.LCPI2_0)], %f0
 ; SPARC64-NEXT:    fcmps %fcc0, %f1, %f0
-; SPARC64-NEXT:    fbe %fcc0, .LBB1_1
+; SPARC64-NEXT:    fbe %fcc0, .LBB2_1
 ; SPARC64-NEXT:    nop
-; SPARC64-NEXT:    ba .LBB1_2
+; SPARC64-NEXT:    ba .LBB2_2
 ; SPARC64-NEXT:    nop
-; SPARC64-NEXT:  .LBB1_1: ! %true
-; SPARC64-NEXT:    sethi %h44(.LCPI1_1), %i0
-; SPARC64-NEXT:    add %i0, %m44(.LCPI1_1), %i0
+; SPARC64-NEXT:  .LBB2_1: ! %true
+; SPARC64-NEXT:    sethi %h44(.LCPI2_1), %i0
+; SPARC64-NEXT:    add %i0, %m44(.LCPI2_1), %i0
 ; SPARC64-NEXT:    sllx %i0, 12, %i0
-; SPARC64-NEXT:    ld [%i0+%l44(.LCPI1_1)], %f0
+; SPARC64-NEXT:    ld [%i0+%l44(.LCPI2_1)], %f0
 ; SPARC64-NEXT:    !APP
 ; SPARC64-NEXT:    nop
 ; SPARC64-NEXT:    nop
@@ -87,7 +138,7 @@ define float @branch_relax_float(float %in) {
 ; SPARC64-NEXT:    !NO_APP
 ; SPARC64-NEXT:    ret
 ; SPARC64-NEXT:    restore
-; SPARC64-NEXT:  .LBB1_2: ! %false
+; SPARC64-NEXT:  .LBB2_2: ! %false
 ; SPARC64-NEXT:    !APP
 ; SPARC64-NEXT:    nop
 ; SPARC64-NEXT:    nop

diff  --git a/llvm/test/CodeGen/SPARC/branches-v9.ll b/llvm/test/CodeGen/SPARC/branches-v9.ll
index c1c765d6025c8..6b76888df065a 100644
--- a/llvm/test/CodeGen/SPARC/branches-v9.ll
+++ b/llvm/test/CodeGen/SPARC/branches-v9.ll
@@ -1,13 +1,15 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=sparcv9 -disable-sparc-leaf-proc | FileCheck %s
 
-;; 1. When emitting code for v9, branches should always explicitly specify
+;; 1. When emitting code for v9, CCR branches should always explicitly specify
 ;;    %icc or %xcc.
-;; 2. There should never be a `ba` that jumps into two instructions immediately
+;; 2. Branches on the result of a 64-bit compare with constant zero should be
+;;    lowered into an instruction in the BPr class (§A.3 in V9 spec).
+;; 3. There should never be a `ba` that jumps into two instructions immediately
 ;;    following it.
 
-define void @i(i32 signext %sel) {
-; CHECK-LABEL: i:
+define void @bricc(i32 signext %sel) {
+; CHECK-LABEL: bricc:
 ; CHECK:         .cfi_startproc
 ; CHECK-NEXT:  ! %bb.0: ! %entry
 ; CHECK-NEXT:    save %sp, -176, %sp
@@ -47,26 +49,68 @@ end:
   ret void
 }
 
-define void @l(i64 %sel) {
-; CHECK-LABEL: l:
+define void @brxcc(i64 %sel) {
+; CHECK-LABEL: brxcc:
 ; CHECK:         .cfi_startproc
 ; CHECK-NEXT:  ! %bb.0: ! %entry
 ; CHECK-NEXT:    save %sp, -176, %sp
 ; CHECK-NEXT:    .cfi_def_cfa_register %fp
 ; CHECK-NEXT:    .cfi_window_save
 ; CHECK-NEXT:    .cfi_register %o7, %i7
-; CHECK-NEXT:    cmp %i0, 0
-; CHECK-NEXT:    be %xcc, .LBB1_2
+; CHECK-NEXT:    cmp %i0, 1
+; CHECK-NEXT:    bne %xcc, .LBB1_2
+; CHECK-NEXT:    nop
+; CHECK-NEXT:  ! %bb.1: ! %tbb
+; CHECK-NEXT:    call f1
+; CHECK-NEXT:    nop
+; CHECK-NEXT:    ba .LBB1_3
+; CHECK-NEXT:    nop
+; CHECK-NEXT:  .LBB1_2: ! %fbb
+; CHECK-NEXT:    call f2
+; CHECK-NEXT:    nop
+; CHECK-NEXT:  .LBB1_3: ! %end
+; CHECK-NEXT:    call f3
+; CHECK-NEXT:    nop
+; CHECK-NEXT:    ret
+; CHECK-NEXT:    restore
+entry:
+  ;; Using 1 here because compares with zero
+  ;; will be lowered into a `brz`, not `be`.
+  %cond = icmp eq i64 %sel, 1
+  br i1 %cond, label %tbb, label %fbb
+
+fbb:
+  call void @f2()
+  br label %end
+
+tbb:
+  call void @f1()
+  br label %end
+
+end:
+  call void @f3()
+  ret void
+}
+
+define void @brreg(i64 %sel) {
+; CHECK-LABEL: brreg:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ! %bb.0: ! %entry
+; CHECK-NEXT:    save %sp, -176, %sp
+; CHECK-NEXT:    .cfi_def_cfa_register %fp
+; CHECK-NEXT:    .cfi_window_save
+; CHECK-NEXT:    .cfi_register %o7, %i7
+; CHECK-NEXT:    brz %i0, .LBB2_2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:  ! %bb.1: ! %fbb
 ; CHECK-NEXT:    call f2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    ba .LBB1_3
+; CHECK-NEXT:    ba .LBB2_3
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:  .LBB1_2: ! %tbb
+; CHECK-NEXT:  .LBB2_2: ! %tbb
 ; CHECK-NEXT:    call f1
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:  .LBB1_3: ! %end
+; CHECK-NEXT:  .LBB2_3: ! %end
 ; CHECK-NEXT:    call f3
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    ret

diff  --git a/llvm/test/CodeGen/SPARC/missinglabel.ll b/llvm/test/CodeGen/SPARC/missinglabel.ll
index 88b09a8592634..e29f5ba344440 100644
--- a/llvm/test/CodeGen/SPARC/missinglabel.ll
+++ b/llvm/test/CodeGen/SPARC/missinglabel.ll
@@ -8,8 +8,7 @@ define void @f(i64 %a0) align 2 {
 ; CHECK-LABEL: f:
 ; CHECK:         .cfi_startproc
 ; CHECK-NEXT:  ! %bb.0: ! %entry
-; CHECK-NEXT:    cmp %o0, 0
-; CHECK-NEXT:    be %xcc, .LBB0_2
+; CHECK-NEXT:    brz %o0, .LBB0_2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:  ! %bb.1: ! %cond.false
 ; CHECK-NEXT:  .LBB0_2: ! %targetblock


        


More information about the llvm-commits mailing list