P4C
The P4 Compiler
Loading...
Searching...
No Matches
fieldslice_live_range.h
1
19#ifndef BACKENDS_TOFINO_BF_P4C_PHV_FIELDSLICE_LIVE_RANGE_H_
20#define BACKENDS_TOFINO_BF_P4C_PHV_FIELDSLICE_LIVE_RANGE_H_
21
22#include <algorithm>
23
24#include "backends/tofino/bf-p4c/common/field_defuse.h"
25#include "backends/tofino/bf-p4c/common/map_tables_to_actions.h"
26#include "backends/tofino/bf-p4c/mau/action_analysis.h"
27#include "backends/tofino/bf-p4c/parde/clot/clot_info.h"
28#include "backends/tofino/bf-p4c/phv/phv.h"
29#include "backends/tofino/bf-p4c/phv/pragma/phv_pragmas.h"
30#include "lib/safe_vector.h"
31#include "mau_backtracker.h"
32
33namespace PHV {
34
36 public:
37 // OpInfo represents the `liveness requirement` of a fieldslice of a stage (including PARDE).
38 // DEAD: fieldslice does not need to be allocated.
39 // READ: fieldslice needs to be allocated before VLIW.
40 // WRITE: fieldslice needs to be allocated after VLIW.
41 // READ_WRITE: fieldslice needs to be allocated before and after VLIW,
42 // (could have different containers for read and write)
43 // LIVE: fieldslice needs to be allocated before and after stage.
44 // (must be the same container)
45 // Note that LIVE and READ_WRITE have almost the same `liveness requirement`, they are
46 // different only when we compute disjoint live ranges, where READ_WRITE could be
47 // a start of a new live range (changing container) but LIVE does not.
48 // Consider two paired-defuse examples,
49 // f1's paired defuse(s): [-1W, 0R], [0W, 2R] // will produce [-1W, 0RW, 1L, 2R]
50 // f2's paired defuse(s): [-1, 2R] // will produce [-1W, 0L, 1L, 2R]
51 // f1 have two disjoint live ranges and they can be allocated to different containers
52 // but f2 has to be allocated into one container.
53 enum class OpInfo { DEAD, READ, WRITE, READ_WRITE, LIVE };
54
55 private:
60 static int num_table_stages;
61
62 // -1 = parser
63 // 0..num_table_stages - 1 = physical MAU stages
64 // num_table_stages = deparser
65 // we merge all together because we need to uniformly iterate
66 // parser + mau + deparser.
67 safe_vector<OpInfo> lives_i;
68
69 public:
71 // Static variable can't be initialized to Device::numStages() as the device isn't known at
72 // initialization time. Instead, check here that it's been set to a positive value.
73 if (num_table_stages <= 0) num_table_stages = Device::numStages();
74 lives_i.resize(num_table_stages + 2, OpInfo::DEAD);
75 }
76 OpInfo &parser() { return lives_i[0]; }
77 const OpInfo &parser() const { return lives_i[0]; }
78 OpInfo &deparser() { return lives_i[num_table_stages + 1]; }
79 const OpInfo &deparser() const { return lives_i[num_table_stages + 1]; }
80 OpInfo &stage(int i) { return lives_i[i + 1]; }
81 const OpInfo &stage(int i) const { return lives_i[i + 1]; }
82
86 static void set_num_table_stages(int stage) {
87 num_table_stages = std::max(stage, Device::numStages());
88 }
89
91 const safe_vector<OpInfo> &vec() const { return lives_i; }
92
109 bool can_overlay(const LiveRangeInfo &other) const;
110
123 std::vector<LiveRange> disjoint_ranges() const;
124
131 static std::vector<LiveRange> merge_invalid_ranges(const std::vector<LiveRange> &ranges);
132};
133
134LiveRangeInfo::OpInfo operator|(const LiveRangeInfo::OpInfo &, const LiveRangeInfo::OpInfo &);
135LiveRangeInfo::OpInfo &operator|=(LiveRangeInfo::OpInfo &, const LiveRangeInfo::OpInfo &);
136
137std::ostream &operator<<(std::ostream &out, const LiveRangeInfo::OpInfo &opinfo);
138std::ostream &operator<<(std::ostream &out, const LiveRangeInfo &lr);
139
141 public:
143 virtual const LiveRangeInfo *get_liverange(const PHV::FieldSlice &) const = 0;
145 virtual const LiveRangeInfo *default_liverange() const = 0;
146};
147
153 class MapFieldSliceToAction : public Inspector {
154 const PhvInfo &phv;
155 const ReductionOrInfo &red_info;
156 Visitor::profile_t init_apply(const IR::Node *root) override;
157
158 public:
162
166
167 bool preorder(const IR::MAU::Action *act) override;
168 MapFieldSliceToAction(const PhvInfo &phv, const ReductionOrInfo &ri)
169 : phv(phv), red_info(ri) {}
170 };
171
172 class DBSetter : public Inspector {
173 struct Location {
174 enum unit { PARSER, TABLE, DEPARSER };
175 unit u;
176 ordered_set<int> stages;
177 };
178 const PhvInfo &phv;
179 const ClotInfo &clot;
180 const MauBacktracker *backtracker;
181 const FieldDefUse *defuse;
182 const MapFieldSliceToAction *fs_action_map;
184 const PHV::Pragmas &pragmas;
185
192 std::optional<Location> to_location(const PHV::Field *field,
193 const FieldDefUse::locpair &loc, bool is_read) const;
194
199 std::pair<int, int> update_live_status(LiveRangeInfo &liverange, const Location &loc,
200 bool is_read) const;
201
204 void update_live_range_info(const PHV::FieldSlice &fs, const Location &use_loc,
205 const Location &def_loc, LiveRangeInfo &liverange) const;
206
208 const ordered_set<const PHV::Field *> &not_implicit_init_fields() const {
209 return pragmas.pa_no_init().getFields();
210 }
211
213 void end_apply() override;
214
215 public:
216 DBSetter(const PhvInfo &phv, const ClotInfo &clot, const MauBacktracker *backtracker,
217 const FieldDefUse *defuse, const MapFieldSliceToAction *fs_action_map,
218 FieldSliceLiveRangeDB &self, const PHV::Pragmas &pragmas)
219 : phv(phv),
220 clot(clot),
221 backtracker(backtracker),
222 defuse(defuse),
223 fs_action_map(fs_action_map),
224 self(self),
225 pragmas(pragmas) {}
226 };
227
228 const PHV::Pragmas &pragmas;
229 MapFieldSliceToAction *fs_action_map;
230 DBSetter *setter;
231
233 Visitor::profile_t init_apply(const IR::Node *root) override;
234
235 void set_liverange(const PHV::FieldSlice &, const LiveRangeInfo &);
236
237 public:
238 FieldSliceLiveRangeDB(const MauBacktracker *backtracker, const FieldDefUse *defuse,
239 const PhvInfo &phv, const ReductionOrInfo &red_info, const ClotInfo &clot,
240 const PHV::Pragmas &pragmas)
241 : pragmas(pragmas) {
242 fs_action_map = new MapFieldSliceToAction(phv, red_info);
243 setter = new DBSetter(phv, clot, backtracker, defuse, fs_action_map, *this, pragmas);
244 addPasses({fs_action_map, setter});
245 }
247 const LiveRangeInfo *get_liverange(const PHV::FieldSlice &) const override;
249 const LiveRangeInfo *default_liverange() const override;
250};
251
252} // namespace PHV
253
254#endif /* BACKENDS_TOFINO_BF_P4C_PHV_FIELDSLICE_LIVE_RANGE_H_ */
Definition clot_info.h:41
Definition mau_backtracker.h:29
Definition node.h:94
Definition visitor.h:400
Definition ir/pass_manager.h:40
Definition visitor.h:78
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition safe_vector.h:27
Definition phv_fields.h:154
Definition phv_fields.h:898
Definition fieldslice_live_range.h:152
const LiveRangeInfo * get_liverange(const PHV::FieldSlice &) const override
Definition phv/fieldslice_live_range.cpp:548
const LiveRangeInfo * default_liverange() const override
Definition phv/fieldslice_live_range.cpp:563
Definition fieldslice_live_range.h:140
virtual const LiveRangeInfo * get_liverange(const PHV::FieldSlice &) const =0
virtual const LiveRangeInfo * default_liverange() const =0
Definition fieldslice_live_range.h:35
bool can_overlay(const LiveRangeInfo &other) const
Definition phv/fieldslice_live_range.cpp:106
static void set_num_table_stages(int stage)
Definition fieldslice_live_range.h:86
static std::vector< LiveRange > merge_invalid_ranges(const std::vector< LiveRange > &ranges)
Definition phv/fieldslice_live_range.cpp:216
std::vector< LiveRange > disjoint_ranges() const
Definition phv/fieldslice_live_range.cpp:165
const safe_vector< OpInfo > & vec() const
Definition fieldslice_live_range.h:91
Definition phv_pragmas.h:46
Definition phv_fields.h:1095
const ordered_set< const PHV::Field * > & getFields() const
Definition pa_no_init.h:61
std::pair< const IR::BFN::Unit *, const IR::Expression * > locpair
Definition field_defuse.h:82
Definition field_defuse.h:77
The namespace encapsulating PHV-related stuff.
Definition gateway.h:32
Definition reduction_or.h:47