diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp index 48a80b88f8..459f17d059 100644 --- a/src/sksl/SkSLInliner.cpp +++ b/src/sksl/SkSLInliner.cpp @@ -928,7 +928,7 @@ public: this->addInlineCandidate(expr); break; } - case Expression::Kind::kIndex:{ + case Expression::Kind::kIndex: { IndexExpression& indexExpr = (*expr)->as(); this->visitExpression(&indexExpr.base()); this->visitExpression(&indexExpr.index()); @@ -1076,18 +1076,14 @@ bool Inliner::analyze(const std::vector>& elemen this->buildCandidateList(elements, symbols, usage, &candidateList); // Inline the candidates where we've determined that it's safe to do so. - std::unordered_set*> enclosingStmtSet; + using StatementRemappingTable = std::unordered_map*, + std::unique_ptr*>; + StatementRemappingTable statementRemappingTable; + bool madeChanges = false; for (const InlineCandidate& candidate : candidateList.fCandidates) { FunctionCall& funcCall = (*candidate.fCandidateExpr)->as(); - // Inlining two expressions using the same enclosing statement in the same inlining pass - // does not work properly. If this happens, skip it; we'll get it in the next pass. - auto [unusedIter, inserted] = enclosingStmtSet.insert(candidate.fEnclosingStmt); - if (!inserted) { - continue; - } - // Convert the function call to its inlined equivalent. InlinedCall inlinedCall = this->inlineCall(&funcCall, candidate.fSymbols, *usage, &candidate.fEnclosingFunction->declaration()); @@ -1103,6 +1099,16 @@ bool Inliner::analyze(const std::vector>& elemen // Add references within the inlined body usage->add(inlinedCall.fInlinedBody.get()); + // Look up the enclosing statement; remap it if necessary. + std::unique_ptr* enclosingStmt = candidate.fEnclosingStmt; + for (;;) { + auto iter = statementRemappingTable.find(enclosingStmt); + if (iter == statementRemappingTable.end()) { + break; + } + enclosingStmt = iter->second; + } + // Move the enclosing statement to the end of the unscoped Block containing the inlined // function, then replace the enclosing statement with that Block. // Before: @@ -1111,14 +1117,18 @@ bool Inliner::analyze(const std::vector>& elemen // After: // fInlinedBody = null // fEnclosingStmt = Block{ stmt1, stmt2, stmt3, stmt4 } - inlinedCall.fInlinedBody->children().push_back(std::move(*candidate.fEnclosingStmt)); - *candidate.fEnclosingStmt = std::move(inlinedCall.fInlinedBody); + inlinedCall.fInlinedBody->children().push_back(std::move(*enclosingStmt)); + *enclosingStmt = std::move(inlinedCall.fInlinedBody); // Replace the candidate function call with our replacement expression. usage->replace(candidate.fCandidateExpr->get(), inlinedCall.fReplacementExpr.get()); *candidate.fCandidateExpr = std::move(inlinedCall.fReplacementExpr); madeChanges = true; + // If anything else pointed at our enclosing statement, it's now pointing at a Block + // containing many other statements as well. Maintain a fix-up table to account for this. + statementRemappingTable[enclosingStmt] = &(*enclosingStmt)->as().children().back(); + // Stop inlining if we've reached our hard cap on new statements. if (fInlinedStatementCounter >= kInlinedStatementLimit) { break; diff --git a/tests/sksl/inliner/InlinerCanBeDisabledStandaloneSettings.glsl b/tests/sksl/inliner/InlinerCanBeDisabledStandaloneSettings.glsl index 692492da0d..8482a00904 100644 --- a/tests/sksl/inliner/InlinerCanBeDisabledStandaloneSettings.glsl +++ b/tests/sksl/inliner/InlinerCanBeDisabledStandaloneSettings.glsl @@ -47,8 +47,8 @@ vec4 blend_hue(vec4 src, vec4 dst) { return vec4((((_blend_set_color_luminance(_blend_set_color_saturation(sda, dsa), alpha, dsa) + dst.xyz) - dsa) + src.xyz) - sda, (src.w + dst.w) - alpha); } void main() { - float _0_c = color.x * color.y + color.z; - sk_FragColor = vec4(_0_c); + float _1_c = color.x * color.y + color.z; + sk_FragColor = vec4(_1_c); sk_FragColor *= 1.25; sk_FragColor *= color.xxyy * color.w; sk_FragColor *= color.zzww * color.y; diff --git a/tests/sksl/inliner/InlinerManglesNames.glsl b/tests/sksl/inliner/InlinerManglesNames.glsl index 54b86627ad..8a82c7dcb3 100644 --- a/tests/sksl/inliner/InlinerManglesNames.glsl +++ b/tests/sksl/inliner/InlinerManglesNames.glsl @@ -2,11 +2,11 @@ out vec4 sk_FragColor; uniform vec4 color; vec4 main() { - float _0_c = color.x * color.y + color.z; - float a = _0_c; - float _1_c = color.y * color.z + color.w; - float b = _1_c; - float _2_c = color.z * color.w + color.x; - float c = _2_c; + float _1_c = color.x * color.y + color.z; + float a = _1_c; + float _2_c = color.y * color.z + color.w; + float b = _2_c; + float _3_c = color.z * color.w + color.x; + float c = _3_c; return vec4(a, b, c * c, a * (b * c)); }