P4C
The P4 Compiler
Loading...
Searching...
No Matches
predication.h
1/*
2 * Copyright 2016 VMware, Inc.
3 * SPDX-FileCopyrightText: 2016 VMware, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef MIDEND_PREDICATION_H_
9#define MIDEND_PREDICATION_H_
10
11#include "frontends/p4/typeChecking/typeChecker.h"
12#include "ir/ir.h"
13
14namespace P4 {
15
32class Predication final : public Transform {
36 class EmptyStatementRemover final : public Transform {
37 public:
38 EmptyStatementRemover() {}
39 const IR::Node *postorder(IR::EmptyStatement *statement) override;
40 const IR::Node *postorder(IR::BlockStatement *statement) override;
41 };
48 class ExpressionReplacer final : public Transform {
49 private:
50 // Original assignment that the replacer works on
51 const IR::AssignmentStatement *const statement;
52 // To keep track of the path used while traversing nested if-else statements:
53 // IF - true / ELSE - false
54 const std::vector<bool> &traversalPath;
55 // To store the condition used in every if-else statement
56 std::vector<const IR::Expression *> &conditions;
57 // Nesting level of Mux expressions
58 unsigned currentNestingLevel = 0;
59 // An indicator used to implement the logic for ArrayIndex transformation
60 bool visitingIndex = false;
61
62 public:
63 explicit ExpressionReplacer(const IR::AssignmentStatement *a, std::vector<bool> &t,
64 std::vector<const IR::Expression *> &c)
65 : statement(a), traversalPath(t), conditions(c) {
66 CHECK_NULL(a);
67 }
68 const IR::Mux *preorder(IR::Mux *mux) override;
69 void emplaceExpression(IR::Mux *mux);
70 void visitBranch(IR::Mux *mux, bool then);
71 void setVisitingIndex(bool val);
72 };
73
74 // Used to dynamically generate names for variables in parts of code
75 MinimalNameGenerator generator;
76 // Used to remove empty statements and empty block statements that appear in the code
77 EmptyStatementRemover remover;
78 bool inside_action;
79 // Used to indicate whether or not an ArrayIndex should be modified.
80 bool modifyIndex = false;
81 // Tracking the nesting level of IF-ELSE statements
82 unsigned ifNestingLevel;
83 // Tracking the nesting level of dependency assignment
84 unsigned depNestingLevel;
85 // To store dependent assignments.
86 // If current statement is equal to any member of dependentNames,
87 // isStatementdependent of the coresponding statement is set to true.
88 std::vector<cstring> dependentNames;
89 // Traverse path of nested if-else statements.
90 // Size of this vector is the current IF nesting level. IF - true / ELSE - false
91 std::vector<bool> traversalPath;
92 std::vector<cstring> dependencies;
93 // Collects assignment statements with transformed right expression.
94 // liveAssignments are pushed at the back of liveAssigns vector.
95 std::map<cstring, const IR::AssignmentStatement *> liveAssignments;
96 // Vector of assignment statements which collects assignments from
97 // liveAssignments and dependencies in adequate order. In preorder
98 // of if statements assignments from liveAssigns are pushed on rv block.
99 std::vector<const IR::AssignmentStatement *> liveAssigns;
100 // Vector of ArrayIndex declarations which is used to temporary
101 // store these declarations so they can later be pushed on the 'rv' block.
102 std::vector<const IR::Declaration *> indexDeclarations;
103 // Map that shows if the current statement is dependent.
104 // Bool value is true for dependent statements,
105 // false for statements that are not dependent.
106 std::map<cstring, bool> isStatementDependent;
107 const IR::Statement *error(const IR::Statement *statement) const {
108 if (inside_action && ifNestingLevel > 0)
109 ::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET,
110 "%1%: Conditional execution in actions unsupported on this target",
111 statement);
112 return statement;
113 }
114
115 public:
116 explicit Predication() : inside_action(false), ifNestingLevel(0), depNestingLevel(0) {
117 setName("Predication");
118 }
119 Visitor::profile_t init_apply(const IR::Node *node) override {
120 auto rv = Transform::init_apply(node);
121 node->apply(generator);
122
123 return rv;
124 }
125
126 const IR::Expression *clone(const IR::Expression *expression);
127 const IR::AssignmentStatement *clone(const IR::AssignmentStatement *statement);
128 const IR::Node *preorder(IR::IfStatement *statement) override;
129 const IR::Node *preorder(IR::P4Action *action) override;
130 const IR::Node *postorder(IR::P4Action *action) override;
131 const IR::Node *preorder(IR::AssignmentStatement *statement) override;
132 const IR::Node *preorder(IR::OpAssignmentStatement *statement) override;
133 // Assignment dependecy checkers
134 const IR::Node *preorder(IR::PathExpression *pathExpr) override;
135 const IR::Node *preorder(IR::Member *member) override;
136 const IR::Node *preorder(IR::ArrayIndex *arrInd) override;
137 // The presence of other statements makes predication impossible to apply
138 const IR::Node *postorder(IR::MethodCallStatement *statement) override {
139 return error(statement);
140 }
141 const IR::Node *postorder(IR::ReturnStatement *statement) override { return error(statement); }
142 const IR::Node *postorder(IR::ExitStatement *statement) override { return error(statement); }
143};
144
145} // namespace P4
146
147#endif /* MIDEND_PREDICATION_H_ */
Definition node.h:53
Definition referenceMap.h:36
Definition visitor.h:442
Definition visitor.h:78
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58