diff options
Diffstat (limited to 'lib/Target/R600/AMDILISelDAGToDAG.cpp')
-rw-r--r-- | lib/Target/R600/AMDILISelDAGToDAG.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/Target/R600/AMDILISelDAGToDAG.cpp b/lib/Target/R600/AMDILISelDAGToDAG.cpp index d15ed393c1..725a5e4f18 100644 --- a/lib/Target/R600/AMDILISelDAGToDAG.cpp +++ b/lib/Target/R600/AMDILISelDAGToDAG.cpp @@ -258,6 +258,87 @@ SDNode *AMDGPUDAGToDAGISel::Select(SDNode *N) { } break; } + + case ISD::INTRINSIC_WO_CHAIN: { + const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); + if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) { + unsigned IntrinsicID = N->getConstantOperandVal(0); + switch (IntrinsicID) { + case AMDGPUIntrinsic::AMDGPU_load_const: { + const R600InstrInfo *TII = + static_cast<const R600InstrInfo*>(CurDAG->getTarget().getInstrInfo()); + int CSel = N->getConstantOperandVal(1); + std::vector<SDValue> Ops; + + // We'll try to fold the const in the alu insts with native operands + for (SDNode::use_iterator Use = N->use_begin(), Next = llvm::next(Use); + Use != SDNode::use_end(); Use = Next) { + Next = llvm::next(Use); + + if (!Use->isMachineOpcode()) + continue; + + unsigned Opcode = Use->getMachineOpcode(); + + const MCInstrDesc & MCDesc = TII->get(Opcode); + if (HAS_NATIVE_OPERANDS(MCDesc.TSFlags)) { + + unsigned SrcNum = MCDesc.TSFlags & R600_InstFlag::OP3 ? 3 : + MCDesc.TSFlags & R600_InstFlag::OP2 ? 2 : 1; + + const unsigned SrcOps[3][2] = { + {R600Operands::SRC0, R600Operands::SRC0_SEL}, + {R600Operands::SRC1, R600Operands::SRC1_SEL}, + {R600Operands::SRC2, R600Operands::SRC2_SEL} + }; + + Ops.clear(); + for (unsigned i = 0; i < Use->getNumOperands(); ++i) { + Ops.push_back(Use->getOperand(i)); + } + + int RegOpIdx = Use.getOperandNo(); + unsigned SrcIdx; + + for (SrcIdx = 0; SrcIdx < SrcNum; ++SrcIdx) { + if (R600Operands::ALUOpTable[SrcNum-1][SrcOps[SrcIdx][0]] == + RegOpIdx + 1) + break; + } + + assert(SrcIdx < SrcNum && "ALU const folding: invalid operand"); + + int SelOpIdx = + R600Operands::ALUOpTable[SrcNum-1][SrcOps[SrcIdx][1]] - 1; + + Ops[RegOpIdx] = CurDAG->getRegister(AMDGPU::ALU_CONST, MVT::f32); + Ops[SelOpIdx] = CurDAG->getTargetConstant(CSel, MVT::i32); + + CurDAG->UpdateNodeOperands(*Use, Ops.data(), Use->getNumOperands()); + } + } + + Ops.clear(); + Ops.push_back(CurDAG->getTargetConstant(1, MVT::i32)); + Ops.push_back(CurDAG->getTargetConstant(0, MVT::i32)); + Ops.push_back(CurDAG->getTargetConstant(0, MVT::i32)); + Ops.push_back(CurDAG->getTargetConstant(0, MVT::i32)); + Ops.push_back(CurDAG->getRegister(AMDGPU::ALU_CONST, MVT::f32)); + Ops.push_back(CurDAG->getTargetConstant(0, MVT::i32)); + Ops.push_back(CurDAG->getTargetConstant(0, MVT::i32)); + Ops.push_back(CurDAG->getTargetConstant(0, MVT::i32)); + Ops.push_back(CurDAG->getTargetConstant(CSel, MVT::i32)); + Ops.push_back(CurDAG->getTargetConstant(1, MVT::i32)); + Ops.push_back(CurDAG->getRegister(AMDGPU::PRED_SEL_OFF, MVT::f32)); + Ops.push_back(CurDAG->getTargetConstant(0, MVT::i32)); + + return CurDAG->SelectNodeTo(N, AMDGPU::MOV, MVT::f32, Ops.data(), + Ops.size()); + + } + } + } + } } return SelectCode(N); } |