diff options
Diffstat (limited to 'llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp')
-rw-r--r-- | llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp | 270 |
1 files changed, 103 insertions, 167 deletions
diff --git a/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp b/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp index 3905d553029..8bde66300a1 100644 --- a/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp +++ b/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp @@ -165,26 +165,25 @@ namespace { struct valtype_map_s { MVT::ValueType VT; - unsigned ldresult_ins; /// LDRESULT instruction (0 = undefined) - int prefslot_byte; /// Byte offset of the "preferred" slot - unsigned insmask_ins; /// Insert mask instruction for a-form + unsigned ldresult_ins; /// LDRESULT instruction (0 = undefined) + int prefslot_byte; /// Byte offset of the "preferred" slot }; const valtype_map_s valtype_map[] = { - { MVT::i1, 0, 3, 0 }, - { MVT::i8, SPU::ORBIr8, 3, 0 }, - { MVT::i16, SPU::ORHIr16, 2, 0 }, - { MVT::i32, SPU::ORIr32, 0, 0 }, - { MVT::i64, SPU::ORIr64, 0, 0 }, - { MVT::f32, 0, 0, 0 }, - { MVT::f64, 0, 0, 0 }, + { MVT::i1, 0, 3 }, + { MVT::i8, SPU::ORBIr8, 3 }, + { MVT::i16, SPU::ORHIr16, 2 }, + { MVT::i32, SPU::ORIr32, 0 }, + { MVT::i64, SPU::ORIr64, 0 }, + { MVT::f32, 0, 0 }, + { MVT::f64, 0, 0 }, // vector types... (sigh!) - { MVT::v16i8, 0, 0, SPU::CBD }, - { MVT::v8i16, 0, 0, SPU::CHD }, - { MVT::v4i32, 0, 0, SPU::CWD }, - { MVT::v2i64, 0, 0, 0 }, - { MVT::v4f32, 0, 0, SPU::CWD }, - { MVT::v2f64, 0, 0, 0 } + { MVT::v16i8, 0, 0 }, + { MVT::v8i16, 0, 0 }, + { MVT::v4i32, 0, 0 }, + { MVT::v2i64, 0, 0 }, + { MVT::v4f32, 0, 0 }, + { MVT::v2f64, 0, 0 } }; const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]); @@ -194,8 +193,8 @@ namespace { const valtype_map_s *retval = 0; for (size_t i = 0; i < n_valtype_map; ++i) { if (valtype_map[i].VT == VT) { - retval = valtype_map + i; - break; + retval = valtype_map + i; + break; } } @@ -203,8 +202,8 @@ namespace { #ifndef NDEBUG if (retval == 0) { cerr << "SPUISelDAGToDAG.cpp: getValueTypeMapEntry returns NULL for " - << MVT::getValueTypeString(VT) - << "\n"; + << MVT::getValueTypeString(VT) + << "\n"; abort(); } #endif @@ -259,42 +258,46 @@ public: /// target-specific node if it hasn't already been changed. SDNode *Select(SDOperand Op); - /// Return true if the address N is a RI7 format address [r+imm] - bool SelectDForm2Addr(SDOperand Op, SDOperand N, SDOperand &Disp, - SDOperand &Base); - //! Returns true if the address N is an A-form (local store) address bool SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Index); + SDOperand &Index); //! D-form address predicate bool SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Index); + SDOperand &Index); + + /// Alternate D-form address using i7 offset predicate + bool SelectDForm2Addr(SDOperand Op, SDOperand N, SDOperand &Disp, + SDOperand &Base); + + /// D-form address selection workhorse + bool DFormAddressPredicate(SDOperand Op, SDOperand N, SDOperand &Disp, + SDOperand &Base, int minOffset, int maxOffset); //! Address predicate if N can be expressed as an indexed [r+r] operation. bool SelectXFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Index); + SDOperand &Index); /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for /// inline asm expressions. virtual bool SelectInlineAsmMemoryOperand(const SDOperand &Op, - char ConstraintCode, - std::vector<SDOperand> &OutOps, - SelectionDAG &DAG) { + char ConstraintCode, + std::vector<SDOperand> &OutOps, + SelectionDAG &DAG) { SDOperand Op0, Op1; switch (ConstraintCode) { default: return true; case 'm': // memory if (!SelectDFormAddr(Op, Op, Op0, Op1) - && !SelectAFormAddr(Op, Op, Op0, Op1)) - SelectXFormAddr(Op, Op, Op0, Op1); + && !SelectAFormAddr(Op, Op, Op0, Op1)) + SelectXFormAddr(Op, Op, Op0, Op1); break; case 'o': // offsetable if (!SelectDFormAddr(Op, Op, Op0, Op1) - && !SelectAFormAddr(Op, Op, Op0, Op1)) { - Op0 = Op; - AddToISelQueue(Op0); // r+0. - Op1 = getSmallIPtrImm(0); + && !SelectAFormAddr(Op, Op, Op0, Op1)) { + Op0 = Op; + AddToISelQueue(Op0); // r+0. + Op1 = getSmallIPtrImm(0); } break; case 'v': // not offsetable @@ -346,52 +349,6 @@ SPUDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) ScheduleAndEmitDAG(DAG); } -bool -SPUDAGToDAGISel::SelectDForm2Addr(SDOperand Op, SDOperand N, SDOperand &Disp, - SDOperand &Base) { - unsigned Opc = N.getOpcode(); - unsigned VT = N.getValueType(); - MVT::ValueType PtrVT = SPUtli.getPointerTy(); - ConstantSDNode *CN = 0; - int Imm; - - if (Opc == ISD::ADD) { - SDOperand Op0 = N.getOperand(0); - SDOperand Op1 = N.getOperand(1); - if (Op1.getOpcode() == ISD::Constant || - Op1.getOpcode() == ISD::TargetConstant) { - CN = cast<ConstantSDNode>(Op1); - Imm = int(CN->getValue()); - if (Imm <= 0xff) { - Disp = CurDAG->getTargetConstant(Imm, SPUtli.getPointerTy()); - Base = Op0; - return true; - } - } - } else if (Opc == ISD::GlobalAddress - || Opc == ISD::TargetGlobalAddress - || Opc == ISD::Register) { - // Plain old local store address: - Disp = CurDAG->getTargetConstant(0, VT); - Base = N; - return true; - } else if (Opc == SPUISD::IndirectAddr) { - SDOperand Op1 = N.getOperand(1); - if (Op1.getOpcode() == ISD::TargetConstant - || Op1.getOpcode() == ISD::Constant) { - CN = cast<ConstantSDNode>(N.getOperand(1)); - assert(CN != 0 && "SelectIndirectAddr/SPUISD::DForm2Addr expecting constant"); - Imm = unsigned(CN->getValue()); - if (Imm < 0xff) { - Disp = CurDAG->getTargetConstant(CN->getValue(), PtrVT); - Base = N.getOperand(0); - return true; - } - } - } - return false; -} - /*! \arg Op The ISD instructio operand \arg N The address to be tested @@ -400,7 +357,7 @@ SPUDAGToDAGISel::SelectDForm2Addr(SDOperand Op, SDOperand N, SDOperand &Disp, */ bool SPUDAGToDAGISel::SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Index) { + SDOperand &Index) { // These match the addr256k operand type: MVT::ValueType OffsVT = MVT::i16; SDOperand Zero = CurDAG->getTargetConstant(0, OffsVT); @@ -450,6 +407,12 @@ SPUDAGToDAGISel::SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, return false; } +bool +SPUDAGToDAGISel::SelectDForm2Addr(SDOperand Op, SDOperand N, SDOperand &Disp, + SDOperand &Base) { + return DFormAddressPredicate(Op, N, Disp, Base, -(1 << 7), (1 << 7) - 1); +} + /*! \arg Op The ISD instruction (ignored) \arg N The address to be tested @@ -464,7 +427,16 @@ SPUDAGToDAGISel::SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, */ bool SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Index) { + SDOperand &Index) { + return DFormAddressPredicate(Op, N, Base, Index, + SPUFrameInfo::minFrameOffset(), + SPUFrameInfo::maxFrameOffset()); +} + +bool +SPUDAGToDAGISel::DFormAddressPredicate(SDOperand Op, SDOperand N, SDOperand &Base, + SDOperand &Index, int minOffset, + int maxOffset) { unsigned Opc = N.getOpcode(); unsigned PtrTy = SPUtli.getPointerTy(); @@ -472,8 +444,8 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, // 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()) { + << FI->getIndex() << "\n"); + if (FI->getIndex() < maxOffset) { Base = CurDAG->getTargetConstant(0, PtrTy); Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy); return true; @@ -498,13 +470,12 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset << " frame index = " << FI->getIndex() << "\n"); - if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) { + if (FI->getIndex() < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy); return true; } - } else if (offset > SPUFrameInfo::minFrameOffset() - && offset < SPUFrameInfo::maxFrameOffset()) { + } else if (offset > minOffset && offset < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = Op0; return true; @@ -519,13 +490,12 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset << " frame index = " << FI->getIndex() << "\n"); - if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) { + if (FI->getIndex() < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy); return true; } - } else if (offset > SPUFrameInfo::minFrameOffset() - && offset < SPUFrameInfo::maxFrameOffset()) { + } else if (offset > minOffset && offset < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = Op1; return true; @@ -535,39 +505,41 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, // Indirect with constant offset -> D-Form address const SDOperand Op0 = N.getOperand(0); const SDOperand Op1 = N.getOperand(1); - SDOperand Zero = CurDAG->getTargetConstant(0, N.getValueType()); - if (Op1.getOpcode() == ISD::Constant - || Op1.getOpcode() == ISD::TargetConstant) { - ConstantSDNode *CN = cast<ConstantSDNode>(Op1); - int32_t offset = int32_t(CN->getSignExtended()); - if (offset > SPUFrameInfo::minFrameOffset() - && offset < SPUFrameInfo::maxFrameOffset()) { - Base = CurDAG->getTargetConstant(CN->getValue(), PtrTy); - Index = Op0; - return true; - } - } else if (Op0.getOpcode() == ISD::Constant - || Op0.getOpcode() == ISD::TargetConstant) { - ConstantSDNode *CN = cast<ConstantSDNode>(Op0); - int32_t offset = int32_t(CN->getSignExtended()); - if (offset > SPUFrameInfo::minFrameOffset() - && offset < SPUFrameInfo::maxFrameOffset()) { - Base = CurDAG->getTargetConstant(CN->getValue(), PtrTy); - Index = Op1; - return true; - } - } else if (Op0.getOpcode() == SPUISD::Hi - && Op1.getOpcode() == SPUISD::Lo) { + if (Op0.getOpcode() == SPUISD::Hi + && Op1.getOpcode() == SPUISD::Lo) { // (SPUindirect (SPUhi <arg>, 0), (SPUlo <arg>, 0)) Base = CurDAG->getTargetConstant(0, PtrTy); Index = N; return true; + } else if (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1)) { + int32_t offset = 0; + SDOperand idxOp; + + if (isa<ConstantSDNode>(Op1)) { + ConstantSDNode *CN = cast<ConstantSDNode>(Op1); + offset = int32_t(CN->getSignExtended()); + idxOp = Op0; + } else if (isa<ConstantSDNode>(Op0)) { + ConstantSDNode *CN = cast<ConstantSDNode>(Op0); + offset = int32_t(CN->getSignExtended()); + idxOp = Op1; + } + + if (offset >= minOffset && offset <= maxOffset) { + Base = CurDAG->getTargetConstant(offset, PtrTy); + Index = idxOp; + return true; + } } } else if (Opc == SPUISD::AFormAddr) { Base = CurDAG->getTargetConstant(0, N.getValueType()); Index = N; return true; + } else if (Opc == SPUISD::LDRESULT) { + Base = CurDAG->getTargetConstant(0, N.getValueType()); + Index = N; + return true; } return false; } @@ -584,7 +556,7 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, */ bool SPUDAGToDAGISel::SelectXFormAddr(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Index) { + SDOperand &Index) { if (SelectAFormAddr(Op, N, Base, Index) || SelectDFormAddr(Op, N, Base, Index)) return false; @@ -637,38 +609,6 @@ SPUDAGToDAGISel::Select(SDOperand Op) { n_ops = 2; } } - } else if (Opc == SPUISD::INSERT_MASK) { - SDOperand Op0 = Op.getOperand(0); - if (Op0.getOpcode() == SPUISD::AFormAddr) { - // (SPUvecinsmask (SPUaform <arg>, 0)) -> - // (CBD|CHD|CWD 0, arg) - const valtype_map_s *vtm = getValueTypeMapEntry(OpVT); - ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getOperand(1)); - assert(vtm->insmask_ins != 0 && "missing insert mask instruction"); - NewOpc = vtm->insmask_ins; - Ops[0] = CurDAG->getTargetConstant(CN->getValue(), Op0.getValueType()); - Ops[1] = Op0; - n_ops = 2; - - AddToISelQueue(Op0); - } else if (Op0.getOpcode() == ISD::FrameIndex) { - // (SPUvecinsmask <fi>) -> - // (CBD|CHD|CWD 0, <fi>) - const valtype_map_s *vtm = getValueTypeMapEntry(OpVT); - NewOpc = vtm->insmask_ins; - Ops[0] = CurDAG->getTargetConstant(0, Op0.getValueType()); - Ops[1] = Op0; - n_ops = 2; - } else if (isHighLow(Op0)) { - // (SPUvecinsmask (SPUindirect (SPUhi <arg>, 0), (SPUlow <arg>, 0))) -> - // (CBD|CHD|CWD 0, arg) - const valtype_map_s *vtm = getValueTypeMapEntry(OpVT); - NewOpc = vtm->insmask_ins; - Ops[0] = CurDAG->getTargetConstant(0, Op0.getValueType()); - Ops[1] = Op0; - n_ops = 2; - AddToISelQueue(Op0); - } } else if (Opc == SPUISD::LDRESULT) { // Custom select instructions for LDRESULT unsigned VT = N->getValueType(0); @@ -682,12 +622,12 @@ SPUDAGToDAGISel::Select(SDOperand Op) { const valtype_map_s *vtm = getValueTypeMapEntry(VT); if (vtm->ldresult_ins == 0) { - cerr << "LDRESULT for unsupported type: " - << MVT::getValueTypeString(VT) - << "\n"; - abort(); + cerr << "LDRESULT for unsupported type: " + << MVT::getValueTypeString(VT) + << "\n"; + abort(); } else - Opc = vtm->ldresult_ins; + Opc = vtm->ldresult_ins; AddToISelQueue(Zero); Result = CurDAG->getTargetNode(Opc, VT, MVT::Other, Arg, Zero, Chain); @@ -702,17 +642,13 @@ SPUDAGToDAGISel::Select(SDOperand Op) { return Result; } else if (Opc == SPUISD::IndirectAddr) { SDOperand Op0 = Op.getOperand(0); - if (Op0.getOpcode() == SPUISD::LDRESULT - || Op0.getOpcode() == SPUISD::AFormAddr) { - // (IndirectAddr (LDRESULT|AFormAddr, imm)) + if (Op0.getOpcode() == SPUISD::LDRESULT) { + /* || Op0.getOpcode() == SPUISD::AFormAddr) */ + // (IndirectAddr (LDRESULT, imm)) SDOperand Op1 = Op.getOperand(1); MVT::ValueType VT = Op.getValueType(); - DEBUG(cerr << "CellSPU: IndirectAddr(" - << (Op0.getOpcode() == SPUISD::LDRESULT - ? "LDRESULT" - : "AFormAddr") - << ", imm):\nOp0 = "); + DEBUG(cerr << "CellSPU: IndirectAddr(LDRESULT, imm):\nOp0 = "); DEBUG(Op.getOperand(0).Val->dump(CurDAG)); DEBUG(cerr << "\nOp1 = "); DEBUG(Op.getOperand(1).Val->dump(CurDAG)); @@ -721,13 +657,13 @@ SPUDAGToDAGISel::Select(SDOperand Op) { if (Op1.getOpcode() == ISD::Constant) { ConstantSDNode *CN = cast<ConstantSDNode>(Op1); Op1 = CurDAG->getTargetConstant(CN->getValue(), VT); + NewOpc = (isI32IntS10Immediate(CN) ? SPU::AIr32 : SPU::Ar32); + AddToISelQueue(Op0); + AddToISelQueue(Op1); + Ops[0] = Op0; + Ops[1] = Op1; + n_ops = 2; } - AddToISelQueue(Op0); - AddToISelQueue(Op1); - NewOpc = SPU::AIr32; - Ops[0] = Op0; - Ops[1] = Op1; - n_ops = 2; } } |