Extract dist range membership and rand-var bound check into named functions

This commit is contained in:
Yilou Wang 2026-07-07 19:52:31 +02:00
parent 8cf0b6ecc2
commit 662e079b13
1 changed files with 37 additions and 37 deletions

View File

@ -4453,6 +4453,39 @@ class RandomizeVisitor final : public VNVisitor {
return new AstConstraintIf{fl, condp, thenBodyp, nullptr};
}
static bool distBoundRefsRandVar(const AstNode* boundp) {
bool found = false;
boundp->foreach([&](const AstVarRef* vrefp) {
if (vrefp->varp()->rand().isRandomizable()) found = true;
});
return found;
}
// (distExpr >= lo) && (distExpr <= hi); signed comparisons for signed vars
static AstNodeExpr* newDistRangeMembership(AstDist* distp, const AstInsideRange* irp) {
FileLine* const fl = distp->fileline();
const bool isSigned = distp->exprp()->isSigned();
AstNodeExpr* const distExprGtep = distp->exprp()->cloneTreePure(false);
AstNodeExpr* const distExprLtep = distp->exprp()->cloneTreePure(false);
distExprGtep->user1(true);
distExprLtep->user1(true);
AstNodeExpr* const gep
= isSigned ? static_cast<AstNodeExpr*>(
new AstGteS{fl, distExprGtep, irp->lhsp()->cloneTreePure(false)})
: static_cast<AstNodeExpr*>(
new AstGte{fl, distExprGtep, irp->lhsp()->cloneTreePure(false)});
AstNodeExpr* const lep
= isSigned ? static_cast<AstNodeExpr*>(
new AstLteS{fl, distExprLtep, irp->rhsp()->cloneTreePure(false)})
: static_cast<AstNodeExpr*>(
new AstLte{fl, distExprLtep, irp->rhsp()->cloneTreePure(false)});
gep->user1(true);
lep->user1(true);
AstNodeExpr* const andp = new AstLogAnd{fl, gep, lep};
andp->user1(true);
return andp;
}
// Replace AstDist with weighted bucket selection via AstConstraintIf chain.
// Supports both constant and variable weight expressions.
void lowerDistConstraints(AstTask* taskp, AstNode* constrItemsp,
@ -4571,47 +4604,13 @@ class RandomizeVisitor final : public VNVisitor {
continue;
}
const auto boundRefsRandVarp = [](const AstNode* boundp) -> bool {
bool found = false;
boundp->foreach([&](const AstVarRef* vrefp) {
if (vrefp->varp()->rand().isRandomizable()) found = true;
});
return found;
};
// (distExpr >= lo) && (distExpr <= hi); signed comparisons for signed vars
const auto rangeMembershipp = [&](const AstInsideRange* irp) -> AstNodeExpr* {
const bool isSigned = distp->exprp()->isSigned();
AstNodeExpr* const distExprGtep = distp->exprp()->cloneTreePure(false);
AstNodeExpr* const distExprLtep = distp->exprp()->cloneTreePure(false);
distExprGtep->user1(true);
distExprLtep->user1(true);
AstNodeExpr* const gep
= isSigned
? static_cast<AstNodeExpr*>(
new AstGteS{fl, distExprGtep, irp->lhsp()->cloneTreePure(false)})
: static_cast<AstNodeExpr*>(
new AstGte{fl, distExprGtep, irp->lhsp()->cloneTreePure(false)});
AstNodeExpr* const lep
= isSigned
? static_cast<AstNodeExpr*>(
new AstLteS{fl, distExprLtep, irp->rhsp()->cloneTreePure(false)})
: static_cast<AstNodeExpr*>(
new AstLte{fl, distExprLtep, irp->rhsp()->cloneTreePure(false)});
gep->user1(true);
lep->user1(true);
AstNodeExpr* const andp = new AstLogAnd{fl, gep, lep};
andp->user1(true);
return andp;
};
// IEEE 1800-2023 18.5.3: values not in the distribution must never appear.
// Build the union of all non-zero-weight ranges as a single hard ConstraintExpr
AstNodeExpr* unionExprp = nullptr;
for (const auto& bucket : buckets) {
AstNodeExpr* memberp;
if (const AstInsideRange* const irp = VN_CAST(bucket.rangep, InsideRange)) {
memberp = rangeMembershipp(irp);
memberp = newDistRangeMembership(distp, irp);
} else {
// distExpr == val
AstNodeExpr* const distExprCopyp = distp->exprp()->cloneTreePure(false);
@ -4690,10 +4689,11 @@ class RandomizeVisitor final : public VNVisitor {
for (int i = static_cast<int>(buckets.size()) - 1; i >= 0; --i) {
AstNodeExpr* constraintExprp;
const AstInsideRange* const irp = VN_CAST(buckets[i].rangep, InsideRange);
if (irp && (boundRefsRandVarp(irp->lhsp()) || boundRefsRandVarp(irp->rhsp()))) {
if (irp
&& (distBoundRefsRandVar(irp->lhsp()) || distBoundRefsRandVar(irp->rhsp()))) {
// Bounds solved concurrently cannot pin a pre-solve value; softly
// prefer the symbolic range so the hard membership stays satisfiable
constraintExprp = rangeMembershipp(irp);
constraintExprp = newDistRangeMembership(distp, irp);
} else if (irp) {
// Pick distExpr = lo + rand64() % (hi - lo + 1) for a uniform value in range
AstNodeExpr* const distExprCopyp = distp->exprp()->cloneTreePure(false);