LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly - WebAssemblyRegisterInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 52 53 98.1 %
Date: 2018-10-20 13:21:21 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- WebAssemblyRegisterInfo.cpp - WebAssembly Register Information ----===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : ///
      10             : /// \file
      11             : /// This file contains the WebAssembly implementation of the
      12             : /// TargetRegisterInfo class.
      13             : ///
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #include "WebAssemblyRegisterInfo.h"
      17             : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
      18             : #include "WebAssemblyFrameLowering.h"
      19             : #include "WebAssemblyInstrInfo.h"
      20             : #include "WebAssemblyMachineFunctionInfo.h"
      21             : #include "WebAssemblySubtarget.h"
      22             : #include "llvm/CodeGen/MachineFrameInfo.h"
      23             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      24             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      25             : #include "llvm/CodeGen/TargetFrameLowering.h"
      26             : #include "llvm/IR/Function.h"
      27             : #include "llvm/Support/raw_ostream.h"
      28             : #include "llvm/Target/TargetOptions.h"
      29             : using namespace llvm;
      30             : 
      31             : #define DEBUG_TYPE "wasm-reg-info"
      32             : 
      33             : #define GET_REGINFO_TARGET_DESC
      34             : #include "WebAssemblyGenRegisterInfo.inc"
      35             : 
      36         293 : WebAssemblyRegisterInfo::WebAssemblyRegisterInfo(const Triple &TT)
      37         293 :     : WebAssemblyGenRegisterInfo(0), TT(TT) {}
      38             : 
      39             : const MCPhysReg *
      40        2891 : WebAssemblyRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const {
      41             :   static const MCPhysReg CalleeSavedRegs[] = {0};
      42        2891 :   return CalleeSavedRegs;
      43             : }
      44             : 
      45             : BitVector
      46        2992 : WebAssemblyRegisterInfo::getReservedRegs(const MachineFunction & /*MF*/) const {
      47        2992 :   BitVector Reserved(getNumRegs());
      48       23936 :   for (auto Reg : {WebAssembly::SP32, WebAssembly::SP64, WebAssembly::FP32,
      49       14960 :                    WebAssembly::FP64})
      50             :     Reserved.set(Reg);
      51        2992 :   return Reserved;
      52             : }
      53             : 
      54         440 : void WebAssemblyRegisterInfo::eliminateFrameIndex(
      55             :     MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum,
      56             :     RegScavenger * /*RS*/) const {
      57             :   assert(SPAdj == 0);
      58             :   MachineInstr &MI = *II;
      59             : 
      60         440 :   MachineBasicBlock &MBB = *MI.getParent();
      61         440 :   MachineFunction &MF = *MBB.getParent();
      62         440 :   MachineRegisterInfo &MRI = MF.getRegInfo();
      63         440 :   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
      64         440 :   const MachineFrameInfo &MFI = MF.getFrameInfo();
      65         440 :   int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex);
      66             : 
      67             :   assert(MFI.getObjectSize(FrameIndex) != 0 &&
      68             :          "We assume that variable-sized objects have already been lowered, "
      69             :          "and don't use FrameIndex operands.");
      70         440 :   unsigned FrameRegister = getFrameRegister(MF);
      71             : 
      72             :   // If this is the address operand of a load or store, make it relative to SP
      73             :   // and fold the frame offset directly in.
      74         759 :   if ((MI.mayLoad() && FIOperandNum == WebAssembly::LoadAddressOperandNo) ||
      75         385 :       (MI.mayStore() && FIOperandNum == WebAssembly::StoreAddressOperandNo)) {
      76             :     assert(FrameOffset >= 0 && MI.getOperand(FIOperandNum - 1).getImm() >= 0);
      77         186 :     int64_t Offset = MI.getOperand(FIOperandNum - 1).getImm() + FrameOffset;
      78             : 
      79         186 :     if (static_cast<uint64_t>(Offset) <= std::numeric_limits<uint32_t>::max()) {
      80             :       MI.getOperand(FIOperandNum - 1).setImm(Offset);
      81             :       MI.getOperand(FIOperandNum)
      82         186 :           .ChangeToRegister(FrameRegister, /*IsDef=*/false);
      83         186 :       return;
      84             :     }
      85             :   }
      86             : 
      87             :   // If this is an address being added to a constant, fold the frame offset
      88             :   // into the constant.
      89         508 :   if (MI.getOpcode() == WebAssembly::ADD_I32) {
      90          96 :     MachineOperand &OtherMO = MI.getOperand(3 - FIOperandNum);
      91          96 :     if (OtherMO.isReg()) {
      92          96 :       unsigned OtherMOReg = OtherMO.getReg();
      93          96 :       if (TargetRegisterInfo::isVirtualRegister(OtherMOReg)) {
      94          96 :         MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(OtherMOReg);
      95             :         // TODO: For now we just opportunistically do this in the case where
      96             :         // the CONST_I32 happens to have exactly one def and one use. We
      97             :         // should generalize this to optimize in more cases.
      98         192 :         if (Def && Def->getOpcode() == WebAssembly::CONST_I32 &&
      99          96 :             MRI.hasOneNonDBGUse(Def->getOperand(0).getReg())) {
     100          12 :           MachineOperand &ImmMO = Def->getOperand(1);
     101          12 :           ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset));
     102          12 :           MI.getOperand(FIOperandNum)
     103          12 :               .ChangeToRegister(FrameRegister, /*IsDef=*/false);
     104          12 :           return;
     105             :         }
     106             :       }
     107             :     }
     108             :   }
     109             : 
     110             :   // Otherwise create an i32.add SP, offset and make it the operand.
     111         242 :   const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
     112             : 
     113             :   unsigned FIRegOperand = FrameRegister;
     114         242 :   if (FrameOffset) {
     115             :     // Create i32.add SP, offset and make it the operand.
     116             :     const TargetRegisterClass *PtrRC =
     117         185 :         MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
     118         185 :     unsigned OffsetOp = MRI.createVirtualRegister(PtrRC);
     119             :     BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::CONST_I32),
     120         370 :             OffsetOp)
     121             :         .addImm(FrameOffset);
     122         185 :     FIRegOperand = MRI.createVirtualRegister(PtrRC);
     123         185 :     BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::ADD_I32),
     124         370 :             FIRegOperand)
     125         185 :         .addReg(FrameRegister)
     126         185 :         .addReg(OffsetOp);
     127             :   }
     128         484 :   MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*IsDef=*/false);
     129             : }
     130             : 
     131             : unsigned
     132         468 : WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
     133             :   static const unsigned Regs[2][2] = {
     134             :       /*            !isArch64Bit       isArch64Bit      */
     135             :       /* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64},
     136             :       /*  hasFP */ {WebAssembly::FP32, WebAssembly::FP64}};
     137         468 :   const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
     138         468 :   return Regs[TFI->hasFP(MF)][TT.isArch64Bit()];
     139             : }
     140             : 
     141             : const TargetRegisterClass *
     142         336 : WebAssemblyRegisterInfo::getPointerRegClass(const MachineFunction &MF,
     143             :                                             unsigned Kind) const {
     144             :   assert(Kind == 0 && "Only one kind of pointer on WebAssembly");
     145         336 :   if (MF.getSubtarget<WebAssemblySubtarget>().hasAddr64())
     146           0 :     return &WebAssembly::I64RegClass;
     147             :   return &WebAssembly::I32RegClass;
     148             : }

Generated by: LCOV version 1.13