xref: /aosp_15_r20/art/compiler/optimizing/graph_visualizer.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <functional>
21*795d594fSAndroid Build Coastguard Worker #include <ostream>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h"
27*795d594fSAndroid Build Coastguard Worker #include "block_namer.h"
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker class CodeGenerator;
32*795d594fSAndroid Build Coastguard Worker class DexCompilationUnit;
33*795d594fSAndroid Build Coastguard Worker class HGraph;
34*795d594fSAndroid Build Coastguard Worker class HInstruction;
35*795d594fSAndroid Build Coastguard Worker class SlowPathCode;
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker /**
38*795d594fSAndroid Build Coastguard Worker  * This class outputs the HGraph in the C1visualizer format.
39*795d594fSAndroid Build Coastguard Worker  * Note: Currently only works if the compiler is single threaded.
40*795d594fSAndroid Build Coastguard Worker  */
41*795d594fSAndroid Build Coastguard Worker struct GeneratedCodeInterval {
42*795d594fSAndroid Build Coastguard Worker   size_t start;
43*795d594fSAndroid Build Coastguard Worker   size_t end;
44*795d594fSAndroid Build Coastguard Worker };
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker struct SlowPathCodeInfo {
47*795d594fSAndroid Build Coastguard Worker   const SlowPathCode* slow_path;
48*795d594fSAndroid Build Coastguard Worker   GeneratedCodeInterval code_interval;
49*795d594fSAndroid Build Coastguard Worker };
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker // This information is filled by the code generator. It will be used by the
52*795d594fSAndroid Build Coastguard Worker // graph visualizer to associate disassembly of the generated code with the
53*795d594fSAndroid Build Coastguard Worker // instructions and slow paths. We assume that the generated code follows the
54*795d594fSAndroid Build Coastguard Worker // following structure:
55*795d594fSAndroid Build Coastguard Worker //   - frame entry
56*795d594fSAndroid Build Coastguard Worker //   - instructions
57*795d594fSAndroid Build Coastguard Worker //   - slow paths
58*795d594fSAndroid Build Coastguard Worker class DisassemblyInformation {
59*795d594fSAndroid Build Coastguard Worker  public:
DisassemblyInformation(ArenaAllocator * allocator)60*795d594fSAndroid Build Coastguard Worker   explicit DisassemblyInformation(ArenaAllocator* allocator)
61*795d594fSAndroid Build Coastguard Worker       : frame_entry_interval_({0, 0}),
62*795d594fSAndroid Build Coastguard Worker         instruction_intervals_(std::less<const HInstruction*>(), allocator->Adapter()),
63*795d594fSAndroid Build Coastguard Worker         slow_path_intervals_(allocator->Adapter()) {}
64*795d594fSAndroid Build Coastguard Worker 
SetFrameEntryInterval(size_t start,size_t end)65*795d594fSAndroid Build Coastguard Worker   void SetFrameEntryInterval(size_t start, size_t end) {
66*795d594fSAndroid Build Coastguard Worker     frame_entry_interval_ = {start, end};
67*795d594fSAndroid Build Coastguard Worker   }
68*795d594fSAndroid Build Coastguard Worker 
AddInstructionInterval(HInstruction * instr,size_t start,size_t end)69*795d594fSAndroid Build Coastguard Worker   void AddInstructionInterval(HInstruction* instr, size_t start, size_t end) {
70*795d594fSAndroid Build Coastguard Worker     instruction_intervals_.Put(instr, {start, end});
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker 
AddSlowPathInterval(SlowPathCode * slow_path,size_t start,size_t end)73*795d594fSAndroid Build Coastguard Worker   void AddSlowPathInterval(SlowPathCode* slow_path, size_t start, size_t end) {
74*795d594fSAndroid Build Coastguard Worker     slow_path_intervals_.push_back({slow_path, {start, end}});
75*795d594fSAndroid Build Coastguard Worker   }
76*795d594fSAndroid Build Coastguard Worker 
GetFrameEntryInterval()77*795d594fSAndroid Build Coastguard Worker   GeneratedCodeInterval GetFrameEntryInterval() const {
78*795d594fSAndroid Build Coastguard Worker     return frame_entry_interval_;
79*795d594fSAndroid Build Coastguard Worker   }
80*795d594fSAndroid Build Coastguard Worker 
GetFrameEntryInterval()81*795d594fSAndroid Build Coastguard Worker   GeneratedCodeInterval* GetFrameEntryInterval() {
82*795d594fSAndroid Build Coastguard Worker     return &frame_entry_interval_;
83*795d594fSAndroid Build Coastguard Worker   }
84*795d594fSAndroid Build Coastguard Worker 
GetInstructionIntervals()85*795d594fSAndroid Build Coastguard Worker   const ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>& GetInstructionIntervals() const {
86*795d594fSAndroid Build Coastguard Worker     return instruction_intervals_;
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker 
GetInstructionIntervals()89*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>* GetInstructionIntervals() {
90*795d594fSAndroid Build Coastguard Worker     return &instruction_intervals_;
91*795d594fSAndroid Build Coastguard Worker   }
92*795d594fSAndroid Build Coastguard Worker 
GetSlowPathIntervals()93*795d594fSAndroid Build Coastguard Worker   const ArenaVector<SlowPathCodeInfo>& GetSlowPathIntervals() const { return slow_path_intervals_; }
94*795d594fSAndroid Build Coastguard Worker 
GetSlowPathIntervals()95*795d594fSAndroid Build Coastguard Worker   ArenaVector<SlowPathCodeInfo>* GetSlowPathIntervals() { return &slow_path_intervals_; }
96*795d594fSAndroid Build Coastguard Worker 
97*795d594fSAndroid Build Coastguard Worker  private:
98*795d594fSAndroid Build Coastguard Worker   GeneratedCodeInterval frame_entry_interval_;
99*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<const HInstruction*, GeneratedCodeInterval> instruction_intervals_;
100*795d594fSAndroid Build Coastguard Worker   ArenaVector<SlowPathCodeInfo> slow_path_intervals_;
101*795d594fSAndroid Build Coastguard Worker };
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker class HGraphVisualizer : public ValueObject {
104*795d594fSAndroid Build Coastguard Worker  public:
105*795d594fSAndroid Build Coastguard Worker   HGraphVisualizer(std::ostream* output,
106*795d594fSAndroid Build Coastguard Worker                    HGraph* graph,
107*795d594fSAndroid Build Coastguard Worker                    const CodeGenerator* codegen,
108*795d594fSAndroid Build Coastguard Worker                    std::optional<std::reference_wrapper<const BlockNamer>> namer = std::nullopt);
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker   void PrintHeader(const char* method_name) const;
111*795d594fSAndroid Build Coastguard Worker   void DumpGraph(const char* pass_name, bool is_after_pass, bool graph_in_bad_state) const;
112*795d594fSAndroid Build Coastguard Worker   void DumpGraphDebug() const;
113*795d594fSAndroid Build Coastguard Worker   void DumpGraphWithDisassembly() const;
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker   // C1visualizer file format does not support inserting arbitrary metadata into a cfg
116*795d594fSAndroid Build Coastguard Worker   // file. As a workaround a fake compilation block with the metadata in the name and the
117*795d594fSAndroid Build Coastguard Worker   // method attributes is used. Such empty blocks don't break the c1visualizer parser.
118*795d594fSAndroid Build Coastguard Worker   static std::string InsertMetaDataAsCompilationBlock(const std::string& meta_data);
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker   static void DumpInstruction(std::ostream* output, HGraph* graph, HInstruction* instruction);
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker  private:
123*795d594fSAndroid Build Coastguard Worker   class OptionalDefaultNamer final : public BlockNamer {
124*795d594fSAndroid Build Coastguard Worker    public:
OptionalDefaultNamer(std::optional<std::reference_wrapper<const BlockNamer>> inner)125*795d594fSAndroid Build Coastguard Worker     explicit OptionalDefaultNamer(std::optional<std::reference_wrapper<const BlockNamer>> inner)
126*795d594fSAndroid Build Coastguard Worker         : namer_(inner) {}
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker     std::ostream& PrintName(std::ostream& os, HBasicBlock* blk) const override;
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker    private:
131*795d594fSAndroid Build Coastguard Worker     std::optional<std::reference_wrapper<const BlockNamer>> namer_;
132*795d594fSAndroid Build Coastguard Worker   };
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker   std::ostream* const output_;
135*795d594fSAndroid Build Coastguard Worker   HGraph* const graph_;
136*795d594fSAndroid Build Coastguard Worker   const CodeGenerator* codegen_;
137*795d594fSAndroid Build Coastguard Worker   OptionalDefaultNamer namer_;
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
140*795d594fSAndroid Build Coastguard Worker };
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker }  // namespace art
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
145