Optimize dead functions in more cases (#6430)

Signed-off-by: Artur Bieniek <abieniek@internships.antmicro.com>
This commit is contained in:
Artur Bieniek 2025-09-19 15:36:57 +02:00 committed by GitHub
parent e24f84f713
commit 08be65a7dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 9 deletions

View File

@ -39,6 +39,7 @@
#include "V3Stats.h"
#include <queue>
#include <vector>
VL_DEFINE_DEBUG_FUNCTIONS;
@ -53,7 +54,7 @@ class DeadVisitor final : public VNVisitor {
// AstVar::user1() -> int. Count of number of references
// AstVarScope::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;
// TYPES
@ -72,7 +73,7 @@ class DeadVisitor final : public VNVisitor {
std::vector<AstCell*> m_cellsp;
std::vector<AstClass*> m_classesp;
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
bool m_sideEffect = false; // Side effects discovered in assign RHS
@ -173,7 +174,7 @@ class DeadVisitor final : public VNVisitor {
void visit(AstNodeFTaskRef* nodep) override {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->taskp()) nodep->taskp()->user1(1);
if (nodep->taskp()) nodep->taskp()->user1Inc();
if (nodep->classOrPackagep()) {
if (m_elimCells) {
nodep->classOrPackagep(nullptr);
@ -325,7 +326,7 @@ class DeadVisitor final : public VNVisitor {
iterateChildren(nodep);
checkAll(nodep);
if (!nodep->taskPublic() && !nodep->dpiExport() && !nodep->dpiImport())
m_tasksp.push_back(nodep);
m_tasksp.push(nodep);
if (nodep->classOrPackagep()) {
if (m_elimCells) {
nodep->classOrPackagep(nullptr);
@ -365,8 +366,17 @@ class DeadVisitor final : public VNVisitor {
}
void deadCheckTasks() {
for (AstNodeFTask* taskp : m_tasksp) {
if (!taskp->user1() && !taskp->classMethod()) {
while (!m_tasksp.empty()) {
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);
m_statFTasksDeadified++;
}
@ -611,12 +621,12 @@ void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
void V3Dead::deadifyAll(AstNetlist* nodep) {
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);
}
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
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);
}

View File

@ -14,7 +14,7 @@ test.scenarios('simulator')
test.compile(verilator_flags2=["--stats"])
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()

View File

@ -22,7 +22,21 @@ module t (input clk);
// These should be deadified
function deadfunc();
deeptask2();
endfunction
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
endmodule