mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-19 04:29:45 +00:00
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
This commit is contained in:
parent
b8bfb62e85
commit
0e16488442
@ -826,6 +826,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
|||||||
|
|
||||||
if (Subtarget->is64Bit()) {
|
if (Subtarget->is64Bit()) {
|
||||||
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
|
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
|
||||||
|
setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: There are instructions available for ATOMIC_FENCE
|
// 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::BRXCC: return "SPISD::BRXCC";
|
||||||
case SPISD::BRFCC: return "SPISD::BRFCC";
|
case SPISD::BRFCC: return "SPISD::BRFCC";
|
||||||
case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC";
|
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_FCC: return "SPISD::SELECT_FCC";
|
||||||
case SPISD::Hi: return "SPISD::Hi";
|
case SPISD::Hi: return "SPISD::Hi";
|
||||||
case SPISD::Lo: return "SPISD::Lo";
|
case SPISD::Lo: return "SPISD::Lo";
|
||||||
@ -926,6 +928,7 @@ void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
|
|||||||
switch (Op.getOpcode()) {
|
switch (Op.getOpcode()) {
|
||||||
default: break;
|
default: break;
|
||||||
case SPISD::SELECT_ICC:
|
case SPISD::SELECT_ICC:
|
||||||
|
case SPISD::SELECT_XCC:
|
||||||
case SPISD::SELECT_FCC:
|
case SPISD::SELECT_FCC:
|
||||||
DAG.ComputeMaskedBits(Op.getOperand(1), KnownZero, KnownOne, Depth+1);
|
DAG.ComputeMaskedBits(Op.getOperand(1), KnownZero, KnownOne, Depth+1);
|
||||||
DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero2, KnownOne2, Depth+1);
|
DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero2, KnownOne2, Depth+1);
|
||||||
@ -946,7 +949,8 @@ static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
|
|||||||
if (isa<ConstantSDNode>(RHS) &&
|
if (isa<ConstantSDNode>(RHS) &&
|
||||||
cast<ConstantSDNode>(RHS)->isNullValue() &&
|
cast<ConstantSDNode>(RHS)->isNullValue() &&
|
||||||
CC == ISD::SETNE &&
|
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.getOperand(3).getOpcode() == SPISD::CMPICC) ||
|
||||||
(LHS.getOpcode() == SPISD::SELECT_FCC &&
|
(LHS.getOpcode() == SPISD::SELECT_FCC &&
|
||||||
LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) &&
|
LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) &&
|
||||||
@ -1064,12 +1068,13 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
|
|||||||
LookThroughSetCC(LHS, RHS, CC, SPCC);
|
LookThroughSetCC(LHS, RHS, CC, SPCC);
|
||||||
|
|
||||||
SDValue CompareFlag;
|
SDValue CompareFlag;
|
||||||
if (LHS.getValueType() == MVT::i32) {
|
if (LHS.getValueType().isInteger()) {
|
||||||
// subcc returns a value
|
// subcc returns a value
|
||||||
EVT VTs[] = { LHS.getValueType(), MVT::Glue };
|
EVT VTs[] = { LHS.getValueType(), MVT::Glue };
|
||||||
SDValue Ops[2] = { LHS, RHS };
|
SDValue Ops[2] = { LHS, RHS };
|
||||||
CompareFlag = DAG.getNode(SPISD::CMPICC, dl, VTs, Ops, 2).getValue(1);
|
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);
|
if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
|
||||||
} else {
|
} else {
|
||||||
CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS);
|
CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS);
|
||||||
|
@ -30,6 +30,7 @@ namespace llvm {
|
|||||||
BRXCC, // Branch to dest on xcc condition (64-bit only).
|
BRXCC, // Branch to dest on xcc condition (64-bit only).
|
||||||
BRFCC, // Branch to dest on fcc condition
|
BRFCC, // Branch to dest on fcc condition
|
||||||
SELECT_ICC, // Select between two values using the current ICC flags.
|
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_FCC, // Select between two values using the current FCC flags.
|
||||||
|
|
||||||
Hi, Lo, // Hi/Lo operations, typically on a global address.
|
Hi, Lo, // Hi/Lo operations, typically on a global address.
|
||||||
|
@ -19,8 +19,8 @@ let Predicates = [Is64Bit] in {
|
|||||||
// The same integer registers are used for i32 and i64 values.
|
// The same integer registers are used for i32 and i64 values.
|
||||||
// When registers hold i32 values, the high bits are don't care.
|
// When registers hold i32 values, the high bits are don't care.
|
||||||
// This give us free trunc and anyext.
|
// This give us free trunc and anyext.
|
||||||
def : Pat<(i64 (anyext i32:$val)), (COPY $val)>;
|
def : Pat<(i64 (anyext i32:$val)), (COPY_TO_REGCLASS $val, I64Regs)>;
|
||||||
def : Pat<(i32 (trunc i64:$val)), (COPY $val)>;
|
def : Pat<(i32 (trunc i64:$val)), (COPY_TO_REGCLASS $val, IntRegs)>;
|
||||||
|
|
||||||
} // Predicates = [Is64Bit]
|
} // 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
|
// We reuse CMPICC SDNodes for compares, but use new BRXCC branch nodes for
|
||||||
// 64-bit compares. See LowerBR_CC.
|
// 64-bit compares. See LowerBR_CC.
|
||||||
|
|
||||||
|
let Predicates = [Is64Bit] in {
|
||||||
|
|
||||||
let Uses = [ICC] in
|
let Uses = [ICC] in
|
||||||
def BPXCC : BranchSP<0, (ins brtarget:$dst, CCOp:$cc),
|
def BPXCC : BranchSP<0, (ins brtarget:$dst, CCOp:$cc),
|
||||||
"bp$cc %xcc, $dst",
|
"bp$cc %xcc, $dst",
|
||||||
[(SPbrxcc bb:$dst, imm:$cc)]>;
|
[(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]
|
||||||
|
@ -114,6 +114,7 @@ def SPftoi : SDNode<"SPISD::FTOI", SDTSPFTOI>;
|
|||||||
def SPitof : SDNode<"SPISD::ITOF", SDTSPITOF>;
|
def SPitof : SDNode<"SPISD::ITOF", SDTSPITOF>;
|
||||||
|
|
||||||
def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInGlue]>;
|
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 SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInGlue]>;
|
||||||
|
|
||||||
// These are target-independent nodes, but have target-specific formats.
|
// These are target-independent nodes, but have target-specific formats.
|
||||||
|
@ -32,3 +32,25 @@ if.then:
|
|||||||
if.end:
|
if.end:
|
||||||
ret void
|
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
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user