From ed17581f92ce5cb92570d1191f7ca1ecc2a24831 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 17 Apr 2010 08:01:22 -0400 Subject: [PATCH] Fix loop unroller out of memory; change --unroll-stmts. --- Changes | 2 ++ src/V3Options.cpp | 2 +- src/V3Unroll.cpp | 33 ++++++++++++++++++++++----------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Changes b/Changes index b7ffb07e4..1370bd0d4 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix "make install" with configure outside srcdir. [Stefan Wallentowitz] +**** Fix loop unroller out of memory; change --unroll-stmts. [Ashutosh Das] + **** Fix trace files with empty modules crashing some viewers. **** Fix parsing single files > 2GB. [Jeffrey Short] diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 8fd7cc5fd..acb82b51c 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1023,7 +1023,7 @@ V3Options::V3Options() { m_outputSplitCTrace = 0; m_traceDepth = 0; m_unrollCount = 64; - m_unrollStmts = 100; + m_unrollStmts = 10000; m_compLimitParens = 0; m_compLimitBlocks = 0; diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 3237d94b7..e0072089f 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -82,6 +82,20 @@ private: : v3Global.opt.unrollCount(); } + bool bodySizeOverRecurse(AstNode* nodep, int& bodySize, int bodyLimit) { + if (!nodep) return false; + bodySize++; + // Exit once exceeds limits, rather than always total + // so don't go O(n^2) when can't unroll + if (bodySize > bodyLimit) return true; + if (bodySizeOverRecurse(nodep->op1p(), bodySize, bodyLimit)) return true; + if (bodySizeOverRecurse(nodep->op2p(), bodySize, bodyLimit)) return true; + if (bodySizeOverRecurse(nodep->op3p(), bodySize, bodyLimit)) return true; + if (bodySizeOverRecurse(nodep->op4p(), bodySize, bodyLimit)) return true; + // Tail recurse. + return bodySizeOverRecurse(nodep->nextp(), bodySize, bodyLimit); + } + bool forUnrollCheck(AstNode* nodep, AstNode* initp, // Maybe under nodep (no nextp), or standalone (ignore nextp) AstNode* precondsp, AstNode* condp, @@ -174,22 +188,19 @@ private: // if (!m_generate) { UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="< unrollCount()) + int loops = ((valStop - valInit)/valInc); + if (loops > unrollCount()) return cantUnroll(nodep, "too many iterations"); // Less than 10 statements in the body? int bodySize = 0; - for (AstNode* bodp = precondsp; bodp; bodp=bodp->nextp()) { - bodySize++; - } - for (AstNode* bodp = bodysp; bodp; bodp=bodp->nextp()) { - bodySize++; - } - for (AstNode* bodp = incp; bodp; bodp=bodp->nextp()) { - bodySize++; - } - if (bodySize > v3Global.opt.unrollStmts()) + int bodyLimit = v3Global.opt.unrollStmts(); + if (loops>0) bodyLimit = v3Global.opt.unrollStmts() / loops; + if (bodySizeOverRecurse(precondsp, bodySize/*ref*/, bodyLimit) + || bodySizeOverRecurse(bodysp, bodySize/*ref*/, bodyLimit) + || bodySizeOverRecurse(incp, bodySize/*ref*/, bodyLimit)) { return cantUnroll(nodep, "too many statements"); + } } // // Now, make sure there's no assignment to this variable in the loop