LLVM 24.0.0git
InstructionPrecedenceTracking.cpp
Go to the documentation of this file.
1//===-- InstructionPrecedenceTracking.cpp -----------------------*- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8// Implements a class that is able to define some instructions as "special"
9// (e.g. as having implicit control flow, or writing memory, or having another
10// interesting property) and then efficiently answers queries of the types:
11// 1. Are there any special instructions in the block of interest?
12// 2. Return first of the special instructions in the given block;
13// 3. Check if the given instruction is preceeded by the first special
14// instruction in the same block.
15// The class provides caching that allows to answer these queries quickly. The
16// user must make sure that the cached data is invalidated properly whenever
17// a content of some tracked block is changed.
18//===----------------------------------------------------------------------===//
19
21#include "AnalysisOptions.h"
24
25using namespace llvm;
26
28 const BasicBlock *BB) {
29#ifndef NDEBUG
30 // If there is a bug connected to invalid cache, turn on
31 // -ipt-expensive-asserts to catch this situation as early as possible.
32 if (getAnalysisOptions(BB->getContext()).ipt_expensive_asserts)
33 validateAll();
34 else
35 validate(BB);
36#endif
37
38 auto [It, Inserted] = FirstSpecialInsts.try_emplace(BB);
39 if (Inserted) {
40 for (const auto &I : *BB) {
41 if (isSpecialInstruction(&I)) {
42 It->second = &I;
43 break;
44 }
45 }
46 }
47 return It->second;
48}
49
54
56 const Instruction *Insn) {
57 const Instruction *MaybeFirstSpecial =
59 return MaybeFirstSpecial && MaybeFirstSpecial->comesBefore(Insn);
60}
61
62#ifndef NDEBUG
63void InstructionPrecedenceTracking::validate(const BasicBlock *BB) const {
64 auto It = FirstSpecialInsts.find(BB);
65 // Bail if we don't have anything cached for this block.
66 if (It == FirstSpecialInsts.end())
67 return;
68
69 for (const Instruction &Insn : *BB)
70 if (isSpecialInstruction(&Insn)) {
71 assert(It->second == &Insn &&
72 "Cached first special instruction is wrong!");
73 return;
74 }
75
76 assert(It->second == nullptr &&
77 "Block is marked as having special instructions but in fact it has "
78 "none!");
79}
80
81void InstructionPrecedenceTracking::validateAll() const {
82 // Check that for every known block the cached value is correct.
83 for (const auto &It : FirstSpecialInsts)
84 validate(It.first);
85}
86#endif
87
89 const BasicBlock *BB) {
90 if (isSpecialInstruction(Inst))
91 FirstSpecialInsts.erase(BB);
92}
93
95 auto *BB = Inst->getParent();
96 assert(BB && "must be called before instruction is actually removed");
97 auto It = FirstSpecialInsts.find(BB);
98 if (It != FirstSpecialInsts.end() && It->second == Inst)
99 FirstSpecialInsts.erase(It);
100}
101
103 for (const auto *U : Inst->users()) {
104 if (const auto *UI = dyn_cast<Instruction>(U))
106 }
107}
108
110 FirstSpecialInsts.clear();
111#ifndef NDEBUG
112 // The map should be valid after clearing (at least empty).
113 validateAll();
114#endif
115}
116
118 const Instruction *Insn) const {
119 // If a block's instruction doesn't always pass the control to its successor
120 // instruction, mark the block as having implicit control flow. We use them
121 // to avoid wrong assumptions of sort "if A is executed and B post-dominates
122 // A, then B is also executed". This is not true is there is an implicit
123 // control flow instruction (e.g. a guard) between them.
125}
126
128 const Instruction *Insn) const {
129 using namespace PatternMatch;
131 return false;
132 return Insn->mayWriteToMemory();
133}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define I(x, y, z)
Definition MD5.cpp:57
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
bool isSpecialInstruction(const Instruction *Insn) const override
A predicate that defines whether or not the instruction Insn is considered special and needs to be tr...
LLVM_ABI void clear()
Invalidates all information from this tracking.
LLVM_ABI void removeUsersOf(const Instruction *Inst)
Notifies this tracking that we are going to replace all uses of Inst.
LLVM_ABI void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB)
Notifies this tracking that we are going to insert a new instruction Inst to the basic block BB.
LLVM_ABI void removeInstruction(const Instruction *Inst)
Notifies this tracking that we are going to remove the instruction Inst It makes all necessary update...
LLVM_ABI const Instruction * getFirstSpecialInstruction(const BasicBlock *BB)
Returns the topmost special instruction from the block BB.
virtual bool isSpecialInstruction(const Instruction *Insn) const =0
A predicate that defines whether or not the instruction Insn is considered special and needs to be tr...
LLVM_ABI bool hasSpecialInstructions(const BasicBlock *BB)
Returns true iff at least one instruction from the basic block BB is special.
LLVM_ABI bool isPreceededBySpecialInstruction(const Instruction *Insn)
Returns true iff the first special instruction of Insn's block exists and dominates Insn.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
bool isSpecialInstruction(const Instruction *Insn) const override
A predicate that defines whether or not the instruction Insn is considered special and needs to be tr...
const ParentTy * getParent() const
Definition ilist_node.h:34
bool match(Val *V, const Pattern &P)
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...