Implement pass to remove advanced statements#925
Conversation
|
launch jenkins |
|
launch jenkins |
|
launch jenkins |
| // Compound assignment | ||
| if(const auto& exprStmt = std::dynamic_pointer_cast<iir::ExprStmt>(*stmtIt)) { | ||
| auto sourceLoc = exprStmt->getSourceLocation(); | ||
| if(const auto& assignmentExpr = | ||
| std::dynamic_pointer_cast<iir::AssignmentExpr>(exprStmt->getExpr())) { | ||
| if(assignmentExpr->getOp() != "=") { | ||
| auto binOp = std::make_shared<ast::BinaryOperator>( | ||
| assignmentExpr->getLeft()->clone(), assignmentExpr->getOp().substr(0, 1), | ||
| assignmentExpr->getRight(), sourceLoc); | ||
| auto newAssignmentExpr = std::make_shared<ast::AssignmentExpr>( | ||
| assignmentExpr->getLeft(), binOp, "=", sourceLoc); | ||
| exprStmt->getExpr() = newAssignmentExpr; | ||
| } | ||
| } |
There was a problem hiding this comment.
Seems to ignore compoung assignments in nested block statements (e.g., nested ifs)
There was a problem hiding this comment.
Thx, need to fix this.
| if(unaryOp->getOp() == "++") { | ||
| binOp = std::make_shared<ast::BinaryOperator>( | ||
| unaryOp->getOperand()->clone(), "+", | ||
| std::make_shared<ast::LiteralAccessExpr>("1", BuiltinTypeID::Integer, sourceLoc), | ||
| sourceLoc); | ||
| } else if(unaryOp->getOp() == "--") { | ||
| binOp = std::make_shared<ast::BinaryOperator>( | ||
| unaryOp->getOperand()->clone(), "-", | ||
| std::make_shared<ast::LiteralAccessExpr>("1", BuiltinTypeID::Integer, sourceLoc), | ||
| sourceLoc); |
There was a problem hiding this comment.
Doesn't work in this case:
if (i == 0 && ++i == 1) { /* ... */ }
will become:
i = i + 1;
if (i == 0 && i == 1) { /* ... */ }
There was a problem hiding this comment.
This is an interesting one! Can we resolve this (without introducing a temporary variable)?
There was a problem hiding this comment.
A valid transformation output would be:
if (i == 0) {
i = i + 1;
if (i == 1) { /* ... */ }
}
But I don't think that such an output would be suitable for a general transformation algorithm.
Note: this isn't equivalent if SIR also has C++'s short-circuit semantics (it would also introduce more ops):
i = i + 1;
if (i - 1 == 0 && i == 1) { /* ... */ }
There was a problem hiding this comment.
As this is not an easy problem to solve, let's leave this open for the next syntax workshop.
There was a problem hiding this comment.
I agree. But do we then merge a pass that only works for a subset of SIR and could change semantics if SIR outside that subset is given?
There was a problem hiding this comment.
@BenWeber42 I wouldn't merge it for now. Let's briefly present the problem at the review meeting. A quick solution could be saying that increment and decrement ops can't be nested in expressions (i.e. only allowed in statements like i++; i--;) from the beginning (frontends/SIR). If this solution is not widely accepted, then this problem will need to be discussed more in detail, because it seems that the only way to solve it is to do the heavy transformation that you showed.
|
launch jenkins |
1 similar comment
|
launch jenkins |
Technical Description
PassSimplifyStatementsto transform compound assignments and increment/decrement ops into simple assignments. And tests.Resolves / Enhances
first point of #917