Optimize dead functions in more cases (#6430)
Signed-off-by: Artur Bieniek <abieniek@internships.antmicro.com>
This commit is contained in:
parent
e24f84f713
commit
08be65a7dd
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include "V3Stats.h"
|
#include "V3Stats.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
@ -53,7 +54,7 @@ class DeadVisitor final : public VNVisitor {
|
||||||
// AstVar::user1() -> int. Count of number of references
|
// AstVar::user1() -> int. Count of number of references
|
||||||
// AstVarScope::user1() -> int. Count of number of references
|
// AstVarScope::user1() -> int. Count of number of references
|
||||||
// AstNodeDType::user1() -> int. Count of number of references
|
// AstNodeDType::user1() -> int. Count of number of references
|
||||||
// AstNodeFTask::user1() -> int. Non-zero if ever referenced (called)
|
// AstNodeFTask::user1() -> int. Count of number of references (via AstNodeFTaskRefs)
|
||||||
const VNUser1InUse m_inuser1;
|
const VNUser1InUse m_inuser1;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
|
|
@ -72,7 +73,7 @@ class DeadVisitor final : public VNVisitor {
|
||||||
std::vector<AstCell*> m_cellsp;
|
std::vector<AstCell*> m_cellsp;
|
||||||
std::vector<AstClass*> m_classesp;
|
std::vector<AstClass*> m_classesp;
|
||||||
std::vector<AstTypedef*> m_typedefsp;
|
std::vector<AstTypedef*> m_typedefsp;
|
||||||
std::vector<AstNodeFTask*> m_tasksp; // All the tasks that could be removed if not called
|
std::queue<AstNodeFTask*> m_tasksp; // All the tasks that could be removed if not called
|
||||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||||
bool m_sideEffect = false; // Side effects discovered in assign RHS
|
bool m_sideEffect = false; // Side effects discovered in assign RHS
|
||||||
|
|
||||||
|
|
@ -173,7 +174,7 @@ class DeadVisitor final : public VNVisitor {
|
||||||
void visit(AstNodeFTaskRef* nodep) override {
|
void visit(AstNodeFTaskRef* nodep) override {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (nodep->taskp()) nodep->taskp()->user1(1);
|
if (nodep->taskp()) nodep->taskp()->user1Inc();
|
||||||
if (nodep->classOrPackagep()) {
|
if (nodep->classOrPackagep()) {
|
||||||
if (m_elimCells) {
|
if (m_elimCells) {
|
||||||
nodep->classOrPackagep(nullptr);
|
nodep->classOrPackagep(nullptr);
|
||||||
|
|
@ -325,7 +326,7 @@ class DeadVisitor final : public VNVisitor {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (!nodep->taskPublic() && !nodep->dpiExport() && !nodep->dpiImport())
|
if (!nodep->taskPublic() && !nodep->dpiExport() && !nodep->dpiImport())
|
||||||
m_tasksp.push_back(nodep);
|
m_tasksp.push(nodep);
|
||||||
if (nodep->classOrPackagep()) {
|
if (nodep->classOrPackagep()) {
|
||||||
if (m_elimCells) {
|
if (m_elimCells) {
|
||||||
nodep->classOrPackagep(nullptr);
|
nodep->classOrPackagep(nullptr);
|
||||||
|
|
@ -365,8 +366,17 @@ class DeadVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
void deadCheckTasks() {
|
void deadCheckTasks() {
|
||||||
for (AstNodeFTask* taskp : m_tasksp) {
|
while (!m_tasksp.empty()) {
|
||||||
if (!taskp->user1() && !taskp->classMethod()) {
|
AstNodeFTask* taskp = m_tasksp.front();
|
||||||
|
m_tasksp.pop();
|
||||||
|
if (taskp->user1() == 0 && !taskp->classMethod()) {
|
||||||
|
taskp->foreach([this](AstNodeFTaskRef* ftaskrefp) {
|
||||||
|
AstNodeFTask* task2p = ftaskrefp->taskp();
|
||||||
|
if (!task2p) return;
|
||||||
|
task2p->user1Inc(-1);
|
||||||
|
if (task2p->user1() == 0) m_tasksp.push(task2p);
|
||||||
|
});
|
||||||
|
taskp->user1(-1); // we don't want to try deleting twice
|
||||||
deleting(taskp);
|
deleting(taskp);
|
||||||
m_statFTasksDeadified++;
|
m_statFTasksDeadified++;
|
||||||
}
|
}
|
||||||
|
|
@ -611,12 +621,12 @@ void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||||
|
|
||||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ":");
|
UINFO(2, __FUNCTION__ << ":");
|
||||||
{ DeadVisitor{nodep, true, true, false, true, false, false}; } // Destruct before checking
|
{ DeadVisitor{nodep, true, true, false, true, false, true}; } // Destruct before checking
|
||||||
V3Global::dumpCheckGlobalTree("deadAll", 0, dumpTreeEitherLevel() >= 3);
|
V3Global::dumpCheckGlobalTree("deadAll", 0, dumpTreeEitherLevel() >= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ":");
|
UINFO(2, __FUNCTION__ << ":");
|
||||||
{ DeadVisitor{nodep, true, true, true, true, false, false}; } // Destruct before checking
|
{ DeadVisitor{nodep, true, true, true, true, false, true}; } // Destruct before checking
|
||||||
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, dumpTreeEitherLevel() >= 3);
|
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, dumpTreeEitherLevel() >= 3);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ test.scenarios('simulator')
|
||||||
test.compile(verilator_flags2=["--stats"])
|
test.compile(verilator_flags2=["--stats"])
|
||||||
|
|
||||||
if test.vlt_all:
|
if test.vlt_all:
|
||||||
test.file_grep(test.stats, r'Optimizations, deadified FTasks\s+(\d+)', 2)
|
test.file_grep(test.stats, r'Optimizations, deadified FTasks\s+(\d+)', 6)
|
||||||
|
|
||||||
test.execute()
|
test.execute()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,21 @@ module t (input clk);
|
||||||
|
|
||||||
// These should be deadified
|
// These should be deadified
|
||||||
function deadfunc();
|
function deadfunc();
|
||||||
|
deeptask2();
|
||||||
endfunction
|
endfunction
|
||||||
task deadtask;
|
task deadtask;
|
||||||
|
deeptask1();
|
||||||
|
endtask
|
||||||
|
// A chain of dead tasks calling each other to ensure V3Dead can remove chained dead tasks
|
||||||
|
task deeptask1;
|
||||||
|
deeptask2();
|
||||||
|
endtask
|
||||||
|
task deeptask2;
|
||||||
|
deeptask3();
|
||||||
|
endtask
|
||||||
|
task deeptask3;
|
||||||
|
deeptask4();
|
||||||
|
endtask
|
||||||
|
task deeptask4;
|
||||||
endtask
|
endtask
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue