summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/radeon/R600ISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeon/R600ISelLowering.cpp')
-rw-r--r--src/gallium/drivers/radeon/R600ISelLowering.cpp740
1 files changed, 0 insertions, 740 deletions
diff --git a/src/gallium/drivers/radeon/R600ISelLowering.cpp b/src/gallium/drivers/radeon/R600ISelLowering.cpp
deleted file mode 100644
index 5dd2f5334c5..00000000000
--- a/src/gallium/drivers/radeon/R600ISelLowering.cpp
+++ /dev/null
@@ -1,740 +0,0 @@
-//===-- R600ISelLowering.cpp - R600 DAG Lowering Implementation -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Most of the DAG lowering is handled in AMDGPUISelLowering.cpp. This file
-// is mostly EmitInstrWithCustomInserter().
-//
-//===----------------------------------------------------------------------===//
-
-#include "R600ISelLowering.h"
-#include "R600Defines.h"
-#include "R600InstrInfo.h"
-#include "R600MachineFunctionInfo.h"
-#include "llvm/Argument.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/SelectionDAG.h"
-
-using namespace llvm;
-
-R600TargetLowering::R600TargetLowering(TargetMachine &TM) :
- AMDGPUTargetLowering(TM),
- TII(static_cast<const R600InstrInfo*>(TM.getInstrInfo()))
-{
- setOperationAction(ISD::MUL, MVT::i64, Expand);
- addRegisterClass(MVT::v4f32, &AMDGPU::R600_Reg128RegClass);
- addRegisterClass(MVT::f32, &AMDGPU::R600_Reg32RegClass);
- addRegisterClass(MVT::v4i32, &AMDGPU::R600_Reg128RegClass);
- addRegisterClass(MVT::i32, &AMDGPU::R600_Reg32RegClass);
- computeRegisterProperties();
-
- setOperationAction(ISD::FADD, MVT::v4f32, Expand);
- setOperationAction(ISD::FMUL, MVT::v4f32, Expand);
-
- setOperationAction(ISD::BR_CC, MVT::i32, Custom);
- setOperationAction(ISD::BR_CC, MVT::f32, Custom);
-
- setOperationAction(ISD::FSUB, MVT::f32, Expand);
-
- setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
- setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
- setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i1, Custom);
-
- setOperationAction(ISD::ROTL, MVT::i32, Custom);
-
- setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
- setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
-
- setOperationAction(ISD::SETCC, MVT::i32, Custom);
- setOperationAction(ISD::SETCC, MVT::f32, Custom);
- setOperationAction(ISD::FP_TO_UINT, MVT::i1, Custom);
-
- setTargetDAGCombine(ISD::FP_ROUND);
-
- setSchedulingPreference(Sched::VLIW);
-}
-
-MachineBasicBlock * R600TargetLowering::EmitInstrWithCustomInserter(
- MachineInstr * MI, MachineBasicBlock * BB) const
-{
- MachineFunction * MF = BB->getParent();
- MachineRegisterInfo &MRI = MF->getRegInfo();
- MachineBasicBlock::iterator I = *MI;
-
- switch (MI->getOpcode()) {
- default: return AMDGPUTargetLowering::EmitInstrWithCustomInserter(MI, BB);
- case AMDGPU::SHADER_TYPE: break;
- case AMDGPU::CLAMP_R600:
- {
- MachineInstr *NewMI =
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV))
- .addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1))
- .addImm(0) // Flags
- .addReg(AMDGPU::PRED_SEL_OFF);
- TII->addFlag(NewMI, 0, MO_FLAG_CLAMP);
- break;
- }
- case AMDGPU::FABS_R600:
- {
- MachineInstr *NewMI =
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV))
- .addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1))
- .addImm(0) // Flags
- .addReg(AMDGPU::PRED_SEL_OFF);
- TII->addFlag(NewMI, 1, MO_FLAG_ABS);
- break;
- }
-
- case AMDGPU::FNEG_R600:
- {
- MachineInstr *NewMI =
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV))
- .addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1))
- .addImm(0) // Flags
- .addReg(AMDGPU::PRED_SEL_OFF);
- TII->addFlag(NewMI, 1, MO_FLAG_NEG);
- break;
- }
-
- case AMDGPU::R600_LOAD_CONST:
- {
- int64_t RegIndex = MI->getOperand(1).getImm();
- unsigned ConstantReg = AMDGPU::R600_CReg32RegClass.getRegister(RegIndex);
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::COPY))
- .addOperand(MI->getOperand(0))
- .addReg(ConstantReg);
- break;
- }
-
- case AMDGPU::MASK_WRITE:
- {
- unsigned maskedRegister = MI->getOperand(0).getReg();
- assert(TargetRegisterInfo::isVirtualRegister(maskedRegister));
- MachineInstr * defInstr = MRI.getVRegDef(maskedRegister);
- TII->addFlag(defInstr, 0, MO_FLAG_MASK);
- // Return early so the instruction is not erased
- return BB;
- }
-
- case AMDGPU::RAT_WRITE_CACHELESS_32_eg:
- case AMDGPU::RAT_WRITE_CACHELESS_128_eg:
- {
- // Convert to DWORD address
- unsigned NewAddr = MRI.createVirtualRegister(
- &AMDGPU::R600_TReg32_XRegClass);
- unsigned ShiftValue = MRI.createVirtualRegister(
- &AMDGPU::R600_TReg32RegClass);
- unsigned EOP = (llvm::next(I)->getOpcode() == AMDGPU::RETURN) ? 1 : 0;
-
- // XXX In theory, we should be able to pass ShiftValue directly to
- // the LSHR_eg instruction as an inline literal, but I tried doing it
- // this way and it didn't produce the correct results.
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV_IMM_I32),
- ShiftValue)
- .addReg(AMDGPU::ALU_LITERAL_X)
- .addReg(AMDGPU::PRED_SEL_OFF)
- .addImm(2);
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::LSHR_eg), NewAddr)
- .addOperand(MI->getOperand(1))
- .addReg(ShiftValue)
- .addReg(AMDGPU::PRED_SEL_OFF);
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(MI->getOpcode()))
- .addOperand(MI->getOperand(0))
- .addReg(NewAddr)
- .addImm(EOP); // Set End of program bit
- break;
- }
-
- case AMDGPU::RESERVE_REG:
- {
- R600MachineFunctionInfo * MFI = MF->getInfo<R600MachineFunctionInfo>();
- int64_t ReservedIndex = MI->getOperand(0).getImm();
- unsigned ReservedReg =
- AMDGPU::R600_TReg32RegClass.getRegister(ReservedIndex);
- MFI->ReservedRegs.push_back(ReservedReg);
- break;
- }
-
- case AMDGPU::TXD:
- {
- unsigned t0 = MRI.createVirtualRegister(&AMDGPU::R600_Reg128RegClass);
- unsigned t1 = MRI.createVirtualRegister(&AMDGPU::R600_Reg128RegClass);
-
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_H), t0)
- .addOperand(MI->getOperand(3))
- .addOperand(MI->getOperand(4))
- .addOperand(MI->getOperand(5));
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_V), t1)
- .addOperand(MI->getOperand(2))
- .addOperand(MI->getOperand(4))
- .addOperand(MI->getOperand(5));
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SAMPLE_G))
- .addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1))
- .addOperand(MI->getOperand(4))
- .addOperand(MI->getOperand(5))
- .addReg(t0, RegState::Implicit)
- .addReg(t1, RegState::Implicit);
- break;
- }
- case AMDGPU::TXD_SHADOW:
- {
- unsigned t0 = MRI.createVirtualRegister(AMDGPU::R600_Reg128RegisterClass);
- unsigned t1 = MRI.createVirtualRegister(AMDGPU::R600_Reg128RegisterClass);
-
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_H), t0)
- .addOperand(MI->getOperand(3))
- .addOperand(MI->getOperand(4))
- .addOperand(MI->getOperand(5));
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_V), t1)
- .addOperand(MI->getOperand(2))
- .addOperand(MI->getOperand(4))
- .addOperand(MI->getOperand(5));
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SAMPLE_C_G))
- .addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1))
- .addOperand(MI->getOperand(4))
- .addOperand(MI->getOperand(5))
- .addReg(t0, RegState::Implicit)
- .addReg(t1, RegState::Implicit);
- break;
- }
- case AMDGPU::BRANCH:
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::JUMP))
- .addOperand(MI->getOperand(0))
- .addReg(0);
- break;
- case AMDGPU::BRANCH_COND_f32:
- {
- MachineInstr *NewMI =
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::PRED_X))
- .addReg(AMDGPU::PREDICATE_BIT)
- .addOperand(MI->getOperand(1))
- .addImm(OPCODE_IS_NOT_ZERO)
- .addImm(0); // Flags
- TII->addFlag(NewMI, 1, MO_FLAG_PUSH);
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::JUMP))
- .addOperand(MI->getOperand(0))
- .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
- break;
- }
- case AMDGPU::BRANCH_COND_i32:
- {
- MachineInstr *NewMI =
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::PRED_X))
- .addReg(AMDGPU::PREDICATE_BIT)
- .addOperand(MI->getOperand(1))
- .addImm(OPCODE_IS_NOT_ZERO_INT)
- .addImm(0); // Flags
- TII->addFlag(NewMI, 1, MO_FLAG_PUSH);
- BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::JUMP))
- .addOperand(MI->getOperand(0))
- .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
- break;
- }
- case AMDGPU::input_perspective:
- {
- R600MachineFunctionInfo *MFI = MF->getInfo<R600MachineFunctionInfo>();
-
- // XXX Be more fine about register reservation
- for (unsigned i = 0; i < 4; i ++) {
- unsigned ReservedReg = AMDGPU::R600_TReg32RegClass.getRegister(i);
- MFI->ReservedRegs.push_back(ReservedReg);
- }
-
- switch (MI->getOperand(1).getImm()) {
- case 0:// Perspective
- MFI->HasPerspectiveInterpolation = true;
- break;
- case 1:// Linear
- MFI->HasLinearInterpolation = true;
- break;
- default:
- assert(0 && "Unknow ij index");
- }
-
- return BB;
- }
- }
-
- MI->eraseFromParent();
- return BB;
-}
-
-//===----------------------------------------------------------------------===//
-// Custom DAG Lowering Operations
-//===----------------------------------------------------------------------===//
-
-using namespace llvm::Intrinsic;
-using namespace llvm::AMDGPUIntrinsic;
-
-SDValue R600TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const
-{
- switch (Op.getOpcode()) {
- default: return AMDGPUTargetLowering::LowerOperation(Op, DAG);
- case ISD::BR_CC: return LowerBR_CC(Op, DAG);
- case ISD::ROTL: return LowerROTL(Op, DAG);
- case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
- case ISD::SETCC: return LowerSETCC(Op, DAG);
- case ISD::INTRINSIC_VOID: {
- SDValue Chain = Op.getOperand(0);
- unsigned IntrinsicID =
- cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
- switch (IntrinsicID) {
- case AMDGPUIntrinsic::AMDGPU_store_output: {
- MachineFunction &MF = DAG.getMachineFunction();
- MachineRegisterInfo &MRI = MF.getRegInfo();
- int64_t RegIndex = cast<ConstantSDNode>(Op.getOperand(3))->getZExtValue();
- unsigned Reg = AMDGPU::R600_TReg32RegClass.getRegister(RegIndex);
- if (!MRI.isLiveOut(Reg)) {
- MRI.addLiveOut(Reg);
- }
- return DAG.getCopyToReg(Chain, Op.getDebugLoc(), Reg, Op.getOperand(2));
- }
- // default for switch(IntrinsicID)
- default: break;
- }
- // break out of case ISD::INTRINSIC_VOID in switch(Op.getOpcode())
- break;
- }
- case ISD::INTRINSIC_WO_CHAIN: {
- unsigned IntrinsicID =
- cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
- EVT VT = Op.getValueType();
- DebugLoc DL = Op.getDebugLoc();
- switch(IntrinsicID) {
- default: return AMDGPUTargetLowering::LowerOperation(Op, DAG);
- case AMDGPUIntrinsic::R600_load_input: {
- int64_t RegIndex = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
- unsigned Reg = AMDGPU::R600_TReg32RegClass.getRegister(RegIndex);
- return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass, Reg, VT);
- }
- case AMDGPUIntrinsic::R600_load_input_perspective: {
- unsigned slot = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
- SDValue FullVector = DAG.getNode(
- AMDGPUISD::INTERP,
- DL, MVT::v4f32,
- DAG.getConstant(0, MVT::i32), DAG.getConstant(slot / 4 , MVT::i32));
- return DAG.getNode(ISD::EXTRACT_VECTOR_ELT,
- DL, VT, FullVector, DAG.getConstant(slot % 4, MVT::i32));
- }
- case AMDGPUIntrinsic::R600_load_input_linear: {
- unsigned slot = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
- SDValue FullVector = DAG.getNode(
- AMDGPUISD::INTERP,
- DL, MVT::v4f32,
- DAG.getConstant(1, MVT::i32), DAG.getConstant(slot / 4 , MVT::i32));
- return DAG.getNode(ISD::EXTRACT_VECTOR_ELT,
- DL, VT, FullVector, DAG.getConstant(slot % 4, MVT::i32));
- }
- case AMDGPUIntrinsic::R600_load_input_constant: {
- unsigned slot = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
- SDValue FullVector = DAG.getNode(
- AMDGPUISD::INTERP_P0,
- DL, MVT::v4f32,
- DAG.getConstant(slot / 4 , MVT::i32));
- return DAG.getNode(ISD::EXTRACT_VECTOR_ELT,
- DL, VT, FullVector, DAG.getConstant(slot % 4, MVT::i32));
- }
- case AMDGPUIntrinsic::R600_load_input_position: {
- unsigned slot = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
- unsigned RegIndex = AMDGPU::R600_TReg32RegClass.getRegister(slot);
- SDValue Reg = CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- RegIndex, MVT::f32);
- if ((slot % 4) == 3) {
- return DAG.getNode(ISD::FDIV,
- DL, VT,
- DAG.getConstantFP(1.0f, MVT::f32),
- Reg);
- } else {
- return Reg;
- }
- }
-
- case r600_read_ngroups_x:
- return LowerImplicitParameter(DAG, VT, DL, 0);
- case r600_read_ngroups_y:
- return LowerImplicitParameter(DAG, VT, DL, 1);
- case r600_read_ngroups_z:
- return LowerImplicitParameter(DAG, VT, DL, 2);
- case r600_read_global_size_x:
- return LowerImplicitParameter(DAG, VT, DL, 3);
- case r600_read_global_size_y:
- return LowerImplicitParameter(DAG, VT, DL, 4);
- case r600_read_global_size_z:
- return LowerImplicitParameter(DAG, VT, DL, 5);
- case r600_read_local_size_x:
- return LowerImplicitParameter(DAG, VT, DL, 6);
- case r600_read_local_size_y:
- return LowerImplicitParameter(DAG, VT, DL, 7);
- case r600_read_local_size_z:
- return LowerImplicitParameter(DAG, VT, DL, 8);
-
- case r600_read_tgid_x:
- return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- AMDGPU::T1_X, VT);
- case r600_read_tgid_y:
- return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- AMDGPU::T1_Y, VT);
- case r600_read_tgid_z:
- return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- AMDGPU::T1_Z, VT);
- case r600_read_tidig_x:
- return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- AMDGPU::T0_X, VT);
- case r600_read_tidig_y:
- return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- AMDGPU::T0_Y, VT);
- case r600_read_tidig_z:
- return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- AMDGPU::T0_Z, VT);
- }
- // break out of case ISD::INTRINSIC_WO_CHAIN in switch(Op.getOpcode())
- break;
- }
- } // end switch(Op.getOpcode())
- return SDValue();
-}
-
-void R600TargetLowering::ReplaceNodeResults(SDNode *N,
- SmallVectorImpl<SDValue> &Results,
- SelectionDAG &DAG) const
-{
- switch (N->getOpcode()) {
- default: return;
- case ISD::FP_TO_UINT: Results.push_back(LowerFPTOUINT(N->getOperand(0), DAG));
- case ISD::INTRINSIC_WO_CHAIN:
- {
- unsigned IntrinsicID =
- cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
- if (IntrinsicID == AMDGPUIntrinsic::R600_load_input_face) {
- Results.push_back(LowerInputFace(N, DAG));
- } else {
- return;
- }
- }
- }
-}
-
-SDValue R600TargetLowering::LowerInputFace(SDNode* Op, SelectionDAG &DAG) const
-{
- unsigned slot = cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue();
- unsigned RegIndex = AMDGPU::R600_TReg32RegClass.getRegister(slot);
- SDValue Reg = CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
- RegIndex, MVT::f32);
- return DAG.getNode(ISD::SETCC, Op->getDebugLoc(), MVT::i1,
- Reg, DAG.getConstantFP(0.0f, MVT::f32),
- DAG.getCondCode(ISD::SETUGT));
-}
-
-SDValue R600TargetLowering::LowerFPTOUINT(SDValue Op, SelectionDAG &DAG) const
-{
- return DAG.getNode(
- ISD::SETCC,
- Op.getDebugLoc(),
- MVT::i1,
- Op, DAG.getConstantFP(0.0f, MVT::f32),
- DAG.getCondCode(ISD::SETNE)
- );
-}
-
-SDValue R600TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const
-{
- SDValue Chain = Op.getOperand(0);
- SDValue CC = Op.getOperand(1);
- SDValue LHS = Op.getOperand(2);
- SDValue RHS = Op.getOperand(3);
- SDValue JumpT = Op.getOperand(4);
- SDValue CmpValue;
- SDValue Result;
-
- if (LHS.getValueType() == MVT::i32) {
- CmpValue = DAG.getNode(
- ISD::SELECT_CC,
- Op.getDebugLoc(),
- MVT::i32,
- LHS, RHS,
- DAG.getConstant(-1, MVT::i32),
- DAG.getConstant(0, MVT::i32),
- CC);
- } else if (LHS.getValueType() == MVT::f32) {
- CmpValue = DAG.getNode(
- ISD::SELECT_CC,
- Op.getDebugLoc(),
- MVT::f32,
- LHS, RHS,
- DAG.getConstantFP(1.0f, MVT::f32),
- DAG.getConstantFP(0.0f, MVT::f32),
- CC);
- } else {
- assert(0 && "Not valid type for br_cc");
- }
- Result = DAG.getNode(
- AMDGPUISD::BRANCH_COND,
- CmpValue.getDebugLoc(),
- MVT::Other, Chain,
- JumpT, CmpValue);
- return Result;
-}
-
-SDValue R600TargetLowering::LowerImplicitParameter(SelectionDAG &DAG, EVT VT,
- DebugLoc DL,
- unsigned DwordOffset) const
-{
- unsigned ByteOffset = DwordOffset * 4;
- PointerType * PtrType = PointerType::get(VT.getTypeForEVT(*DAG.getContext()),
- AMDGPUAS::PARAM_I_ADDRESS);
-
- // We shouldn't be using an offset wider than 16-bits for implicit parameters.
- assert(isInt<16>(ByteOffset));
-
- return DAG.getLoad(VT, DL, DAG.getEntryNode(),
- DAG.getConstant(ByteOffset, MVT::i32), // PTR
- MachinePointerInfo(ConstantPointerNull::get(PtrType)),
- false, false, false, 0);
-}
-
-SDValue R600TargetLowering::LowerROTL(SDValue Op, SelectionDAG &DAG) const
-{
- DebugLoc DL = Op.getDebugLoc();
- EVT VT = Op.getValueType();
-
- return DAG.getNode(AMDGPUISD::BITALIGN, DL, VT,
- Op.getOperand(0),
- Op.getOperand(0),
- DAG.getNode(ISD::SUB, DL, VT,
- DAG.getConstant(32, MVT::i32),
- Op.getOperand(1)));
-}
-
-bool R600TargetLowering::isZero(SDValue Op) const
-{
- if(ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Op)) {
- return Cst->isNullValue();
- } else if(ConstantFPSDNode *CstFP = dyn_cast<ConstantFPSDNode>(Op)){
- return CstFP->isZero();
- } else {
- return false;
- }
-}
-
-SDValue R600TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const
-{
- DebugLoc DL = Op.getDebugLoc();
- EVT VT = Op.getValueType();
-
- SDValue LHS = Op.getOperand(0);
- SDValue RHS = Op.getOperand(1);
- SDValue True = Op.getOperand(2);
- SDValue False = Op.getOperand(3);
- SDValue CC = Op.getOperand(4);
- SDValue Temp;
-
- // LHS and RHS are guaranteed to be the same value type
- EVT CompareVT = LHS.getValueType();
-
- // We need all the operands of SELECT_CC to have the same value type, so if
- // necessary we need to convert LHS and RHS to be the same type True and
- // False. True and False are guaranteed to have the same type as this
- // SELECT_CC node.
-
- if (isHWTrueValue(True) && isHWFalseValue(False)) {
- if (CompareVT != VT) {
- if (VT == MVT::f32 && CompareVT == MVT::i32) {
- SDValue Boolean = DAG.getNode(ISD::SELECT_CC, DL, CompareVT,
- LHS, RHS,
- DAG.getConstant(-1, MVT::i32),
- DAG.getConstant(0, MVT::i32),
- CC);
- return DAG.getNode(ISD::UINT_TO_FP, DL, VT, Boolean);
- } else if (VT == MVT::i32 && CompareVT == MVT::f32) {
- SDValue BoolAsFlt = DAG.getNode(ISD::SELECT_CC, DL, CompareVT,
- LHS, RHS,
- DAG.getConstantFP(1.0f, MVT::f32),
- DAG.getConstantFP(0.0f, MVT::f32),
- CC);
- return DAG.getNode(ISD::FP_TO_UINT, DL, VT, BoolAsFlt);
- } else {
- // I don't think there will be any other type pairings.
- assert(!"Unhandled operand type parings in SELECT_CC");
- }
- } else {
- return DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, True, False, CC);
- }
- }
-
-
- // XXX If True is a hardware TRUE value and False is a hardware FALSE value,
- // we can handle this with a native instruction, but we need to swap true
- // and false and change the conditional.
- if (isHWTrueValue(False) && isHWFalseValue(True)) {
- }
-
- // Check if we can lower this to a native operation.
- // CND* instructions requires all operands to have the same type,
- // and RHS to be zero.
-
- if (isZero(LHS) || isZero(RHS)) {
- SDValue Cond = (isZero(LHS) ? RHS : LHS);
- SDValue Zero = (isZero(LHS) ? LHS : RHS);
- ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();
- if (CompareVT != VT) {
- True = DAG.getNode(ISD::BITCAST, DL, CompareVT, True);
- False = DAG.getNode(ISD::BITCAST, DL, CompareVT, False);
- }
- if (isZero(LHS)) {
- CCOpcode = ISD::getSetCCSwappedOperands(CCOpcode);
- }
-
- switch (CCOpcode) {
- case ISD::SETONE:
- case ISD::SETUNE:
- case ISD::SETNE:
- case ISD::SETULE:
- case ISD::SETULT:
- case ISD::SETOLE:
- case ISD::SETOLT:
- case ISD::SETLE:
- case ISD::SETLT:
- CCOpcode = ISD::getSetCCInverse(CCOpcode, CompareVT == MVT::i32);
- Temp = True;
- True = False;
- False = Temp;
- break;
- default:
- break;
- }
- SDValue SelectNode = DAG.getNode(ISD::SELECT_CC, DL, CompareVT,
- Cond, Zero,
- True, False,
- DAG.getCondCode(CCOpcode));
- return DAG.getNode(ISD::BITCAST, DL, VT, SelectNode);
- }
-
-
- // If we make it this for it means we have no native instructions to handle
- // this SELECT_CC, so we must lower it.
- SDValue HWTrue, HWFalse;
-
- if (CompareVT == MVT::f32) {
- HWTrue = DAG.getConstantFP(1.0f, CompareVT);
- HWFalse = DAG.getConstantFP(0.0f, CompareVT);
- } else if (CompareVT == MVT::i32) {
- HWTrue = DAG.getConstant(-1, CompareVT);
- HWFalse = DAG.getConstant(0, CompareVT);
- }
- else {
- assert(!"Unhandled value type in LowerSELECT_CC");
- }
-
- // Lower this unsupported SELECT_CC into a combination of two supported
- // SELECT_CC operations.
- SDValue Cond = DAG.getNode(ISD::SELECT_CC, DL, CompareVT, LHS, RHS, HWTrue, HWFalse, CC);
-
- return DAG.getNode(ISD::SELECT_CC, DL, VT,
- Cond, HWFalse,
- True, False,
- DAG.getCondCode(ISD::SETNE));
-}
-
-SDValue R600TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const
-{
- SDValue Cond;
- SDValue LHS = Op.getOperand(0);
- SDValue RHS = Op.getOperand(1);
- SDValue CC = Op.getOperand(2);
- DebugLoc DL = Op.getDebugLoc();
- assert(Op.getValueType() == MVT::i32);
- if (LHS.getValueType() == MVT::i32) {
- Cond = DAG.getNode(
- ISD::SELECT_CC,
- Op.getDebugLoc(),
- MVT::i32,
- LHS, RHS,
- DAG.getConstant(-1, MVT::i32),
- DAG.getConstant(0, MVT::i32),
- CC);
- } else if (LHS.getValueType() == MVT::f32) {
- Cond = DAG.getNode(
- ISD::SELECT_CC,
- Op.getDebugLoc(),
- MVT::f32,
- LHS, RHS,
- DAG.getConstantFP(1.0f, MVT::f32),
- DAG.getConstantFP(0.0f, MVT::f32),
- CC);
- Cond = DAG.getNode(
- ISD::FP_TO_SINT,
- DL,
- MVT::i32,
- Cond);
- } else {
- assert(0 && "Not valid type for set_cc");
- }
- Cond = DAG.getNode(
- ISD::AND,
- DL,
- MVT::i32,
- DAG.getConstant(1, MVT::i32),
- Cond);
- return Cond;
-}
-
-// XXX Only kernel functions are supporte, so we can assume for now that
-// every function is a kernel function, but in the future we should use
-// separate calling conventions for kernel and non-kernel functions.
-// Only kernel functions are supported, so we can assume for now
-SDValue R600TargetLowering::LowerFormalArguments(
- SDValue Chain,
- CallingConv::ID CallConv,
- bool isVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins,
- DebugLoc DL, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals) const
-{
- unsigned ParamOffsetBytes = 36;
- for (unsigned i = 0, e = Ins.size(); i < e; ++i) {
- EVT VT = Ins[i].VT;
- PointerType *PtrTy = PointerType::get(VT.getTypeForEVT(*DAG.getContext()),
- AMDGPUAS::PARAM_I_ADDRESS);
- SDValue Arg = DAG.getLoad(VT, DL, DAG.getRoot(),
- DAG.getConstant(ParamOffsetBytes, MVT::i32),
- MachinePointerInfo(new Argument(PtrTy)),
- false, false, false, 4);
- InVals.push_back(Arg);
- ParamOffsetBytes += (VT.getStoreSize());
- }
- return Chain;
-}
-
-//===----------------------------------------------------------------------===//
-// Custom DAG Optimizations
-//===----------------------------------------------------------------------===//
-
-SDValue R600TargetLowering::PerformDAGCombine(SDNode *N,
- DAGCombinerInfo &DCI) const
-{
- SelectionDAG &DAG = DCI.DAG;
-
- switch (N->getOpcode()) {
- // (f32 fp_round (f64 uint_to_fp a)) -> (f32 uint_to_fp a)
- case ISD::FP_ROUND: {
- SDValue Arg = N->getOperand(0);
- if (Arg.getOpcode() == ISD::UINT_TO_FP && Arg.getValueType() == MVT::f64) {
- return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), N->getValueType(0),
- Arg.getOperand(0));
- }
- break;
- }
- }
- return SDValue();
-}