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

          Line data    Source code
       1             : //===-- WebAssemblyStoreResults.cpp - Optimize using store result values --===//
       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 implements an optimization pass using store result values.
      12             : ///
      13             : /// WebAssembly's store instructions return the stored value. This is to enable
      14             : /// an optimization wherein uses of the stored value can be replaced by uses of
      15             : /// the store's result value, making the stored value register more likely to
      16             : /// be single-use, thus more likely to be useful to register stackifying, and
      17             : /// potentially also exposing the store to register stackifying. These both can
      18             : /// reduce get_local/set_local traffic.
      19             : ///
      20             : /// This pass also performs this optimization for memcpy, memmove, and memset
      21             : /// calls, since the LLVM intrinsics for these return void so they can't use the
      22             : /// returned attribute and consequently aren't handled by the OptimizeReturned
      23             : /// pass.
      24             : ///
      25             : //===----------------------------------------------------------------------===//
      26             : 
      27             : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
      28             : #include "WebAssembly.h"
      29             : #include "WebAssemblyMachineFunctionInfo.h"
      30             : #include "WebAssemblySubtarget.h"
      31             : #include "llvm/Analysis/TargetLibraryInfo.h"
      32             : #include "llvm/CodeGen/LiveIntervals.h"
      33             : #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
      34             : #include "llvm/CodeGen/MachineDominators.h"
      35             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      36             : #include "llvm/CodeGen/Passes.h"
      37             : #include "llvm/Support/Debug.h"
      38             : #include "llvm/Support/raw_ostream.h"
      39             : using namespace llvm;
      40             : 
      41             : #define DEBUG_TYPE "wasm-store-results"
      42             : 
      43             : namespace {
      44             : class WebAssemblyStoreResults final : public MachineFunctionPass {
      45             : public:
      46             :   static char ID; // Pass identification, replacement for typeid
      47         298 :   WebAssemblyStoreResults() : MachineFunctionPass(ID) {}
      48             : 
      49         298 :   StringRef getPassName() const override { return "WebAssembly Store Results"; }
      50             : 
      51         298 :   void getAnalysisUsage(AnalysisUsage &AU) const override {
      52         298 :     AU.setPreservesCFG();
      53             :     AU.addRequired<MachineBlockFrequencyInfo>();
      54             :     AU.addPreserved<MachineBlockFrequencyInfo>();
      55             :     AU.addRequired<MachineDominatorTree>();
      56             :     AU.addPreserved<MachineDominatorTree>();
      57             :     AU.addRequired<LiveIntervals>();
      58             :     AU.addPreserved<SlotIndexes>();
      59             :     AU.addPreserved<LiveIntervals>();
      60             :     AU.addRequired<TargetLibraryInfoWrapperPass>();
      61         298 :     MachineFunctionPass::getAnalysisUsage(AU);
      62         298 :   }
      63             : 
      64             :   bool runOnMachineFunction(MachineFunction &MF) override;
      65             : 
      66             : private:
      67             : };
      68             : } // end anonymous namespace
      69             : 
      70             : char WebAssemblyStoreResults::ID = 0;
      71      199030 : INITIALIZE_PASS(WebAssemblyStoreResults, DEBUG_TYPE,
      72             :                 "Optimize store result values for WebAssembly", false, false)
      73             : 
      74         298 : FunctionPass *llvm::createWebAssemblyStoreResults() {
      75         298 :   return new WebAssemblyStoreResults();
      76             : }
      77             : 
      78             : // Replace uses of FromReg with ToReg if they are dominated by MI.
      79          14 : static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
      80             :                                  unsigned FromReg, unsigned ToReg,
      81             :                                  const MachineRegisterInfo &MRI,
      82             :                                  MachineDominatorTree &MDT,
      83             :                                  LiveIntervals &LIS) {
      84             :   bool Changed = false;
      85             : 
      86          14 :   LiveInterval *FromLI = &LIS.getInterval(FromReg);
      87          14 :   LiveInterval *ToLI = &LIS.getInterval(ToReg);
      88             : 
      89          14 :   SlotIndex FromIdx = LIS.getInstructionIndex(MI).getRegSlot();
      90          28 :   VNInfo *FromVNI = FromLI->getVNInfoAt(FromIdx);
      91             : 
      92             :   SmallVector<SlotIndex, 4> Indices;
      93             : 
      94          14 :   for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end();
      95          45 :        I != E;) {
      96             :     MachineOperand &O = *I++;
      97          31 :     MachineInstr *Where = O.getParent();
      98             : 
      99             :     // Check that MI dominates the instruction in the normal way.
     100          31 :     if (&MI == Where || !MDT.dominates(&MI, Where))
     101          20 :       continue;
     102             : 
     103             :     // If this use gets a different value, skip it.
     104          11 :     SlotIndex WhereIdx = LIS.getInstructionIndex(*Where);
     105          11 :     VNInfo *WhereVNI = FromLI->getVNInfoAt(WhereIdx);
     106          11 :     if (WhereVNI && WhereVNI != FromVNI)
     107             :       continue;
     108             : 
     109             :     // Make sure ToReg isn't clobbered before it gets there.
     110          11 :     VNInfo *ToVNI = ToLI->getVNInfoAt(WhereIdx);
     111          11 :     if (ToVNI && ToVNI != FromVNI)
     112             :       continue;
     113             : 
     114             :     Changed = true;
     115             :     LLVM_DEBUG(dbgs() << "Setting operand " << O << " in " << *Where << " from "
     116             :                       << MI << "\n");
     117          11 :     O.setReg(ToReg);
     118             : 
     119             :     // If the store's def was previously dead, it is no longer.
     120          11 :     if (!O.isUndef()) {
     121          11 :       MI.getOperand(0).setIsDead(false);
     122             : 
     123          11 :       Indices.push_back(WhereIdx.getRegSlot());
     124             :     }
     125             :   }
     126             : 
     127          14 :   if (Changed) {
     128             :     // Extend ToReg's liveness.
     129           9 :     LIS.extendToIndices(*ToLI, Indices);
     130             : 
     131             :     // Shrink FromReg's liveness.
     132           9 :     LIS.shrinkToUses(FromLI);
     133             : 
     134             :     // If we replaced all dominated uses, FromReg is now killed at MI.
     135           9 :     if (!FromLI->liveAt(FromIdx.getDeadSlot()))
     136           9 :       MI.addRegisterKilled(FromReg, MBB.getParent()
     137           9 :                                         ->getSubtarget<WebAssemblySubtarget>()
     138             :                                         .getRegisterInfo());
     139             :   }
     140             : 
     141          14 :   return Changed;
     142             : }
     143             : 
     144         177 : static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI,
     145             :                          const MachineRegisterInfo &MRI,
     146             :                          MachineDominatorTree &MDT, LiveIntervals &LIS,
     147             :                          const WebAssemblyTargetLowering &TLI,
     148             :                          const TargetLibraryInfo &LibInfo) {
     149         177 :   MachineOperand &Op1 = MI.getOperand(1);
     150         177 :   if (!Op1.isSymbol())
     151             :     return false;
     152             : 
     153          18 :   StringRef Name(Op1.getSymbolName());
     154             :   bool callReturnsInput = Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
     155             :                           Name == TLI.getLibcallName(RTLIB::MEMMOVE) ||
     156             :                           Name == TLI.getLibcallName(RTLIB::MEMSET);
     157             :   if (!callReturnsInput)
     158             :     return false;
     159             : 
     160             :   LibFunc Func;
     161          14 :   if (!LibInfo.getLibFunc(Name, Func))
     162             :     return false;
     163             : 
     164          14 :   unsigned FromReg = MI.getOperand(2).getReg();
     165          14 :   unsigned ToReg = MI.getOperand(0).getReg();
     166          14 :   if (MRI.getRegClass(FromReg) != MRI.getRegClass(ToReg))
     167           0 :     report_fatal_error("Store results: call to builtin function with wrong "
     168             :                        "signature, from/to mismatch");
     169          14 :   return ReplaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
     170             : }
     171             : 
     172        2891 : bool WebAssemblyStoreResults::runOnMachineFunction(MachineFunction &MF) {
     173             :   LLVM_DEBUG({
     174             :     dbgs() << "********** Store Results **********\n"
     175             :            << "********** Function: " << MF.getName() << '\n';
     176             :   });
     177             : 
     178        2891 :   MachineRegisterInfo &MRI = MF.getRegInfo();
     179        2891 :   MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
     180             :   const WebAssemblyTargetLowering &TLI =
     181        2891 :       *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
     182        2891 :   const auto &LibInfo = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
     183        2891 :   LiveIntervals &LIS = getAnalysis<LiveIntervals>();
     184             :   bool Changed = false;
     185             : 
     186             :   // We don't preserve SSA form.
     187        2891 :   MRI.leaveSSA();
     188             : 
     189             :   assert(MRI.tracksLiveness() && "StoreResults expects liveness tracking");
     190             : 
     191        6317 :   for (auto &MBB : MF) {
     192             :     LLVM_DEBUG(dbgs() << "Basic Block: " << MBB.getName() << '\n');
     193       28308 :     for (auto &MI : MBB)
     194       49764 :       switch (MI.getOpcode()) {
     195             :       default:
     196             :         break;
     197         177 :       case WebAssembly::CALL_I32:
     198             :       case WebAssembly::CALL_I64:
     199         177 :         Changed |= optimizeCall(MBB, MI, MRI, MDT, LIS, TLI, LibInfo);
     200         177 :         break;
     201             :       }
     202             :   }
     203             : 
     204        2891 :   return Changed;
     205             : }

Generated by: LCOV version 1.13