some minor ZAM optimization improvements

This commit is contained in:
Vern Paxson 2023-11-05 16:33:19 -08:00 committed by Arne Welzel
parent fadda05782
commit e3b75ac391
4 changed files with 68 additions and 0 deletions

View file

@ -4377,6 +4377,12 @@ bool ListExpr::IsPure() const {
return true; return true;
} }
bool ListExpr::HasConstantOps() const {
loop_over_list(exprs, i) if ( exprs[i]->Tag() != EXPR_CONST ) return false;
return true;
}
ValPtr ListExpr::Eval(Frame* f) const { ValPtr ListExpr::Eval(Frame* f) const {
std::vector<ValPtr> evs; std::vector<ValPtr> evs;

View file

@ -1273,6 +1273,10 @@ public:
// Optimization-related: // Optimization-related:
ExprPtr Duplicate() override; ExprPtr Duplicate() override;
bool IsReduced(Reducer* c) const override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
const std::vector<int>& Map() const { return map; } const std::vector<int>& Map() const { return map; }
protected: protected:
@ -1362,7 +1366,9 @@ public:
// Optimization-related: // Optimization-related:
ExprPtr Duplicate() override; ExprPtr Duplicate() override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override; bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected: protected:
ValPtr Fold(Val* v1, Val* v2) const override; ValPtr Fold(Val* v1, Val* v2) const override;
@ -1485,6 +1491,9 @@ public:
// True if the entire list represents pure values. // True if the entire list represents pure values.
bool IsPure() const override; bool IsPure() const override;
// True if the entire list represents constant values.
bool HasConstantOps() const;
ValPtr Eval(Frame* f) const override; ValPtr Eval(Frame* f) const override;
TypePtr InitType() const override; TypePtr InitType() const override;

View file

@ -83,6 +83,11 @@ const RecordCoerceExpr* Expr::AsRecordCoerceExpr() const {
return (const RecordCoerceExpr*)this; return (const RecordCoerceExpr*)this;
} }
RecordConstructorExpr* Expr::AsRecordConstructorExpr() {
CHECK_TAG(tag, EXPR_RECORD_CONSTRUCTOR, "ExprVal::AsRecordConstructorExpr", expr_name)
return (RecordConstructorExpr*)this;
}
const RecordConstructorExpr* Expr::AsRecordConstructorExpr() const { const RecordConstructorExpr* Expr::AsRecordConstructorExpr() const {
CHECK_TAG(tag, EXPR_RECORD_CONSTRUCTOR, "ExprVal::AsRecordConstructorExpr", expr_name) CHECK_TAG(tag, EXPR_RECORD_CONSTRUCTOR, "ExprVal::AsRecordConstructorExpr", expr_name)
return (const RecordConstructorExpr*)this; return (const RecordConstructorExpr*)this;
@ -502,6 +507,11 @@ ExprPtr BinaryExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
red_stmt = MergeStmts(red_stmt, std::move(red2_stmt)); red_stmt = MergeStmts(red_stmt, std::move(red2_stmt));
auto op1_fold_val = op1->FoldVal(); auto op1_fold_val = op1->FoldVal();
if ( ! op1_fold_val && op1->Tag() == EXPR_LIST && op1->AsListExpr()->HasConstantOps() )
// We can turn the list into a ListVal.
op1_fold_val = op1->Eval(nullptr);
auto op2_fold_val = op2->FoldVal(); auto op2_fold_val = op2->FoldVal();
if ( op1_fold_val && op2_fold_val ) { if ( op1_fold_val && op2_fold_val ) {
auto fold = Fold(op1_fold_val.get(), op2_fold_val.get()); auto fold = Fold(op1_fold_val.get(), op2_fold_val.get());
@ -1909,6 +1919,27 @@ ExprPtr RecordCoerceExpr::Duplicate() {
return SetSucc(new RecordCoerceExpr(op_dup, GetType<RecordType>())); return SetSucc(new RecordCoerceExpr(op_dup, GetType<RecordType>()));
} }
bool RecordCoerceExpr::IsReduced(Reducer* c) const {
if ( WillTransform(c) )
return NonReduced(this);
return UnaryExpr::IsReduced(c);
}
bool RecordCoerceExpr::WillTransform(Reducer* c) const { return op->Tag() == EXPR_RECORD_CONSTRUCTOR; }
ExprPtr RecordCoerceExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
if ( WillTransform(c) ) {
auto rt = cast_intrusive<RecordType>(type);
auto rc_op = op->AsRecordConstructorExpr();
auto known_constr = make_intrusive<RecordConstructorExpr>(rt, rc_op->Op());
auto red_e = known_constr->Reduce(c, red_stmt);
return TransformMe(std::move(red_e), c, red_stmt);
}
return UnaryExpr::Reduce(c, red_stmt);
}
ExprPtr TableCoerceExpr::Duplicate() { ExprPtr TableCoerceExpr::Duplicate() {
auto op_dup = op->Duplicate(); auto op_dup = op->Duplicate();
return SetSucc(new TableCoerceExpr(op_dup, GetType<TableType>())); return SetSucc(new TableCoerceExpr(op_dup, GetType<TableType>()));
@ -1979,8 +2010,22 @@ ExprPtr InExpr::Duplicate() {
return SetSucc(new InExpr(op1_d, op2_d)); return SetSucc(new InExpr(op1_d, op2_d));
} }
bool InExpr::IsReduced(Reducer* c) const {
if ( op2->Tag() == EXPR_SET_CONSTRUCTOR && op2->GetOp1()->AsListExpr()->HasConstantOps() )
return NonReduced(this);
return BinaryExpr::IsReduced(c);
}
bool InExpr::HasReducedOps(Reducer* c) const { return op1->HasReducedOps(c) && op2->IsSingleton(c); } bool InExpr::HasReducedOps(Reducer* c) const { return op1->HasReducedOps(c) && op2->IsSingleton(c); }
ExprPtr InExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
if ( op2->Tag() == EXPR_SET_CONSTRUCTOR && op2->GetOp1()->AsListExpr()->HasConstantOps() )
op2 = make_intrusive<ConstExpr>(op2->Eval(nullptr));
return BinaryExpr::Reduce(c, red_stmt);
}
ExprPtr CallExpr::Duplicate() { ExprPtr CallExpr::Duplicate() {
auto func_d = func->Duplicate(); auto func_d = func->Duplicate();
auto args_d = args->Duplicate()->AsListExprPtr(); auto args_d = args->Duplicate()->AsListExprPtr();

View file

@ -228,6 +228,14 @@ bool ZAMCompiler::PruneUnused() {
continue; continue;
} }
if ( i == insts1.size() - 1 && inst->op == OP_RETURN_X ) {
// A non-value return at the very end of the body
// doesn't actually do anything.
did_prune = true;
KillInst(i);
continue;
}
if ( inst->IsLoad() && ! VarIsUsed(inst->v1) ) { if ( inst->IsLoad() && ! VarIsUsed(inst->v1) ) {
did_prune = true; did_prune = true;
KillInst(i); KillInst(i);