mirror of
https://github.com/verilator/verilator.git
synced 2025-01-09 16:17:36 +00:00
Fix some AstExprStmt handling issues, towards side effect fixes.
This commit is contained in:
parent
70b82f1aec
commit
1069652701
@ -78,6 +78,7 @@ private:
|
||||
bool m_sideEffect = false; // Side effects discovered in assign RHS
|
||||
|
||||
// STATE - for current visit position (use VL_RESTORER)
|
||||
bool m_inAssign = false; // Currently in an assign
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstSelLoopVars* m_selloopvarsp = nullptr; // Current loop vars
|
||||
|
||||
@ -281,9 +282,13 @@ private:
|
||||
// See if simple assignments to variables may be eliminated because
|
||||
// that variable is never used.
|
||||
// Similar code in V3Life
|
||||
VL_RESTORER(m_sideEffect);
|
||||
const bool assignInAssign = m_inAssign; // Might be Assign(..., ExprStmt(Assign), ...)
|
||||
{
|
||||
VL_RESTORER(m_inAssign);
|
||||
VL_RESTORER(m_sideEffect);
|
||||
m_inAssign = true;
|
||||
m_sideEffect = false;
|
||||
if (assignInAssign) m_sideEffect = true;
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
checkAll(nodep);
|
||||
// Has to be direct assignment without any EXTRACTing.
|
||||
@ -298,6 +303,7 @@ private:
|
||||
}
|
||||
iterateNull(nodep->timingControlp());
|
||||
}
|
||||
if (assignInAssign) m_sideEffect = true; // Parent assign shouldn't optimize
|
||||
}
|
||||
|
||||
//-----
|
||||
|
@ -424,6 +424,12 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
||||
iterateAndNextConstNull(nodep->exprsp());
|
||||
puts(")");
|
||||
}
|
||||
void visit(AstExprStmt* nodep) override {
|
||||
putfs(nodep, "$_EXPRSTMT(\n");
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
putbs(", ");
|
||||
puts(");\n");
|
||||
}
|
||||
|
||||
void visit(AstCMethodHard* nodep) override {
|
||||
iterateConst(nodep->fromp());
|
||||
@ -434,6 +440,15 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
||||
}
|
||||
puts(")");
|
||||
}
|
||||
void visit(AstCMethodCall* nodep) override {
|
||||
iterateConst(nodep->fromp());
|
||||
puts("." + nodep->name() + "(");
|
||||
for (AstNode* pinp = nodep->argsp(); pinp; pinp = pinp->nextp()) {
|
||||
if (pinp != nodep->argsp()) puts(", ");
|
||||
iterateConst(pinp);
|
||||
}
|
||||
puts(")");
|
||||
}
|
||||
|
||||
// Operators
|
||||
virtual void emitVerilogFormat(AstNode* nodep, const string& format, AstNode* lhsp = nullptr,
|
||||
|
@ -333,6 +333,7 @@ private:
|
||||
AstActive* m_activep = nullptr; // Current active
|
||||
bool m_activeReducible = true; // Is activation block reducible?
|
||||
bool m_inSenItem = false; // Underneath AstSenItem; any varrefs are clocks
|
||||
bool m_inExprStmt = false; // Underneath ExprStmt; don't optimize LHS vars
|
||||
bool m_inSlow = false; // Inside a slow structure
|
||||
std::vector<AstNode*> m_optimized; // Logic blocks optimized
|
||||
|
||||
@ -498,6 +499,10 @@ private:
|
||||
// the weight will increase
|
||||
if (nodep->access().isWriteOrRW()) {
|
||||
new V3GraphEdge{&m_graph, m_logicVertexp, vvertexp, 1};
|
||||
if (m_inExprStmt) {
|
||||
m_logicVertexp->clearReducibleAndDedupable("LHS var in ExprStmt");
|
||||
m_logicVertexp->setConsumed("LHS var in ExprStmt");
|
||||
}
|
||||
}
|
||||
if (nodep->access().isReadOrRW()) {
|
||||
new V3GraphEdge{&m_graph, vvertexp, m_logicVertexp, 1};
|
||||
@ -513,6 +518,11 @@ private:
|
||||
iterateNewStmt(nodep, "User C Function", "User C Function");
|
||||
}
|
||||
void visit(AstClocking* nodep) override { iterateNewStmt(nodep, nullptr, nullptr); }
|
||||
void visit(AstExprStmt* nodep) override {
|
||||
VL_RESTORER(m_inExprStmt);
|
||||
m_inExprStmt = true;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstSenItem* nodep) override {
|
||||
VL_RESTORER(m_inSenItem);
|
||||
m_inSenItem = true;
|
||||
|
@ -886,7 +886,8 @@ private:
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
if (!optimizable()) return;
|
||||
iterateAndNextConstNull(nodep->resultp());
|
||||
newValue(nodep, fetchValue(nodep->resultp()));
|
||||
if (!optimizable()) return;
|
||||
if (!m_checkOnly) newValue(nodep, fetchValue(nodep->resultp()));
|
||||
}
|
||||
|
||||
void visit(AstJumpBlock* nodep) override {
|
||||
|
@ -112,7 +112,8 @@ class SliceVisitor final : public VNVisitor {
|
||||
: offset));
|
||||
newp = new AstArraySel{nodep->fileline(), snodep->fromp()->cloneTree(false), leOffset};
|
||||
} else if (VN_IS(nodep, ArraySel) || VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel)
|
||||
|| VN_IS(nodep, CMethodHard) || VN_IS(nodep, MemberSel)) {
|
||||
|| VN_IS(nodep, CMethodHard) || VN_IS(nodep, MemberSel)
|
||||
|| VN_IS(nodep, ExprStmt)) {
|
||||
UINFO(9, " cloneSel(" << elements << "," << offset << ") " << nodep << endl);
|
||||
const int leOffset = !arrayp->rangep()->ascending()
|
||||
? arrayp->rangep()->elementsConst() - 1 - offset
|
||||
|
@ -48,6 +48,12 @@ private:
|
||||
m_splitVscp = nodep->varScopep();
|
||||
}
|
||||
}
|
||||
void visit(AstExprStmt* nodep) override {
|
||||
// A function call inside the splitting assignment
|
||||
// We need to presume the whole call is preserved (if the upper statement is)
|
||||
// This will break if the m_splitVscp is a "ref" argument to the function,
|
||||
// but little we can do.
|
||||
}
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
@ -102,6 +108,12 @@ private:
|
||||
m_keepStmt = oldKeep || m_keepStmt;
|
||||
UINFO(9, " upKeep=" << m_keepStmt << " STMT " << nodep << endl);
|
||||
}
|
||||
void visit(AstExprStmt* nodep) override {
|
||||
// A function call inside the splitting assignment
|
||||
// We need to presume the whole call is preserved (if the upper statement is)
|
||||
// This will break if the m_splitVscp is a "ref" argument to the function,
|
||||
// but little we can do.
|
||||
}
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user