19#ifndef BF_P4C_PHV_ACTION_PHV_CONSTRAINTS_H_
20#define BF_P4C_PHV_ACTION_PHV_CONSTRAINTS_H_
24#include "backends/tofino/bf-p4c/common/map_tables_to_actions.h"
25#include "backends/tofino/bf-p4c/ir/bitrange.h"
26#include "backends/tofino/bf-p4c/lib/union_find.hpp"
27#include "backends/tofino/bf-p4c/mau/action_analysis.h"
28#include "backends/tofino/bf-p4c/mau/table_dependency_graph.h"
29#include "backends/tofino/bf-p4c/phv/analysis/pack_conflicts.h"
30#include "backends/tofino/bf-p4c/phv/phv_fields.h"
31#include "backends/tofino/bf-p4c/phv/phv_parde_mau_use.h"
32#include "backends/tofino/bf-p4c/phv/utils/utils.h"
34#include "lib/safe_vector.h"
36using ::P4::operator<<;
47 std::optional<ActionPhvConstraintLogging> logging;
48 std::optional<PHV::Allocation::ConditionalConstraint> conditional_constraints;
51enum class CanPackErrorCode :
unsigned {
54 PACK_CONSTRAINT_PRESENT = 2,
55 STATEFUL_DEST_CONSTRAINT = 3,
56 BITMASK_CONSTRAINT = 4,
59 NONE_ADJACENT_FIELD = 7,
60 COMPLEX_AD_PACKING = 8,
62 TF2_MORE_THAN_ONE_SOURCE = 10,
63 TF2_ALL_WRITTEN_TOGETHER = 11,
64 MORE_THAN_TWO_SOURCES = 12,
65 TWO_SOURCES_AND_CONSTANT = 13,
66 MOVE_AND_UNALLOCATED_SOURCE = 14,
67 BITWISE_AND_UNALLOCATED_SOURCE = 15,
69 PACK_AND_ALIGNED = 17,
71 SLICE_DIFF_OFFSET = 19,
72 COPACK_UNSATISFIED = 20,
73 MULTIPLE_ALIGNMENTS = 21,
74 OVERLAPPING_SLICES = 22,
75 CONSTRAINT_CHECKER_FAILED = 23,
78std::ostream &operator<<(std::ostream &out,
const CanPackErrorCode &
info);
80using CanPackReturnType =
81 std::tuple<CanPackErrorCode, std::optional<PHV::Allocation::ConditionalConstraints>>;
88 CanPackErrorCode
code;
90 bool remove_align_req =
false;
91 const std::vector<PHV::AllocSlice> *invalid_dest_packing =
nullptr;
94 :
code(
code), remove_align_req(clear_align) {}
97 const std::vector<PHV::AllocSlice> *dest_cont)
98 :
code(
code), msg(msg), invalid_dest_packing(dest_cont) {}
99 bool ok()
const {
return code == CanPackErrorCode::NO_ERROR; }
117 bool prelim_constraints_ok =
true;
119 struct ClassifiedSource {
126 friend std::ostream &operator<<(std::ostream &out,
127 const ActionPhvConstraints::ClassifiedSource &src);
129 using ClassifiedSources = std::array<ClassifiedSource, 2>;
133 struct NumContainers {
134 size_t num_allocated;
135 size_t num_unallocated;
136 bool double_unallocated =
false;
138 explicit NumContainers(
const size_t numAlloc,
const size_t numUnalloc)
139 : num_allocated(numAlloc), num_unallocated(numUnalloc) {}
141 NumContainers() : num_allocated(0), num_unallocated(0) {}
144 typedef enum action_data_uses_t {
145 SOME_AD_CONSTANT = 0,
147 COMPLEX_AD_PACKING_REQ = 2,
155 int unique_action_id = -1;
156 enum field_read_flags_t {
159 WHOLE_CONTAINER = (1 << 2),
160 ANOTHER_OPERAND = (1 << 3),
162 WHOLE_CONTAINER_SAME_FIELD = (1 << 5),
163 PART_OF_CONTAINER = (1 << 6),
170 unsigned special_ad = ActionAnalysis::ActionParam::NO_SPECIAL;
171 bool constant =
false;
172 int64_t const_value = 0;
173 std::optional<PHV::FieldSlice> phv_used = std::nullopt;
177 bool operator<(OperandInfo other)
const {
181 else if (!ad && other.ad)
183 else if (constant && !other.constant)
185 else if (!constant && other.constant)
187 else if (constant && other.constant)
188 return const_value < other.const_value;
189 else if (phv_used && !other.phv_used)
191 else if (!phv_used && other.phv_used)
193 else if (!phv_used && !other.phv_used)
195 else if (phv_used->field()->id != other.phv_used->field()->id)
196 return phv_used->field()->id < other.phv_used->field()->id;
197 else if (phv_used->range().lo != other.phv_used->range().lo)
198 return phv_used->range().lo < other.phv_used->range().lo;
200 return phv_used->range().hi < other.phv_used->range().hi;
203 bool operator==(OperandInfo other)
const {
204 return phv_used == other.phv_used && ad == other.ad && constant == other.constant &&
205 const_value == other.const_value;
208 bool operator==(
const PHV::Field *field)
const {
209 return phv_used && phv_used->field()->id == field->
id;
212 std::string toString()
const {
213 std::stringstream ss;
219 : unique_action_id(
id), phv_used(slice) {}
224 friend std::ostream &operator<<(std::ostream &out,
225 const ActionPhvConstraints::OperandInfo &
info);
227 friend std::ostream &operator<<(std::ostream &out,
230 class ConstraintTracker {
238 field_writes_to_actions;
256 write_to_reads_per_action;
261 read_to_writes_per_action;
271 static int current_action;
280 void add_action(
const IR::MAU::Action *act,
282 const IR::MAU::Table *tbl);
287 std::optional<bool> hasPHVSource(
const PHV::Field *field,
const IR::MAU::Action *act)
const;
292 std::optional<bool> hasActionDataOrConstantSource(
const PHV::Field *field,
293 const IR::MAU::Action *act)
const;
301 const IR::MAU::Action *act)
const;
306 const IR::MAU::Action *act)
const {
316 const IR::MAU::Action *act)
const;
321 const IR::MAU::Action *act)
const {
354 const IR::MAU::Action *act)
const;
361 const IR::MAU::Action *act)
const {
387 std::optional<int> can_be_both_sources(
const std::vector<PHV::AllocSlice> &slices,
392 void printMapStates()
const;
397 void print_field_ordering(
const std::vector<PHV::AllocSlice> &slices)
const;
404 getStatefulWrites()
const {
405 return statefulWrites;
409 const IR::MAU::Table *action_table(
const IR::MAU::Action *)
const;
412 ConstraintTracker constraint_tracker;
415 struct ActionContainerProperty {
417 NumContainers sources;
418 bool must_be_aligned;
425 bool aligned_one_unallocated =
false;
426 bool aligned_two_unallocated =
false;
427 bool aligned_unallocated_requires_aligment =
false;
440 bool preorder(
const IR::MAU::Action *act)
override;
443 void end_apply()
override;
445 void determine_same_byte_fields();
453 bool early_check_ok(
const IR::MAU::Action *action);
458 UnionFind<PHV::FieldSlice> classify_PHV_sources(
467 bool diagnoseInvalidPacking(
468 const IR::MAU::Action *action,
const PHV::SuperCluster::SliceList *list,
471 std::stringstream &ss)
const;
481 void throw_too_many_sources_error(
484 const UnionFind<PHV::FieldSlice> &phvSources,
486 const IR::MAU::Action *action, std::stringstream &ss)
const;
492 void throw_non_contiguous_mask_error(
496 std::stringstream &ss)
const;
507 const IR::MAU::Action *action)
const;
514 std::optional<PHV::AllocSlice> getSourcePHVSlice(
const PHV::Allocation &alloc,
515 const std::vector<PHV::AllocSlice> &slices,
517 const IR::MAU::Action *action,
518 const int stage)
const;
523 bool has_ad_or_constant_sources(
531 ActionDataUses all_or_none_constant_sources(
557 bool valid_container_operation_type(
const IR::MAU::Action *act,
559 std::stringstream &ss)
const;
568 unsigned container_operation_type(
const IR::MAU::Action *,
585 const IR::MAU::Action *action,
bool pack_unallocated_only,
586 bool has_ad_source =
false)
const;
591 std::optional<ClassifiedSources> verify_two_container_alignment(
594 ActionContainerProperty *action_prop)
const;
604 bool masks_valid(
const ClassifiedSources &sources)
const;
618 const IR::MAU::Action *action,
bool actionDataOnly,
625 const IR::MAU::Action *action)
const;
632 bool assign_containers_to_unallocated_sources(
633 const PHV::Allocation &alloc,
const UnionFind<PHV::FieldSlice> &copacking_constraints,
649 std::optional<PHV::FieldSlice> get_smaller_source_slice(
650 const PHV::Allocation &alloc,
const UnionFind<PHV::FieldSlice> &copacking_constraints,
653 std::optional<PHV::FieldSlice> get_unallocated_slice(
654 const PHV::Allocation &alloc,
const UnionFind<PHV::FieldSlice> &copacking_constraints,
683 bool check_and_generate_constraints_for_move_with_unallocated_sources(
687 ActionContainerProperty *action_props,
PackingConstraints *copacking_constraints)
const;
691 bool generate_conditional_constraints_for_bitwise_op(
704 bool check_and_generate_constraints_for_bitwise_op_with_unallocated_sources(
729 CanPackErrorCode check_and_generate_constraints_for_bitwise_or_move(
736 CanPackErrorCode check_and_generate_rotational_alignment_constraints(
737 const PHV::Allocation &alloc,
const std::vector<PHV::AllocSlice> &slices,
742 CanPackErrorCode check_and_generate_copack_set(
749 CanPackReturnType check_and_generate_conditional_constraints(
750 const PHV::Allocation &alloc,
const std::vector<PHV::AllocSlice> &slices,
756 bool stateful_destinations_constraints_violated(
761 bool check_speciality_read_and_bitmask(
785 std::set<int> stages(
const IR::MAU::Action *action,
bool physical_stage)
const;
791 bool has_const =
false;
810 constraint_tracker(ConstraintTracker(p, *this)) {}
814 return meter_color_destinations.count(f) > 0;
821 return meter_color_destinations_8bit.count(f) > 0;
826 return conflicts.hasPackConflict(fs1, fs2);
838 return meter_color_destinations;
843 return meter_color_destinations_8bit;
848 return meter_color_destinations_8bit;
859 return constraint_tracker.written_in(fieldSlice);
874 const PHV::Field *dest,
const std::vector<PHV::FieldSlice> &slices)
const;
882 const PHV::Field *src,
const std::vector<PHV::FieldSlice> &slices)
const;
887 const IR::MAU::Action *action)
const;
903 const std::vector<PHV::AllocSlice> &slices)
const;
932 const std::vector<PHV::AllocSlice> &slices,
940 const ActionPropertyMap *action_props)
const;
944 const std::vector<PHV::AllocSlice> &slices)
const;
956 const std::vector<PHV::AllocSlice> &slices,
972 void sort(std::list<const PHV::SuperCluster::SliceList *> &slice_list)
const;
977 void sort(std::vector<PHV::FieldSlice> &slice_list)
const;
986 void dest_first_sort(std::vector<const PHV::SuperCluster::SliceList *> &slice_list)
const;
993 return constraint_tracker.reads(act);
1002 auto &writtenSlices = constraint_tracker.writes(act);
1003 for (
auto &
info : writtenSlices)
1004 if (
info.phv_used != std::nullopt) rs.insert(*(
info.phv_used));
1031 std::stringstream &error_msg)
const;
1041 return constraint_tracker.written_in(field_slice).count(act);
1113 const std::vector<PHV::AllocSlice> &slices,
1136 const PHV::Allocation &alloc,
const std::vector<PHV::AllocSlice> &candidates,
1142 const PHV::Allocation &alloc,
const std::vector<PHV::AllocSlice> &candidates,
1143 const IR::MAU::Action *action,
1149 const PHV::Allocation &alloc,
const std::vector<PHV::AllocSlice> &candidates,
1150 const IR::MAU::Action *action)
const;
1153std::ostream &operator<<(std::ostream &out,
const ActionPhvConstraints::OperandInfo &
info);
1154std::ostream &operator<<(std::ostream &out,
1156std::ostream &operator<<(std::ostream &out,
const ActionPhvConstraints::ClassifiedSource &src);
Definition action_phv_constraints.h:107
CanPackErrorV2 can_pack_v2(const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &slices) const
can_pack_v2 checks whether allocating slices will violate any action constraints.
Definition action_phv_constraints.cpp:2765
ordered_set< const PHV::Field * > actionWrites(const IR::MAU::Action *act) const
Definition action_phv_constraints.cpp:3495
bool diagnoseSuperCluster(const ordered_set< const PHV::SuperCluster::SliceList * > &sc, const ordered_map< PHV::FieldSlice, unsigned > &fieldAlignments, std::stringstream &error_msg) const
Definition action_phv_constraints.cpp:3877
int count_bitmasked_set_instructions(const std::vector< PHV::AllocSlice > &slices, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const
Definition action_phv_constraints.cpp:1509
bool is_meter_color_destination(const PHV::Field *f) const
Track all the meter color destination to prioritize 8-bit PHV for such field.
Definition action_phv_constraints.h:813
ordered_set< const PHV::Field * > actionReads(const IR::MAU::Action *act) const
Definition action_phv_constraints.cpp:3488
CanPackErrorV2 check_move_constraints(const PHV::Allocation &alloc, const IR::MAU::Action *action, const std::vector< PHV::AllocSlice > &slices, const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::Container &c, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const
Definition action_phv_constraints.cpp:4317
void dest_first_sort(std::vector< const PHV::SuperCluster::SliceList * > &slice_list) const
Definition action_phv_constraints.cpp:647
bool creates_container_conflicts(const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::Allocation::LiveRangeShrinkingMap &initActions, const MapTablesToActions &tableActionsMap) const
Definition action_phv_constraints.cpp:2861
bool is_in_action_to_writes(const IR::MAU::Action *, cstring) const
Definition action_phv_constraints.cpp:3987
bool written_by_ad_constant(const PHV::Field *f, const IR::MAU::Action *act) const
Definition action_phv_constraints.cpp:3416
ordered_set< const PHV::Field * > & meter_color_dests()
Definition action_phv_constraints.h:834
bool all_field_slices_written_together(const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::ActionSet &set_of_actions, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const
Definition action_phv_constraints.cpp:3295
bool is_in_field_writes_to_actions(cstring, const IR::MAU::Action *) const
Definition action_phv_constraints.cpp:3978
ordered_set< const PHV::Field * > slices_destinations(const PHV::Field *src, const std::vector< PHV::FieldSlice > &slices) const
Definition action_phv_constraints.cpp:3521
bool move_only_operations(const PHV::Field *f) const
Definition action_phv_constraints.cpp:3546
bool hasPackConflict(const PHV::FieldSlice fs1, const PHV::FieldSlice fs2) const
Definition action_phv_constraints.h:825
CanPackErrorV2 check_move_constraints_from_read(const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &candidates, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const
Definition action_phv_constraints.cpp:4209
ordered_set< const PHV::Field * > slices_sources(const PHV::Field *dest, const std::vector< PHV::FieldSlice > &slices) const
Definition action_phv_constraints.cpp:3504
void sort(std::list< const PHV::SuperCluster::SliceList * > &slice_list) const
Definition action_phv_constraints.cpp:538
ordered_set< const IR::MAU::Action * > actions_reading_fields(const PHV::Field *f) const
Definition action_phv_constraints.h:863
CanPackErrorV2 check_read_action_move_constraints(const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &candidates, const IR::MAU::Action *action, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const
Definition action_phv_constraints.cpp:4082
bool parser_constant_extract_satisfied(const PHV::Container &c, const PHV::Allocation::MutuallyLiveSlices &container_state) const
Definition action_phv_constraints.cpp:1697
bool pack_conflicts_present(const PHV::Allocation::MutuallyLiveSlices &container_state, const std::vector< PHV::AllocSlice > &slices) const
Definition action_phv_constraints.cpp:1563
bool is_in_write_to_reads(cstring, const IR::MAU::Action *, cstring) const
Definition action_phv_constraints.cpp:3997
bool is_bitmasked_set(const std::vector< PHV::AllocSlice > &container_state, const ordered_set< PHV::AllocSlice > &fields_not_written_to) const
Definition action_phv_constraints.cpp:1546
CanPackErrorV2 check_read_action_num_source_constraints(const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &candidates, const IR::MAU::Action *action) const
Definition action_phv_constraints.cpp:4132
ordered_set< const IR::MAU::Action * > actions_writing_fields(const PHV::Field *f) const
Definition action_phv_constraints.h:852
bool written_in(const PHV::AllocSlice &slice, const IR::MAU::Action *act) const
Definition action_phv_constraints.h:1039
CanPackErrorV2 check_bitwise_and_basic_move_constraints(const PHV::ActionSet &actions, const PHV::Allocation::MutuallyLiveSlices &container_state, const ActionPropertyMap *action_props) const
Definition action_phv_constraints.cpp:2115
bool can_pack_pov(const PHV::SuperCluster::SliceList *slice_list, const PHV::Field *f) const
Definition action_phv_constraints.cpp:3557
ordered_set< const PHV::Field * > & meter_color_dests_8bit()
Definition action_phv_constraints.h:842
const ordered_set< const PHV::Field * > & meter_color_dests() const
Definition action_phv_constraints.h:837
ActionSources getActionSources(const IR::MAU::Action *act, const PHV::Container &c, ordered_set< PHV::AllocSlice > &new_slices, const PHV::Allocation &alloc) const
Definition action_phv_constraints.cpp:4036
bool hasSpecialityReads(const PHV::Field *f) const
Definition action_phv_constraints.h:831
bool written_in(const PHV::Field *f, const IR::MAU::Action *act) const
Definition action_phv_constraints.cpp:3408
CanPackErrorCode check_ara_move_constraints(const PHV::Allocation &alloc, const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::Container &c, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const
Definition action_phv_constraints.cpp:4242
bool is_meter_color_destination_8bit(const PHV::Field *f) const
Definition action_phv_constraints.h:820
ordered_map< const PHV::Field *, int > compute_sources_first_order(const ordered_map< const PHV::Field *, std::vector< PHV::FieldSlice > > &fields) const
Definition action_phv_constraints.cpp:4009
std::optional< const PHV::Field * > field_destination(const PHV::Field *f, const IR::MAU::Action *action) const
Definition action_phv_constraints.cpp:3533
bool checkBridgedPackingConstraints(const ordered_set< const PHV::Field * > &packing) const
Definition action_phv_constraints.cpp:3328
CanPackReturnType can_pack(const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &slices, const PHV::Allocation::MutuallyLiveSlices &original_container_state, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const
Definition action_phv_constraints.cpp:2605
bool cannot_initialize(const PHV::Container &c, const IR::MAU::Action *action, const PHV::Allocation &alloc) const
Definition action_phv_constraints.cpp:3450
const ordered_set< const PHV::Field * > & meter_color_dests_8bit() const
Definition action_phv_constraints.h:847
Definition action_phv_constraints.h:789
Definition map_tables_to_actions.h:29
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition safe_vector.h:27
Definition slice_alloc.h:136
Definition phv/utils/utils.h:117
Definition phv_fields.h:154
int size
Total size of Field in bits.
Definition phv_fields.h:194
int id
Unique field ID.
Definition phv_fields.h:164
Definition phv_fields.h:898
const PHV::Field * field() const override
Definition phv_fields.h:977
Definition pack_conflicts.h:36
Definition phv_fields.h:1095
Definition phv_parde_mau_use.h:154
void info(const int kind, const char *format, const T *node, Args &&...args)
Report info messages of type kind. Requires that the node argument have source info.
Definition lib/error.h:148
Definition action_phv_constraints.h:46
Definition action_phv_constraints.h:38
Definition action_phv_constraints.h:87
Definition table_dependency_graph.h:52
Definition lib/bitrange.h:158
Definition common/field_defuse.cpp:590