brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · ebb5f55 Raw
157 lines · cpp
1//===-- WebAssemblyRegisterInfo.cpp - WebAssembly Register Information ----===//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/// This file contains the WebAssembly implementation of the11/// TargetRegisterInfo class.12///13//===----------------------------------------------------------------------===//14 15#include "WebAssemblyRegisterInfo.h"16#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"17#include "WebAssemblyFrameLowering.h"18#include "WebAssemblyInstrInfo.h"19#include "WebAssemblyMachineFunctionInfo.h"20#include "WebAssemblySubtarget.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22#include "llvm/CodeGen/MachineInstrBuilder.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/CodeGen/TargetFrameLowering.h"25#include "llvm/Target/TargetOptions.h"26using namespace llvm;27 28#define DEBUG_TYPE "wasm-reg-info"29 30#define GET_REGINFO_TARGET_DESC31#include "WebAssemblyGenRegisterInfo.inc"32 33WebAssemblyRegisterInfo::WebAssemblyRegisterInfo(const Triple &TT)34    : WebAssemblyGenRegisterInfo(0), TT(TT) {}35 36const MCPhysReg *37WebAssemblyRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const {38  static const MCPhysReg CalleeSavedRegs[] = {0};39  return CalleeSavedRegs;40}41 42BitVector43WebAssemblyRegisterInfo::getReservedRegs(const MachineFunction & /*MF*/) const {44  BitVector Reserved(getNumRegs());45  for (auto Reg : {WebAssembly::SP32, WebAssembly::SP64, WebAssembly::FP32,46                   WebAssembly::FP64})47    Reserved.set(Reg);48  return Reserved;49}50 51bool WebAssemblyRegisterInfo::eliminateFrameIndex(52    MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum,53    RegScavenger * /*RS*/) const {54  assert(SPAdj == 0);55  MachineInstr &MI = *II;56 57  MachineBasicBlock &MBB = *MI.getParent();58  MachineFunction &MF = *MBB.getParent();59  MachineRegisterInfo &MRI = MF.getRegInfo();60  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();61  const MachineFrameInfo &MFI = MF.getFrameInfo();62  int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex);63 64  assert(MFI.getObjectSize(FrameIndex) != 0 &&65         "We assume that variable-sized objects have already been lowered, "66         "and don't use FrameIndex operands.");67  Register FrameRegister = getFrameRegister(MF);68 69  // If this is the address operand of a load or store, make it relative to SP70  // and fold the frame offset directly in.71  unsigned AddrOperandNum = WebAssembly::getNamedOperandIdx(72      MI.getOpcode(), WebAssembly::OpName::addr);73  if (AddrOperandNum == FIOperandNum) {74    unsigned OffsetOperandNum = WebAssembly::getNamedOperandIdx(75        MI.getOpcode(), WebAssembly::OpName::off);76    assert(FrameOffset >= 0 && MI.getOperand(OffsetOperandNum).getImm() >= 0);77    int64_t Offset = MI.getOperand(OffsetOperandNum).getImm() + FrameOffset;78 79    if (static_cast<uint64_t>(Offset) <= std::numeric_limits<uint32_t>::max()) {80      MI.getOperand(OffsetOperandNum).setImm(Offset);81      MI.getOperand(FIOperandNum)82          .ChangeToRegister(FrameRegister, /*isDef=*/false);83      return false;84    }85  }86 87  // If this is an address being added to a constant, fold the frame offset88  // into the constant.89  if (MI.getOpcode() == WebAssemblyFrameLowering::getOpcAdd(MF)) {90    MachineOperand &OtherMO = MI.getOperand(3 - FIOperandNum);91    if (OtherMO.isReg()) {92      Register OtherMOReg = OtherMO.getReg();93      if (OtherMOReg.isVirtual()) {94        MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(OtherMOReg);95        // TODO: For now we just opportunistically do this in the case where96        // the CONST_I32/64 happens to have exactly one def and one use. We97        // should generalize this to optimize in more cases.98        if (Def && Def->getOpcode() ==99              WebAssemblyFrameLowering::getOpcConst(MF) &&100            MRI.hasOneNonDBGUse(Def->getOperand(0).getReg())) {101          MachineOperand &ImmMO = Def->getOperand(1);102          if (ImmMO.isImm()) {103            ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset));104            MI.getOperand(FIOperandNum)105                .ChangeToRegister(FrameRegister, /*isDef=*/false);106            return false;107          }108        }109      }110    }111  }112 113  // Otherwise create an i32/64.add SP, offset and make it the operand.114  const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();115 116  unsigned FIRegOperand = FrameRegister;117  if (FrameOffset) {118    // Create i32/64.add SP, offset and make it the operand.119    const TargetRegisterClass *PtrRC =120        MRI.getTargetRegisterInfo()->getPointerRegClass();121    Register OffsetOp = MRI.createVirtualRegister(PtrRC);122    BuildMI(MBB, *II, II->getDebugLoc(),123            TII->get(WebAssemblyFrameLowering::getOpcConst(MF)),124            OffsetOp)125        .addImm(FrameOffset);126    FIRegOperand = MRI.createVirtualRegister(PtrRC);127    BuildMI(MBB, *II, II->getDebugLoc(),128            TII->get(WebAssemblyFrameLowering::getOpcAdd(MF)),129            FIRegOperand)130        .addReg(FrameRegister)131        .addReg(OffsetOp);132  }133  MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*isDef=*/false);134  return false;135}136 137Register138WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {139  // If the PReg has been replaced by a VReg, return that.140  const auto &MFI = MF.getInfo<WebAssemblyFunctionInfo>();141  if (MFI->isFrameBaseVirtual())142    return MFI->getFrameBaseVreg();143  static const unsigned Regs[2][2] = {144      /*            !isArch64Bit       isArch64Bit      */145      /* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64},146      /*  hasFP */ {WebAssembly::FP32, WebAssembly::FP64}};147  const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);148  return Regs[TFI->hasFP(MF)][TT.isArch64Bit()];149}150 151const TargetRegisterClass *152WebAssemblyRegisterInfo::getPointerRegClass(unsigned Kind) const {153  assert(Kind == 0 && "Only one kind of pointer on WebAssembly");154  return TT.getArch() == Triple::wasm64 ? &WebAssembly::I64RegClass155                                        : &WebAssembly::I32RegClass;156}157