diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 789ef0c0721..a9ce75a7eb8 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -824,6 +824,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); + if (Subtarget->is64Bit()) { + setOperationAction(ISD::BR_CC, MVT::i64, Custom); + } + // FIXME: There are instructions available for ATOMIC_FENCE // on SparcV8 and later. setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); @@ -893,6 +897,7 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { case SPISD::CMPICC: return "SPISD::CMPICC"; case SPISD::CMPFCC: return "SPISD::CMPFCC"; case SPISD::BRICC: return "SPISD::BRICC"; + case SPISD::BRXCC: return "SPISD::BRXCC"; case SPISD::BRFCC: return "SPISD::BRFCC"; case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; @@ -1029,12 +1034,13 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) { // Get the condition flag. SDValue CompareFlag; - if (LHS.getValueType() == MVT::i32) { - EVT VTs[] = { MVT::i32, MVT::Glue }; + if (LHS.getValueType().isInteger()) { + EVT VTs[] = { LHS.getValueType(), MVT::Glue }; SDValue Ops[2] = { LHS, RHS }; CompareFlag = DAG.getNode(SPISD::CMPICC, dl, VTs, Ops, 2).getValue(1); if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); - Opc = SPISD::BRICC; + // 32-bit compares use the icc flags, 64-bit uses the xcc flags. + Opc = LHS.getValueType() == MVT::i32 ? SPISD::BRICC : SPISD::BRXCC; } else { CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h index 08e6f211bf3..274673cd4da 100644 --- a/lib/Target/Sparc/SparcISelLowering.h +++ b/lib/Target/Sparc/SparcISelLowering.h @@ -24,9 +24,10 @@ namespace llvm { namespace SPISD { enum { FIRST_NUMBER = ISD::BUILTIN_OP_END, - CMPICC, // Compare two GPR operands, set icc. + CMPICC, // Compare two GPR operands, set icc+xcc. CMPFCC, // Compare two FP operands, set fcc. BRICC, // Branch to dest on icc condition + 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_FCC, // Select between two values using the current FCC flags. diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td index e7c505c8546..a726b358a10 100644 --- a/lib/Target/Sparc/SparcInstr64Bit.td +++ b/lib/Target/Sparc/SparcInstr64Bit.td @@ -161,6 +161,8 @@ def : Pat<(sube i64:$a, i64:$b), (SUBXrr $a, $b)>; def : Pat<(addc i64:$a, i64:$b), (ADDCCrr $a, $b)>; def : Pat<(subc i64:$a, i64:$b), (SUBCCrr $a, $b)>; +def : Pat<(SPcmpicc i64:$a, i64:$b), (SUBCCrr $a, $b)>; + // Register-immediate instructions. def : Pat<(and i64:$a, (i64 simm13:$b)), (ANDri $a, (as_i32imm $b))>; @@ -170,6 +172,8 @@ def : Pat<(xor i64:$a, (i64 simm13:$b)), (XORri $a, (as_i32imm $b))>; def : Pat<(add i64:$a, (i64 simm13:$b)), (ADDri $a, (as_i32imm $b))>; def : Pat<(sub i64:$a, (i64 simm13:$b)), (SUBri $a, (as_i32imm $b))>; +def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (SUBCCri $a, (as_i32imm $b))>; + } // Predicates = [Is64Bit] @@ -239,3 +243,20 @@ def : Pat<(truncstorei32 i64:$src, ADDRrr:$addr), (STrr ADDRrr:$addr, $src)>; def : Pat<(truncstorei32 i64:$src, ADDRri:$addr), (STri ADDRri:$addr, $src)>; } // Predicates = [Is64Bit] + + +//===----------------------------------------------------------------------===// +// 64-bit Conditionals. +//===----------------------------------------------------------------------===// +// +// Flag-setting instructions like subcc and addcc set both icc and xcc flags. +// The icc flags correspond to the 32-bit result, and the xcc are for the +// full 64-bit result. +// +// We reuse CMPICC SDNodes for compares, but use new BRXCC branch nodes for +// 64-bit compares. See LowerBR_CC. + +let Uses = [ICC] in +def BPXCC : BranchSP<0, (ins brtarget:$dst, CCOp:$cc), + "bp$cc %xcc, $dst", + [(SPbrxcc bb:$dst, imm:$cc)]>; diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index b5a02780fb8..c2453fa04b5 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -104,6 +104,7 @@ SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>; def SPcmpicc : SDNode<"SPISD::CMPICC", SDTIntBinOp, [SDNPOutGlue]>; def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>; def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; +def SPbrxcc : SDNode<"SPISD::BRXCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; def SPbrfcc : SDNode<"SPISD::BRFCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; def SPhi : SDNode<"SPISD::Hi", SDTIntUnaryOp>; diff --git a/lib/Target/Sparc/SparcRegisterInfo.td b/lib/Target/Sparc/SparcRegisterInfo.td index e8ccd20af8b..497e7c5d561 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.td +++ b/lib/Target/Sparc/SparcRegisterInfo.td @@ -43,7 +43,7 @@ class Rd num, string n, list subregs> : SparcReg { } // Control Registers -def ICC : SparcCtrlReg<"ICC">; +def ICC : SparcCtrlReg<"ICC">; // This represents icc and xcc in 64-bit code. def FCC : SparcCtrlReg<"FCC">; // Y register diff --git a/test/CodeGen/SPARC/64cond.ll b/test/CodeGen/SPARC/64cond.ll new file mode 100644 index 00000000000..694909f9e72 --- /dev/null +++ b/test/CodeGen/SPARC/64cond.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s -march=sparcv9 | FileCheck %s +; Testing 64-bit conditionals. + +; CHECK: cmpri +; CHECK: subcc %i1, 1 +; CHECK: bpe %xcc, +define void @cmpri(i64* %p, i64 %x) { +entry: + %tobool = icmp eq i64 %x, 1 + br i1 %tobool, label %if.end, label %if.then + +if.then: + store i64 %x, i64* %p, align 8 + br label %if.end + +if.end: + ret void +} + +; CHECK: cmprr +; CHECK: subcc %i1, %i2 +; CHECK: bpgu %xcc, +define void @cmprr(i64* %p, i64 %x, i64 %y) { +entry: + %tobool = icmp ugt i64 %x, %y + br i1 %tobool, label %if.end, label %if.then + +if.then: + store i64 %x, i64* %p, align 8 + br label %if.end + +if.end: + ret void +}