diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp @@ -189,12 +189,20 @@ 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 --- a/llvm/lib/Target/Sparc/Sparc.h +++ b/llvm/lib/Target/Sparc/Sparc.h @@ -37,58 +37,68 @@ // 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 @@ 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.h b/llvm/lib/Target/Sparc/SparcISelLowering.h --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -34,6 +34,8 @@ 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/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp --- 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 @@ 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 @@ 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 @@ // 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 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(Op.getOperand(4))->get(); @@ -2615,9 +2640,18 @@ // 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 @@ 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 @@ 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/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td --- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -385,47 +385,33 @@ 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 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 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 --- a/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td @@ -59,6 +59,34 @@ (fmovd DFPRegs:$rd, FCCRegs:$cc, DFPRegs:$rs2, condVal)>; } +// movr rs1, rs2, rd +multiclass regcond_mov_alias { + + // movr $rs1, $rs2, $rd + def : InstAlias; + + // movr $rs1, $simm10, $rd + def : InstAlias; + + // fmovrs $rs1, $rs2, $rd + def : InstAlias; + + // fmovrd $rs1, $rs2, $rd + def : InstAlias; + + // fmovrq $rs1, $rs2, $rd + let Predicates = [HasHardQuad] in + def : InstAlias; +} + // Instruction aliases for integer conditional branches and moves. multiclass int_cond_alias { @@ -265,6 +293,14 @@ (CBCONDA brtarget:$imm, condVal), 0>; } +// Instruction aliases for register conditional branches and moves. +multiclass reg_cond_alias { + defm : regcond_mov_alias, + 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<"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 --- a/llvm/lib/Target/Sparc/SparcInstrFormats.td +++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td @@ -296,12 +296,13 @@ let Inst{4-0} = rs2; } -class F4_4r op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins, +class F4_4r op3, bits<5> opf_low, dag outs, dag ins, string asmstr, list pattern, InstrItinClass itin = NoItinerary> : F4 { - 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_4i op3, bits<3> rcond, dag outs, dag ins, +class F4_4i op3, dag outs, dag ins, string asmstr, list pattern, InstrItinClass itin = NoItinerary> : F4 { - 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 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp @@ -136,6 +136,21 @@ // 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 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -78,6 +78,8 @@ // 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 @@ } // Operand for printing out a condition code. -let PrintMethod = "printCCOperand" in +let PrintMethod = "printCCOperand" in { def CCOp : Operand; + def RegCCOp : Operand; +} def SDTSPcmpicc : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>; @@ -222,6 +226,8 @@ 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 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_013 : CPCC_VAL<46>; // 0 or 1 or 3 def CPCC_012 : CPCC_VAL<47>; // 0 or 1 or 2 +class RegCC_VAL : 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 --- a/llvm/test/CodeGen/SPARC/64bit.ll +++ b/llvm/test/CodeGen/SPARC/64bit.ll @@ -239,8 +239,7 @@ 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 --- a/llvm/test/CodeGen/SPARC/64cond.ll +++ b/llvm/test/CodeGen/SPARC/64cond.ll @@ -117,8 +117,7 @@ ; 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 --- a/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll +++ b/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll @@ -232,8 +232,7 @@ ; 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 --- a/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll +++ b/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll @@ -164,6 +164,7 @@ ; 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 @@ ; 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 --- 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