LLVM  8.0.0svn
TypeMetadataUtils.cpp
Go to the documentation of this file.
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 
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Dominators.h"
18 #include "llvm/IR/Intrinsics.h"
19 #include "llvm/IR/Module.h"
20 
21 using namespace llvm;
22 
23 // Search for virtual calls that call FPtr and add them to DevirtCalls.
24 static void
26  bool *HasNonCallUses, Value *FPtr, uint64_t Offset,
27  const CallInst *CI, DominatorTree &DT) {
28  for (const Use &U : FPtr->uses()) {
29  Instruction *User = cast<Instruction>(U.getUser());
30  // Ignore this instruction if it is not dominated by the type intrinsic
31  // being analyzed. Otherwise we may transform a call sharing the same
32  // vtable pointer incorrectly. Specifically, this situation can arise
33  // after indirect call promotion and inlining, where we may have uses
34  // of the vtable pointer guarded by a function pointer check, and a fallback
35  // indirect call.
36  if (!DT.dominates(CI, User))
37  continue;
38  if (isa<BitCastInst>(User)) {
39  findCallsAtConstantOffset(DevirtCalls, HasNonCallUses, User, Offset, CI,
40  DT);
41  } else if (auto CI = dyn_cast<CallInst>(User)) {
42  DevirtCalls.push_back({Offset, CI});
43  } else if (auto II = dyn_cast<InvokeInst>(User)) {
44  DevirtCalls.push_back({Offset, II});
45  } else if (HasNonCallUses) {
46  *HasNonCallUses = true;
47  }
48  }
49 }
50 
51 // Search for virtual calls that load from VPtr and add them to DevirtCalls.
53  const Module *M, SmallVectorImpl<DevirtCallSite> &DevirtCalls, Value *VPtr,
54  int64_t Offset, const CallInst *CI, DominatorTree &DT) {
55  for (const Use &U : VPtr->uses()) {
56  Value *User = U.getUser();
57  if (isa<BitCastInst>(User)) {
58  findLoadCallsAtConstantOffset(M, DevirtCalls, User, Offset, CI, DT);
59  } else if (isa<LoadInst>(User)) {
60  findCallsAtConstantOffset(DevirtCalls, nullptr, User, Offset, CI, DT);
61  } else if (auto GEP = dyn_cast<GetElementPtrInst>(User)) {
62  // Take into account the GEP offset.
63  if (VPtr == GEP->getPointerOperand() && GEP->hasAllConstantIndices()) {
64  SmallVector<Value *, 8> Indices(GEP->op_begin() + 1, GEP->op_end());
65  int64_t GEPOffset = M->getDataLayout().getIndexedOffsetInType(
66  GEP->getSourceElementType(), Indices);
67  findLoadCallsAtConstantOffset(M, DevirtCalls, User, Offset + GEPOffset,
68  CI, DT);
69  }
70  }
71  }
72 }
73 
76  SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI,
77  DominatorTree &DT) {
78  assert(CI->getCalledFunction()->getIntrinsicID() == Intrinsic::type_test);
79 
80  const Module *M = CI->getParent()->getParent()->getParent();
81 
82  // Find llvm.assume intrinsics for this llvm.type.test call.
83  for (const Use &CIU : CI->uses()) {
84  if (auto *AssumeCI = dyn_cast<CallInst>(CIU.getUser())) {
85  Function *F = AssumeCI->getCalledFunction();
86  if (F && F->getIntrinsicID() == Intrinsic::assume)
87  Assumes.push_back(AssumeCI);
88  }
89  }
90 
91  // If we found any, search for virtual calls based on %p and add them to
92  // DevirtCalls.
93  if (!Assumes.empty())
95  M, DevirtCalls, CI->getArgOperand(0)->stripPointerCasts(), 0, CI, DT);
96 }
97 
100  SmallVectorImpl<Instruction *> &LoadedPtrs,
101  SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses,
102  const CallInst *CI, DominatorTree &DT) {
104  Intrinsic::type_checked_load);
105 
106  auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
107  if (!Offset) {
108  HasNonCallUses = true;
109  return;
110  }
111 
112  for (const Use &U : CI->uses()) {
113  auto CIU = U.getUser();
114  if (auto EVI = dyn_cast<ExtractValueInst>(CIU)) {
115  if (EVI->getNumIndices() == 1 && EVI->getIndices()[0] == 0) {
116  LoadedPtrs.push_back(EVI);
117  continue;
118  }
119  if (EVI->getNumIndices() == 1 && EVI->getIndices()[0] == 1) {
120  Preds.push_back(EVI);
121  continue;
122  }
123  }
124  HasNonCallUses = true;
125  }
126 
127  for (Value *LoadedPtr : LoadedPtrs)
128  findCallsAtConstantOffset(DevirtCalls, &HasNonCallUses, LoadedPtr,
129  Offset->getZExtValue(), CI, DT);
130 }
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
iterator_range< use_iterator > uses()
Definition: Value.h:355
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:64
void findDevirtualizableCallsForTypeTest(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< CallInst *> &Assumes, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.test, find all devirtualizable call sites based on the call ...
This class represents a function call, abstracting a target machine&#39;s calling convention.
static void findLoadCallsAtConstantOffset(const Module *M, SmallVectorImpl< DevirtCallSite > &DevirtCalls, Value *VPtr, int64_t Offset, const CallInst *CI, DominatorTree &DT)
F(f)
Hexagon Common GEP
void findDevirtualizableCallsForTypeCheckedLoad(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< Instruction *> &LoadedPtrs, SmallVectorImpl< Instruction *> &Preds, bool &HasNonCallUses, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.checked.load, find all devirtualizable call sites based on t...
const DataLayout & getDataLayout() const
Get the data layout for the module&#39;s target platform.
Definition: Module.cpp:364
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Definition: Dominators.h:145
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs, and aliases.
Definition: Value.cpp:539
This is the shared class of boolean and integer constants.
Definition: Constants.h:84
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
Definition: Dominators.cpp:249
Module.h This file contains the declarations for the Module class.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition: Function.h:194
static void findCallsAtConstantOffset(SmallVectorImpl< DevirtCallSite > &DevirtCalls, bool *HasNonCallUses, Value *FPtr, uint64_t Offset, const CallInst *CI, DominatorTree &DT)
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:56
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:107
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:566
LLVM Value Representation.
Definition: Value.h:73
int64_t getIndexedOffsetInType(Type *ElemTy, ArrayRef< Value *> Indices) const
Returns the offset from the beginning of the type for the specified indices.
Definition: DataLayout.cpp:779
const BasicBlock * getParent() const
Definition: Instruction.h:67