brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.6 KiB · 288f143 Raw
202 lines · cpp
1//===-- R600ISelDAGToDAG.cpp - A dag to dag inst selector for R600 --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//==-----------------------------------------------------------------------===//8//9/// \file10/// Defines an instruction selector for the R600 subtarget.11//12//===----------------------------------------------------------------------===//13 14#include "AMDGPU.h"15#include "AMDGPUISelDAGToDAG.h"16#include "MCTargetDesc/R600MCTargetDesc.h"17#include "R600.h"18#include "R600Subtarget.h"19 20using namespace llvm;21 22namespace {23class R600DAGToDAGISel : public AMDGPUDAGToDAGISel {24  const R600Subtarget *Subtarget = nullptr;25 26  bool isConstantLoad(const MemSDNode *N, int cbID) const;27  bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue &IntPtr);28  bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg,29                                       SDValue &Offset);30 31public:32  R600DAGToDAGISel() = delete;33 34  explicit R600DAGToDAGISel(TargetMachine &TM, CodeGenOptLevel OptLevel)35      : AMDGPUDAGToDAGISel(TM, OptLevel) {}36 37  void Select(SDNode *N) override;38 39  bool SelectADDRIndirect(SDValue Addr, SDValue &Base,40                          SDValue &Offset) override;41  bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base,42                          SDValue &Offset) override;43 44  bool runOnMachineFunction(MachineFunction &MF) override;45 46  void PreprocessISelDAG() override {}47 48protected:49  // Include the pieces autogenerated from the target description.50#include "R600GenDAGISel.inc"51};52 53class R600DAGToDAGISelLegacy : public SelectionDAGISelLegacy {54public:55  static char ID;56  explicit R600DAGToDAGISelLegacy(TargetMachine &TM, CodeGenOptLevel OptLevel)57      : SelectionDAGISelLegacy(58            ID, std::make_unique<R600DAGToDAGISel>(TM, OptLevel)) {}59};60 61char R600DAGToDAGISelLegacy::ID = 0;62 63} // namespace64 65bool R600DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {66  Subtarget = &MF.getSubtarget<R600Subtarget>();67  return SelectionDAGISel::runOnMachineFunction(MF);68}69 70bool R600DAGToDAGISel::isConstantLoad(const MemSDNode *N, int CbId) const {71  if (!N->readMem())72    return false;73  if (CbId == -1)74    return N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||75           N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT;76 77  return N->getAddressSpace() == AMDGPUAS::CONSTANT_BUFFER_0 + CbId;78}79 80bool R600DAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr,81                                                       SDValue &IntPtr) {82  if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) {83    IntPtr =84        CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr), true);85    return true;86  }87  return false;88}89 90bool R600DAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr,91                                                       SDValue &BaseReg,92                                                       SDValue &Offset) {93  if (!isa<ConstantSDNode>(Addr)) {94    BaseReg = Addr;95    Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true);96    return true;97  }98  return false;99}100 101void R600DAGToDAGISel::Select(SDNode *N) {102  unsigned int Opc = N->getOpcode();103  if (N->isMachineOpcode()) {104    N->setNodeId(-1);105    return; // Already selected.106  }107 108  switch (Opc) {109  default:110    break;111  case AMDGPUISD::BUILD_VERTICAL_VECTOR:112  case ISD::SCALAR_TO_VECTOR:113  case ISD::BUILD_VECTOR: {114    EVT VT = N->getValueType(0);115    unsigned NumVectorElts = VT.getVectorNumElements();116    unsigned RegClassID;117    // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG118    // that adds a 128 bits reg copy when going through TwoAddressInstructions119    // pass. We want to avoid 128 bits copies as much as possible because they120    // can't be bundled by our scheduler.121    switch (NumVectorElts) {122    case 2:123      RegClassID = R600::R600_Reg64RegClassID;124      break;125    case 4:126      if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR)127        RegClassID = R600::R600_Reg128VerticalRegClassID;128      else129        RegClassID = R600::R600_Reg128RegClassID;130      break;131    default:132      llvm_unreachable("Do not know how to lower this BUILD_VECTOR");133    }134    SelectBuildVector(N, RegClassID);135    return;136  }137  }138 139  SelectCode(N);140}141 142bool R600DAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base,143                                          SDValue &Offset) {144  ConstantSDNode *C;145  SDLoc DL(Addr);146 147  if ((C = dyn_cast<ConstantSDNode>(Addr))) {148    Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);149    Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);150  } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) &&151             (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) {152    Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);153    Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);154  } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) &&155             (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {156    Base = Addr.getOperand(0);157    Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);158  } else {159    Base = Addr;160    Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);161  }162 163  return true;164}165 166bool R600DAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,167                                          SDValue &Offset) {168  ConstantSDNode *IMMOffset;169 170  if (Addr.getOpcode() == ISD::ADD &&171      (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&172      isInt<16>(IMMOffset->getZExtValue())) {173 174    Base = Addr.getOperand(0);175    Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),176                                       MVT::i32);177    return true;178    // If the pointer address is constant, we can move it to the offset field.179  }180  if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr)) &&181      isInt<16>(IMMOffset->getZExtValue())) {182    Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),183                                  SDLoc(CurDAG->getEntryNode()), R600::ZERO,184                                  MVT::i32);185    Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),186                                       MVT::i32);187    return true;188  }189 190  // Default case, no offset191  Base = Addr;192  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);193  return true;194}195 196/// This pass converts a legalized DAG into a R600-specific197// DAG, ready for instruction scheduling.198FunctionPass *llvm::createR600ISelDag(TargetMachine &TM,199                                      CodeGenOptLevel OptLevel) {200  return new R600DAGToDAGISelLegacy(TM, OptLevel);201}202