Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp
35268 views
//===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines an instruction selector for the VE target.9//10//===----------------------------------------------------------------------===//1112#include "VE.h"13#include "VETargetMachine.h"14#include "llvm/CodeGen/MachineRegisterInfo.h"15#include "llvm/CodeGen/SelectionDAGISel.h"16#include "llvm/IR/Intrinsics.h"17#include "llvm/Support/Debug.h"18#include "llvm/Support/ErrorHandling.h"19#include "llvm/Support/raw_ostream.h"20using namespace llvm;2122#define DEBUG_TYPE "ve-isel"23#define PASS_NAME "VE DAG->DAG Pattern Instruction Selection"2425//===--------------------------------------------------------------------===//26/// VEDAGToDAGISel - VE specific code to select VE machine27/// instructions for SelectionDAG operations.28///29namespace {30class VEDAGToDAGISel : public SelectionDAGISel {31/// Subtarget - Keep a pointer to the VE Subtarget around so that we can32/// make the right decision when generating code for different targets.33const VESubtarget *Subtarget;3435public:36VEDAGToDAGISel() = delete;3738explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}3940bool runOnMachineFunction(MachineFunction &MF) override {41Subtarget = &MF.getSubtarget<VESubtarget>();42return SelectionDAGISel::runOnMachineFunction(MF);43}4445void Select(SDNode *N) override;4647// Complex Pattern Selectors.48bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);49bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);50bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);51bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);52bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);53bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);5455/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for56/// inline asm expressions.57bool SelectInlineAsmMemoryOperand(const SDValue &Op,58InlineAsm::ConstraintCode ConstraintID,59std::vector<SDValue> &OutOps) override;6061// Include the pieces autogenerated from the target description.62#include "VEGenDAGISel.inc"6364private:65SDNode *getGlobalBaseReg();6667bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);68bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);69};7071class VEDAGToDAGISelLegacy : public SelectionDAGISelLegacy {72public:73static char ID;74explicit VEDAGToDAGISelLegacy(VETargetMachine &tm)75: SelectionDAGISelLegacy(ID, std::make_unique<VEDAGToDAGISel>(tm)) {}76};77} // end anonymous namespace7879char VEDAGToDAGISelLegacy::ID = 0;8081INITIALIZE_PASS(VEDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)8283bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,84SDValue &Offset) {85if (Addr.getOpcode() == ISD::FrameIndex)86return false;87if (Addr.getOpcode() == ISD::TargetExternalSymbol ||88Addr.getOpcode() == ISD::TargetGlobalAddress ||89Addr.getOpcode() == ISD::TargetGlobalTLSAddress)90return false; // direct calls.9192SDValue LHS, RHS;93if (matchADDRri(Addr, LHS, RHS)) {94if (matchADDRrr(LHS, Base, Index)) {95Offset = RHS;96return true;97}98// Return false to try selectADDRrii.99return false;100}101if (matchADDRrr(Addr, LHS, RHS)) {102// If the input is a pair of a frame-index and a register, move a103// frame-index to LHS. This generates MI with following operands.104// %dest, #FI, %reg, offset105// In the eliminateFrameIndex, above MI is converted to the following.106// %dest, %fp, %reg, fi_offset + offset107if (isa<FrameIndexSDNode>(RHS))108std::swap(LHS, RHS);109110if (matchADDRri(RHS, Index, Offset)) {111Base = LHS;112return true;113}114if (matchADDRri(LHS, Base, Offset)) {115Index = RHS;116return true;117}118Base = LHS;119Index = RHS;120Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);121return true;122}123return false; // Let the reg+imm(=0) pattern catch this!124}125126bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,127SDValue &Offset) {128if (matchADDRri(Addr, Base, Offset)) {129Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);130return true;131}132133Base = Addr;134Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);135Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);136return true;137}138139bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,140SDValue &Offset) {141// Prefer ADDRrii.142return false;143}144145bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,146SDValue &Offset) {147if (isa<FrameIndexSDNode>(Addr))148return false;149if (Addr.getOpcode() == ISD::TargetExternalSymbol ||150Addr.getOpcode() == ISD::TargetGlobalAddress ||151Addr.getOpcode() == ISD::TargetGlobalTLSAddress)152return false; // direct calls.153154if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {155if (isInt<32>(CN->getSExtValue())) {156Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);157Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);158Offset =159CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);160return true;161}162}163return false;164}165166bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,167SDValue &Offset) {168if (matchADDRri(Addr, Base, Offset))169return true;170171Base = Addr;172Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);173return true;174}175176bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,177SDValue &Offset) {178if (isa<FrameIndexSDNode>(Addr))179return false;180if (Addr.getOpcode() == ISD::TargetExternalSymbol ||181Addr.getOpcode() == ISD::TargetGlobalAddress ||182Addr.getOpcode() == ISD::TargetGlobalTLSAddress)183return false; // direct calls.184185if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {186if (isInt<32>(CN->getSExtValue())) {187Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);188Offset =189CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);190return true;191}192}193return false;194}195196bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {197if (isa<FrameIndexSDNode>(Addr))198return false;199if (Addr.getOpcode() == ISD::TargetExternalSymbol ||200Addr.getOpcode() == ISD::TargetGlobalAddress ||201Addr.getOpcode() == ISD::TargetGlobalTLSAddress)202return false; // direct calls.203204if (Addr.getOpcode() == ISD::ADD) {205; // Nothing to do here.206} else if (Addr.getOpcode() == ISD::OR) {207// We want to look through a transform in InstCombine and DAGCombiner that208// turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.209if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))210return false;211} else {212return false;213}214215if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||216Addr.getOperand(1).getOpcode() == VEISD::Lo)217return false; // Let the LEASL patterns catch this!218219Base = Addr.getOperand(0);220Index = Addr.getOperand(1);221return true;222}223224bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {225auto AddrTy = Addr->getValueType(0);226if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {227Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);228Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);229return true;230}231if (Addr.getOpcode() == ISD::TargetExternalSymbol ||232Addr.getOpcode() == ISD::TargetGlobalAddress ||233Addr.getOpcode() == ISD::TargetGlobalTLSAddress)234return false; // direct calls.235236if (CurDAG->isBaseWithConstantOffset(Addr)) {237ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));238if (isInt<32>(CN->getSExtValue())) {239if (FrameIndexSDNode *FIN =240dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {241// Constant offset from frame ref.242Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);243} else {244Base = Addr.getOperand(0);245}246Offset =247CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);248return true;249}250}251return false;252}253254void VEDAGToDAGISel::Select(SDNode *N) {255SDLoc dl(N);256if (N->isMachineOpcode()) {257N->setNodeId(-1);258return; // Already selected.259}260261switch (N->getOpcode()) {262263// Late eliminate the LEGALAVL wrapper264case VEISD::LEGALAVL:265ReplaceNode(N, N->getOperand(0).getNode());266return;267268// Lower (broadcast 1) and (broadcast 0) to VM[P]0269case VEISD::VEC_BROADCAST: {270MVT SplatResTy = N->getSimpleValueType(0);271if (SplatResTy.getVectorElementType() != MVT::i1)272break;273274// Constant non-zero broadcast.275auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0));276if (!BConst)277break;278bool BCTrueMask = (BConst->getSExtValue() != 0);279if (!BCTrueMask)280break;281282// Packed or non-packed.283SDValue New;284if (SplatResTy.getVectorNumElements() == StandardVectorWidth) {285New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0,286MVT::v256i1);287} else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) {288New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0,289MVT::v512i1);290} else291break;292293// Replace.294ReplaceNode(N, New.getNode());295return;296}297298case VEISD::GLOBAL_BASE_REG:299ReplaceNode(N, getGlobalBaseReg());300return;301}302303SelectCode(N);304}305306/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for307/// inline asm expressions.308bool VEDAGToDAGISel::SelectInlineAsmMemoryOperand(309const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,310std::vector<SDValue> &OutOps) {311SDValue Op0, Op1;312switch (ConstraintID) {313default:314llvm_unreachable("Unexpected asm memory constraint");315case InlineAsm::ConstraintCode::o:316case InlineAsm::ConstraintCode::m: // memory317// Try to match ADDRri since reg+imm style is safe for all VE instructions318// with a memory operand.319if (selectADDRri(Op, Op0, Op1)) {320OutOps.push_back(Op0);321OutOps.push_back(Op1);322return false;323}324// Otherwise, require the address to be in a register and immediate 0.325OutOps.push_back(Op);326OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));327return false;328}329return true;330}331332SDNode *VEDAGToDAGISel::getGlobalBaseReg() {333Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);334return CurDAG335->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))336.getNode();337}338339/// createVEISelDag - This pass converts a legalized DAG into a340/// VE-specific DAG, ready for instruction scheduling.341///342FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {343return new VEDAGToDAGISelLegacy(TM);344}345346347