[llvm] f8f41c3 - [SPARC] Lower SELECT_CC to MOVr on 64-bit target whenever possible

Brad Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 7 12:35:22 PST 2022


Author: Koakuma
Date: 2022-12-07T15:34:58-05:00
New Revision: f8f41c3fcd77829b8a4f10190699adb8b6451f56

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

LOG: [SPARC] Lower SELECT_CC to MOVr on 64-bit target whenever possible

On 64-bit target, when doing i64 SELECT_CC where one of the comparison operands
is a constant zero, try to fold the compare and MOVcc into a MOVr 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/D138922

Added: 
    

Modified: 
    llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
    llvm/lib/Target/Sparc/Sparc.h
    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/64bit.ll
    llvm/test/CodeGen/SPARC/64cond.ll
    llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll
    llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll
    llvm/test/MC/Sparc/sparc64-ctrl-instructions.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
index cc65b95a00d4f..3826dfd46c2b4 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
@@ -189,12 +189,20 @@ void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
   case SP::FMOVD_FCC: case SP::V9FMOVD_FCC:
   case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC:
     // Make sure CC is a fp conditional flag.
-    CC = (CC < 16) ? (CC + 16) : CC;
+    CC = (CC < SPCC::FCC_BEGIN) ? (CC + SPCC::FCC_BEGIN) : CC;
     break;
   case SP::CBCOND:
   case SP::CBCONDA:
     // Make sure CC is a cp conditional flag.
-    CC = (CC < 32) ? (CC + 32) : CC;
+    CC = (CC < SPCC::CPCC_BEGIN) ? (CC + SPCC::CPCC_BEGIN) : CC;
+    break;
+  case SP::MOVRri:
+  case SP::MOVRrr:
+  case SP::FMOVRS:
+  case SP::FMOVRD:
+  case SP::FMOVRQ:
+    // Make sure CC is a register conditional flag.
+    CC = (CC < SPCC::REG_BEGIN) ? (CC + SPCC::REG_BEGIN) : CC;
     break;
   }
   O << SPARCCondCodeToString((SPCC::CondCodes)CC);

diff  --git a/llvm/lib/Target/Sparc/Sparc.h b/llvm/lib/Target/Sparc/Sparc.h
index aabc4f1498296..4caae7838249b 100644
--- a/llvm/lib/Target/Sparc/Sparc.h
+++ b/llvm/lib/Target/Sparc/Sparc.h
@@ -37,58 +37,68 @@ namespace llvm {
   // Enums corresponding to Sparc condition codes, both icc's and fcc's.  These
   // values must be kept in sync with the ones in the .td file.
   namespace SPCC {
-    enum CondCodes {
-      ICC_A   =  8   ,  // Always
-      ICC_N   =  0   ,  // Never
-      ICC_NE  =  9   ,  // Not Equal
-      ICC_E   =  1   ,  // Equal
-      ICC_G   = 10   ,  // Greater
-      ICC_LE  =  2   ,  // Less or Equal
-      ICC_GE  = 11   ,  // Greater or Equal
-      ICC_L   =  3   ,  // Less
-      ICC_GU  = 12   ,  // Greater Unsigned
-      ICC_LEU =  4   ,  // Less or Equal Unsigned
-      ICC_CC  = 13   ,  // Carry Clear/Great or Equal Unsigned
-      ICC_CS  =  5   ,  // Carry Set/Less Unsigned
-      ICC_POS = 14   ,  // Positive
-      ICC_NEG =  6   ,  // Negative
-      ICC_VC  = 15   ,  // Overflow Clear
-      ICC_VS  =  7   ,  // Overflow Set
+  enum CondCodes {
+    ICC_A = 8,    // Always
+    ICC_N = 0,    // Never
+    ICC_NE = 9,   // Not Equal
+    ICC_E = 1,    // Equal
+    ICC_G = 10,   // Greater
+    ICC_LE = 2,   // Less or Equal
+    ICC_GE = 11,  // Greater or Equal
+    ICC_L = 3,    // Less
+    ICC_GU = 12,  // Greater Unsigned
+    ICC_LEU = 4,  // Less or Equal Unsigned
+    ICC_CC = 13,  // Carry Clear/Great or Equal Unsigned
+    ICC_CS = 5,   // Carry Set/Less Unsigned
+    ICC_POS = 14, // Positive
+    ICC_NEG = 6,  // Negative
+    ICC_VC = 15,  // Overflow Clear
+    ICC_VS = 7,   // Overflow Set
 
-      FCC_A   =  8+16,  // Always
-      FCC_N   =  0+16,  // Never
-      FCC_U   =  7+16,  // Unordered
-      FCC_G   =  6+16,  // Greater
-      FCC_UG  =  5+16,  // Unordered or Greater
-      FCC_L   =  4+16,  // Less
-      FCC_UL  =  3+16,  // Unordered or Less
-      FCC_LG  =  2+16,  // Less or Greater
-      FCC_NE  =  1+16,  // Not Equal
-      FCC_E   =  9+16,  // Equal
-      FCC_UE  = 10+16,  // Unordered or Equal
-      FCC_GE  = 11+16,  // Greater or Equal
-      FCC_UGE = 12+16,  // Unordered or Greater or Equal
-      FCC_LE  = 13+16,  // Less or Equal
-      FCC_ULE = 14+16,  // Unordered or Less or Equal
-      FCC_O   = 15+16,  // Ordered
+    FCC_BEGIN = 16,
+    FCC_A = 8 + FCC_BEGIN,    // Always
+    FCC_N = 0 + FCC_BEGIN,    // Never
+    FCC_U = 7 + FCC_BEGIN,    // Unordered
+    FCC_G = 6 + FCC_BEGIN,    // Greater
+    FCC_UG = 5 + FCC_BEGIN,   // Unordered or Greater
+    FCC_L = 4 + FCC_BEGIN,    // Less
+    FCC_UL = 3 + FCC_BEGIN,   // Unordered or Less
+    FCC_LG = 2 + FCC_BEGIN,   // Less or Greater
+    FCC_NE = 1 + FCC_BEGIN,   // Not Equal
+    FCC_E = 9 + FCC_BEGIN,    // Equal
+    FCC_UE = 10 + FCC_BEGIN,  // Unordered or Equal
+    FCC_GE = 11 + FCC_BEGIN,  // Greater or Equal
+    FCC_UGE = 12 + FCC_BEGIN, // Unordered or Greater or Equal
+    FCC_LE = 13 + FCC_BEGIN,  // Less or Equal
+    FCC_ULE = 14 + FCC_BEGIN, // Unordered or Less or Equal
+    FCC_O = 15 + FCC_BEGIN,   // Ordered
 
-      CPCC_A   =  8+32,  // Always
-      CPCC_N   =  0+32,  // Never
-      CPCC_3   =  7+32,
-      CPCC_2   =  6+32,
-      CPCC_23  =  5+32,
-      CPCC_1   =  4+32,
-      CPCC_13  =  3+32,
-      CPCC_12  =  2+32,
-      CPCC_123 =  1+32,
-      CPCC_0   =  9+32,
-      CPCC_03  = 10+32,
-      CPCC_02  = 11+32,
-      CPCC_023 = 12+32,
-      CPCC_01  = 13+32,
-      CPCC_013 = 14+32,
-      CPCC_012 = 15+32
-    };
+    CPCC_BEGIN = 32,
+    CPCC_A = 8 + CPCC_BEGIN, // Always
+    CPCC_N = 0 + CPCC_BEGIN, // Never
+    CPCC_3 = 7 + CPCC_BEGIN,
+    CPCC_2 = 6 + CPCC_BEGIN,
+    CPCC_23 = 5 + CPCC_BEGIN,
+    CPCC_1 = 4 + CPCC_BEGIN,
+    CPCC_13 = 3 + CPCC_BEGIN,
+    CPCC_12 = 2 + CPCC_BEGIN,
+    CPCC_123 = 1 + CPCC_BEGIN,
+    CPCC_0 = 9 + CPCC_BEGIN,
+    CPCC_03 = 10 + CPCC_BEGIN,
+    CPCC_02 = 11 + CPCC_BEGIN,
+    CPCC_023 = 12 + CPCC_BEGIN,
+    CPCC_01 = 13 + CPCC_BEGIN,
+    CPCC_013 = 14 + CPCC_BEGIN,
+    CPCC_012 = 15 + CPCC_BEGIN,
+
+    REG_BEGIN = 48,
+    REG_Z = 1 + REG_BEGIN,   // Is zero
+    REG_LEZ = 2 + REG_BEGIN, // Less or equal to zero
+    REG_LZ = 3 + REG_BEGIN,  // Less than zero
+    REG_NZ = 5 + REG_BEGIN,  // Is not zero
+    REG_GZ = 6 + REG_BEGIN,  // Greater than zero
+    REG_GEZ = 7 + REG_BEGIN  // Greater than or equal to zero
+  };
   }
 
   inline static const char *SPARCCondCodeToString(SPCC::CondCodes CC) {
@@ -141,6 +151,20 @@ namespace llvm {
     case SPCC::CPCC_01:  return "01";
     case SPCC::CPCC_013: return "013";
     case SPCC::CPCC_012: return "012";
+    case SPCC::REG_BEGIN:
+      llvm_unreachable("Use of reserved cond code");
+    case SPCC::REG_Z:
+      return "z";
+    case SPCC::REG_LEZ:
+      return "lez";
+    case SPCC::REG_LZ:
+      return "lz";
+    case SPCC::REG_NZ:
+      return "nz";
+    case SPCC::REG_GZ:
+      return "gz";
+    case SPCC::REG_GEZ:
+      return "gez";
     }
     llvm_unreachable("Invalid cond code");
   }

diff  --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index e3e69f3564ca8..b1baf1e55e612 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -25,6 +25,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
@@ -1473,6 +1474,27 @@ TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWIn
   return AtomicExpansionKind::CmpXChg;
 }
 
+/// intCondCCodeToRcond - Convert a DAG integer condition code to a SPARC
+/// rcond condition.
+static SPCC::CondCodes intCondCCodeToRcond(ISD::CondCode CC) {
+  switch (CC) {
+  default:
+    llvm_unreachable("Unknown/unsigned integer condition code!");
+  case ISD::SETEQ:
+    return SPCC::REG_Z;
+  case ISD::SETNE:
+    return SPCC::REG_NZ;
+  case ISD::SETLT:
+    return SPCC::REG_LZ;
+  case ISD::SETGT:
+    return SPCC::REG_GZ;
+  case ISD::SETLE:
+    return SPCC::REG_LEZ;
+  case ISD::SETGE:
+    return SPCC::REG_GEZ;
+  }
+}
+
 /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC
 /// condition.
 static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
@@ -1961,6 +1983,8 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case SPISD::SELECT_ICC:      return "SPISD::SELECT_ICC";
   case SPISD::SELECT_XCC:      return "SPISD::SELECT_XCC";
   case SPISD::SELECT_FCC:      return "SPISD::SELECT_FCC";
+  case SPISD::SELECT_REG:
+    return "SPISD::SELECT_REG";
   case SPISD::Hi:              return "SPISD::Hi";
   case SPISD::Lo:              return "SPISD::Lo";
   case SPISD::FTOI:            return "SPISD::FTOI";
@@ -2573,6 +2597,7 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
   // If this is a br_cc of a "setcc", and if the setcc got lowered into
   // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
   LookThroughSetCC(LHS, RHS, CC, SPCC);
+  assert(LHS.getValueType() == RHS.getValueType());
 
   // Get the condition flag.
   SDValue CompareFlag;
@@ -2603,7 +2628,7 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
 
 static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
                               const SparcTargetLowering &TLI, bool hasHardQuad,
-                              bool isV9) {
+                              bool isV9, bool is64Bit) {
   SDValue LHS = Op.getOperand(0);
   SDValue RHS = Op.getOperand(1);
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
@@ -2615,9 +2640,18 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
   // If this is a select_cc of a "setcc", and if the setcc got lowered into
   // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
   LookThroughSetCC(LHS, RHS, CC, SPCC);
+  assert(LHS.getValueType() == RHS.getValueType());
 
   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 select.
+    if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 &&
+        isNullConstant(RHS) && !ISD::isUnsignedIntSetCC(CC))
+      return DAG.getNode(
+          SPISD::SELECT_REG, dl, TrueVal.getValueType(), TrueVal, FalseVal,
+          DAG.getConstant(intCondCCodeToRcond(CC), dl, MVT::i32), LHS);
+
     CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
     Opc = LHS.getValueType() == MVT::i32 ?
           SPISD::SELECT_ICC : SPISD::SELECT_XCC;
@@ -3154,6 +3188,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
 
   bool hasHardQuad = Subtarget->hasHardQuad();
   bool isV9        = Subtarget->isV9();
+  bool is64Bit = Subtarget->is64Bit();
 
   switch (Op.getOpcode()) {
   default: llvm_unreachable("Should not custom lower this!");
@@ -3177,7 +3212,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::BR_CC:
     return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9);
   case ISD::SELECT_CC:
-    return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9);
+    return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit);
   case ISD::VASTART:            return LowerVASTART(Op, DAG, *this);
   case ISD::VAARG:              return LowerVAARG(Op, DAG);
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,

diff  --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index b382bef25fb26..563a832ee61ee 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -34,6 +34,8 @@ namespace llvm {
     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.
+    SELECT_REG, // Select between two values using the comparison of a register
+                // with zero.
 
     Hi,
     Lo, // Hi/Lo operations, typically on a global address.

diff  --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
index b334d533083f2..ccb5c0caac064 100644
--- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
@@ -385,47 +385,33 @@ defm : bpr_alias<"brgz",  BPGZnapt,  BPGZapt >;
 defm : bpr_alias<"brgez", BPGEZnapt, BPGEZapt>;
 
 // Move integer register on register condition (MOVr).
-multiclass MOVR< bits<3> rcond,  string OpcStr> {
-  def rr : F4_4r<0b101111, 0b00000, rcond, (outs I64Regs:$rd),
-                   (ins I64Regs:$rs1, IntRegs:$rs2),
-                   !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>;
-
-  def ri : F4_4i<0b101111, rcond, (outs I64Regs:$rd),
-                   (ins I64Regs:$rs1, i64imm:$simm10),
-                   !strconcat(OpcStr, " $rs1, $simm10, $rd"), []>;
+let Predicates = [Is64Bit], Constraints = "$f = $rd" in {
+  def MOVRrr : F4_4r<0b101111, 0b00000, (outs IntRegs:$rd),
+                   (ins I64Regs:$rs1, IntRegs:$rs2, IntRegs:$f, RegCCOp:$rcond),
+                   "movr$rcond $rs1, $rs2, $rd",
+                   [(set i32:$rd, (SPselectreg i32:$rs2, i32:$f, imm:$rcond, i64:$rs1))]>;
+
+  def MOVRri : F4_4i<0b101111, (outs IntRegs:$rd),
+                   (ins I64Regs:$rs1, i32imm:$simm10, IntRegs:$f, RegCCOp:$rcond),
+                   "movr$rcond $rs1, $simm10, $rd",
+                   [(set i32:$rd, (SPselectreg simm10:$simm10, i32:$f, imm:$rcond, i64:$rs1))]>;
 }
 
-defm MOVRRZ  : MOVR<0b001, "movrz">;
-defm MOVRLEZ : MOVR<0b010, "movrlez">;
-defm MOVRLZ  : MOVR<0b011, "movrlz">;
-defm MOVRNZ  : MOVR<0b101, "movrnz">;
-defm MOVRGZ  : MOVR<0b110, "movrgz">;
-defm MOVRGEZ : MOVR<0b111, "movrgez">;
-
 // Move FP register on integer register condition (FMOVr).
-multiclass FMOVR<bits<3> rcond, string OpcStr> {
-
-  def S : F4_4r<0b110101, 0b00101, rcond,
-                (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2),
-                !strconcat(!strconcat("fmovrs", OpcStr)," $rs1, $rs2, $rd"),
-                []>;
-  def D : F4_4r<0b110101, 0b00110, rcond,
-                (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2),
-                !strconcat(!strconcat("fmovrd", OpcStr)," $rs1, $rs2, $rd"),
-                []>;
-  def Q : F4_4r<0b110101, 0b00111, rcond,
-                (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2),
-                !strconcat(!strconcat("fmovrq", OpcStr)," $rs1, $rs2, $rd"),
-                []>, Requires<[HasHardQuad]>;
-}
-
-let Predicates = [HasV9] in {
-  defm FMOVRZ   : FMOVR<0b001, "z">;
-  defm FMOVRLEZ : FMOVR<0b010, "lez">;
-  defm FMOVRLZ  : FMOVR<0b011, "lz">;
-  defm FMOVRNZ  : FMOVR<0b101, "nz">;
-  defm FMOVRGZ  : FMOVR<0b110, "gz">;
-  defm FMOVRGEZ : FMOVR<0b111, "gez">;
+let Predicates = [Is64Bit], Constraints = "$f = $rd" in {
+  def FMOVRS : F4_4r<0b110101, 0b00101,
+                (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2, FPRegs:$f,  RegCCOp:$rcond),
+                "fmovrs$rcond $rs1, $rs2, $rd",
+                [(set f32:$rd, (SPselectreg f32:$rs2, f32:$f, imm:$rcond, i64:$rs1))]>;
+  def FMOVRD : F4_4r<0b110101, 0b00110,
+                (outs DFPRegs:$rd), (ins I64Regs:$rs1, DFPRegs:$rs2, DFPRegs:$f, RegCCOp:$rcond),
+                "fmovrd$rcond $rs1, $rs2, $rd",
+                [(set f64:$rd, (SPselectreg f64:$rs2, f64:$f, imm:$rcond, i64:$rs1))]>;
+  let Predicates = [HasHardQuad] in
+  def FMOVRQ : F4_4r<0b110101, 0b00111,
+                (outs QFPRegs:$rd), (ins I64Regs:$rs1, QFPRegs:$rs2, QFPRegs:$f, RegCCOp:$rcond),
+                "fmovrq$rcond $rs1, $rs2, $rd",
+                [(set f128:$rd, (SPselectreg f128:$rs2, f128:$f, imm:$rcond, i64:$rs1))]>;
 }
 
 //===----------------------------------------------------------------------===//
@@ -479,6 +465,11 @@ def : Pat<(SPselectfcc i64:$t, i64:$f, imm:$cond),
 def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, imm:$cond),
           (MOVFCCri (as_i32imm $t), $f, imm:$cond)>;
 
+def : Pat<(SPselectreg i64:$t, i64:$f, imm:$rcond, i64:$rs1),
+          (MOVRrr $rs1, $t, $f, imm:$rcond)>;
+def : Pat<(SPselectreg (i64 simm10:$t), i64:$f, imm:$rcond, i64:$rs1),
+          (MOVRri $rs1, (as_i32imm $t), $f, imm:$rcond)>;
+
 } // Predicates = [Is64Bit]
 
 

diff  --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td
index 1b3ec199fc163..4344ba221a660 100644
--- a/llvm/lib/Target/Sparc/SparcInstrAliases.td
+++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td
@@ -59,6 +59,34 @@ multiclass fpcond_mov_alias<string cond, int condVal,
                   (fmovd DFPRegs:$rd, FCCRegs:$cc, DFPRegs:$rs2, condVal)>;
 }
 
+// movr<cond> rs1, rs2, rd
+multiclass regcond_mov_alias<string rcond, int condVal,
+                          Instruction movrrr, Instruction movrri,
+                          Instruction fmovrs, Instruction fmovrd,
+                          Instruction fmovrq> {
+
+  // movr<cond> $rs1, $rs2, $rd
+  def : InstAlias<!strconcat(!strconcat("movr", rcond), " $rs1, $rs2, $rd"),
+                  (movrrr IntRegs:$rd, I64Regs:$rs1, IntRegs:$rs2, condVal)>;
+
+  // movr<cond> $rs1, $simm10, $rd
+  def : InstAlias<!strconcat(!strconcat("movr", rcond), " $rs1, $simm10, $rd"),
+                  (movrri IntRegs:$rd, I64Regs:$rs1, i32imm:$simm10, condVal)>;
+
+  // fmovrs<cond> $rs1, $rs2, $rd
+  def : InstAlias<!strconcat(!strconcat("fmovrs", rcond), " $rs1, $rs2, $rd"),
+                  (fmovrs FPRegs:$rd, I64Regs:$rs1, FPRegs:$rs2, condVal)>;
+
+  // fmovrd<cond> $rs1, $rs2, $rd
+  def : InstAlias<!strconcat(!strconcat("fmovrd", rcond), " $rs1, $rs2, $rd"),
+                  (fmovrd DFPRegs:$rd, I64Regs:$rs1, DFPRegs:$rs2, condVal)>;
+
+  // fmovrq<cond> $rs1, $rs2, $rd
+  let Predicates = [HasHardQuad] in
+  def : InstAlias<!strconcat(!strconcat("fmovrq", rcond), " $rs1, $rs2, $rd"),
+                  (fmovrq QFPRegs:$rd, I64Regs:$rs1, QFPRegs:$rs2, condVal)>;
+}
+
 // Instruction aliases for integer conditional branches and moves.
 multiclass int_cond_alias<string cond, int condVal> {
 
@@ -265,6 +293,14 @@ multiclass cp_cond_alias<string cond, int condVal> {
                   (CBCONDA brtarget:$imm, condVal), 0>;
 }
 
+// Instruction aliases for register conditional branches and moves.
+multiclass reg_cond_alias<string rcond, int condVal> {
+  defm : regcond_mov_alias<rcond, condVal,
+                            MOVRrr, MOVRri,
+                            FMOVRS, FMOVRD, FMOVRQ>,
+                            Requires<[Is64Bit]>;
+}
+
 defm : int_cond_alias<"a",    0b1000>;
 defm : int_cond_alias<"n",    0b0000>;
 defm : int_cond_alias<"ne",   0b1001>;
@@ -331,6 +367,13 @@ defm : cp_cond_alias<"013",   0b1110>;
 defm : cp_cond_alias<"012",   0b1111>;
 let EmitPriority = 0 in defm : cp_cond_alias<"",      0b1000>; // same as a; gnu asm, not in manual
 
+defm : reg_cond_alias<"z",    0b001>;
+defm : reg_cond_alias<"lez",  0b010>;
+defm : reg_cond_alias<"lz",   0b011>;
+defm : reg_cond_alias<"nz",   0b101>;
+defm : reg_cond_alias<"gz",   0b110>;
+defm : reg_cond_alias<"gez",  0b111>;
+
 // Section A.3 Synthetic Instructions
 
 // Most are marked as Emit=0, so that they are not used for disassembly. This is

diff  --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td
index 259ce967f2df7..522dcd96a1125 100644
--- a/llvm/lib/Target/Sparc/SparcInstrFormats.td
+++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td
@@ -296,12 +296,13 @@ class F4_3<bits<6> op3, bits<6> opf_low, dag outs, dag ins,
   let Inst{4-0}    = rs2;
 }
 
-class F4_4r<bits<6> op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins,
+class F4_4r<bits<6> op3, bits<5> opf_low, dag outs, dag ins,
             string asmstr, list<dag> pattern,
             InstrItinClass itin = NoItinerary>
    : F4<op3, outs, ins, asmstr, pattern, itin> {
-  bits <5> rs1;
-  bits <5> rs2;
+  bits<5> rs1;
+  bits<5> rs2;
+  bits<3> rcond;
   let Inst{18-14} = rs1;
   let Inst{13}    = 0;  // IsImm
   let Inst{12-10} = rcond;
@@ -310,12 +311,13 @@ class F4_4r<bits<6> op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins,
 }
 
 
-class F4_4i<bits<6> op3, bits<3> rcond, dag outs, dag ins,
+class F4_4i<bits<6> op3, dag outs, dag ins,
             string asmstr, list<dag> pattern,
            InstrItinClass itin = NoItinerary>
    : F4<op3, outs, ins, asmstr, pattern, itin> {
-  bits<5> rs1;
+  bits<5>  rs1;
   bits<10> simm10;
+  bits<3>  rcond;
   let Inst{18-14} = rs1;
   let Inst{13}    = 1;  // IsImm
   let Inst{12-10} = rcond;

diff  --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index c7c643b57a51a..2a3b4bf81f91e 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -136,6 +136,21 @@ static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
       // only be used in inline assembler, so this code should
       // not be reached in a normal compilation pass.
       llvm_unreachable("Meaningless inversion of co-processor cond code");
+
+  case SPCC::REG_BEGIN:
+      llvm_unreachable("Use of reserved cond code");
+  case SPCC::REG_Z:
+      return SPCC::REG_NZ;
+  case SPCC::REG_LEZ:
+      return SPCC::REG_GZ;
+  case SPCC::REG_LZ:
+      return SPCC::REG_GEZ;
+  case SPCC::REG_NZ:
+      return SPCC::REG_Z;
+  case SPCC::REG_GZ:
+      return SPCC::REG_LEZ;
+  case SPCC::REG_GEZ:
+      return SPCC::REG_LZ;
   }
   llvm_unreachable("Invalid cond code");
 }

diff  --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index ca8c4889c8abe..99bdae977e997 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -78,6 +78,8 @@ def UseDeprecatedInsts : Predicate<"Subtarget->useDeprecatedV8Instructions()">;
 // Instruction Pattern Stuff
 //===----------------------------------------------------------------------===//
 
+def simm10  : PatLeaf<(imm), [{ return isInt<10>(N->getSExtValue()); }]>;
+
 def simm11  : PatLeaf<(imm), [{ return isInt<11>(N->getSExtValue()); }]>;
 
 def simm13  : PatLeaf<(imm), [{ return isInt<13>(N->getSExtValue()); }]>;
@@ -211,8 +213,10 @@ def simm13Op : Operand<i32> {
 }
 
 // Operand for printing out a condition code.
-let PrintMethod = "printCCOperand" in
+let PrintMethod = "printCCOperand" in {
   def CCOp : Operand<i32>;
+  def RegCCOp : Operand<i32>;
+}
 
 def SDTSPcmpicc :
 SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>;
@@ -222,6 +226,8 @@ def SDTSPbrcc :
 SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>;
 def SDTSPselectcc :
 SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>]>;
+def SDTSPselectreg :
+SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>, SDTCisVT<4, i64>]>;
 def SDTSPFTOI :
 SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>;
 def SDTSPITOF :
@@ -259,6 +265,7 @@ def SPxtof  : SDNode<"SPISD::XTOF", SDTSPXTOF>;
 def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInGlue]>;
 def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>;
 def SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInGlue]>;
+def SPselectreg : SDNode<"SPISD::SELECT_REG", SDTSPselectreg, [SDNPInGlue]>;
 
 //  These are target-independent nodes, but have target-specific formats.
 def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>,
@@ -353,6 +360,14 @@ def CPCC_01  : CPCC_VAL<45>;  // 0 or 1
 def CPCC_013 : CPCC_VAL<46>;  // 0 or 1 or 3
 def CPCC_012 : CPCC_VAL<47>;  // 0 or 1 or 2
 
+class RegCC_VAL<int N> : PatLeaf<(i32 N)>;
+def RegCC_Z   : RegCC_VAL<49>;  // Zero
+def RegCC_LEZ : RegCC_VAL<50>;  // Lees or equal than zero
+def RegCC_LZ  : RegCC_VAL<51>;  // Less than zero
+def RegCC_NZ  : RegCC_VAL<53>;  // Not zero
+def RegCC_GZ  : RegCC_VAL<54>;  // Greater than zero
+def RegCC_GEZ : RegCC_VAL<55>;  // Greater or equal to zero
+
 //===----------------------------------------------------------------------===//
 // Instruction Class Templates
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/test/CodeGen/SPARC/64bit.ll b/llvm/test/CodeGen/SPARC/64bit.ll
index c079d901a03d1..bf021845540c3 100644
--- a/llvm/test/CodeGen/SPARC/64bit.ll
+++ b/llvm/test/CodeGen/SPARC/64bit.ll
@@ -239,8 +239,7 @@ entry:
 declare void @g(i8*)
 
 ; CHECK: expand_setcc
-; CHECK: cmp %i0, 0
-; CHECK: movg %xcc, 1,
+; CHECK: movrgz %i0, 1,
 define i32 @expand_setcc(i64 %a) {
   %cond = icmp sle i64 %a, 0
   %cast2 = zext i1 %cond to i32

diff  --git a/llvm/test/CodeGen/SPARC/64cond.ll b/llvm/test/CodeGen/SPARC/64cond.ll
index ffdb10a814899..af635b08f85b2 100644
--- a/llvm/test/CodeGen/SPARC/64cond.ll
+++ b/llvm/test/CodeGen/SPARC/64cond.ll
@@ -117,8 +117,7 @@ entry:
 ; CHECK-DAG:       mov %o0, %o2
 ; CHECK-DAG:       mov 32, %o3
 ; CHECK-DAG:       call __multi3
-; CHECK:       cmp
-; CHECK:       movne %xcc, 1, [[R:%[gilo][0-7]]]
+; CHECK:       movrnz %o0, 1, [[R:%[gilo][0-7]]]
 ; CHECK:       or [[R]], %i1, %i0
 
 define i1 @setcc_resultty(i64 %a, i1 %b) {

diff  --git a/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll
index 466668f2196a5..26e8cd6b6bd9b 100644
--- a/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll
+++ b/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll
@@ -232,8 +232,7 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 {
 ; SPARC64-NEXT:    or %i0, %i4, %i0
 ; SPARC64-NEXT:    xor %i0, %i5, %i0
 ; SPARC64-NEXT:    or %i0, %i2, %i0
-; SPARC64-NEXT:    cmp %i0, 0
-; SPARC64-NEXT:    movne %xcc, 1, %l7
+; SPARC64-NEXT:    movrnz %i0, 1, %l7
 ; SPARC64-NEXT:    srl %l0, 0, %i0
 ; SPARC64-NEXT:    or %i3, %i0, %i0
 ; SPARC64-NEXT:    srl %l7, 0, %i2

diff  --git a/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll
index e870ad2f0bd93..de299392cbadc 100644
--- a/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll
+++ b/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll
@@ -164,6 +164,7 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 {
 ; SPARC64-LABEL: muloti_test:
 ; SPARC64:         .cfi_startproc
 ; SPARC64-NEXT:    .register %g2, #scratch
+; SPARC64-NEXT:    .register %g3, #scratch
 ; SPARC64-NEXT:  ! %bb.0: ! %start
 ; SPARC64-NEXT:    save %sp, -176, %sp
 ; SPARC64-NEXT:    .cfi_def_cfa_register %fp
@@ -194,19 +195,15 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 {
 ; SPARC64-NEXT:    cmp %i1, %o0
 ; SPARC64-NEXT:    mov %i3, %i4
 ; SPARC64-NEXT:    movcs %xcc, 1, %i4
-; SPARC64-NEXT:    cmp %l1, 0
 ; SPARC64-NEXT:    mov %i3, %g2
-; SPARC64-NEXT:    movne %xcc, 1, %g2
-; SPARC64-NEXT:    cmp %i2, 0
+; SPARC64-NEXT:    movrnz %l1, 1, %g2
+; SPARC64-NEXT:    mov %i3, %g3
+; SPARC64-NEXT:    movrnz %i2, 1, %g3
 ; SPARC64-NEXT:    mov %i3, %i2
-; SPARC64-NEXT:    movne %xcc, 1, %i2
-; SPARC64-NEXT:    cmp %i0, 0
-; SPARC64-NEXT:    mov %i3, %i0
-; SPARC64-NEXT:    movne %xcc, 1, %i0
-; SPARC64-NEXT:    and %i0, %i2, %i0
+; SPARC64-NEXT:    movrnz %i0, 1, %i2
+; SPARC64-NEXT:    and %i2, %g3, %i0
 ; SPARC64-NEXT:    or %i0, %g2, %i0
-; SPARC64-NEXT:    cmp %i5, 0
-; SPARC64-NEXT:    movne %xcc, 1, %i3
+; SPARC64-NEXT:    movrnz %i5, 1, %i3
 ; SPARC64-NEXT:    or %i0, %i3, %i0
 ; SPARC64-NEXT:    or %i0, %i4, %i0
 ; SPARC64-NEXT:    srl %i0, 0, %i2

diff  --git a/llvm/test/MC/Sparc/sparc64-ctrl-instructions.s b/llvm/test/MC/Sparc/sparc64-ctrl-instructions.s
index d1a744f7526a0..737b95338c998 100644
--- a/llvm/test/MC/Sparc/sparc64-ctrl-instructions.s
+++ b/llvm/test/MC/Sparc/sparc64-ctrl-instructions.s
@@ -1214,6 +1214,19 @@
         movrgz  %g1, %g2, %g3
         movrgez %g1, %g2, %g3
 
+        ! CHECK: movrz   %g1, 2, %g3 ! encoding: [0x87,0x78,0x64,0x02]
+        ! CHECK: movrlez %g1, 2, %g3 ! encoding: [0x87,0x78,0x68,0x02]
+        ! CHECK: movrlz  %g1, 2, %g3 ! encoding: [0x87,0x78,0x6c,0x02]
+        ! CHECK: movrnz  %g1, 2, %g3 ! encoding: [0x87,0x78,0x74,0x02]
+        ! CHECK: movrgz  %g1, 2, %g3 ! encoding: [0x87,0x78,0x78,0x02]
+        ! CHECK: movrgez %g1, 2, %g3 ! encoding: [0x87,0x78,0x7c,0x02]
+        movrz   %g1, 2, %g3
+        movrlez %g1, 2, %g3
+        movrlz  %g1, 2, %g3
+        movrnz  %g1, 2, %g3
+        movrgz  %g1, 2, %g3
+        movrgez %g1, 2, %g3
+
         ! CHECK: fmovrsz %g1, %f2, %f3         ! encoding: [0x87,0xa8,0x44,0xa2]
         ! CHECK: fmovrslez %g1, %f2, %f3       ! encoding: [0x87,0xa8,0x48,0xa2]
         ! CHECK: fmovrslz %g1, %f2, %f3        ! encoding: [0x87,0xa8,0x4c,0xa2]
@@ -1227,6 +1240,32 @@
         fmovrsgz  %g1, %f2, %f3
         fmovrsgez %g1, %f2, %f3
 
+        ! CHECK: fmovrdz %g1, %f2, %f4         ! encoding: [0x89,0xa8,0x44,0xc2]
+        ! CHECK: fmovrdlez %g1, %f2, %f4       ! encoding: [0x89,0xa8,0x48,0xc2]
+        ! CHECK: fmovrdlz %g1, %f2, %f4        ! encoding: [0x89,0xa8,0x4c,0xc2]
+        ! CHECK: fmovrdnz %g1, %f2, %f4        ! encoding: [0x89,0xa8,0x54,0xc2]
+        ! CHECK: fmovrdgz %g1, %f2, %f4        ! encoding: [0x89,0xa8,0x58,0xc2]
+        ! CHECK: fmovrdgez %g1, %f2, %f4       ! encoding: [0x89,0xa8,0x5c,0xc2]
+        fmovrdz   %g1, %f2, %f4
+        fmovrdlez %g1, %f2, %f4
+        fmovrdlz  %g1, %f2, %f4
+        fmovrdnz  %g1, %f2, %f4
+        fmovrdgz  %g1, %f2, %f4
+        fmovrdgez %g1, %f2, %f4
+
+        ! CHECK: fmovrqz %g1, %f4, %f8         ! encoding: [0x91,0xa8,0x44,0xe4]
+        ! CHECK: fmovrqlez %g1, %f4, %f8       ! encoding: [0x91,0xa8,0x48,0xe4]
+        ! CHECK: fmovrqlz %g1, %f4, %f8        ! encoding: [0x91,0xa8,0x4c,0xe4]
+        ! CHECK: fmovrqnz %g1, %f4, %f8        ! encoding: [0x91,0xa8,0x54,0xe4]
+        ! CHECK: fmovrqgz %g1, %f4, %f8        ! encoding: [0x91,0xa8,0x58,0xe4]
+        ! CHECK: fmovrqgez %g1, %f4, %f8       ! encoding: [0x91,0xa8,0x5c,0xe4]
+        fmovrqz   %g1, %f4, %f8
+        fmovrqlez %g1, %f4, %f8
+        fmovrqlz  %g1, %f4, %f8
+        fmovrqnz  %g1, %f4, %f8
+        fmovrqgz  %g1, %f4, %f8
+        fmovrqgez %g1, %f4, %f8
+
         ! CHECK:  rett %i7+8   ! encoding: [0x81,0xcf,0xe0,0x08]
         return %i7 + 8
 


        


More information about the llvm-commits mailing list