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