[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