Add 64-bit compare + branch for SPARC v9.

The same compare instruction is used for 32-bit and 64-bit compares. It
sets two different sets of flags: icc and xcc.

This patch adds a conditional branch instruction using the xcc flags for
64-bit compares.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178621 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2013-04-03 04:41:44 +00:00
parent 2d8f62017d
commit 8534e9998c
6 changed files with 68 additions and 5 deletions

View File

@ -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);

View File

@ -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.

View File

@ -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)]>;

View File

@ -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>;

View File

@ -43,7 +43,7 @@ class Rd<bits<5> num, string n, list<Register> subregs> : SparcReg<n> {
}
// 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

View File

@ -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
}