Internals: Add more statistics in V3Expand
- Per pattern stats, similar to DfgPeephole - Impure rejection count - Number of temporaries introduced Tweak output for consistency
This commit is contained in:
parent
7523a0cd8e
commit
2ba4bd9211
164
src/V3Expand.cpp
164
src/V3Expand.cpp
|
|
@ -32,8 +32,75 @@
|
|||
#include "V3Const.h"
|
||||
#include "V3Stats.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// The distinct expansion patterns, for statistics. One entry for each
|
||||
// unique transformation ExpandVisitor applies. Keep sorted.
|
||||
|
||||
// clang-format off
|
||||
#define FOR_EACH_EXPAND_PATTERN(macro) \
|
||||
macro(ASSIGN_AND) \
|
||||
macro(ASSIGN_ARRAYSEL) \
|
||||
macro(ASSIGN_CONCAT) \
|
||||
macro(ASSIGN_COND) \
|
||||
macro(ASSIGN_CONST) \
|
||||
macro(ASSIGN_EXTEND) \
|
||||
macro(ASSIGN_NOT) \
|
||||
macro(ASSIGN_OR) \
|
||||
macro(ASSIGN_REPLICATE) \
|
||||
macro(ASSIGN_SEL_ALIGNED) \
|
||||
macro(ASSIGN_SEL_UNALIGNED) \
|
||||
macro(ASSIGN_SHIFTL) \
|
||||
macro(ASSIGN_SHIFTR) \
|
||||
macro(ASSIGN_TO_SEL_CONST_NARROW) \
|
||||
macro(ASSIGN_TO_SEL_CONST_WIDE) \
|
||||
macro(ASSIGN_TO_SEL_VAR_NARROW) \
|
||||
macro(ASSIGN_TO_SEL_VAR_WIDE_ONE_BIT) \
|
||||
macro(ASSIGN_VARREF) \
|
||||
macro(ASSIGN_XOR) \
|
||||
macro(CONCAT) \
|
||||
macro(REDAND_TO_EQ) \
|
||||
macro(REDOR_TO_NEQ) \
|
||||
macro(REPLICATE) \
|
||||
macro(REPLICATE_ONE_BIT) \
|
||||
macro(SEL_FROM_NARROW) \
|
||||
macro(SEL_FROM_WIDE) \
|
||||
macro(WORDIZE_EQ) \
|
||||
macro(WORDIZE_NEQ) \
|
||||
macro(WORDIZE_REDAND) \
|
||||
macro(WORDIZE_REDOR) \
|
||||
macro(WORDIZE_REDXOR)
|
||||
// clang-format on
|
||||
|
||||
class VExpandPattern final {
|
||||
public:
|
||||
enum en : uint8_t {
|
||||
#define EXPAND_PATTERN_ID(id) id,
|
||||
FOR_EACH_EXPAND_PATTERN(EXPAND_PATTERN_ID)
|
||||
#undef EXPAND_PATTERN_ID
|
||||
_ENUM_END
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = {
|
||||
#define EXPAND_PATTERN_NAME(id) #id,
|
||||
FOR_EACH_EXPAND_PATTERN(EXPAND_PATTERN_NAME)
|
||||
#undef EXPAND_PATTERN_NAME
|
||||
"_ENUM_END" //
|
||||
};
|
||||
return names[m_e];
|
||||
}
|
||||
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
VExpandPattern(en _e)
|
||||
: m_e{_e} {}
|
||||
operator en() const { return m_e; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Find nodes with side effects, to mark as non-expandable
|
||||
|
||||
|
|
@ -81,14 +148,24 @@ class ExpandVisitor final : public VNVisitor {
|
|||
|
||||
// STATE - across all visitors
|
||||
AstCFunc* m_funcp = nullptr; // Current function
|
||||
VDouble0 m_statImpure; // Statistic tracking
|
||||
VDouble0 m_statWides; // Statistic tracking
|
||||
VDouble0 m_statWideWords; // Statistic tracking
|
||||
VDouble0 m_statWideLimited; // Statistic tracking
|
||||
VDouble0 m_statTemps; // Statistic tracking
|
||||
// Number of applications of each expansion pattern for statistics
|
||||
std::array<VDouble0, VExpandPattern::_ENUM_END> m_statPatterns;
|
||||
|
||||
// STATE - for current function
|
||||
size_t m_nTmps = 0; // Sequence numbers for temopraries
|
||||
|
||||
// METHODS
|
||||
// Note the application of the given expansion pattern to 'nodep'
|
||||
void didPattern(VExpandPattern pattern, AstNode* nodep) {
|
||||
UINFO(8, " " << pattern.ascii() << " " << nodep);
|
||||
++m_statPatterns[pattern];
|
||||
}
|
||||
|
||||
// Use state that ExpandOkVisitor calculated
|
||||
static bool isImpure(AstNode* nodep) {
|
||||
const bool impure = nodep->user2();
|
||||
|
|
@ -97,7 +174,10 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
bool doExpandWide(AstNode* nodep) {
|
||||
if (isImpure(nodep)) return false;
|
||||
if (isImpure(nodep)) {
|
||||
++m_statImpure;
|
||||
return false;
|
||||
}
|
||||
if (nodep->widthWords() <= v3Global.opt.expandLimit()) {
|
||||
++m_statWides;
|
||||
m_statWideWords += nodep->widthWords();
|
||||
|
|
@ -164,6 +244,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
tmpp->substConstOnly(true);
|
||||
m_funcp->addVarsp(tmpp);
|
||||
insertBefore(placep, new AstAssign{flp, new AstVarRef{flp, tmpp, VAccess::WRITE}, valuep});
|
||||
++m_statTemps;
|
||||
return tmpp;
|
||||
}
|
||||
|
||||
|
|
@ -287,8 +368,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
//====================
|
||||
|
||||
bool expandWide(AstNodeAssign* nodep, AstConst* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(CONST) " << nodep);
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_CONST, nodep);
|
||||
// -> {for each_word{ ASSIGN(WORDSEL(wide,#),WORDSEL(CONST,#))}}
|
||||
if (rhsp->num().isFourState()) {
|
||||
rhsp->v3warn(E_UNSUPPORTED, // LCOV_EXCL_LINE // impossible?
|
||||
|
|
@ -303,30 +384,30 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
//-------- Uniops
|
||||
bool expandWide(AstNodeAssign* nodep, AstVarRef* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(VARREF) " << nodep);
|
||||
// Special case: do not expand assignment of constant pool variables.
|
||||
// V3Subst undestands these directly.
|
||||
if (rhsp->varp()->user3()) return false;
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_VARREF, nodep);
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone(rhsp, w));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstArraySel* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(ARRAYSEL) " << nodep);
|
||||
UASSERT_OBJ(!VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType), nodep,
|
||||
"ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_ARRAYSEL, nodep);
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone(rhsp, w));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstNot* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(NOT) " << nodep);
|
||||
// -> {for each_word{ ASSIGN(WORDSEL(wide,#),NOT(WORDSEL(lhs,#))) }}
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_NOT, nodep);
|
||||
FileLine* const fl = rhsp->fileline();
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w, new AstNot{fl, newAstWordSelClone(rhsp->lhsp(), w)});
|
||||
|
|
@ -335,8 +416,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
//-------- Biops
|
||||
bool expandWide(AstNodeAssign* nodep, AstAnd* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(AND) " << nodep);
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_AND, nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w,
|
||||
|
|
@ -346,8 +427,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
return true;
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstOr* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(OR) " << nodep);
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_OR, nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w,
|
||||
|
|
@ -357,8 +438,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
return true;
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstXor* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(XOR) " << nodep);
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_XOR, nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w,
|
||||
|
|
@ -381,7 +462,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
const int shiftWords = std::min<int>(VL_BITWORD_E(shiftBits), widthWords);
|
||||
FileLine* const flp = rhsp->fileline();
|
||||
if (isLeftShift) {
|
||||
UINFO(8, " Wordize ASSIGN(SHIFTL,words) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_SHIFTL, nodep);
|
||||
// Low words of the result are zero
|
||||
for (int w = 0; w < shiftWords; ++w) {
|
||||
addWordAssign(nodep, w, new AstConst{flp, AstConst::SizedEData{}, 0});
|
||||
|
|
@ -391,7 +472,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w - shiftWords));
|
||||
}
|
||||
} else {
|
||||
UINFO(8, " Wordize ASSIGN(SHIFTR,words) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_SHIFTR, nodep);
|
||||
// Low words of the result are copied from higher words of the source
|
||||
for (int w = 0; w < widthWords - shiftWords; ++w) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w + shiftWords));
|
||||
|
|
@ -410,8 +491,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
|
||||
//-------- Triops
|
||||
bool expandWide(AstNodeAssign* nodep, AstCond* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(COND) " << nodep);
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_COND, nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w,
|
||||
|
|
@ -462,7 +543,6 @@ class ExpandVisitor final : public VNVisitor {
|
|||
} else if (lhsp->isWide()) {
|
||||
nodep->v3fatalSrc("extending larger thing into smaller?");
|
||||
} else {
|
||||
UINFO(8, " EXTEND(q<-l) " << nodep);
|
||||
newp = new AstCCast{nodep->fileline(), lhsp, nodep};
|
||||
}
|
||||
} else { // Long
|
||||
|
|
@ -474,8 +554,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstExtend* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(EXTEND) " << nodep);
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_EXTEND, nodep);
|
||||
AstNodeExpr* const rlhsp = rhsp->lhsp();
|
||||
for (int w = 0; w < rlhsp->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone(rlhsp, w));
|
||||
|
|
@ -510,7 +590,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
|
||||
if (nodep->fromp()->isWide()) { // Long/Quad from Wide
|
||||
if (isImpure(nodep)) return;
|
||||
UINFO(8, " SEL(wide) " << nodep);
|
||||
didPattern(VExpandPattern::SEL_FROM_WIDE, nodep);
|
||||
FileLine* const nfl = nodep->fileline();
|
||||
FileLine* const lfl = nodep->lsbp()->fileline();
|
||||
FileLine* const ffl = nodep->fromp()->fileline();
|
||||
|
|
@ -649,7 +729,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
} else { // Long/Quad from Long/Quad
|
||||
// No isImpure() check - can handle side effects in below
|
||||
UINFO(8, " SEL->SHIFT " << nodep);
|
||||
didPattern(VExpandPattern::SEL_FROM_NARROW, nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNodeExpr* fromp = nodep->fromp()->unlinkFrBack();
|
||||
AstNodeExpr* const lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
|
|
@ -674,7 +754,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
if (const AstConst* const lsbConstp = VN_CAST(rhsp->lsbp(), Const)) {
|
||||
const uint32_t lsb = lsbConstp->toUInt();
|
||||
if (VL_BITBIT_E(lsb) == 0) {
|
||||
UINFO(8, " Wordize ASSIGN(SEL,align) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_SEL_ALIGNED, nodep);
|
||||
const uint32_t word = VL_BITWORD_E(lsb);
|
||||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone(rhsp->fromp(), w + word));
|
||||
|
|
@ -683,7 +763,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
UINFO(8, " Wordize ASSIGN(EXTRACT,misalign) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_SEL_UNALIGNED, nodep);
|
||||
FileLine* const flp = rhsp->fileline();
|
||||
|
||||
// Use fresh set of temporaries
|
||||
|
|
@ -797,7 +877,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
V3Number maskold{nodep, destp->widthMin()};
|
||||
maskold.opNot(maskset);
|
||||
if (destwide) {
|
||||
UINFO(8, " ASSIGNSEL(const,wide) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_TO_SEL_CONST_WIDE, nodep);
|
||||
for (int w = 0; w < destp->widthWords(); ++w) {
|
||||
if (w >= VL_BITWORD_E(lsb) && w <= VL_BITWORD_E(msb)) {
|
||||
// else we would just be setting it to the same exact value
|
||||
|
|
@ -829,7 +909,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(rhsp->deleteTree(), rhsp);
|
||||
VL_DO_DANGLING(destp->deleteTree(), destp);
|
||||
} else {
|
||||
UINFO(8, " ASSIGNSEL(const,narrow) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_TO_SEL_CONST_NARROW, nodep);
|
||||
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast{nfl, rhsp, nodep};
|
||||
AstNodeExpr* oldvalp = destp->cloneTreePure(true);
|
||||
fixCloneLvalue(oldvalp);
|
||||
|
|
@ -851,7 +931,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
return true;
|
||||
} else { // non-const select offset
|
||||
if (destwide && lhsp->widthConst() == 1) {
|
||||
UINFO(8, " ASSIGNSEL(varlsb,wide,1bit) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_TO_SEL_VAR_WIDE_ONE_BIT, nodep);
|
||||
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack();
|
||||
AstNodeExpr* oldvalp
|
||||
|
|
@ -889,7 +969,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
// Reconsider if we get subexpression elimination.
|
||||
return false;
|
||||
} else {
|
||||
UINFO(8, " ASSIGNSEL(varlsb,narrow) " << nodep);
|
||||
didPattern(VExpandPattern::ASSIGN_TO_SEL_VAR_NARROW, nodep);
|
||||
// nodep->dumpTree("- old: ");
|
||||
AstNodeExpr* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack();
|
||||
|
|
@ -933,7 +1013,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
// See under ASSIGN(WIDE)
|
||||
} else {
|
||||
// No isImpure() check - can handle side effects in below
|
||||
UINFO(8, " CONCAT " << nodep);
|
||||
didPattern(VExpandPattern::CONCAT, nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNodeExpr* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||
|
|
@ -947,8 +1027,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstConcat* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(CONCAT) " << nodep);
|
||||
if (!doExpandWide(rhsp)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_CONCAT, nodep);
|
||||
FileLine* const fl = rhsp->fileline();
|
||||
// Lhs or Rhs may be word, long, or quad.
|
||||
// newAstWordSelClone nicely abstracts the difference.
|
||||
|
|
@ -976,10 +1056,10 @@ class ExpandVisitor final : public VNVisitor {
|
|||
AstNodeExpr* newp;
|
||||
const int lhswidth = lhsp->widthMin();
|
||||
if (lhswidth == 1) {
|
||||
UINFO(8, " REPLICATE(w1) " << nodep);
|
||||
didPattern(VExpandPattern::REPLICATE_ONE_BIT, nodep);
|
||||
newp = new AstNegate{fl, lhsp};
|
||||
} else {
|
||||
UINFO(8, " REPLICATE " << nodep);
|
||||
didPattern(VExpandPattern::REPLICATE, nodep);
|
||||
const AstConst* const constp = VN_AS(nodep->countp(), Const);
|
||||
UASSERT_OBJ(constp, nodep,
|
||||
"Replication value isn't a constant. Checked earlier!");
|
||||
|
|
@ -1003,8 +1083,8 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstReplicate* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(REPLICATE) " << nodep);
|
||||
if (!doExpandWide(rhsp)) return false;
|
||||
didPattern(VExpandPattern::ASSIGN_REPLICATE, nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNodeExpr* const lhsp = rhsp->srcp();
|
||||
const int lhswidth = lhsp->widthMin();
|
||||
|
|
@ -1038,7 +1118,9 @@ class ExpandVisitor final : public VNVisitor {
|
|||
if (isImpure(nodep)) return;
|
||||
if (!doExpandWide(nodep->lhsp())) return;
|
||||
if (!doExpandWide(nodep->rhsp())) return;
|
||||
UINFO(8, " Wordize EQ/NEQ " << nodep);
|
||||
didPattern(VN_IS(nodep, Neq) ? VExpandPattern::WORDIZE_NEQ
|
||||
: VExpandPattern::WORDIZE_EQ,
|
||||
nodep);
|
||||
// -> (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}}
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNodeExpr* newp = nullptr;
|
||||
|
|
@ -1065,7 +1147,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
if (nodep->lhsp()->isWide()) {
|
||||
if (isImpure(nodep)) return;
|
||||
if (!doExpandWide(nodep->lhsp())) return;
|
||||
UINFO(8, " Wordize REDOR " << nodep);
|
||||
didPattern(VExpandPattern::WORDIZE_REDOR, nodep);
|
||||
// -> (0!={or{for each_word{WORDSEL(lhs,#)}}}
|
||||
AstNodeExpr* newp = nullptr;
|
||||
for (int w = 0; w < nodep->lhsp()->widthWords(); ++w) {
|
||||
|
|
@ -1076,7 +1158,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
} else {
|
||||
// No isImpure() check - can handle side effects in below
|
||||
UINFO(8, " REDOR->EQ " << nodep);
|
||||
didPattern(VExpandPattern::REDOR_TO_NEQ, nodep);
|
||||
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const newp = new AstNeq{
|
||||
fl, new AstConst{fl, AstConst::WidthedValue{}, longOrQuadWidth(nodep), 0}, lhsp};
|
||||
|
|
@ -1090,7 +1172,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
if (nodep->lhsp()->isWide()) {
|
||||
if (isImpure(nodep)) return;
|
||||
if (!doExpandWide(nodep->lhsp())) return;
|
||||
UINFO(8, " Wordize REDAND " << nodep);
|
||||
didPattern(VExpandPattern::WORDIZE_REDAND, nodep);
|
||||
// -> (0!={and{for each_word{WORDSEL(lhs,#)}}}
|
||||
AstNodeExpr* newp = nullptr;
|
||||
for (int w = 0; w < nodep->lhsp()->widthWords(); ++w) {
|
||||
|
|
@ -1110,7 +1192,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
} else {
|
||||
// No isImpure() check - can handle side effects in below
|
||||
UINFO(8, " REDAND->EQ " << nodep);
|
||||
didPattern(VExpandPattern::REDAND_TO_EQ, nodep);
|
||||
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const newp = new AstEq{fl, new AstConst{fl, wordMask(lhsp)}, lhsp};
|
||||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
|
|
@ -1122,7 +1204,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
if (nodep->lhsp()->isWide()) {
|
||||
if (isImpure(nodep)) return;
|
||||
if (!doExpandWide(nodep->lhsp())) return;
|
||||
UINFO(8, " Wordize REDXOR " << nodep);
|
||||
didPattern(VExpandPattern::WORDIZE_REDXOR, nodep);
|
||||
// -> (0!={redxor{for each_word{XOR(WORDSEL(lhs,#))}}}
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNodeExpr* newp = nullptr;
|
||||
|
|
@ -1202,9 +1284,21 @@ public:
|
|||
// CONSTRUCTORS
|
||||
explicit ExpandVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
~ExpandVisitor() override {
|
||||
V3Stats::addStat("Optimizations, expand wides", m_statWides);
|
||||
V3Stats::addStat("Optimizations, expand wide words", m_statWideWords);
|
||||
V3Stats::addStat("Optimizations, expand limited", m_statWideLimited);
|
||||
V3Stats::addStat("Optimizations, Expand, expanded wides", m_statWides);
|
||||
V3Stats::addStat("Optimizations, Expand, expanded wide words", m_statWideWords);
|
||||
V3Stats::addStat("Optimizations, Expand, not expanded impure", m_statImpure);
|
||||
V3Stats::addStat("Optimizations, Expand, not expanded limit", m_statWideLimited);
|
||||
V3Stats::addStat("Optimizations, Expand, temporaries created", m_statTemps);
|
||||
const auto emitStat = [this](VExpandPattern pattern) {
|
||||
std::string str{pattern.ascii()};
|
||||
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { //
|
||||
return c == '_' ? ' ' : std::tolower(c);
|
||||
});
|
||||
V3Stats::addStat("Optimizations, Expand, pattern " + str, m_statPatterns[pattern]);
|
||||
};
|
||||
#define EXPAND_PATTERN_EMIT_STAT(id) emitStat(VExpandPattern::id);
|
||||
FOR_EACH_EXPAND_PATTERN(EXPAND_PATTERN_EMIT_STAT)
|
||||
#undef EXPAND_PATTERN_EMIT_STAT
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@ test.scenarios('vlt')
|
|||
|
||||
test.compile(verilator_flags2=['--expand-limit 1 --stats -fno-dfg'])
|
||||
|
||||
test.file_grep(test.stats, r'Optimizations, expand limited\s+(\d+)', 29)
|
||||
test.file_grep(test.stats, r'Optimizations, Expand, not expanded limit\s+(\d+)', 29)
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
Loading…
Reference in New Issue