brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.1 KiB · 823bfbc Raw
342 lines · cpp
1//===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//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// This file defines an instruction selector for the VE target.10//11//===----------------------------------------------------------------------===//12 13#include "VE.h"14#include "VESelectionDAGInfo.h"15#include "VETargetMachine.h"16#include "llvm/CodeGen/SelectionDAGISel.h"17#include "llvm/Support/ErrorHandling.h"18using namespace llvm;19 20#define DEBUG_TYPE "ve-isel"21#define PASS_NAME "VE DAG->DAG Pattern Instruction Selection"22 23//===--------------------------------------------------------------------===//24/// VEDAGToDAGISel - VE specific code to select VE machine25/// instructions for SelectionDAG operations.26///27namespace {28class VEDAGToDAGISel : public SelectionDAGISel {29  /// Subtarget - Keep a pointer to the VE Subtarget around so that we can30  /// make the right decision when generating code for different targets.31  const VESubtarget *Subtarget;32 33public:34  VEDAGToDAGISel() = delete;35 36  explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}37 38  bool runOnMachineFunction(MachineFunction &MF) override {39    Subtarget = &MF.getSubtarget<VESubtarget>();40    return SelectionDAGISel::runOnMachineFunction(MF);41  }42 43  void Select(SDNode *N) override;44 45  // Complex Pattern Selectors.46  bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);47  bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);48  bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);49  bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);50  bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);51  bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);52 53  /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for54  /// inline asm expressions.55  bool SelectInlineAsmMemoryOperand(const SDValue &Op,56                                    InlineAsm::ConstraintCode ConstraintID,57                                    std::vector<SDValue> &OutOps) override;58 59  // Include the pieces autogenerated from the target description.60#include "VEGenDAGISel.inc"61 62private:63  SDNode *getGlobalBaseReg();64 65  bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);66  bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);67};68 69class VEDAGToDAGISelLegacy : public SelectionDAGISelLegacy {70public:71  static char ID;72  explicit VEDAGToDAGISelLegacy(VETargetMachine &tm)73      : SelectionDAGISelLegacy(ID, std::make_unique<VEDAGToDAGISel>(tm)) {}74};75} // end anonymous namespace76 77char VEDAGToDAGISelLegacy::ID = 0;78 79INITIALIZE_PASS(VEDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)80 81bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,82                                   SDValue &Offset) {83  if (Addr.getOpcode() == ISD::FrameIndex)84    return false;85  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||86      Addr.getOpcode() == ISD::TargetGlobalAddress ||87      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)88    return false; // direct calls.89 90  SDValue LHS, RHS;91  if (matchADDRri(Addr, LHS, RHS)) {92    if (matchADDRrr(LHS, Base, Index)) {93      Offset = RHS;94      return true;95    }96    // Return false to try selectADDRrii.97    return false;98  }99  if (matchADDRrr(Addr, LHS, RHS)) {100    // If the input is a pair of a frame-index and a register, move a101    // frame-index to LHS.  This generates MI with following operands.102    //    %dest, #FI, %reg, offset103    // In the eliminateFrameIndex, above MI is converted to the following.104    //    %dest, %fp, %reg, fi_offset + offset105    if (isa<FrameIndexSDNode>(RHS))106      std::swap(LHS, RHS);107 108    if (matchADDRri(RHS, Index, Offset)) {109      Base = LHS;110      return true;111    }112    if (matchADDRri(LHS, Base, Offset)) {113      Index = RHS;114      return true;115    }116    Base = LHS;117    Index = RHS;118    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);119    return true;120  }121  return false; // Let the reg+imm(=0) pattern catch this!122}123 124bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,125                                   SDValue &Offset) {126  if (matchADDRri(Addr, Base, Offset)) {127    Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);128    return true;129  }130 131  Base = Addr;132  Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);133  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);134  return true;135}136 137bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,138                                   SDValue &Offset) {139  // Prefer ADDRrii.140  return false;141}142 143bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,144                                   SDValue &Offset) {145  if (isa<FrameIndexSDNode>(Addr))146    return false;147  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||148      Addr.getOpcode() == ISD::TargetGlobalAddress ||149      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)150    return false; // direct calls.151 152  if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {153    if (isInt<32>(CN->getSExtValue())) {154      Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);155      Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);156      Offset =157          CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);158      return true;159    }160  }161  return false;162}163 164bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,165                                  SDValue &Offset) {166  if (matchADDRri(Addr, Base, Offset))167    return true;168 169  Base = Addr;170  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);171  return true;172}173 174bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,175                                  SDValue &Offset) {176  if (isa<FrameIndexSDNode>(Addr))177    return false;178  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||179      Addr.getOpcode() == ISD::TargetGlobalAddress ||180      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)181    return false; // direct calls.182 183  if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {184    if (isInt<32>(CN->getSExtValue())) {185      Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);186      Offset =187          CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);188      return true;189    }190  }191  return false;192}193 194bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {195  if (isa<FrameIndexSDNode>(Addr))196    return false;197  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||198      Addr.getOpcode() == ISD::TargetGlobalAddress ||199      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)200    return false; // direct calls.201 202  if (Addr.getOpcode() == ISD::ADD) {203    ; // Nothing to do here.204  } else if (Addr.getOpcode() == ISD::OR) {205    // We want to look through a transform in InstCombine and DAGCombiner that206    // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.207    if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))208      return false;209  } else {210    return false;211  }212 213  if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||214      Addr.getOperand(1).getOpcode() == VEISD::Lo)215    return false; // Let the LEASL patterns catch this!216 217  Base = Addr.getOperand(0);218  Index = Addr.getOperand(1);219  return true;220}221 222bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {223  auto AddrTy = Addr->getValueType(0);224  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {225    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);226    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);227    return true;228  }229  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||230      Addr.getOpcode() == ISD::TargetGlobalAddress ||231      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)232    return false; // direct calls.233 234  if (CurDAG->isBaseWithConstantOffset(Addr)) {235    ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));236    if (isInt<32>(CN->getSExtValue())) {237      if (FrameIndexSDNode *FIN =238              dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {239        // Constant offset from frame ref.240        Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);241      } else {242        Base = Addr.getOperand(0);243      }244      Offset =245          CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);246      return true;247    }248  }249  return false;250}251 252void VEDAGToDAGISel::Select(SDNode *N) {253  if (N->isMachineOpcode()) {254    N->setNodeId(-1);255    return; // Already selected.256  }257 258  switch (N->getOpcode()) {259 260  // Late eliminate the LEGALAVL wrapper261  case VEISD::LEGALAVL:262    ReplaceNode(N, N->getOperand(0).getNode());263    return;264 265  // Lower (broadcast 1) and (broadcast 0) to VM[P]0266  case VEISD::VEC_BROADCAST: {267    MVT SplatResTy = N->getSimpleValueType(0);268    if (SplatResTy.getVectorElementType() != MVT::i1)269      break;270 271    // Constant non-zero broadcast.272    auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0));273    if (!BConst)274      break;275    bool BCTrueMask = (BConst->getSExtValue() != 0);276    if (!BCTrueMask)277      break;278 279    // Packed or non-packed.280    SDValue New;281    if (SplatResTy.getVectorNumElements() == StandardVectorWidth) {282      New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0,283                                   MVT::v256i1);284    } else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) {285      New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0,286                                   MVT::v512i1);287    } else288      break;289 290    // Replace.291    ReplaceNode(N, New.getNode());292    return;293  }294 295  case VEISD::GLOBAL_BASE_REG:296    ReplaceNode(N, getGlobalBaseReg());297    return;298  }299 300  SelectCode(N);301}302 303/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for304/// inline asm expressions.305bool VEDAGToDAGISel::SelectInlineAsmMemoryOperand(306    const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,307    std::vector<SDValue> &OutOps) {308  SDValue Op0, Op1;309  switch (ConstraintID) {310  default:311    llvm_unreachable("Unexpected asm memory constraint");312  case InlineAsm::ConstraintCode::o:313  case InlineAsm::ConstraintCode::m: // memory314    // Try to match ADDRri since reg+imm style is safe for all VE instructions315    // with a memory operand.316    if (selectADDRri(Op, Op0, Op1)) {317      OutOps.push_back(Op0);318      OutOps.push_back(Op1);319      return false;320    }321    // Otherwise, require the address to be in a register and immediate 0.322    OutOps.push_back(Op);323    OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));324    return false;325  }326  return true;327}328 329SDNode *VEDAGToDAGISel::getGlobalBaseReg() {330  Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);331  return CurDAG332      ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))333      .getNode();334}335 336/// createVEISelDag - This pass converts a legalized DAG into a337/// VE-specific DAG, ready for instruction scheduling.338///339FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {340  return new VEDAGToDAGISelLegacy(TM);341}342