From 0e164884423e9f0f22670015a428946ebf178545 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 4 Apr 2013 03:08:00 +0000 Subject: [PATCH] Add SPARC v9 support for select on 64-bit compares. This requires v9 cmov instructions using the %xcc flags instead of the %icc flags. Still missing: - Select floats on %xcc flags. - Select i64 on %fcc flags. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178737 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/SparcISelLowering.cpp | 11 ++++++++--- lib/Target/Sparc/SparcISelLowering.h | 1 + lib/Target/Sparc/SparcInstr64Bit.td | 27 +++++++++++++++++++++++++-- lib/Target/Sparc/SparcInstrInfo.td | 1 + test/CodeGen/SPARC/64cond.ll | 22 ++++++++++++++++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index a9ce75a7eb8..325f13424b4 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -826,6 +826,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) if (Subtarget->is64Bit()) { setOperationAction(ISD::BR_CC, MVT::i64, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); } // FIXME: There are instructions available for ATOMIC_FENCE @@ -900,6 +901,7 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { case SPISD::BRXCC: return "SPISD::BRXCC"; case SPISD::BRFCC: return "SPISD::BRFCC"; 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::Hi: return "SPISD::Hi"; case SPISD::Lo: return "SPISD::Lo"; @@ -926,6 +928,7 @@ void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, switch (Op.getOpcode()) { default: break; case SPISD::SELECT_ICC: + case SPISD::SELECT_XCC: case SPISD::SELECT_FCC: DAG.ComputeMaskedBits(Op.getOperand(1), KnownZero, KnownOne, Depth+1); DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero2, KnownOne2, Depth+1); @@ -946,7 +949,8 @@ static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, if (isa(RHS) && cast(RHS)->isNullValue() && CC == ISD::SETNE && - ((LHS.getOpcode() == SPISD::SELECT_ICC && + (((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)) && @@ -1064,12 +1068,13 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { LookThroughSetCC(LHS, RHS, CC, SPCC); SDValue CompareFlag; - if (LHS.getValueType() == MVT::i32) { + if (LHS.getValueType().isInteger()) { // subcc returns a value EVT VTs[] = { LHS.getValueType(), MVT::Glue }; SDValue Ops[2] = { LHS, RHS }; CompareFlag = DAG.getNode(SPISD::CMPICC, dl, VTs, Ops, 2).getValue(1); - Opc = SPISD::SELECT_ICC; + Opc = LHS.getValueType() == MVT::i32 ? + SPISD::SELECT_ICC : SPISD::SELECT_XCC; if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); } else { CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h index 274673cd4da..aa2ef711a08 100644 --- a/lib/Target/Sparc/SparcISelLowering.h +++ b/lib/Target/Sparc/SparcISelLowering.h @@ -30,6 +30,7 @@ namespace llvm { BRXCC, // Branch to dest on xcc condition (64-bit only). BRFCC, // Branch to dest on fcc condition 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. Hi, Lo, // Hi/Lo operations, typically on a global address. diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td index a726b358a10..ca1153b3fe8 100644 --- a/lib/Target/Sparc/SparcInstr64Bit.td +++ b/lib/Target/Sparc/SparcInstr64Bit.td @@ -19,8 +19,8 @@ let Predicates = [Is64Bit] in { // The same integer registers are used for i32 and i64 values. // When registers hold i32 values, the high bits are don't care. // This give us free trunc and anyext. -def : Pat<(i64 (anyext i32:$val)), (COPY $val)>; -def : Pat<(i32 (trunc i64:$val)), (COPY $val)>; +def : Pat<(i64 (anyext i32:$val)), (COPY_TO_REGCLASS $val, I64Regs)>; +def : Pat<(i32 (trunc i64:$val)), (COPY_TO_REGCLASS $val, IntRegs)>; } // Predicates = [Is64Bit] @@ -256,7 +256,30 @@ def : Pat<(truncstorei32 i64:$src, ADDRri:$addr), (STri ADDRri:$addr, $src)>; // We reuse CMPICC SDNodes for compares, but use new BRXCC branch nodes for // 64-bit compares. See LowerBR_CC. +let Predicates = [Is64Bit] in { + let Uses = [ICC] in def BPXCC : BranchSP<0, (ins brtarget:$dst, CCOp:$cc), "bp$cc %xcc, $dst", [(SPbrxcc bb:$dst, imm:$cc)]>; + +// Conditional moves on %xcc. +let Uses = [ICC], Constraints = "$f = $rd" in { +def MOVXCCrr : Pseudo<(outs IntRegs:$rd), + (ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond), + "mov$cond %xcc, $rs2, $rd", + [(set i32:$rd, + (SPselectxcc i32:$rs2, i32:$f, imm:$cond))]>; +def MOVXCCri : Pseudo<(outs IntRegs:$rd), + (ins i32imm:$i, IntRegs:$f, CCOp:$cond), + "mov$cond %xcc, $i, $rd", + [(set i32:$rd, + (SPselecticc simm11:$i, i32:$f, imm:$cond))]>; +} // Uses, Constraints + +def : Pat<(SPselectxcc i64:$t, i64:$f, imm:$cond), + (MOVXCCrr $t, $f, imm:$cond)>; +def : Pat<(SPselectxcc (i64 simm11:$t), i64:$f, imm:$cond), + (MOVXCCri (as_i32imm $t), $f, imm:$cond)>; + +} // Predicates = [Is64Bit] diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index c2453fa04b5..5ff439583c5 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -114,6 +114,7 @@ def SPftoi : SDNode<"SPISD::FTOI", SDTSPFTOI>; def SPitof : SDNode<"SPISD::ITOF", SDTSPITOF>; def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInGlue]>; +def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>; def SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInGlue]>; // These are target-independent nodes, but have target-specific formats. diff --git a/test/CodeGen/SPARC/64cond.ll b/test/CodeGen/SPARC/64cond.ll index 694909f9e72..6e66a262a4f 100644 --- a/test/CodeGen/SPARC/64cond.ll +++ b/test/CodeGen/SPARC/64cond.ll @@ -32,3 +32,25 @@ if.then: if.end: ret void } + +; CHECK: selecti32_xcc +; CHECK: subcc %i0, %i1 +; CHECK: movg %xcc, %i2, %i3 +; CHECK: or %g0, %i3, %i0 +define i32 @selecti32_xcc(i64 %x, i64 %y, i32 %a, i32 %b) { +entry: + %tobool = icmp sgt i64 %x, %y + %rv = select i1 %tobool, i32 %a, i32 %b + ret i32 %rv +} + +; CHECK: selecti64_xcc +; CHECK: subcc %i0, %i1 +; CHECK: movg %xcc, %i2, %i3 +; CHECK: or %g0, %i3, %i0 +define i64 @selecti64_xcc(i64 %x, i64 %y, i64 %a, i64 %b) { +entry: + %tobool = icmp sgt i64 %x, %y + %rv = select i1 %tobool, i64 %a, i64 %b + ret i64 %rv +} -- 2.11.0