diff options
Diffstat (limited to 'lib/Target/CellSPU/SPUISelDAGToDAG.cpp')
-rw-r--r-- | lib/Target/CellSPU/SPUISelDAGToDAG.cpp | 125 |
1 files changed, 72 insertions, 53 deletions
diff --git a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp index 73e46fff1b..bb3b100d57 100644 --- a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp +++ b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp @@ -384,11 +384,17 @@ bool SPUDAGToDAGISel::SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Index) { // These match the addr256k operand type: - MVT::ValueType PtrVT = SPUtli.getPointerTy(); MVT::ValueType OffsVT = MVT::i16; + MVT::ValueType PtrVT = SPUtli.getPointerTy(); switch (N.getOpcode()) { case ISD::Constant: + case ISD::ConstantPool: + case ISD::GlobalAddress: + cerr << "SPU SelectAFormAddr: Constant/Pool/Global not lowered.\n"; + abort(); + /*NOTREACHED*/ + case ISD::TargetConstant: { // Loading from a constant address. ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N); @@ -400,23 +406,15 @@ SPUDAGToDAGISel::SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, return true; } } - case ISD::ConstantPool: - case ISD::TargetConstantPool: { - // The constant pool address is N. Base is a dummy that will be ignored by + case ISD::TargetGlobalAddress: + case ISD::TargetConstantPool: + case SPUISD::AFormAddr: { + // The address is in Base. N is a dummy that will be ignored by // the assembly printer. Base = N; Index = CurDAG->getTargetConstant(0, OffsVT); return true; } - - case ISD::GlobalAddress: - case ISD::TargetGlobalAddress: { - // The global address is N. Base is a dummy that is ignored by the - // assembly printer. - Base = N; - Index = CurDAG->getTargetConstant(0, OffsVT); - return true; - } } return false; @@ -445,10 +443,9 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, Index = CurDAG->getTargetConstant(0, PtrTy); return true; } else if (Opc == ISD::FrameIndex) { - // Stack frame index must be less than 512 (divided by 16): FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N); DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = " - << FI->getIndex() << "\n"); + << FI->getIndex() << "\n"); if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) { Base = CurDAG->getTargetConstant(0, PtrTy); Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy); @@ -458,45 +455,49 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, // Generated by getelementptr const SDOperand Op0 = N.getOperand(0); // Frame index/base const SDOperand Op1 = N.getOperand(1); // Offset within base - ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1); - // Not a constant? - if (CN == 0) - return false; - - int32_t offset = (int32_t) CN->getSignExtended(); - unsigned Opc0 = Op0.getOpcode(); - - if ((offset & 0xf) != 0) { - cerr << "SelectDFormAddr: unaligned offset = " << offset << "\n"; - abort(); - /*NOTREACHED*/ - } + if (Op1.getOpcode() == ISD::Constant + || Op1.getOpcode() == ISD::TargetConstant) { + ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1); + assert(CN != 0 && "SelectDFormAddr: Expected a constant"); - if (Opc0 == ISD::FrameIndex) { - FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op0); - DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset - << " frame index = " << FI->getIndex() << "\n"); + int32_t offset = (int32_t) CN->getSignExtended(); + unsigned Opc0 = Op0.getOpcode(); - if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) { - Base = CurDAG->getTargetConstant(offset, PtrTy); - Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy); - return true; + if ((offset & 0xf) != 0) { + // Unaligned offset: punt and let X-form address handle it. + // NOTE: This really doesn't have to be strictly 16-byte aligned, + // since the load/store quadword instructions will implicitly + // zero the lower 4 bits of the resulting address. + return false; } - } else if (offset > SPUFrameInfo::minFrameOffset() - && offset < SPUFrameInfo::maxFrameOffset()) { - Base = CurDAG->getTargetConstant(offset, PtrTy); - if (Opc0 == ISD::GlobalAddress) { - // Convert global address to target global address - GlobalAddressSDNode *GV = dyn_cast<GlobalAddressSDNode>(Op0); - Index = CurDAG->getTargetGlobalAddress(GV->getGlobal(), PtrTy); - return true; - } else { - // Otherwise, just take operand 0 - Index = Op0; - return true; + + if (Opc0 == ISD::FrameIndex) { + FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op0); + DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset + << " frame index = " << FI->getIndex() << "\n"); + + if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) { + Base = CurDAG->getTargetConstant(offset, PtrTy); + Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy); + return true; + } + } else if (offset > SPUFrameInfo::minFrameOffset() + && offset < SPUFrameInfo::maxFrameOffset()) { + Base = CurDAG->getTargetConstant(offset, PtrTy); + if (Opc0 == ISD::GlobalAddress) { + // Convert global address to target global address + GlobalAddressSDNode *GV = dyn_cast<GlobalAddressSDNode>(Op0); + Index = CurDAG->getTargetGlobalAddress(GV->getGlobal(), PtrTy); + return true; + } else { + // Otherwise, just take operand 0 + Index = Op0; + return true; + } } - } + } else + return false; } else if (Opc == SPUISD::DFormAddr) { // D-Form address: This is pretty straightforward, naturally... ConstantSDNode *CN = cast<ConstantSDNode>(N.getOperand(1)); @@ -504,6 +505,16 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, Base = CurDAG->getTargetConstant(CN->getValue(), PtrTy); Index = N.getOperand(0); return true; + } else if (Opc == ISD::FrameIndex) { + // Stack frame index must be less than 512 (divided by 16): + FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N); + DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = " + << FI->getIndex() << "\n"); + if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) { + Base = CurDAG->getTargetConstant(0, PtrTy); + Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy); + return true; + } } return false; @@ -535,7 +546,8 @@ SPUDAGToDAGISel::SelectXFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, unsigned N2Opc = N2.getOpcode(); if ((N1Opc == SPUISD::Hi && N2Opc == SPUISD::Lo) - || (N1Opc == SPUISD::Lo && N2Opc == SPUISD::Hi)) { + || (N1Opc == SPUISD::Lo && N2Opc == SPUISD::Hi) + || (N1Opc == SPUISD::XFormAddr)) { Base = N.getOperand(0); Index = N.getOperand(1); return true; @@ -548,6 +560,10 @@ SPUDAGToDAGISel::SelectXFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, abort(); /*UNREACHED*/ } + } else if (Opc == SPUISD::XFormAddr) { + Base = N; + Index = N.getOperand(1); + return true; } else if (N.getNumOperands() == 2) { SDOperand N1 = N.getOperand(0); SDOperand N2 = N.getOperand(1); @@ -591,11 +607,14 @@ SPUDAGToDAGISel::Select(SDOperand Op) { } else if (Opc == ISD::FrameIndex) { // Selects to AIr32 FI, 0 which in turn will become AIr32 SP, imm. int FI = cast<FrameIndexSDNode>(N)->getIndex(); - SDOperand TFI = CurDAG->getTargetFrameIndex(FI, SPUtli.getPointerTy()); + MVT::ValueType PtrVT = SPUtli.getPointerTy(); + SDOperand Zero = CurDAG->getTargetConstant(0, PtrVT); + SDOperand TFI = CurDAG->getTargetFrameIndex(FI, PtrVT); DEBUG(cerr << "SPUDAGToDAGISel: Replacing FrameIndex with AI32 <FI>, 0\n"); - return CurDAG->SelectNodeTo(N, SPU::AIr32, Op.getValueType(), TFI, - CurDAG->getTargetConstant(0, MVT::i32)); + if (N->hasOneUse()) + return CurDAG->SelectNodeTo(N, SPU::AIr32, Op.getValueType(), TFI, Zero); + CurDAG->getTargetNode(SPU::AIr32, Op.getValueType(), TFI, Zero); } else if (Opc == SPUISD::LDRESULT) { // Custom select instructions for LDRESULT unsigned VT = N->getValueType(0); |