mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-25 05:25:53 +00:00
[Sparc] Custom lower addc/adde/subc/sube on i64 in sparc64.
This is required because i64 is a legal type but addxcc/subxcc reads icc carry bit, which are 32 bit conditional codes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192054 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bb0ec9840b
commit
20b10abf4e
@ -1376,6 +1376,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f128, Custom);
|
||||
|
||||
if (Subtarget->is64Bit()) {
|
||||
setOperationAction(ISD::ADDC, MVT::i64, Custom);
|
||||
setOperationAction(ISD::ADDE, MVT::i64, Custom);
|
||||
setOperationAction(ISD::SUBC, MVT::i64, Custom);
|
||||
setOperationAction(ISD::SUBE, MVT::i64, Custom);
|
||||
setOperationAction(ISD::BITCAST, MVT::f64, Expand);
|
||||
setOperationAction(ISD::BITCAST, MVT::i64, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::i64, Expand);
|
||||
@ -2426,7 +2430,54 @@ static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
|
||||
return DstReg128;
|
||||
}
|
||||
|
||||
static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
|
||||
|
||||
if (Op.getValueType() != MVT::i64)
|
||||
return Op;
|
||||
|
||||
SDLoc dl(Op);
|
||||
SDValue Src1 = Op.getOperand(0);
|
||||
SDValue Src1Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1);
|
||||
SDValue Src1Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src1,
|
||||
DAG.getConstant(32, MVT::i64));
|
||||
Src1Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1Hi);
|
||||
|
||||
SDValue Src2 = Op.getOperand(1);
|
||||
SDValue Src2Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2);
|
||||
SDValue Src2Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src2,
|
||||
DAG.getConstant(32, MVT::i64));
|
||||
Src2Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2Hi);
|
||||
|
||||
|
||||
bool hasChain = false;
|
||||
unsigned hiOpc = Op.getOpcode();
|
||||
switch (Op.getOpcode()) {
|
||||
default: llvm_unreachable("Invalid opcode");
|
||||
case ISD::ADDC: hiOpc = ISD::ADDE; break;
|
||||
case ISD::ADDE: hasChain = true; break;
|
||||
case ISD::SUBC: hiOpc = ISD::SUBE; break;
|
||||
case ISD::SUBE: hasChain = true; break;
|
||||
}
|
||||
SDValue Lo;
|
||||
SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Glue);
|
||||
if (hasChain) {
|
||||
Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo,
|
||||
Op.getOperand(2));
|
||||
} else {
|
||||
Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo);
|
||||
}
|
||||
SDValue Hi = DAG.getNode(hiOpc, dl, VTs, Src1Hi, Src2Hi, Lo.getValue(1));
|
||||
SDValue Carry = Hi.getValue(1);
|
||||
|
||||
Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Lo);
|
||||
Hi = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Hi);
|
||||
Hi = DAG.getNode(ISD::SHL, dl, MVT::i64, Hi,
|
||||
DAG.getConstant(32, MVT::i64));
|
||||
|
||||
SDValue Dst = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, Lo);
|
||||
SDValue Ops[2] = { Dst, Carry };
|
||||
return DAG.getMergeValues(Ops, 2, dl);
|
||||
}
|
||||
|
||||
SDValue SparcTargetLowering::
|
||||
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
@ -2472,6 +2523,10 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
case ISD::FABS: return LowerFABS(Op, DAG, isV9);
|
||||
case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this);
|
||||
case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this);
|
||||
case ISD::ADDC:
|
||||
case ISD::ADDE:
|
||||
case ISD::SUBC:
|
||||
case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,13 +153,6 @@ def : Pat<(xor i64:$a, (not i64:$b)), (XNORrr $a, $b)>;
|
||||
def : Pat<(add i64:$a, i64:$b), (ADDrr $a, $b)>;
|
||||
def : Pat<(sub i64:$a, i64:$b), (SUBrr $a, $b)>;
|
||||
|
||||
// Add/sub with carry were renamed to addc/subc in SPARC v9.
|
||||
def : Pat<(adde i64:$a, i64:$b), (ADDXrr $a, $b)>;
|
||||
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), (CMPrr $a, $b)>;
|
||||
|
||||
def : Pat<(tlsadd i64:$a, i64:$b, tglobaltlsaddr:$sym),
|
||||
|
@ -1,5 +1,6 @@
|
||||
; RUN: llc -march=sparc <%s | FileCheck %s -check-prefix=V8
|
||||
; RUN: llc -march=sparc -mattr=v9 <%s | FileCheck %s -check-prefix=V9
|
||||
; RUN: llc -mtriple=sparc64-unknown-linux <%s | FileCheck %s -check-prefix=SPARC64
|
||||
|
||||
|
||||
define i32 @test_addx(i64 %a, i64 %b, i64 %c) nounwind readnone noinline {
|
||||
@ -157,6 +158,16 @@ exit.1:
|
||||
; V9: subxcc
|
||||
; V9: subxcc
|
||||
|
||||
; SPARC64-LABEL: test_adde_sube
|
||||
; SPARC64: addcc
|
||||
; SPARC64: addxcc
|
||||
; SPARC64: addxcc
|
||||
; SPARC64: addxcc
|
||||
; SPARC64: subcc
|
||||
; SPARC64: subxcc
|
||||
; SPARC64: subxcc
|
||||
; SPARC64: subxcc
|
||||
|
||||
|
||||
define void @test_adde_sube(i8* %a, i8* %b, i8* %sum, i8* %diff) {
|
||||
entry:
|
||||
|
Loading…
Reference in New Issue
Block a user