LCOV - code coverage report
Current view: top level - lib/Analysis - TypeMetadataUtils.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 48 52 92.3 %
Date: 2017-09-14 15:23:50 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TypeMetadataUtils.cpp - Utilities related to type metadata ---------===//
       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             : // This file contains functions that make it easier to manipulate type metadata
      11             : // for devirtualization.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/Analysis/TypeMetadataUtils.h"
      16             : #include "llvm/IR/Constants.h"
      17             : #include "llvm/IR/Intrinsics.h"
      18             : #include "llvm/IR/Module.h"
      19             : 
      20             : using namespace llvm;
      21             : 
      22             : // Search for virtual calls that call FPtr and add them to DevirtCalls.
      23             : static void
      24         178 : findCallsAtConstantOffset(SmallVectorImpl<DevirtCallSite> &DevirtCalls,
      25             :                           bool *HasNonCallUses, Value *FPtr, uint64_t Offset) {
      26         534 :   for (const Use &U : FPtr->uses()) {
      27         178 :     Value *User = U.getUser();
      28         178 :     if (isa<BitCastInst>(User)) {
      29          89 :       findCallsAtConstantOffset(DevirtCalls, HasNonCallUses, User, Offset);
      30         177 :     } else if (auto CI = dyn_cast<CallInst>(User)) {
      31         176 :       DevirtCalls.push_back({Offset, CI});
      32           2 :     } else if (auto II = dyn_cast<InvokeInst>(User)) {
      33           2 :       DevirtCalls.push_back({Offset, II});
      34           0 :     } else if (HasNonCallUses) {
      35           0 :       *HasNonCallUses = true;
      36             :     }
      37             :   }
      38         178 : }
      39             : 
      40             : // Search for virtual calls that load from VPtr and add them to DevirtCalls.
      41             : static void
      42         207 : findLoadCallsAtConstantOffset(const Module *M,
      43             :                               SmallVectorImpl<DevirtCallSite> &DevirtCalls,
      44             :                               Value *VPtr, int64_t Offset) {
      45         690 :   for (const Use &U : VPtr->uses()) {
      46         276 :     Value *User = U.getUser();
      47         276 :     if (isa<BitCastInst>(User)) {
      48          72 :       findLoadCallsAtConstantOffset(M, DevirtCalls, User, Offset);
      49         204 :     } else if (isa<LoadInst>(User)) {
      50          67 :       findCallsAtConstantOffset(DevirtCalls, nullptr, User, Offset);
      51         204 :     } else if (auto GEP = dyn_cast<GetElementPtrInst>(User)) {
      52             :       // Take into account the GEP offset.
      53          67 :       if (VPtr == GEP->getPointerOperand() && GEP->hasAllConstantIndices()) {
      54         268 :         SmallVector<Value *, 8> Indices(GEP->op_begin() + 1, GEP->op_end());
      55         201 :         int64_t GEPOffset = M->getDataLayout().getIndexedOffsetInType(
      56          67 :             GEP->getSourceElementType(), Indices);
      57          67 :         findLoadCallsAtConstantOffset(M, DevirtCalls, User, Offset + GEPOffset);
      58             :       }
      59             :     }
      60             :   }
      61         207 : }
      62             : 
      63          93 : void llvm::findDevirtualizableCallsForTypeTest(
      64             :     SmallVectorImpl<DevirtCallSite> &DevirtCalls,
      65             :     SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI) {
      66             :   assert(CI->getCalledFunction()->getIntrinsicID() == Intrinsic::type_test);
      67             : 
      68          93 :   const Module *M = CI->getParent()->getParent()->getParent();
      69             : 
      70             :   // Find llvm.assume intrinsics for this llvm.type.test call.
      71         370 :   for (const Use &CIU : CI->uses()) {
      72         182 :     if (auto *AssumeCI = dyn_cast<CallInst>(CIU.getUser())) {
      73         136 :       Function *F = AssumeCI->getCalledFunction();
      74          68 :       if (F && F->getIntrinsicID() == Intrinsic::assume)
      75          68 :         Assumes.push_back(AssumeCI);
      76             :     }
      77             :   }
      78             : 
      79             :   // If we found any, search for virtual calls based on %p and add them to
      80             :   // DevirtCalls.
      81          93 :   if (!Assumes.empty())
      82         136 :     findLoadCallsAtConstantOffset(M, DevirtCalls,
      83             :                                   CI->getArgOperand(0)->stripPointerCasts(), 0);
      84          93 : }
      85             : 
      86          26 : void llvm::findDevirtualizableCallsForTypeCheckedLoad(
      87             :     SmallVectorImpl<DevirtCallSite> &DevirtCalls,
      88             :     SmallVectorImpl<Instruction *> &LoadedPtrs,
      89             :     SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses,
      90             :     const CallInst *CI) {
      91             :   assert(CI->getCalledFunction()->getIntrinsicID() ==
      92             :          Intrinsic::type_checked_load);
      93             : 
      94          52 :   auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
      95             :   if (!Offset) {
      96           0 :     HasNonCallUses = true;
      97           0 :     return;
      98             :   }
      99             : 
     100         122 :   for (const Use &U : CI->uses()) {
     101          44 :     auto CIU = U.getUser();
     102          41 :     if (auto EVI = dyn_cast<ExtractValueInst>(CIU)) {
     103         104 :       if (EVI->getNumIndices() == 1 && EVI->getIndices()[0] == 0) {
     104          22 :         LoadedPtrs.push_back(EVI);
     105          22 :         continue;
     106             :       }
     107          57 :       if (EVI->getNumIndices() == 1 && EVI->getIndices()[0] == 1) {
     108          19 :         Preds.push_back(EVI);
     109          19 :         continue;
     110             :       }
     111             :     }
     112           3 :     HasNonCallUses = true;
     113             :   }
     114             : 
     115         100 :   for (Value *LoadedPtr : LoadedPtrs)
     116          22 :     findCallsAtConstantOffset(DevirtCalls, &HasNonCallUses, LoadedPtr,
     117             :                               Offset->getZExtValue());
     118             : }

Generated by: LCOV version 1.13