Fixes #6293
This commit is contained in:
parent
d273e2cbd0
commit
6f69c990fd
|
|
@ -406,31 +406,6 @@ private:
|
||||||
return lhsp()->isPure() && rhsp()->isPure() && thsp()->isPure();
|
return lhsp()->isPure() && rhsp()->isPure() && thsp()->isPure();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class AstNodeCond VL_NOT_FINAL : public AstNodeTriop {
|
|
||||||
// @astgen alias op1 := condp
|
|
||||||
// @astgen alias op2 := thenp
|
|
||||||
// @astgen alias op3 := elsep
|
|
||||||
protected:
|
|
||||||
AstNodeCond(VNType t, FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp,
|
|
||||||
AstNodeExpr* elsep);
|
|
||||||
|
|
||||||
public:
|
|
||||||
ASTGEN_MEMBERS_AstNodeCond;
|
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
||||||
const V3Number& ths) override;
|
|
||||||
string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; }
|
|
||||||
string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; }
|
|
||||||
string emitSMT() const override { return "(ite (__Vbool %l) %r %t)"; }
|
|
||||||
bool cleanOut() const override { return false; } // clean if e1 & e2 clean
|
|
||||||
bool cleanLhs() const override { return true; }
|
|
||||||
bool cleanRhs() const override { return false; }
|
|
||||||
bool cleanThs() const override { return false; } // Propagates up
|
|
||||||
bool sizeMattersLhs() const override { return false; }
|
|
||||||
bool sizeMattersRhs() const override { return false; }
|
|
||||||
bool sizeMattersThs() const override { return false; }
|
|
||||||
int instrCount() const override { return INSTR_COUNT_BRANCH; }
|
|
||||||
virtual AstNodeExpr* cloneType(AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep) = 0;
|
|
||||||
};
|
|
||||||
class AstNodeDistTriop VL_NOT_FINAL : public AstNodeTriop {
|
class AstNodeDistTriop VL_NOT_FINAL : public AstNodeTriop {
|
||||||
public:
|
public:
|
||||||
AstNodeDistTriop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
|
AstNodeDistTriop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
|
||||||
|
|
@ -4681,6 +4656,30 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// === AstNodeTriop ===
|
// === AstNodeTriop ===
|
||||||
|
|
||||||
|
class AstCond final : public AstNodeTriop {
|
||||||
|
// @astgen alias op1 := condp
|
||||||
|
// @astgen alias op2 := thenp
|
||||||
|
// @astgen alias op3 := elsep
|
||||||
|
public:
|
||||||
|
AstCond(FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep);
|
||||||
|
ASTGEN_MEMBERS_AstCond;
|
||||||
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
||||||
|
const V3Number& ths) override {
|
||||||
|
out.opAssign(lhs.isNeqZero() ? rhs : ths);
|
||||||
|
}
|
||||||
|
string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; }
|
||||||
|
string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; }
|
||||||
|
string emitSMT() const override { return "(ite (__Vbool %l) %r %t)"; }
|
||||||
|
bool cleanOut() const override { return false; } // clean if e1 & e2 clean
|
||||||
|
bool cleanLhs() const override { return true; }
|
||||||
|
bool cleanRhs() const override { return false; }
|
||||||
|
bool cleanThs() const override { return false; } // Propagates up
|
||||||
|
bool sizeMattersLhs() const override { return false; }
|
||||||
|
bool sizeMattersRhs() const override { return false; }
|
||||||
|
bool sizeMattersThs() const override { return false; }
|
||||||
|
int instrCount() const override { return INSTR_COUNT_BRANCH; }
|
||||||
|
};
|
||||||
class AstPostAdd final : public AstNodeTriop {
|
class AstPostAdd final : public AstNodeTriop {
|
||||||
// Post-increment/add
|
// Post-increment/add
|
||||||
// Children: lhsp: AstConst (1) as currently support only ++ not +=
|
// Children: lhsp: AstConst (1) as currently support only ++ not +=
|
||||||
|
|
@ -4859,28 +4858,6 @@ public:
|
||||||
bool sizeMattersThs() const override { return false; }
|
bool sizeMattersThs() const override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// === AstNodeCond ===
|
|
||||||
class AstCond final : public AstNodeCond {
|
|
||||||
// Conditional ?: expression
|
|
||||||
public:
|
|
||||||
AstCond(FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep)
|
|
||||||
: ASTGEN_SUPER_Cond(fl, condp, thenp, elsep) {}
|
|
||||||
ASTGEN_MEMBERS_AstCond;
|
|
||||||
AstNodeExpr* cloneType(AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep) override {
|
|
||||||
return new AstCond{fileline(), condp, thenp, elsep};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class AstCondBound final : public AstNodeCond {
|
|
||||||
// Conditional ?: expression, specially made for safety checking of array bounds
|
|
||||||
public:
|
|
||||||
AstCondBound(FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep)
|
|
||||||
: ASTGEN_SUPER_CondBound(fl, condp, thenp, elsep) {}
|
|
||||||
ASTGEN_MEMBERS_AstCondBound;
|
|
||||||
AstNodeExpr* cloneType(AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep) override {
|
|
||||||
return new AstCondBound{fileline(), condp, thenp, elsep};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// === AstNodeDistTriop ===
|
// === AstNodeDistTriop ===
|
||||||
class AstDistErlang final : public AstNodeDistTriop {
|
class AstDistErlang final : public AstNodeDistTriop {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -166,9 +166,8 @@ const char* AstNodeQuadop::broken() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeCond::AstNodeCond(VNType t, FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp,
|
AstCond::AstCond(FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep)
|
||||||
AstNodeExpr* elsep)
|
: ASTGEN_SUPER_Cond(fl, condp, thenp, elsep) {
|
||||||
: AstNodeTriop{t, fl, condp, thenp, elsep} {
|
|
||||||
UASSERT_OBJ(thenp, this, "No thenp expression");
|
UASSERT_OBJ(thenp, this, "No thenp expression");
|
||||||
UASSERT_OBJ(elsep, this, "No elsep expression");
|
UASSERT_OBJ(elsep, this, "No elsep expression");
|
||||||
if (thenp->isClassHandleValue() && elsep->isClassHandleValue()) {
|
if (thenp->isClassHandleValue() && elsep->isClassHandleValue()) {
|
||||||
|
|
@ -180,14 +179,6 @@ AstNodeCond::AstNodeCond(VNType t, FileLine* fl, AstNodeExpr* condp, AstNodeExpr
|
||||||
dtypeFrom(thenp);
|
dtypeFrom(thenp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
||||||
const V3Number& ths) {
|
|
||||||
if (lhs.isNeqZero()) {
|
|
||||||
out.opAssign(rhs);
|
|
||||||
} else {
|
|
||||||
out.opAssign(ths);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AstAddrOfCFunc::dump(std::ostream& str) const {
|
void AstAddrOfCFunc::dump(std::ostream& str) const {
|
||||||
this->AstNodeExpr::dump(str);
|
this->AstNodeExpr::dump(str);
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ class CastVisitor final : public VNVisitor {
|
||||||
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
||||||
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
// All class types are castable to each other. If they are of different types,
|
// All class types are castable to each other. If they are of different types,
|
||||||
// a compilation error will be thrown, so an explicit cast is required. Types were
|
// a compilation error will be thrown, so an explicit cast is required. Types were
|
||||||
// already checked by V3Width and dtypep of a condition operator is a type of their
|
// already checked by V3Width and dtypep of a condition operator is a type of their
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ class CleanVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control flow operators
|
// Control flow operators
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
ensureClean(nodep->condp());
|
ensureClean(nodep->condp());
|
||||||
setClean(nodep, isClean(nodep->thenp()) && isClean(nodep->elsep()));
|
setClean(nodep, isClean(nodep->thenp()) && isClean(nodep->elsep()));
|
||||||
|
|
|
||||||
|
|
@ -1099,17 +1099,17 @@ class ConstVisitor final : public VNVisitor {
|
||||||
// (otherwise we'd be trading one operation for two operations)
|
// (otherwise we'd be trading one operation for two operations)
|
||||||
// V3Clean often makes this pattern, as it postpones the AND until
|
// V3Clean often makes this pattern, as it postpones the AND until
|
||||||
// as high as possible, which is usually the right choice, except for this.
|
// as high as possible, which is usually the right choice, except for this.
|
||||||
AstNodeCond* const condp = VN_CAST(nodep->rhsp(), NodeCond);
|
AstCond* const condp = VN_CAST(nodep->rhsp(), Cond);
|
||||||
if (!condp) return false;
|
if (!condp) return false;
|
||||||
if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false;
|
if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false;
|
||||||
AstConst* const maskp = VN_CAST(nodep->lhsp(), Const);
|
AstConst* const maskp = VN_CAST(nodep->lhsp(), Const);
|
||||||
if (!maskp) return false;
|
if (!maskp) return false;
|
||||||
UINFO(4, "AND(CONSTm, CONDcond(c, i, e))->CONDcond(c, AND(m,i), AND(m, e)) " << nodep);
|
UINFO(4, "AND(CONSTm, CONDcond(c, i, e))->CONDcond(c, AND(m,i), AND(m, e)) " << nodep);
|
||||||
AstNodeCond* const newp = static_cast<AstNodeCond*>(condp->cloneType(
|
AstCond* const newp = new AstCond{
|
||||||
condp->condp()->unlinkFrBack(),
|
condp->fileline(), condp->condp()->unlinkFrBack(),
|
||||||
new AstAnd{nodep->fileline(), maskp->cloneTree(false), condp->thenp()->unlinkFrBack()},
|
new AstAnd{nodep->fileline(), maskp->cloneTree(false), condp->thenp()->unlinkFrBack()},
|
||||||
new AstAnd{nodep->fileline(), maskp->cloneTree(false),
|
new AstAnd{nodep->fileline(), maskp->cloneTree(false),
|
||||||
condp->elsep()->unlinkFrBack()}));
|
condp->elsep()->unlinkFrBack()}};
|
||||||
newp->thenp()->dtypeFrom(nodep); // As And might have been to change widths
|
newp->thenp()->dtypeFrom(nodep); // As And might have been to change widths
|
||||||
newp->elsep()->dtypeFrom(nodep);
|
newp->elsep()->dtypeFrom(nodep);
|
||||||
nodep->replaceWithKeepDType(newp);
|
nodep->replaceWithKeepDType(newp);
|
||||||
|
|
@ -3658,20 +3658,20 @@ class ConstVisitor final : public VNVisitor {
|
||||||
TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b)
|
TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b)
|
||||||
// Trinary ops
|
// Trinary ops
|
||||||
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
|
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
|
||||||
TREEOP ("AstNodeCond{$condp.isZero, $thenp, $elsep}", "replaceWChild(nodep,$elsep)");
|
TREEOP ("AstCond{$condp.isZero, $thenp, $elsep}", "replaceWChild(nodep,$elsep)");
|
||||||
TREEOP ("AstNodeCond{$condp.isNeqZero, $thenp, $elsep}", "replaceWChild(nodep,$thenp)");
|
TREEOP ("AstCond{$condp.isNeqZero, $thenp, $elsep}", "replaceWChild(nodep,$thenp)");
|
||||||
TREEOPA("AstNodeCond{$condp.isZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$elsep)");
|
TREEOPA("AstCond{$condp.isZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$elsep)");
|
||||||
TREEOPA("AstNodeCond{$condp.isNeqZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$thenp)");
|
TREEOPA("AstCond{$condp.isNeqZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$thenp)");
|
||||||
TREEOP ("AstNodeCond{$condp, operandsSame($thenp,,$elsep)}","replaceWChild(nodep,$thenp)");
|
TREEOP ("AstCond{$condp, operandsSame($thenp,,$elsep)}","replaceWChild(nodep,$thenp)");
|
||||||
// This visit function here must allow for short-circuiting.
|
// This visit function here must allow for short-circuiting.
|
||||||
TREEOPS("AstCond{$condp.isZero}", "replaceWIteratedThs(nodep)");
|
TREEOPS("AstCond{$condp.isZero}", "replaceWIteratedThs(nodep)");
|
||||||
TREEOPS("AstCond{$condp.isNeqZero}", "replaceWIteratedRhs(nodep)");
|
TREEOPS("AstCond{$condp.isNeqZero}", "replaceWIteratedRhs(nodep)");
|
||||||
TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->castNot()->lhsp(), $elsep, $thenp}");
|
TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->castNot()->lhsp(), $elsep, $thenp}");
|
||||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isAllOnes, $elsep}", "AstLogOr {$condp, $elsep}"); // a?1:b == a||b
|
TREEOP ("AstCond{$condp.width1, $thenp.width1, $thenp.isAllOnes, $elsep}", "AstLogOr {$condp, $elsep}"); // a?1:b == a||b
|
||||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isZero, !$elsep.isClassHandleValue}", "AstLogAnd{$condp, $thenp}"); // a?b:0 == a&&b
|
TREEOP ("AstCond{$condp.width1, $thenp.width1, $thenp, $elsep.isZero, !$elsep.isClassHandleValue}", "AstLogAnd{$condp, $thenp}"); // a?b:0 == a&&b
|
||||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isAllOnes}", "AstLogOr {AstNot{$condp}, $thenp}"); // a?b:1 == ~a||b
|
TREEOP ("AstCond{$condp.width1, $thenp.width1, $thenp, $elsep.isAllOnes}", "AstLogOr {AstNot{$condp}, $thenp}"); // a?b:1 == ~a||b
|
||||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isZero, !$thenp.isClassHandleValue, $elsep}", "AstLogAnd{AstNot{$condp}, $elsep}"); // a?0:b == ~a&&b
|
TREEOP ("AstCond{$condp.width1, $thenp.width1, $thenp.isZero, !$thenp.isClassHandleValue, $elsep}", "AstLogAnd{AstNot{$condp}, $elsep}"); // a?0:b == ~a&&b
|
||||||
TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
TREEOP ("AstCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
||||||
// Prefer constants on left, since that often needs a shift, it lets
|
// Prefer constants on left, since that often needs a shift, it lets
|
||||||
// constant red remove the shift
|
// constant red remove the shift
|
||||||
TREEOP ("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
TREEOP ("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||||
|
|
|
||||||
|
|
@ -1349,7 +1349,7 @@ public:
|
||||||
iterateAndNextConstNull(nodep->lhsp());
|
iterateAndNextConstNull(nodep->lhsp());
|
||||||
puts(")");
|
puts(")");
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
// Widths match up already, so we'll just use C++'s operator w/o any temps.
|
// Widths match up already, so we'll just use C++'s operator w/o any temps.
|
||||||
if (nodep->thenp()->isWide()) {
|
if (nodep->thenp()->isWide()) {
|
||||||
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->thenp(), nodep->elsep());
|
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->thenp(), nodep->elsep());
|
||||||
|
|
|
||||||
|
|
@ -616,7 +616,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||||
}
|
}
|
||||||
puts("}");
|
puts("}");
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
putbs("(");
|
putbs("(");
|
||||||
iterateAndNextConstNull(nodep->condp());
|
iterateAndNextConstNull(nodep->condp());
|
||||||
putfs(nodep, " ? ");
|
putfs(nodep, " ? ");
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
// e.g. "logic [95:0] var[0]; logic [0] sel; out = var[sel];"
|
// e.g. "logic [95:0] var[0]; logic [0] sel; out = var[sel];"
|
||||||
// Squash before C++ to avoid getting a C++ compiler warning
|
// Squash before C++ to avoid getting a C++ compiler warning
|
||||||
// (even though code would be unreachable as presumably a
|
// (even though code would be unreachable as presumably a
|
||||||
// AstCondBound is protecting above this node.
|
// AstCond is protecting above this node.
|
||||||
return new AstConst{fl, AstConst::SizedEData{}, 0};
|
return new AstConst{fl, AstConst::SizedEData{}, 0};
|
||||||
} else {
|
} else {
|
||||||
AstNodeExpr* wordp;
|
AstNodeExpr* wordp;
|
||||||
|
|
@ -240,25 +240,13 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static AstNodeExpr* dropCondBound(AstNodeExpr* nodep) {
|
|
||||||
// Experimental only...
|
|
||||||
// If there's a CONDBOUND safety to keep arrays in bounds,
|
|
||||||
// we're going to AND it to a value that always fits inside a
|
|
||||||
// word, so we don't need it.
|
|
||||||
// if (VN_IS(nodep, CondBound) && VN_IS(VN_AS(nodep, CondBound)->lhsp(), Lte)) {
|
|
||||||
// nodep = VN_AS(nodep, CondBound)->rhsp();
|
|
||||||
//}
|
|
||||||
return nodep;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AstNodeExpr* newSelBitBit(AstNodeExpr* lsbp) {
|
static AstNodeExpr* newSelBitBit(AstNodeExpr* lsbp) {
|
||||||
// Return equation to get the VL_BITBIT of a constant or non-constant
|
// Return equation to get the VL_BITBIT of a constant or non-constant
|
||||||
FileLine* const fl = lsbp->fileline();
|
FileLine* const fl = lsbp->fileline();
|
||||||
if (VN_IS(lsbp, Const)) {
|
if (VN_IS(lsbp, Const)) {
|
||||||
return new AstConst{fl, VL_BITBIT_E(VN_AS(lsbp, Const)->toUInt())};
|
return new AstConst{fl, VL_BITBIT_E(VN_AS(lsbp, Const)->toUInt())};
|
||||||
} else {
|
} else {
|
||||||
return new AstAnd{fl, new AstConst{fl, VL_EDATASIZE - 1},
|
return new AstAnd{fl, new AstConst{fl, VL_EDATASIZE - 1}, lsbp->cloneTreePure(true)};
|
||||||
dropCondBound(lsbp)->cloneTreePure(true)};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,7 +331,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-------- Triops
|
//-------- Triops
|
||||||
bool expandWide(AstNodeAssign* nodep, AstNodeCond* rhsp) {
|
bool expandWide(AstNodeAssign* nodep, AstCond* rhsp) {
|
||||||
UINFO(8, " Wordize ASSIGN(COND) " << nodep);
|
UINFO(8, " Wordize ASSIGN(COND) " << nodep);
|
||||||
if (!doExpandWide(nodep)) return false;
|
if (!doExpandWide(nodep)) return false;
|
||||||
FileLine* const fl = nodep->fileline();
|
FileLine* const fl = nodep->fileline();
|
||||||
|
|
@ -498,7 +486,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
AstNodeExpr* const lsbp = nodep->lsbp()->unlinkFrBack();
|
AstNodeExpr* const lsbp = nodep->lsbp()->unlinkFrBack();
|
||||||
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCCast{fl, fromp, nodep};
|
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCCast{fl, fromp, nodep};
|
||||||
// {large}>>32 requires 64-bit shift operation; then cast
|
// {large}>>32 requires 64-bit shift operation; then cast
|
||||||
AstNodeExpr* newp = new AstShiftR{fl, fromp, dropCondBound(lsbp), fromp->width()};
|
AstNodeExpr* newp = new AstShiftR{fl, fromp, lsbp, fromp->width()};
|
||||||
newp->dtypeFrom(fromp);
|
newp->dtypeFrom(fromp);
|
||||||
if (!nodep->isQuad() && fromp->isQuad()) newp = new AstCCast{fl, newp, nodep};
|
if (!nodep->isQuad() && fromp->isQuad()) newp = new AstCCast{fl, newp, nodep};
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
|
|
@ -944,7 +932,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
did = expandWide(nodep, rhsp);
|
did = expandWide(nodep, rhsp);
|
||||||
} else if (AstXor* const rhsp = VN_CAST(nodep->rhsp(), Xor)) {
|
} else if (AstXor* const rhsp = VN_CAST(nodep->rhsp(), Xor)) {
|
||||||
did = expandWide(nodep, rhsp);
|
did = expandWide(nodep, rhsp);
|
||||||
} else if (AstNodeCond* const rhsp = VN_CAST(nodep->rhsp(), NodeCond)) {
|
} else if (AstCond* const rhsp = VN_CAST(nodep->rhsp(), Cond)) {
|
||||||
did = expandWide(nodep, rhsp);
|
did = expandWide(nodep, rhsp);
|
||||||
}
|
}
|
||||||
} else if (AstSel* const lhsp = VN_CAST(nodep->lhsp(), Sel)) {
|
} else if (AstSel* const lhsp = VN_CAST(nodep->lhsp(), Sel)) {
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ private:
|
||||||
if (nodep->thensp()) nodep->thensp()->user2(0); // Don't dump it
|
if (nodep->thensp()) nodep->thensp()->user2(0); // Don't dump it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
if (m_ignoreRemaining) return;
|
if (m_ignoreRemaining) return;
|
||||||
// Just like if/else above, the ternary operator only evaluates
|
// Just like if/else above, the ternary operator only evaluates
|
||||||
// one of the two expressions, so only count the max.
|
// one of the two expressions, so only count the max.
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ class LinkIncVisitor final : public VNVisitor {
|
||||||
void visit(AstLogOr* nodep) override { unsupported_visit(nodep); }
|
void visit(AstLogOr* nodep) override { unsupported_visit(nodep); }
|
||||||
void visit(AstLogEq* nodep) override { unsupported_visit(nodep); }
|
void visit(AstLogEq* nodep) override { unsupported_visit(nodep); }
|
||||||
void visit(AstLogIf* nodep) override { unsupported_visit(nodep); }
|
void visit(AstLogIf* nodep) override { unsupported_visit(nodep); }
|
||||||
void visit(AstNodeCond* nodep) override { unsupported_visit(nodep); }
|
void visit(AstCond* nodep) override { unsupported_visit(nodep); }
|
||||||
void visit(AstPropSpec* nodep) override { unsupported_visit(nodep); }
|
void visit(AstPropSpec* nodep) override { unsupported_visit(nodep); }
|
||||||
void prepost_visit(AstNodeTriop* nodep) {
|
void prepost_visit(AstNodeTriop* nodep) {
|
||||||
// Check if we are underneath a statement
|
// Check if we are underneath a statement
|
||||||
|
|
|
||||||
|
|
@ -95,11 +95,11 @@ namespace {
|
||||||
// if there is one and it is in a supported position, which are:
|
// if there is one and it is in a supported position, which are:
|
||||||
// - RHS is the Cond
|
// - RHS is the Cond
|
||||||
// - RHS is And(Const, Cond). This And is inserted often by V3Clean.
|
// - RHS is And(Const, Cond). This And is inserted often by V3Clean.
|
||||||
AstNodeCond* extractCondFromRhs(AstNode* rhsp) {
|
AstCond* extractCondFromRhs(AstNode* rhsp) {
|
||||||
if (AstNodeCond* const condp = VN_CAST(rhsp, NodeCond)) {
|
if (AstCond* const condp = VN_CAST(rhsp, Cond)) {
|
||||||
return condp;
|
return condp;
|
||||||
} else if (const AstAnd* const andp = VN_CAST(rhsp, And)) {
|
} else if (const AstAnd* const andp = VN_CAST(rhsp, And)) {
|
||||||
if (AstNodeCond* const condp = VN_CAST(andp->rhsp(), NodeCond)) {
|
if (AstCond* const condp = VN_CAST(andp->rhsp(), Cond)) {
|
||||||
if (VN_IS(andp->lhsp(), Const)) return condp;
|
if (VN_IS(andp->lhsp(), Const)) return condp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +177,7 @@ class CodeMotionAnalysisVisitor final : public VNVisitorConst {
|
||||||
static AstNodeExpr* extractCondition(const AstNodeStmt* nodep) {
|
static AstNodeExpr* extractCondition(const AstNodeStmt* nodep) {
|
||||||
AstNodeExpr* conditionp = nullptr;
|
AstNodeExpr* conditionp = nullptr;
|
||||||
if (const AstNodeAssign* const assignp = VN_CAST(nodep, NodeAssign)) {
|
if (const AstNodeAssign* const assignp = VN_CAST(nodep, NodeAssign)) {
|
||||||
if (AstNodeCond* const conditionalp = extractCondFromRhs(assignp->rhsp())) {
|
if (AstCond* const conditionalp = extractCondFromRhs(assignp->rhsp())) {
|
||||||
conditionp = conditionalp->condp();
|
conditionp = conditionalp->condp();
|
||||||
}
|
}
|
||||||
} else if (const AstNodeIf* const ifp = VN_CAST(nodep, NodeIf)) {
|
} else if (const AstNodeIf* const ifp = VN_CAST(nodep, NodeIf)) {
|
||||||
|
|
@ -564,7 +564,7 @@ class MergeCondVisitor final : public VNVisitor {
|
||||||
return yieldsOneOrZero(biopp->lhsp()) && yieldsOneOrZero(biopp->rhsp());
|
return yieldsOneOrZero(biopp->lhsp()) && yieldsOneOrZero(biopp->rhsp());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (const AstNodeCond* const condp = VN_CAST(nodep, NodeCond)) {
|
if (const AstCond* const condp = VN_CAST(nodep, Cond)) {
|
||||||
return yieldsOneOrZero(condp->thenp()) && yieldsOneOrZero(condp->elsep());
|
return yieldsOneOrZero(condp->thenp()) && yieldsOneOrZero(condp->elsep());
|
||||||
}
|
}
|
||||||
if (const AstCCast* const castp = VN_CAST(nodep, CCast)) {
|
if (const AstCCast* const castp = VN_CAST(nodep, CCast)) {
|
||||||
|
|
@ -591,7 +591,7 @@ class MergeCondVisitor final : public VNVisitor {
|
||||||
AstNodeExpr* foldAndUnlink(AstNodeExpr* rhsp, bool condTrue) {
|
AstNodeExpr* foldAndUnlink(AstNodeExpr* rhsp, bool condTrue) {
|
||||||
if (rhsp->sameTree(m_mgCondp)) {
|
if (rhsp->sameTree(m_mgCondp)) {
|
||||||
return new AstConst{rhsp->fileline(), AstConst::BitTrue{}, condTrue};
|
return new AstConst{rhsp->fileline(), AstConst::BitTrue{}, condTrue};
|
||||||
} else if (const AstNodeCond* const condp = extractCondFromRhs(rhsp)) {
|
} else if (const AstCond* const condp = extractCondFromRhs(rhsp)) {
|
||||||
AstNodeExpr* const resp
|
AstNodeExpr* const resp
|
||||||
= condTrue ? condp->thenp()->unlinkFrBack() : condp->elsep()->unlinkFrBack();
|
= condTrue ? condp->thenp()->unlinkFrBack() : condp->elsep()->unlinkFrBack();
|
||||||
if (condp == rhsp) return resp;
|
if (condp == rhsp) return resp;
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,7 @@ class PremitVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
checkNode(nodep);
|
checkNode(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (nodep->thenp()->isWide() && !VN_IS(nodep->condp(), Const)
|
if (nodep->thenp()->isWide() && !VN_IS(nodep->condp(), Const)
|
||||||
&& !VN_IS(nodep->condp(), VarRef)) {
|
&& !VN_IS(nodep->condp(), VarRef)) {
|
||||||
|
|
|
||||||
|
|
@ -766,7 +766,7 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
if (editFormat(nodep)) return;
|
if (editFormat(nodep)) return;
|
||||||
editSMT(nodep, nodep->lhsp(), nodep->rhsp(), nodep->thsp());
|
editSMT(nodep, nodep->lhsp(), nodep->rhsp(), nodep->thsp());
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
if (editFormat(nodep)) return;
|
if (editFormat(nodep)) return;
|
||||||
if (!nodep->condp()->user1()) {
|
if (!nodep->condp()->user1()) {
|
||||||
// Do not burden the solver if cond computable: (cond ? "then" : "else")
|
// Do not burden the solver if cond computable: (cond ? "then" : "else")
|
||||||
|
|
|
||||||
|
|
@ -672,7 +672,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
// We could use above visit(AstNodeTriop), but need to do short circuiting.
|
// We could use above visit(AstNodeTriop), but need to do short circuiting.
|
||||||
// It's also slower even O(n^2) to evaluate both sides when we
|
// It's also slower even O(n^2) to evaluate both sides when we
|
||||||
// really only need to evaluate one side.
|
// really only need to evaluate one side.
|
||||||
|
|
|
||||||
|
|
@ -190,11 +190,11 @@ class SliceVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!newp) newp = new AstConst{nodep->fileline(), 0};
|
if (!newp) newp = new AstConst{nodep->fileline(), 0};
|
||||||
} else if (AstNodeCond* const snodep = VN_CAST(nodep, NodeCond)) {
|
} else if (AstCond* const snodep = VN_CAST(nodep, Cond)) {
|
||||||
UINFO(9, " cloneCond(" << elements << "," << elemIdx << ") " << nodep);
|
UINFO(9, " cloneCond(" << elements << "," << elemIdx << ") " << nodep);
|
||||||
return snodep->cloneType(snodep->condp()->cloneTree(false, needPure),
|
return new AstCond{snodep->fileline(), snodep->condp()->cloneTree(false, needPure),
|
||||||
cloneAndSel(snodep->thenp(), elements, elemIdx, needPure),
|
cloneAndSel(snodep->thenp(), elements, elemIdx, needPure),
|
||||||
cloneAndSel(snodep->elsep(), elements, elemIdx, needPure));
|
cloneAndSel(snodep->elsep(), elements, elemIdx, needPure)};
|
||||||
} else if (const AstSliceSel* const snodep = VN_CAST(nodep, SliceSel)) {
|
} else if (const AstSliceSel* const snodep = VN_CAST(nodep, SliceSel)) {
|
||||||
UINFO(9, " cloneSliceSel(" << elements << "," << elemIdx << ") " << nodep);
|
UINFO(9, " cloneSliceSel(" << elements << "," << elemIdx << ") " << nodep);
|
||||||
const int leOffset = (snodep->declRange().lo()
|
const int leOffset = (snodep->declRange().lo()
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ private:
|
||||||
if (nodep->thensp()) nodep->thensp()->user2(0); // Don't dump it
|
if (nodep->thensp()) nodep->thensp()->user2(0); // Don't dump it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
if (m_ignoreRemaining) return;
|
if (m_ignoreRemaining) return;
|
||||||
// Just like if/else above, the ternary operator only evaluates
|
// Just like if/else above, the ternary operator only evaluates
|
||||||
// one of the two expressions, so only count the max.
|
// one of the two expressions, so only count the max.
|
||||||
|
|
|
||||||
|
|
@ -411,7 +411,7 @@ class UnknownVisitor final : public VNVisitor {
|
||||||
AstNodeExpr* const xexprp = new AstConst{nodep->fileline(), xnum};
|
AstNodeExpr* const xexprp = new AstConst{nodep->fileline(), xnum};
|
||||||
AstNodeExpr* const newp
|
AstNodeExpr* const newp
|
||||||
= condp->isZero() ? xexprp
|
= condp->isZero() ? xexprp
|
||||||
: new AstCondBound{nodep->fileline(), condp, nodep, xexprp};
|
: new AstCond{nodep->fileline(), condp, nodep, xexprp};
|
||||||
UINFOTREE(9, newp, "", "_new");
|
UINFOTREE(9, newp, "", "_new");
|
||||||
// Link in conditional
|
// Link in conditional
|
||||||
replaceHandle.relink(newp);
|
replaceHandle.relink(newp);
|
||||||
|
|
@ -485,7 +485,7 @@ class UnknownVisitor final : public VNVisitor {
|
||||||
} else {
|
} else {
|
||||||
xnum.setAllBitsX();
|
xnum.setAllBitsX();
|
||||||
}
|
}
|
||||||
AstNode* const newp = new AstCondBound{nodep->fileline(), condp, nodep,
|
AstNode* const newp = new AstCond{nodep->fileline(), condp, nodep,
|
||||||
new AstConst{nodep->fileline(), xnum}};
|
new AstConst{nodep->fileline(), xnum}};
|
||||||
UINFOTREE(9, newp, "", "_new");
|
UINFOTREE(9, newp, "", "_new");
|
||||||
// Link in conditional, can blow away temp xor
|
// Link in conditional, can blow away temp xor
|
||||||
|
|
@ -496,7 +496,7 @@ class UnknownVisitor final : public VNVisitor {
|
||||||
// ARRAYSEL(...) -> ARRAYSEL(COND(LT(bit<maxbit), bit, 0))
|
// ARRAYSEL(...) -> ARRAYSEL(COND(LT(bit<maxbit), bit, 0))
|
||||||
VNRelinker replaceHandle;
|
VNRelinker replaceHandle;
|
||||||
AstNodeExpr* const bitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
|
AstNodeExpr* const bitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
|
||||||
AstNodeExpr* const newp = new AstCondBound{
|
AstNodeExpr* const newp = new AstCond{
|
||||||
bitp->fileline(), condp, bitp,
|
bitp->fileline(), condp, bitp,
|
||||||
new AstConst{bitp->fileline(), AstConst::WidthedValue{}, bitp->width(), 0}};
|
new AstConst{bitp->fileline(), AstConst::WidthedValue{}, bitp->width(), 0}};
|
||||||
// Added X's, tristate them too
|
// Added X's, tristate them too
|
||||||
|
|
|
||||||
|
|
@ -492,7 +492,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
nodep->dtypeSetUInt64(); // A pointer, but not that it matters
|
nodep->dtypeSetUInt64(); // A pointer, but not that it matters
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(AstNodeCond* nodep) override {
|
void visit(AstCond* nodep) override {
|
||||||
// op = cond ? expr1 : expr2
|
// op = cond ? expr1 : expr2
|
||||||
// See IEEE-2012 11.4.11 and Table 11-21.
|
// See IEEE-2012 11.4.11 and Table 11-21.
|
||||||
// LHS is self-determined
|
// LHS is self-determined
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue