Internals: Enable future JumpGo to non-end. No functional change intended.

This commit is contained in:
Wilson Snyder 2020-05-06 21:33:05 -04:00
parent ca77a93214
commit 546ccd56c4
10 changed files with 133 additions and 43 deletions

View File

@ -1508,6 +1508,7 @@ public:
}
bool brokeExists() const;
bool brokeExistsAbove() const;
bool brokeExistsBelow() const;
// CONSTRUCTORS
virtual ~AstNode() {}

View File

@ -746,6 +746,14 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) {
return nodep;
}
const char* AstJumpBlock::broken() const {
BROKEN_RTN(!labelp()->brokeExistsBelow());
return NULL;
}
void AstJumpBlock::cloneRelink() {
if (m_labelp->clonep()) m_labelp = m_labelp->clonep();
}
const char* AstScope::broken() const {
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
@ -753,7 +761,6 @@ const char* AstScope::broken() const {
BROKEN_RTN(m_modp && !m_modp->brokeExists());
return NULL;
}
void AstScope::cloneRelink() {
if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep();
if (m_aboveCellp && m_aboveCellp->clonep()) m_aboveCellp->clonep();
@ -761,7 +768,6 @@ void AstScope::cloneRelink() {
static_cast<AstNode*>(m_modp)->clonep();
}
}
string AstScope::nameDotless() const {
string out = shortName();
string::size_type pos;
@ -780,7 +786,6 @@ string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const {
if (out.substr(0, 1) == ".") out.replace(0, 1, "");
return AstNode::prettyName(out);
}
string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const {
string out;
for (AstText* textp = scopeTextp; textp; textp = VN_CAST(textp->nextp(), Text)) {
@ -1142,6 +1147,15 @@ void AstJumpGo::dump(std::ostream& str) const {
str << "%Error:UNLINKED";
}
}
void AstJumpLabel::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " -> ";
if (blockp()) {
blockp()->dump(str);
} else {
str << "%Error:UNLINKED";
}
}
void AstMemberSel::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " -> ";

View File

@ -4292,44 +4292,81 @@ public:
void priorityPragma(bool flag) { m_priorityPragma = flag; }
};
class AstJumpLabel : public AstNodeStmt {
// Jump point declaration
// Separate from AstJumpGo; as a declaration can't be deleted
class AstJumpBlock : public AstNodeStmt {
// Block of code including a JumpGo and JumpLabel
// Parents: {statement list}
// Children: {statement list, with JumpGo below}
// Children: {statement list, with JumpGo and JumpLabel below}
private:
AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration
int m_labelNum; // Set by V3EmitCSyms to tell final V3Emit what to increment
public:
AstJumpLabel(FileLine* fl, AstNode* stmtsp)
// After construction must call ->labelp to associate with appropriate label
AstJumpBlock(FileLine* fl, AstNode* stmtsp)
: ASTGEN_SUPER(fl)
, m_labelNum(0) {
addNOp1p(stmtsp);
}
virtual const char* broken() const;
virtual void cloneRelink();
ASTNODE_NODE_FUNCS(JumpBlock)
virtual int instrCount() const { return 0; }
ASTNODE_NODE_FUNCS(JumpLabel)
virtual bool maybePointedTo() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
// op1 = Statements
AstNode* stmtsp() const { return op1p(); } // op1 = List of statements
void addStmtsp(AstNode* nodep) { addNOp1p(nodep); }
AstNode* endStmtsp() const { return op2p(); } // op1 = List of end-of-block
void addEndStmtsp(AstNode* nodep) { addNOp2p(nodep); }
int labelNum() const { return m_labelNum; }
void labelNum(int flag) { m_labelNum = flag; }
AstJumpLabel* labelp() const { return m_labelp; }
void labelp(AstJumpLabel* labelp) { m_labelp = labelp; }
};
class AstJumpLabel : public AstNodeStmt {
// Jump point declaration
// Parents: {statement list with JumpBlock above}
// Children: none
private:
AstJumpBlock* m_blockp; // [After V3Jump] Pointer to declaration
public:
AstJumpLabel(FileLine* fl, AstJumpBlock* blockp)
: ASTGEN_SUPER(fl)
, m_blockp(blockp) {}
ASTNODE_NODE_FUNCS(JumpLabel)
virtual bool maybePointedTo() const { return true; }
virtual const char* broken() const {
BROKEN_RTN(!blockp()->brokeExistsAbove());
BROKEN_RTN(blockp()->labelp() != this);
return NULL;
}
virtual void cloneRelink() {
if (m_blockp->clonep()) m_blockp = m_blockp->clonep();
}
virtual void dump(std::ostream& str) const;
virtual int instrCount() const { return 0; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const {
return blockp() == static_cast<const AstJumpLabel*>(samep)->blockp();
}
AstJumpBlock* blockp() const { return m_blockp; }
};
class AstJumpGo : public AstNodeStmt {
// Jump point; branch up to the JumpLabel
// Parents: {statement list}
// Jump point; branch down to a JumpLabel
// No support for backward jumps at present
// Parents: {statement list with JumpBlock above}
// Children: none
private:
AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration
public:
AstJumpGo(FileLine* fl, AstJumpLabel* labelp)
: ASTGEN_SUPER(fl) {
m_labelp = labelp;
}
ASTNODE_NODE_FUNCS(JumpGo)
: ASTGEN_SUPER(fl)
, m_labelp(labelp) {}
ASTNODE_NODE_FUNCS(JumpGo);
virtual const char* broken() const {
BROKEN_RTN(!labelp()->brokeExistsAbove());
BROKEN_RTN(!labelp()->brokeExistsBelow());
return NULL;
}
virtual void cloneRelink() {
@ -4339,7 +4376,6 @@ public:
virtual int instrCount() const { return instrCountBranch(); }
virtual V3Hash sameHash() const { return V3Hash(labelp()); }
virtual bool same(const AstNode* samep) const {
// Also same if identical tree structure all the way down, but hard to detect
return labelp() == static_cast<const AstJumpGo*>(samep)->labelp();
}
virtual bool isGateOptimizable() const { return false; }

View File

@ -131,6 +131,14 @@ public:
if (!(iter->second & FLAG_LINKABLE)) return false;
return true;
}
static bool okIfAbove(const AstNode* nodep) {
// Must be linked to and below current node
if (!okIfLinkedTo(nodep)) return false;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) return false;
if ((iter->second & FLAG_UNDER_NOW)) return false;
return true;
}
static bool okIfBelow(const AstNode* nodep) {
// Must be linked to and below current node
if (!okIfLinkedTo(nodep)) return false;
@ -193,6 +201,10 @@ bool AstNode::brokeExistsAbove() const {
// Called by node->broken() routines to do table lookup
return BrokenTable::okIfBelow(this);
}
bool AstNode::brokeExistsBelow() const {
// Called by node->broken() routines to do table lookup
return BrokenTable::okIfAbove(this);
}
//######################################################################

View File

@ -2167,24 +2167,32 @@ private:
}
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
iterateChildren(nodep);
m_hasJumpDelay = true;
// Jump to label where label immediately follows label is not useful
if (nodep->labelp() == VN_CAST(nodep->nextp(), JumpLabel)) {
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
// Keep the label, might be other jumps pointing to it, gets cleaned later
return;
}
if (m_doExpensive) {
// If last statement in a jump label we have JumpLabel(...., JumpGo)
// Often caused by "return" in a Verilog function. The Go is pointless, remove.
if (!nodep->nextp()) {
if (AstJumpLabel* aboveLabelp = VN_CAST(nodep->abovep(), JumpLabel)) {
if (aboveLabelp == nodep->labelp()) {
UINFO(4, "JUMPGO => last remove " << nodep << endl);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
if (AstJumpBlock* aboveBlockp = VN_CAST(nodep->abovep(), JumpBlock)) {
if (aboveBlockp == nodep->labelp()->blockp()) {
if (aboveBlockp->endStmtsp() == nodep->labelp()) {
UINFO(4, "JUMPGO => last remove " << nodep << endl);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
}
}
}
nodep->labelp()->user4(true);
nodep->labelp()->blockp()->user4(true);
}
m_hasJumpDelay = true;
}
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
// Because JumpLabels disable many optimizations,
// remove JumpLabels that are not pointed to by any AstJumpGos
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
@ -2199,6 +2207,7 @@ private:
} else {
nodep->unlinkFrBack();
}
nodep->labelp()->unlinkFrBack()->deleteTree();
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}

View File

@ -697,15 +697,18 @@ public:
iterateAndNextNull(nodep->lhsp());
puts(")");
}
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
puts("goto __Vlabel" + cvtToStr(nodep->labelp()->labelNum()) + ";\n");
}
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
nodep->labelNum(++m_labelNum);
puts("{\n"); // Make it visually obvious label jumps outside these
iterateAndNextNull(nodep->stmtsp());
iterateAndNextNull(nodep->endStmtsp());
puts("}\n");
puts("__Vlabel" + cvtToStr(nodep->labelNum()) + ": ;\n");
}
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
puts("goto __Vlabel" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n");
}
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
puts("__Vlabel" + cvtToStr(nodep->blockp()->labelNum()) + ": ;\n");
}
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->precondsp());

View File

@ -272,14 +272,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
if (nodep->filep()) iterateAndNextNull(nodep->filep());
puts(");\n");
}
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
putbs("disable " + cvtToHex(nodep->labelp()) + ";\n");
}
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
putbs("begin : " + cvtToHex(nodep) + "\n");
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n");
if (nodep->stmtsp()) iterateAndNextNull(nodep->stmtsp());
puts("end\n");
}
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
putbs("disable label" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n");
}
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
putbs("// " + cvtToStr(nodep->blockp()) + ":\n");
}
virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs(" (");

View File

@ -390,7 +390,7 @@ private:
VL_DO_DANGLING(delete condLifep, condLifep);
VL_DO_DANGLING(delete bodyLifep, bodyLifep);
}
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
// As with While's we can't predict if a JumpGo will kill us or not
// It's worse though as an IF(..., JUMPGO) may change the control flow.
// Just don't optimize blocks with labels; they're rare - so far.

View File

@ -21,9 +21,11 @@
// FOR -> WHILEs
//
// Add JumpLabel which branches to after statements within JumpLabel
// RETURN -> JUMPLABEL(statements with RETURN changed to JUMPGO)
// WHILE(... BREAK) -> JUMPLABEL(WHILE(... statements with BREAK changed to JUMPGO)
// WHILE(... CONTINUE) -> WHILE(JUMPLABEL(... statements with CONTINUE changed to JUMPGO)
// RETURN -> JUMPBLOCK(statements with RETURN changed to JUMPGO, ..., JUMPLABEL)
// WHILE(... BREAK) -> JUMPBLOCK(WHILE(... statements with BREAK changed to JUMPGO),
// ... JUMPLABEL)
// WHILE(... CONTINUE) -> WHILE(JUMPBLOCK(... statements with CONTINUE changed to JUMPGO,
// ... JUMPPABEL))
//
//*************************************************************************
@ -90,7 +92,9 @@ private:
if (VN_IS(underp, JumpLabel)) {
return VN_CAST(underp, JumpLabel);
} else { // Move underp stuff to be under a new label
AstJumpLabel* labelp = new AstJumpLabel(nodep->fileline(), NULL);
AstJumpBlock* blockp = new AstJumpBlock(nodep->fileline(), NULL);
AstJumpLabel* labelp = new AstJumpLabel(nodep->fileline(), blockp);
blockp->labelp(labelp);
AstNRelinker repHandle;
if (under_and_next) {
@ -98,14 +102,16 @@ private:
} else {
underp->unlinkFrBack(&repHandle);
}
repHandle.relink(labelp);
repHandle.relink(blockp);
labelp->addStmtsp(underp);
blockp->addStmtsp(underp);
// Keep any AstVars under the function not under the new JumpLabel
for (AstNode *nextp, *varp = underp; varp; varp = nextp) {
nextp = varp->nextp();
if (VN_IS(varp, Var)) labelp->addPrev(varp->unlinkFrBack());
if (VN_IS(varp, Var)) blockp->addPrev(varp->unlinkFrBack());
}
// Label goes last
blockp->addEndStmtsp(labelp);
return labelp;
}
}

View File

@ -818,6 +818,10 @@ private:
virtual void visit(AstComment*) VL_OVERRIDE {}
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
if (jumpingOver(nodep)) return;
iterateChildren(nodep);
}
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
if (jumpingOver(nodep)) return;
checkNodeInfo(nodep);
@ -827,6 +831,8 @@ private:
}
}
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
// This only supports forward jumps. That's all we make at present,
// AstJumpGo::broken uses brokeExistsBelow() to check this.
if (jumpingOver(nodep)) return;
checkNodeInfo(nodep);
iterateChildren(nodep);