Deleted Added
full compact
15a16
> #include "MCTargetDesc/SparcMCExpr.h"
19a21
> #include "SparcTargetObjectFile.h"
83c85,86
< assert((LocVT == MVT::f32 || LocVT.getSizeInBits() == 64) &&
---
> assert((LocVT == MVT::f32 || LocVT == MVT::f128
> || LocVT.getSizeInBits() == 64) &&
87c90,92
< unsigned Offset = State.AllocateStack(8, 8);
---
> unsigned size = (LocVT == MVT::f128) ? 16 : 8;
> unsigned alignment = (LocVT == MVT::f128) ? 16 : 8;
> unsigned Offset = State.AllocateStack(size, alignment);
98a104,106
> else if (LocVT == MVT::f128 && Offset < 16*8)
> // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7).
> Reg = SP::Q0 + Offset/16;
251c259
< CCInfo.AnalyzeReturn(Outs, CC_Sparc64);
---
> CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64);
890a899,900
> unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
> ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
892c902
< Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
---
> Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
894c904
< Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
---
> Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
1000a1011
> MVT ValTy = VA.getLocVT();
1003c1014
< if (!VA.isRegLoc() || VA.getLocVT() != MVT::f64)
---
> if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128))
1013c1024,1026
< unsigned Offset = 8 * (VA.getLocReg() - SP::D0);
---
> unsigned firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0;
> unsigned argSize = (ValTy == MVT::f64) ? 8 : 16;
> unsigned Offset = argSize * (VA.getLocReg() - firstReg);
1019,1021c1032,1042
< // Full register, just bitconvert into i64.
< NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
< IReg, MVT::i64, CCValAssign::BCvt);
---
> if (ValTy == MVT::f64)
> // Full register, just bitconvert into i64.
> NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
> IReg, MVT::i64, CCValAssign::BCvt);
> else {
> assert(ValTy == MVT::f128 && "Unexpected type!");
> // Full register, just bitconvert into i128 -- We will lower this into
> // two i64s in LowerCall_64.
> NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(),
> IReg, MVT::i128, CCValAssign::BCvt);
> }
1097c1118,1122
< Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
---
> // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But
> // SPARC does not support i128 natively. Lower it into two i64, see below.
> if (!VA.needsCustom() || VA.getValVT() != MVT::f128
> || VA.getLocVT() != MVT::i128)
> Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
1101a1127,1157
> if (VA.needsCustom() && VA.getValVT() == MVT::f128
> && VA.getLocVT() == MVT::i128) {
> // Store and reload into the interger register reg and reg+1.
> unsigned Offset = 8 * (VA.getLocReg() - SP::I0);
> unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128;
> SDValue StackPtr = DAG.getRegister(SP::O6, getPointerTy());
> SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset);
> HiPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
> HiPtrOff);
> SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8);
> LoPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
> LoPtrOff);
>
> // Store to %sp+BIAS+128+Offset
> SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff,
> MachinePointerInfo(),
> false, false, 0);
> // Load into Reg and Reg+1
> SDValue Hi64 = DAG.getLoad(MVT::i64, DL, Store, HiPtrOff,
> MachinePointerInfo(),
> false, false, false, 0);
> SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff,
> MachinePointerInfo(),
> false, false, false, 0);
> RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()),
> Hi64));
> RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1),
> Lo64));
> continue;
> }
>
1158a1215,1216
> unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
> ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
1160c1218,1219
< Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy());
---
> Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0,
> TF);
1162c1221
< Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy());
---
> Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF);
1203d1261
< RVInfo.AnalyzeCallResult(CLI.Ins, CC_Sparc64);
1204a1263,1269
> // Set inreg flag manually for codegen generated library calls that
> // return float.
> if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0)
> CLI.Ins[0].Flags.setInReg();
>
> RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64);
>
1306c1371
< : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
---
> : TargetLowering(TM, new SparcELFTargetObjectFile()) {
1406c1471,1472
< setOperationAction(ISD::CTPOP, MVT::i64, Legal);
---
> setOperationAction(ISD::CTPOP, MVT::i64,
> Subtarget->usePopc() ? Legal : Expand);
1417,1419c1483,1485
< // FIXME: There are instructions available for ATOMIC_FENCE
< // on SparcV8 and later.
< setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
---
> // ATOMICs.
> // FIXME: We insert fences for each atomics and generate sub-optimal code
> // for PSO/TSO. Also, implement other atomicrmw operations.
1420a1487,1506
> setInsertFencesForAtomic(true);
>
> setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal);
> setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32,
> (Subtarget->isV9() ? Legal: Expand));
>
>
> setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal);
>
> // Custom Lower Atomic LOAD/STORE
> setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
> setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
>
> if (Subtarget->is64Bit()) {
> setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal);
> setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal);
> setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
> setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
> }
>
1442d1527
< setOperationAction(ISD::CTPOP, MVT::i32, Expand);
1469a1555,1561
>
> setOperationAction(ISD::UMULO, MVT::i64, Custom);
> setOperationAction(ISD::SMULO, MVT::i64, Custom);
>
> setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
> setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
> setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
1476a1569,1570
> setOperationAction(ISD::TRAP , MVT::Other, Legal);
>
1489,1490c1583,1584
< if (Subtarget->isV9())
< setOperationAction(ISD::CTPOP, MVT::i32, Legal);
---
> setOperationAction(ISD::CTPOP, MVT::i32,
> Subtarget->usePopc() ? Legal : Expand);
1717c1811,1812
< SDValue HiLo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
---
> SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
> SparcMCExpr::VK_Sparc_GOT10, DAG);
1732d1826
< case CodeModel::JITDefault:
1735c1829,1830
< return makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
---
> return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
> SparcMCExpr::VK_Sparc_LO, DAG);
1738c1833,1834
< SDValue H44 = makeHiLoPair(Op, SPII::MO_H44, SPII::MO_M44, DAG);
---
> SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44,
> SparcMCExpr::VK_Sparc_M44, DAG);
1740c1836
< SDValue L44 = withTargetFlags(Op, SPII::MO_L44, DAG);
---
> SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG);
1746c1842,1843
< SDValue Hi = makeHiLoPair(Op, SPII::MO_HH, SPII::MO_HM, DAG);
---
> SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH,
> SparcMCExpr::VK_Sparc_HM, DAG);
1748c1845,1846
< SDValue Lo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
---
> SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
> SparcMCExpr::VK_Sparc_LO, DAG);
1780,1787c1878,1889
< unsigned HiTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_HI22
< : SPII::MO_TLS_LDM_HI22);
< unsigned LoTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_LO10
< : SPII::MO_TLS_LDM_LO10);
< unsigned addTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_ADD
< : SPII::MO_TLS_LDM_ADD);
< unsigned callTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_CALL
< : SPII::MO_TLS_LDM_CALL);
---
> unsigned HiTF = ((model == TLSModel::GeneralDynamic)
> ? SparcMCExpr::VK_Sparc_TLS_GD_HI22
> : SparcMCExpr::VK_Sparc_TLS_LDM_HI22);
> unsigned LoTF = ((model == TLSModel::GeneralDynamic)
> ? SparcMCExpr::VK_Sparc_TLS_GD_LO10
> : SparcMCExpr::VK_Sparc_TLS_LDM_LO10);
> unsigned addTF = ((model == TLSModel::GeneralDynamic)
> ? SparcMCExpr::VK_Sparc_TLS_GD_ADD
> : SparcMCExpr::VK_Sparc_TLS_LDM_ADD);
> unsigned callTF = ((model == TLSModel::GeneralDynamic)
> ? SparcMCExpr::VK_Sparc_TLS_GD_CALL
> : SparcMCExpr::VK_Sparc_TLS_LDM_CALL);
1825c1927
< withTargetFlags(Op, SPII::MO_TLS_LDO_HIX22, DAG));
---
> withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG));
1827c1929
< withTargetFlags(Op, SPII::MO_TLS_LDO_LOX10, DAG));
---
> withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG));
1830c1932
< withTargetFlags(Op, SPII::MO_TLS_LDO_ADD, DAG));
---
> withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG));
1834,1835c1936,1937
< unsigned ldTF = ((PtrVT == MVT::i64)? SPII::MO_TLS_IE_LDX
< : SPII::MO_TLS_IE_LD);
---
> unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX
> : SparcMCExpr::VK_Sparc_TLS_IE_LD);
1845c1947,1948
< SPII::MO_TLS_IE_HI22, SPII::MO_TLS_IE_LO10, DAG);
---
> SparcMCExpr::VK_Sparc_TLS_IE_HI22,
> SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG);
1852c1955,1956
< withTargetFlags(Op, SPII::MO_TLS_IE_ADD, DAG));
---
> withTargetFlags(Op,
> SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG));
1857c1961
< withTargetFlags(Op, SPII::MO_TLS_LE_HIX22, DAG));
---
> withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG));
1859c1963
< withTargetFlags(Op, SPII::MO_TLS_LE_LOX10, DAG));
---
> withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG));
2337c2441,2442
< static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
---
> static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
> const SparcSubtarget *Subtarget) {
2343a2449
> unsigned stackBias = Subtarget->getStackPointerBias();
2345,2346d2450
< uint64_t depth = Op.getConstantOperandVal(0);
<
2348c2452,2453
< if (depth == 0)
---
>
> if (depth == 0) {
2350,2353c2455,2459
< else {
< // flush first to make sure the windowed registers' values are in stack
< SDValue Chain = getFLUSHW(Op, DAG);
< FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
---
> if (Subtarget->is64Bit())
> FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
> DAG.getIntPtrConstant(stackBias));
> return FrameAddr;
> }
2355,2363c2461,2471
< for (uint64_t i = 0; i != depth; ++i) {
< SDValue Ptr = DAG.getNode(ISD::ADD,
< dl, MVT::i32,
< FrameAddr, DAG.getIntPtrConstant(56));
< FrameAddr = DAG.getLoad(MVT::i32, dl,
< Chain,
< Ptr,
< MachinePointerInfo(), false, false, false, 0);
< }
---
> // flush first to make sure the windowed registers' values are in stack
> SDValue Chain = getFLUSHW(Op, DAG);
> FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
>
> unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
>
> while (depth--) {
> SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
> DAG.getIntPtrConstant(Offset));
> FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(),
> false, false, false, 0);
2364a2473,2475
> if (Subtarget->is64Bit())
> FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
> DAG.getIntPtrConstant(stackBias));
2367a2479,2488
>
> static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
> const SparcSubtarget *Subtarget) {
>
> uint64_t depth = Op.getConstantOperandVal(0);
>
> return getFRAMEADDR(depth, Op, DAG, Subtarget);
>
> }
>
2369c2490,2491
< const SparcTargetLowering &TLI) {
---
> const SparcTargetLowering &TLI,
> const SparcSubtarget *Subtarget) {
2383,2385c2505,2506
< } else {
< // Need frame address to find return address of the caller.
< MFI->setFrameAddressIsTaken(true);
---
> return RetAddr;
> }
2387,2389c2508,2509
< // flush first to make sure the windowed registers' values are in stack
< SDValue Chain = getFLUSHW(Op, DAG);
< RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT);
---
> // Need frame address to find return address of the caller.
> SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget);
2391,2401c2511,2518
< for (uint64_t i = 0; i != depth; ++i) {
< SDValue Ptr = DAG.getNode(ISD::ADD,
< dl, MVT::i32,
< RetAddr,
< DAG.getIntPtrConstant((i == depth-1)?60:56));
< RetAddr = DAG.getLoad(MVT::i32, dl,
< Chain,
< Ptr,
< MachinePointerInfo(), false, false, false, 0);
< }
< }
---
> unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
> SDValue Ptr = DAG.getNode(ISD::ADD,
> dl, VT,
> FrameAddr,
> DAG.getIntPtrConstant(Offset));
> RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr,
> MachinePointerInfo(), false, false, false, 0);
>
2530,2538c2647,2648
< static SDValue LowerFNEG(SDValue Op, SelectionDAG &DAG,
< const SparcTargetLowering &TLI,
< bool is64Bit) {
< if (Op.getValueType() == MVT::f64)
< return LowerF64Op(Op, DAG, ISD::FNEG);
< if (Op.getValueType() == MVT::f128)
< return TLI.LowerF128Op(Op, DAG, ((is64Bit) ? "_Qp_neg" : "_Q_neg"), 1);
< return Op;
< }
---
> static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
> assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) && "invalid");
2540d2649
< static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
2542c2651
< return LowerF64Op(Op, DAG, ISD::FABS);
---
> return LowerF64Op(Op, DAG, Op.getOpcode());
2546,2547c2655,2656
< // Lower fabs on f128 to fabs on f64
< // fabs f128 => fabs f64:sub_even64, fmov f64:sub_odd64
---
> // Lower fabs/fneg on f128 to fabs/fneg on f64
> // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64
2558c2667
< Hi64 = LowerF64Op(Hi64, DAG, ISD::FABS);
---
> Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode());
2617a2727,2783
> // Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode()
> // in LegalizeDAG.cpp except the order of arguments to the library function.
> static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG,
> const SparcTargetLowering &TLI)
> {
> unsigned opcode = Op.getOpcode();
> assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode.");
>
> bool isSigned = (opcode == ISD::SMULO);
> EVT VT = MVT::i64;
> EVT WideVT = MVT::i128;
> SDLoc dl(Op);
> SDValue LHS = Op.getOperand(0);
>
> if (LHS.getValueType() != VT)
> return Op;
>
> SDValue ShiftAmt = DAG.getConstant(63, VT);
>
> SDValue RHS = Op.getOperand(1);
> SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt);
> SDValue HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt);
> SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
>
> SDValue MulResult = TLI.makeLibCall(DAG,
> RTLIB::MUL_I128, WideVT,
> Args, 4, isSigned, dl).first;
> SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
> MulResult, DAG.getIntPtrConstant(0));
> SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
> MulResult, DAG.getIntPtrConstant(1));
> if (isSigned) {
> SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt);
> TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE);
> } else {
> TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, VT),
> ISD::SETNE);
> }
> // MulResult is a node with an illegal type. Because such things are not
> // generally permitted during this phase of legalization, delete the
> // node. The above EXTRACT_ELEMENT nodes should have been folded.
> DAG.DeleteNode(MulResult.getNode());
>
> SDValue Ops[2] = { BottomHalf, TopHalf } ;
> return DAG.getMergeValues(Ops, 2, dl);
> }
>
> static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
> // Monotonic load/stores are legal.
> if (cast<AtomicSDNode>(Op)->getOrdering() <= Monotonic)
> return Op;
>
> // Otherwise, expand with a fence.
> return SDValue();
> }
>
>
2622d2787
< bool is64Bit = Subtarget->is64Bit();
2628,2629c2793,2796
< case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this);
< case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
---
> case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this,
> Subtarget);
> case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG,
> Subtarget);
2663,2664c2830,2831
< case ISD::FNEG: return LowerFNEG(Op, DAG, *this, is64Bit);
< case ISD::FABS: return LowerFABS(Op, DAG, isV9);
---
> case ISD::FABS:
> case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9);
2670a2838,2841
> case ISD::UMULO:
> case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this);
> case ISD::ATOMIC_LOAD:
> case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG);
2677,2681d2847
< const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
< unsigned BROpcode;
< unsigned CC;
< DebugLoc dl = MI->getDebugLoc();
< // Figure out the conditional branch opcode to use for this select_cc.
2688,2689c2854
< BROpcode = SP::BCOND;
< break;
---
> return expandSelectCC(MI, BB, SP::BCOND);
2694,2695c2859,2904
< BROpcode = SP::FBCOND;
< break;
---
> return expandSelectCC(MI, BB, SP::FBCOND);
>
> case SP::ATOMIC_LOAD_ADD_32:
> return expandAtomicRMW(MI, BB, SP::ADDrr);
> case SP::ATOMIC_LOAD_ADD_64:
> return expandAtomicRMW(MI, BB, SP::ADDXrr);
> case SP::ATOMIC_LOAD_SUB_32:
> return expandAtomicRMW(MI, BB, SP::SUBrr);
> case SP::ATOMIC_LOAD_SUB_64:
> return expandAtomicRMW(MI, BB, SP::SUBXrr);
> case SP::ATOMIC_LOAD_AND_32:
> return expandAtomicRMW(MI, BB, SP::ANDrr);
> case SP::ATOMIC_LOAD_AND_64:
> return expandAtomicRMW(MI, BB, SP::ANDXrr);
> case SP::ATOMIC_LOAD_OR_32:
> return expandAtomicRMW(MI, BB, SP::ORrr);
> case SP::ATOMIC_LOAD_OR_64:
> return expandAtomicRMW(MI, BB, SP::ORXrr);
> case SP::ATOMIC_LOAD_XOR_32:
> return expandAtomicRMW(MI, BB, SP::XORrr);
> case SP::ATOMIC_LOAD_XOR_64:
> return expandAtomicRMW(MI, BB, SP::XORXrr);
> case SP::ATOMIC_LOAD_NAND_32:
> return expandAtomicRMW(MI, BB, SP::ANDrr);
> case SP::ATOMIC_LOAD_NAND_64:
> return expandAtomicRMW(MI, BB, SP::ANDXrr);
>
> case SP::ATOMIC_SWAP_64:
> return expandAtomicRMW(MI, BB, 0);
>
> case SP::ATOMIC_LOAD_MAX_32:
> return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G);
> case SP::ATOMIC_LOAD_MAX_64:
> return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_G);
> case SP::ATOMIC_LOAD_MIN_32:
> return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LE);
> case SP::ATOMIC_LOAD_MIN_64:
> return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LE);
> case SP::ATOMIC_LOAD_UMAX_32:
> return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_GU);
> case SP::ATOMIC_LOAD_UMAX_64:
> return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_GU);
> case SP::ATOMIC_LOAD_UMIN_32:
> return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LEU);
> case SP::ATOMIC_LOAD_UMIN_64:
> return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LEU);
2696a2906
> }
2698c2908,2914
< CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
---
> MachineBasicBlock*
> SparcTargetLowering::expandSelectCC(MachineInstr *MI,
> MachineBasicBlock *BB,
> unsigned BROpcode) const {
> const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
> DebugLoc dl = MI->getDebugLoc();
> unsigned CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
2751a2968,3062
> MachineBasicBlock*
> SparcTargetLowering::expandAtomicRMW(MachineInstr *MI,
> MachineBasicBlock *MBB,
> unsigned Opcode,
> unsigned CondCode) const {
> const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
> MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
> DebugLoc DL = MI->getDebugLoc();
>
> // MI is an atomic read-modify-write instruction of the form:
> //
> // rd = atomicrmw<op> addr, rs2
> //
> // All three operands are registers.
> unsigned DestReg = MI->getOperand(0).getReg();
> unsigned AddrReg = MI->getOperand(1).getReg();
> unsigned Rs2Reg = MI->getOperand(2).getReg();
>
> // SelectionDAG has already inserted memory barriers before and after MI, so
> // we simply have to implement the operatiuon in terms of compare-and-swap.
> //
> // %val0 = load %addr
> // loop:
> // %val = phi %val0, %dest
> // %upd = op %val, %rs2
> // %dest = cas %addr, %val, %upd
> // cmp %val, %dest
> // bne loop
> // done:
> //
> bool is64Bit = SP::I64RegsRegClass.hasSubClassEq(MRI.getRegClass(DestReg));
> const TargetRegisterClass *ValueRC =
> is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
> unsigned Val0Reg = MRI.createVirtualRegister(ValueRC);
>
> BuildMI(*MBB, MI, DL, TII.get(is64Bit ? SP::LDXri : SP::LDri), Val0Reg)
> .addReg(AddrReg).addImm(0);
>
> // Split the basic block MBB before MI and insert the loop block in the hole.
> MachineFunction::iterator MFI = MBB;
> const BasicBlock *LLVM_BB = MBB->getBasicBlock();
> MachineFunction *MF = MBB->getParent();
> MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
> MachineBasicBlock *DoneMBB = MF->CreateMachineBasicBlock(LLVM_BB);
> ++MFI;
> MF->insert(MFI, LoopMBB);
> MF->insert(MFI, DoneMBB);
>
> // Move MI and following instructions to DoneMBB.
> DoneMBB->splice(DoneMBB->begin(), MBB, MI, MBB->end());
> DoneMBB->transferSuccessorsAndUpdatePHIs(MBB);
>
> // Connect the CFG again.
> MBB->addSuccessor(LoopMBB);
> LoopMBB->addSuccessor(LoopMBB);
> LoopMBB->addSuccessor(DoneMBB);
>
> // Build the loop block.
> unsigned ValReg = MRI.createVirtualRegister(ValueRC);
> // Opcode == 0 means try to write Rs2Reg directly (ATOMIC_SWAP).
> unsigned UpdReg = (Opcode ? MRI.createVirtualRegister(ValueRC) : Rs2Reg);
>
> BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg)
> .addReg(Val0Reg).addMBB(MBB)
> .addReg(DestReg).addMBB(LoopMBB);
>
> if (CondCode) {
> // This is one of the min/max operations. We need a CMPrr followed by a
> // MOVXCC/MOVICC.
> BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg);
> BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg)
> .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode);
> } else if (Opcode) {
> BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg)
> .addReg(ValReg).addReg(Rs2Reg);
> }
>
> if (MI->getOpcode() == SP::ATOMIC_LOAD_NAND_32 ||
> MI->getOpcode() == SP::ATOMIC_LOAD_NAND_64) {
> unsigned TmpReg = UpdReg;
> UpdReg = MRI.createVirtualRegister(ValueRC);
> BuildMI(LoopMBB, DL, TII.get(SP::XORri), UpdReg).addReg(TmpReg).addImm(-1);
> }
>
> BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg)
> .addReg(AddrReg).addReg(ValReg).addReg(UpdReg)
> .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
> BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg);
> BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND))
> .addMBB(LoopMBB).addImm(SPCC::ICC_NE);
>
> MI->eraseFromParent();
> return DoneMBB;
> }
>
2763a3075,3076
> case 'I': // SIMM13
> return C_Other;
2769a3083,3140
> TargetLowering::ConstraintWeight SparcTargetLowering::
> getSingleConstraintMatchWeight(AsmOperandInfo &info,
> const char *constraint) const {
> ConstraintWeight weight = CW_Invalid;
> Value *CallOperandVal = info.CallOperandVal;
> // If we don't have a value, we can't do a match,
> // but allow it at the lowest weight.
> if (CallOperandVal == NULL)
> return CW_Default;
>
> // Look at the constraint type.
> switch (*constraint) {
> default:
> weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
> break;
> case 'I': // SIMM13
> if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
> if (isInt<13>(C->getSExtValue()))
> weight = CW_Constant;
> }
> break;
> }
> return weight;
> }
>
> /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
> /// vector. If it is invalid, don't add anything to Ops.
> void SparcTargetLowering::
> LowerAsmOperandForConstraint(SDValue Op,
> std::string &Constraint,
> std::vector<SDValue> &Ops,
> SelectionDAG &DAG) const {
> SDValue Result(0, 0);
>
> // Only support length 1 constraints for now.
> if (Constraint.length() > 1)
> return;
>
> char ConstraintLetter = Constraint[0];
> switch (ConstraintLetter) {
> default: break;
> case 'I':
> if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
> if (isInt<13>(C->getSExtValue())) {
> Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType());
> break;
> }
> return;
> }
> }
>
> if (Result.getNode()) {
> Ops.push_back(Result);
> return;
> }
> TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
> }
>
2777a3149,3168
> } else if (!Constraint.empty() && Constraint.size() <= 5
> && Constraint[0] == '{' && *(Constraint.end()-1) == '}') {
> // constraint = '{r<d>}'
> // Remove the braces from around the name.
> StringRef name(Constraint.data()+1, Constraint.size()-2);
> // Handle register aliases:
> // r0-r7 -> g0-g7
> // r8-r15 -> o0-o7
> // r16-r23 -> l0-l7
> // r24-r31 -> i0-i7
> uint64_t intVal = 0;
> if (name.substr(0, 1).equals("r")
> && !name.substr(1).getAsInteger(10, intVal) && intVal <= 31) {
> const char regTypes[] = { 'g', 'o', 'l', 'i' };
> char regType = regTypes[intVal/8];
> char regIdx = '0' + (intVal % 8);
> char tmp[] = { '{', regType, regIdx, '}', 0 };
> std::string newConstraint = std::string(tmp);
> return TargetLowering::getRegForInlineAsmConstraint(newConstraint, VT);
> }