diff options
author | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2013-10-06 03:36:18 +0000 |
---|---|---|
committer | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2013-10-06 03:36:18 +0000 |
commit | 20b10abf4e88ca532810fbf749b029ce582d6793 (patch) | |
tree | 04cdec5e29bbef663602c2cd653e8dc844971436 | |
parent | bb0ec9840bf6fd06fed967d5e70bee1983971344 (diff) | |
download | llvm-20b10abf4e88ca532810fbf749b029ce582d6793.tar.gz llvm-20b10abf4e88ca532810fbf749b029ce582d6793.tar.bz2 llvm-20b10abf4e88ca532810fbf749b029ce582d6793.tar.xz |
[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
-rw-r--r-- | lib/Target/Sparc/SparcISelLowering.cpp | 55 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcInstr64Bit.td | 7 | ||||
-rw-r--r-- | test/CodeGen/SPARC/2011-01-11-CC.ll | 11 |
3 files changed, 66 insertions, 7 deletions
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 22662c097b..8057b39e95 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -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); } } diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td index e31ba55204..d44c18dd42 100644 --- a/lib/Target/Sparc/SparcInstr64Bit.td +++ b/lib/Target/Sparc/SparcInstr64Bit.td @@ -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), diff --git a/test/CodeGen/SPARC/2011-01-11-CC.ll b/test/CodeGen/SPARC/2011-01-11-CC.ll index 30f7134722..0cb864a7d5 100644 --- a/test/CodeGen/SPARC/2011-01-11-CC.ll +++ b/test/CodeGen/SPARC/2011-01-11-CC.ll @@ -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: |