diff --git a/src/script_opt/Expr.cc b/src/script_opt/Expr.cc index 95f2274150..8cc45b654f 100644 --- a/src/script_opt/Expr.cc +++ b/src/script_opt/Expr.cc @@ -881,40 +881,77 @@ ExprPtr AddToExpr::Duplicate() return SetSucc(new AddToExpr(op1_d, op2_d)); } +bool AddToExpr::IsReduced(Reducer* c) const + { + auto t = op1->GetType(); + auto tag = t->Tag(); + + if ( tag == TYPE_PATTERN ) + return op1->HasReducedOps(c) && op2->IsReduced(c); + + if ( tag == TYPE_TABLE ) + return op1->IsReduced(c) && op2->IsReduced(c); + + if ( tag == TYPE_VECTOR && same_type(t, op2->GetType()) ) + return op1->IsReduced(c) && op2->IsReduced(c); + + return NonReduced(this); + } + ExprPtr AddToExpr::Reduce(Reducer* c, StmtPtr& red_stmt) { - if ( IsVector(op1->GetType()->Tag()) ) + auto tag = op1->GetType()->Tag(); + + switch ( tag ) { - StmtPtr red_stmt1; - StmtPtr red_stmt2; + case TYPE_PATTERN: + case TYPE_TABLE: + case TYPE_VECTOR: + { + StmtPtr red_stmt1; + StmtPtr red_stmt2; - if ( op1->Tag() == EXPR_FIELD ) - red_stmt1 = op1->ReduceToSingletons(c); - else - op1 = op1->Reduce(c, red_stmt1); + if ( tag == TYPE_PATTERN && op1->Tag() == EXPR_FIELD ) + red_stmt1 = op1->ReduceToSingletons(c); + else + op1 = op1->Reduce(c, red_stmt1); - op2 = op2->Reduce(c, red_stmt2); + auto& t = op1->GetType(); + op2 = op2->Reduce(c, red_stmt2); - auto append = make_intrusive(op1->Duplicate(), op2); - append->SetOriginal(ThisPtr()); + red_stmt = MergeStmts(red_stmt1, red_stmt2); - auto append_stmt = make_intrusive(append); + if ( tag == TYPE_VECTOR && ! same_type(t, op2->GetType()) ) + { + auto append = make_intrusive(op1->Duplicate(), op2); + append->SetOriginal(ThisPtr()); - red_stmt = MergeStmts(red_stmt1, red_stmt2, append_stmt); + auto append_stmt = make_intrusive(append); - return op1; + red_stmt = MergeStmts(red_stmt, append_stmt); + + return op1; + } + + return ThisPtr(); + } + + default: + { + auto rhs = op1->AsRefExprPtr()->GetOp1(); + auto do_incr = make_intrusive(rhs->Duplicate(), op2); + auto assign = make_intrusive(op1, do_incr, false, nullptr, nullptr, false); + + return assign->ReduceToSingleton(c, red_stmt); + } } + } - else - { - // We could do an ASSERT that op1 is an EXPR_REF, but - // the following is basically equivalent. - auto rhs = op1->AsRefExprPtr()->GetOp1(); - auto do_incr = make_intrusive(rhs->Duplicate(), op2); - auto assign = make_intrusive(op1, do_incr, false, nullptr, nullptr, false); - - return assign->ReduceToSingleton(c, red_stmt); - } +ExprPtr AddToExpr::ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) + { + auto at_stmt = make_intrusive(Duplicate()); + red_stmt = at_stmt->Reduce(c); + return op1; } ExprPtr SubExpr::Duplicate() @@ -972,15 +1009,43 @@ ExprPtr RemoveFromExpr::Duplicate() return SetSucc(new RemoveFromExpr(op1_d, op2_d)); } +bool RemoveFromExpr::IsReduced(Reducer* c) const + { + if ( op1->GetType()->Tag() == TYPE_TABLE ) + return op1->IsReduced(c) && op2->IsReduced(c); + + return NonReduced(this); + } + ExprPtr RemoveFromExpr::Reduce(Reducer* c, StmtPtr& red_stmt) { - auto rhs = op1->AsRefExprPtr()->GetOp1(); - auto do_decr = make_intrusive(rhs->Duplicate(), op2); + if ( op1->GetType()->Tag() == TYPE_TABLE ) + { + StmtPtr red_stmt1; + StmtPtr red_stmt2; + + op1 = op1->Reduce(c, red_stmt1); + op2 = op2->Reduce(c, red_stmt2); + + red_stmt = MergeStmts(red_stmt1, red_stmt2); + + return ThisPtr(); + } + + auto lhs = op1->AsRefExprPtr()->GetOp1(); + auto do_decr = make_intrusive(lhs->Duplicate(), op2); auto assign = make_intrusive(op1, do_decr, false, nullptr, nullptr, false); return assign->Reduce(c, red_stmt); } +ExprPtr RemoveFromExpr::ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) + { + auto rf_stmt = make_intrusive(Duplicate()); + red_stmt = rf_stmt->Reduce(c); + return op1; + } + ExprPtr TimesExpr::Duplicate() { auto op1_d = op1->Duplicate(); @@ -2676,6 +2741,13 @@ ExprPtr AppendToExpr::Reduce(Reducer* c, StmtPtr& red_stmt) return ThisPtr(); } +ExprPtr AppendToExpr::ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) + { + auto at_stmt = make_intrusive(Duplicate()); + red_stmt = at_stmt->Reduce(c); + return op1->AsRefExprPtr()->GetOp1(); + } + IndexAssignExpr::IndexAssignExpr(ExprPtr arg_op1, ExprPtr arg_op2, ExprPtr arg_op3) : BinaryExpr(EXPR_INDEX_ASSIGN, std::move(arg_op1), std::move(arg_op2)) { diff --git a/src/script_opt/Stmt.cc b/src/script_opt/Stmt.cc index feea66a927..8251e05c71 100644 --- a/src/script_opt/Stmt.cc +++ b/src/script_opt/Stmt.cc @@ -161,7 +161,8 @@ StmtPtr ExprStmt::DoReduce(Reducer* c) return TransformMe(make_intrusive(), c); if ( (t == EXPR_ASSIGN || t == EXPR_CALL || t == EXPR_INDEX_ASSIGN || - t == EXPR_FIELD_LHS_ASSIGN || t == EXPR_APPEND_TO) && + t == EXPR_FIELD_LHS_ASSIGN || t == EXPR_APPEND_TO || t == EXPR_ADD_TO || + t == EXPR_REMOVE_FROM) && e->IsReduced(c) ) return ThisPtr(); diff --git a/src/script_opt/UseDefs.cc b/src/script_opt/UseDefs.cc index de204cc558..21ebb59548 100644 --- a/src/script_opt/UseDefs.cc +++ b/src/script_opt/UseDefs.cc @@ -466,6 +466,15 @@ UDs UseDefs::ExprUDs(const Expr* e) AddInExprUDs(uds, e->GetOp1()->AsRefExprPtr()->GetOp1().get()); break; + case EXPR_ADD_TO: + case EXPR_REMOVE_FROM: + { + AddInExprUDs(uds, e->GetOp1().get()); + auto rhs_UDs = ExprUDs(e->GetOp2().get()); + uds = UD_Union(uds, rhs_UDs); + break; + } + case EXPR_RECORD_CONSTRUCTOR: { auto r = static_cast(e); @@ -527,6 +536,10 @@ void UseDefs::AddInExprUDs(UDs uds, const Expr* e) { switch ( e->Tag() ) { + case EXPR_REF: + AddInExprUDs(uds, e->GetOp1().get()); + break; + case EXPR_NAME: AddID(uds, e->AsNameExpr()->Id()); break; @@ -548,8 +561,9 @@ void UseDefs::AddInExprUDs(UDs uds, const Expr* e) AddInExprUDs(uds, e->GetOp1()->AsRefExprPtr()->GetOp1().get()); break; - case EXPR_ASSIGN: - // These occur inside of table constructors. + case EXPR_ASSIGN: // can occur inside a table constructor + case EXPR_ADD_TO: + case EXPR_REMOVE_FROM: AddInExprUDs(uds, e->GetOp1().get()); AddInExprUDs(uds, e->GetOp2().get()); break;