Path: blob/main/contrib/llvm-project/llvm/lib/Target/Lanai/LanaiISelDAGToDAG.cpp
35271 views
//===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===//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 Lanai target.9//10//===----------------------------------------------------------------------===//1112#include "LanaiAluCode.h"13#include "LanaiMachineFunctionInfo.h"14#include "LanaiRegisterInfo.h"15#include "LanaiSubtarget.h"16#include "LanaiTargetMachine.h"17#include "llvm/CodeGen/MachineConstantPool.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineFunction.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineRegisterInfo.h"22#include "llvm/CodeGen/SelectionDAGISel.h"23#include "llvm/IR/CFG.h"24#include "llvm/IR/GlobalValue.h"25#include "llvm/IR/Instructions.h"26#include "llvm/IR/Intrinsics.h"27#include "llvm/IR/Type.h"28#include "llvm/Support/Debug.h"29#include "llvm/Support/ErrorHandling.h"30#include "llvm/Support/raw_ostream.h"31#include "llvm/Target/TargetMachine.h"3233using namespace llvm;3435#define DEBUG_TYPE "lanai-isel"36#define PASS_NAME "Lanai DAG->DAG Pattern Instruction Selection"3738//===----------------------------------------------------------------------===//39// Instruction Selector Implementation40//===----------------------------------------------------------------------===//4142//===----------------------------------------------------------------------===//43// LanaiDAGToDAGISel - Lanai specific code to select Lanai machine44// instructions for SelectionDAG operations.45//===----------------------------------------------------------------------===//46namespace {4748class LanaiDAGToDAGISel : public SelectionDAGISel {49public:50LanaiDAGToDAGISel() = delete;5152explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine)53: SelectionDAGISel(TargetMachine) {}5455bool SelectInlineAsmMemoryOperand(const SDValue &Op,56InlineAsm::ConstraintCode ConstraintCode,57std::vector<SDValue> &OutOps) override;5859private:60// Include the pieces autogenerated from the target description.61#include "LanaiGenDAGISel.inc"6263// Instruction Selection not handled by the auto-generated tablgen64void Select(SDNode *N) override;6566// Support functions for the opcodes of Instruction Selection67// not handled by the auto-generated tablgen68void selectFrameIndex(SDNode *N);6970// Complex Pattern for address selection.71bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset,72SDValue &AluOp);73bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp);74bool selectAddrSls(SDValue Addr, SDValue &Offset);75bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset,76SDValue &AluOp);7778// getI32Imm - Return a target constant with the specified value, of type i32.79inline SDValue getI32Imm(unsigned Imm, const SDLoc &DL) {80return CurDAG->getTargetConstant(Imm, DL, MVT::i32);81}8283private:84bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset,85SDValue &AluOp, bool RiMode);86};8788bool canBeRepresentedAsSls(const ConstantSDNode &CN) {89// Fits in 21-bit signed immediate and two low-order bits are zero.90return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0);91}9293class LanaiDAGToDAGISelLegacy : public SelectionDAGISelLegacy {94public:95static char ID;96explicit LanaiDAGToDAGISelLegacy(LanaiTargetMachine &TM)97: SelectionDAGISelLegacy(ID, std::make_unique<LanaiDAGToDAGISel>(TM)) {}98};99100} // namespace101102char LanaiDAGToDAGISelLegacy::ID = 0;103104INITIALIZE_PASS(LanaiDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)105106// Helper functions for ComplexPattern used on LanaiInstrInfo107// Used on Lanai Load/Store instructions.108bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) {109if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {110SDLoc DL(Addr);111// Loading from a constant address.112if (canBeRepresentedAsSls(*CN)) {113int32_t Imm = CN->getSExtValue();114Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));115return true;116}117}118if (Addr.getOpcode() == ISD::OR &&119Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) {120Offset = Addr.getOperand(1).getOperand(0);121return true;122}123return false;124}125126bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base,127SDValue &Offset, SDValue &AluOp,128bool RiMode) {129SDLoc DL(Addr);130131if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {132if (RiMode) {133// Fits in 16-bit signed immediate.134if (isInt<16>(CN->getSExtValue())) {135int16_t Imm = CN->getSExtValue();136Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));137Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));138AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);139return true;140}141// Allow SLS to match if the constant doesn't fit in 16 bits but can be142// represented as an SLS.143if (canBeRepresentedAsSls(*CN))144return false;145} else {146// Fits in 10-bit signed immediate.147if (isInt<10>(CN->getSExtValue())) {148int16_t Imm = CN->getSExtValue();149Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));150Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));151AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);152return true;153}154}155}156157// if Address is FI, get the TargetFrameIndex.158if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {159Base = CurDAG->getTargetFrameIndex(160FIN->getIndex(),161getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));162Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);163AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);164return true;165}166167// Skip direct calls168if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||169Addr.getOpcode() == ISD::TargetGlobalAddress))170return false;171172// Address of the form imm + reg173ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());174if (AluOperator == ISD::ADD) {175AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);176// Addresses of the form FI+const177if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))178if ((RiMode && isInt<16>(CN->getSExtValue())) ||179(!RiMode && isInt<10>(CN->getSExtValue()))) {180// If the first operand is a FI, get the TargetFI Node181if (FrameIndexSDNode *FIN =182dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {183Base = CurDAG->getTargetFrameIndex(184FIN->getIndex(),185getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));186} else {187Base = Addr.getOperand(0);188}189190Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32);191return true;192}193}194195// Let SLS match SMALL instead of RI.196if (AluOperator == ISD::OR && RiMode &&197Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)198return false;199200Base = Addr;201Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);202AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);203return true;204}205206bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,207SDValue &Offset, SDValue &AluOp) {208return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/true);209}210211bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,212SDValue &Offset, SDValue &AluOp) {213return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);214}215216namespace llvm {217namespace LPAC {218static AluCode isdToLanaiAluCode(ISD::NodeType Node_type) {219switch (Node_type) {220case ISD::ADD:221return AluCode::ADD;222case ISD::ADDE:223return AluCode::ADDC;224case ISD::SUB:225return AluCode::SUB;226case ISD::SUBE:227return AluCode::SUBB;228case ISD::AND:229return AluCode::AND;230case ISD::OR:231return AluCode::OR;232case ISD::XOR:233return AluCode::XOR;234case ISD::SHL:235return AluCode::SHL;236case ISD::SRL:237return AluCode::SRL;238case ISD::SRA:239return AluCode::SRA;240default:241return AluCode::UNKNOWN;242}243}244} // namespace LPAC245} // namespace llvm246247bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2,248SDValue &AluOp) {249// if Address is FI, get the TargetFrameIndex.250if (Addr.getOpcode() == ISD::FrameIndex)251return false;252253// Skip direct calls254if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||255Addr.getOpcode() == ISD::TargetGlobalAddress))256return false;257258// Address of the form OP + OP259ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());260LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator);261if (AluCode != LPAC::UNKNOWN) {262// Skip addresses of the form FI OP const263if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))264if (isInt<16>(CN->getSExtValue()))265return false;266267// Skip addresses with hi/lo operands268if (Addr.getOperand(0).getOpcode() == LanaiISD::HI ||269Addr.getOperand(0).getOpcode() == LanaiISD::LO ||270Addr.getOperand(0).getOpcode() == LanaiISD::SMALL ||271Addr.getOperand(1).getOpcode() == LanaiISD::HI ||272Addr.getOperand(1).getOpcode() == LanaiISD::LO ||273Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)274return false;275276// Addresses of the form register OP register277R1 = Addr.getOperand(0);278R2 = Addr.getOperand(1);279AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32);280return true;281}282283// Skip addresses with zero offset284return false;285}286287bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(288const SDValue &Op, InlineAsm::ConstraintCode ConstraintCode,289std::vector<SDValue> &OutOps) {290SDValue Op0, Op1, AluOp;291switch (ConstraintCode) {292default:293return true;294case InlineAsm::ConstraintCode::m: // memory295if (!selectAddrRr(Op, Op0, Op1, AluOp) &&296!selectAddrRi(Op, Op0, Op1, AluOp))297return true;298break;299}300301OutOps.push_back(Op0);302OutOps.push_back(Op1);303OutOps.push_back(AluOp);304return false;305}306307// Select instructions not customized! Used for308// expanded, promoted and normal instructions309void LanaiDAGToDAGISel::Select(SDNode *Node) {310unsigned Opcode = Node->getOpcode();311312// If we have a custom node, we already have selected!313if (Node->isMachineOpcode()) {314LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");315return;316}317318// Instruction Selection not handled by the auto-generated tablegen selection319// should be handled here.320EVT VT = Node->getValueType(0);321switch (Opcode) {322case ISD::Constant:323if (VT == MVT::i32) {324ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node);325// Materialize zero constants as copies from R0. This allows the coalescer326// to propagate these into other instructions.327if (ConstNode->isZero()) {328SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),329SDLoc(Node), Lanai::R0, MVT::i32);330return ReplaceNode(Node, New.getNode());331}332// Materialize all ones constants as copies from R1. This allows the333// coalescer to propagate these into other instructions.334if (ConstNode->isAllOnes()) {335SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),336SDLoc(Node), Lanai::R1, MVT::i32);337return ReplaceNode(Node, New.getNode());338}339}340break;341case ISD::FrameIndex:342selectFrameIndex(Node);343return;344default:345break;346}347348// Select the default instruction349SelectCode(Node);350}351352void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) {353SDLoc DL(Node);354SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32);355int FI = cast<FrameIndexSDNode>(Node)->getIndex();356EVT VT = Node->getValueType(0);357SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);358unsigned Opc = Lanai::ADD_I_LO;359if (Node->hasOneUse()) {360CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm);361return;362}363ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm));364}365366// createLanaiISelDag - This pass converts a legalized DAG into a367// Lanai-specific DAG, ready for instruction scheduling.368FunctionPass *llvm::createLanaiISelDag(LanaiTargetMachine &TM) {369return new LanaiDAGToDAGISelLegacy(TM);370}371372373