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 @@ -23,12 +23,14 @@ namespace SPISD { enum NodeType : unsigned { FIRST_NUMBER = ISD::BUILTIN_OP_END, - CMPICC, // Compare two GPR operands, set icc+xcc. - CMPFCC, // Compare two FP operands, set fcc. - BRICC, // Branch to dest on icc condition - BPICC, // Branch to dest on icc condition, with prediction (64-bit only). - BPXCC, // Branch to dest on xcc condition, with prediction (64-bit only). - BRFCC, // Branch to dest on fcc condition + CMPICC, // Compare two GPR operands, set icc+xcc. + CMPFCC, // Compare two FP operands, set fcc. + CMPFCC_V9, // Compare two FP operands, set fcc (v9 variant). + BRICC, // Branch to dest on icc condition + BPICC, // Branch to dest on icc condition, with prediction (64-bit only). + 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). 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/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -1927,12 +1927,16 @@ case SPISD::FIRST_NUMBER: break; case SPISD::CMPICC: return "SPISD::CMPICC"; case SPISD::CMPFCC: return "SPISD::CMPFCC"; + case SPISD::CMPFCC_V9: + return "SPISD::CMPFCC_V9"; case SPISD::BRICC: return "SPISD::BRICC"; case SPISD::BPICC: return "SPISD::BPICC"; case SPISD::BPXCC: return "SPISD::BPXCC"; case SPISD::BRFCC: return "SPISD::BRFCC"; + case SPISD::BRFCC_V9: + return "SPISD::BRFCC_V9"; case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC"; case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; @@ -1992,15 +1996,14 @@ // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, ISD::CondCode CC, unsigned &SPCC) { - if (isNullConstant(RHS) && - CC == ISD::SETNE && + if (isNullConstant(RHS) && CC == ISD::SETNE && (((LHS.getOpcode() == SPISD::SELECT_ICC || LHS.getOpcode() == SPISD::SELECT_XCC) && LHS.getOperand(3).getOpcode() == SPISD::CMPICC) || (LHS.getOpcode() == SPISD::SELECT_FCC && - LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && - isOneConstant(LHS.getOperand(0)) && - isNullConstant(LHS.getOperand(1))) { + (LHS.getOperand(3).getOpcode() == SPISD::CMPFCC || + LHS.getOperand(3).getOpcode() == SPISD::CMPFCC_V9))) && + isOneConstant(LHS.getOperand(0)) && isNullConstant(LHS.getOperand(1))) { SDValue CMPCC = LHS.getOperand(3); SPCC = cast(LHS.getOperand(2))->getZExtValue(); LHS = CMPCC.getOperand(0); @@ -2567,9 +2570,10 @@ CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); Opc = isV9 ? SPISD::BPICC : SPISD::BRICC; } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); + unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC; + CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS); if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); - Opc = SPISD::BRFCC; + Opc = isV9 ? SPISD::BRFCC_V9 : SPISD::BRFCC; } } return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest, @@ -2577,8 +2581,8 @@ } static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { + const SparcTargetLowering &TLI, bool hasHardQuad, + bool isV9) { SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); ISD::CondCode CC = cast(Op.getOperand(4))->get(); @@ -2603,7 +2607,8 @@ CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); Opc = SPISD::SELECT_ICC; } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); + unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC; + CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS); Opc = SPISD::SELECT_FCC; if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); } @@ -3150,8 +3155,8 @@ hasHardQuad); case ISD::BR_CC: return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9); - case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this, - hasHardQuad); + case ISD::SELECT_CC: + return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9); case ISD::VASTART: return LowerVASTART(Op, DAG, *this); case ISD::VAARG: return LowerVAARG(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG, @@ -3240,6 +3245,8 @@ case SP::SELECT_CC_FP_FCC: case SP::SELECT_CC_DFP_FCC: case SP::SELECT_CC_QFP_FCC: + if (Subtarget->isV9()) + return expandSelectCC(MI, BB, SP::FBCOND_V9); return expandSelectCC(MI, BB, SP::FBCOND); } } 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 @@ -241,10 +241,12 @@ def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>; def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>; +def SPcmpfccv9 : SDNode<"SPISD::CMPFCC_V9", SDTSPcmpfcc, [SDNPOutGlue]>; def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; 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 SPhi : SDNode<"SPISD::Hi", SDTIntUnaryOp>; def SPlo : SDNode<"SPISD::Lo", SDTIntUnaryOp>; @@ -962,6 +964,19 @@ "fb$cond,a $imm22", []>; } +// Variants of FBCOND that uses V9 opcode +let Predicates = [HasV9], Uses = [FCC0], cc = 0, + isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in { + def FBCOND_V9 : F2_3<0b101, 0, 1, (outs), + (ins bprtarget:$imm19, CCOp:$cond), + "fb$cond %fcc0, $imm19", + [(SPbrfccv9 bb:$imm19, imm:$cond)], IIC_fpu_normal_instr>; + def FBCONDA_V9 : F2_3<0b101, 1, 1, (outs), + (ins bprtarget:$imm19, CCOp:$cond), + "fb$cond,a %fcc0, $imm19", + [(SPbrfccv9 bb:$imm19, imm:$cond)], IIC_fpu_normal_instr>; +} + let Predicates = [HasV9] in defm BPF : FPredBranch; @@ -1408,6 +1423,31 @@ Requires<[HasHardQuad]>; } +// A.13 Floating-Point Compare (SPARC v9) +// Note that these always write to %fcc0 instead of having its destination +// allocated automatically. +// This avoids complications with the scheduler sometimes wanting to spill +// the contents of an FCC, since SPARC v9 doesn't have facilities to spill +// an individual FCC. + +let Predicates = [HasV9], Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in { + def FCMPS_V9 : F3_3c<2, 0b110101, 0b001010001, + (outs), (ins FPRegs:$rs1, FPRegs:$rs2), + "fcmps %fcc0, $rs1, $rs2", + [(SPcmpfccv9 f32:$rs1, f32:$rs2)], + IIC_fpu_fast_instr>; + def FCMPD_V9 : F3_3c<2, 0b110101, 0b001010010, + (outs), (ins DFPRegs:$rs1, DFPRegs:$rs2), + "fcmpd %fcc0, $rs1, $rs2", + [(SPcmpfccv9 f64:$rs1, f64:$rs2)], + IIC_fpu_fast_instr>; + def FCMPQ_V9 : F3_3c<2, 0b110101, 0b001010011, + (outs), (ins QFPRegs:$rs1, QFPRegs:$rs2), + "fcmpq %fcc0, $rs1, $rs2", + [(SPcmpfccv9 f128:$rs1, f128:$rs2)]>, + Requires<[HasHardQuad]>; +} + //===----------------------------------------------------------------------===// // Instructions for Thread Local Storage(TLS). //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll b/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll --- a/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll +++ b/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll @@ -118,10 +118,10 @@ ; V8: {{fbule|fbg}} .LBB ; V9-LABEL: test_float_cc -; V9: fcmpd -; V9: {{fbl|fbuge}} .LBB -; V9: fcmpd -; V9: {{fbule|fbg}} .LBB +; V9: fcmpd %fcc0 +; V9: {{fbl|fbuge}} %fcc0, .LBB +; V9: fcmpd %fcc0 +; V9: {{fbule|fbg}} %fcc0, .LBB %0 = fcmp uge double %a, 0.000000e+00 br i1 %0, label %loop, label %loop.2 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 @@ -68,7 +68,7 @@ ; CHECK: selecti64_fcc ; CHECK: mov %i3, %i0 -; CHECK: fcmps %f1, %f3 +; CHECK: fcmps %fcc0, %f1, %f3 ; CHECK: movul %fcc0, %i2, %i0 ; CHECK: restore define i64 @selecti64_fcc(float %x, float %y, i64 %a, i64 %b) {