diff --git a/documentation/source/release-notes/2024.2.rst b/documentation/source/release-notes/2024.2.rst index e45a75bd3..36b51d907 100644 --- a/documentation/source/release-notes/2024.2.rst +++ b/documentation/source/release-notes/2024.2.rst @@ -26,6 +26,19 @@ Compiler * The build rules for unified executables now properly depend on copying included run-time libraries such as libunwind. +* Optimizations that allow the type of ``if`` expressions to be more + accurately estimated have been improved. For example, in this + function: + + .. code-block:: + + define function if-example (arg :: false-or()) => (result :: ); + min(arg | 20, 30) + end; + + the comparison can now be properly inlined because the first + argument to :drm:`min` is known to be an :drm:``. + Tools ===== diff --git a/sources/dfmc/optimization/assignment.dylan b/sources/dfmc/optimization/assignment.dylan index 254833bff..af2b44503 100644 --- a/sources/dfmc/optimization/assignment.dylan +++ b/sources/dfmc/optimization/assignment.dylan @@ -190,14 +190,20 @@ define method maybe-rename-temporaries-in-conditional (c.environment, , value: to-be-renamed, type: constraint); let then-f = c.consequent; + let merge-c :: = c.next-computation; let changed? = #f; rename-temporary!(to-be-renamed, tt-t); - for-computations(tc from then-f before c.next-computation) + for-computations(tc from then-f before merge-c) let now-changed? = rename-temporary-references!(tc, to-be-renamed, tt-t); changed? := (changed? | now-changed?); end; + // The left side of the merge is also part of the consequent + if (merge-c.merge-left-value == to-be-renamed) + merge-replace-left-value!(merge-c, to-be-renamed, tt-t); + changed? := #t; + end; if (changed?) - insert-computation-before!(then-f, tt-c); + insert-computation-before-reference!(then-f, tt-c, tt-t); else // It's not used in the consequent, so get rid of it. remove-user!(to-be-renamed, tt-c); end; diff --git a/sources/dfmc/optimization/calls.dylan b/sources/dfmc/optimization/calls.dylan index 3ad03bfd2..9f53b3910 100644 --- a/sources/dfmc/optimization/calls.dylan +++ b/sources/dfmc/optimization/calls.dylan @@ -79,13 +79,19 @@ define method do-optimize-instance?-user(c :: , object, type) => (); = make-with-temporary(c.environment, , value: object, type: type); let then-f = c.consequent; + let merge-c :: = c.next-computation; let changed? = #f; - for-computations(tc from then-f before c.next-computation) + for-computations(tc from then-f before merge-c) let now-changed? = rename-temporary-references!(tc, object, tt-t); changed? := (changed? | now-changed?); end; + // The left side of the merge is also part of the consequent + if (merge-c.merge-left-value == object) + merge-replace-left-value!(merge-c, object, tt-t); + changed? := #t; + end; if (changed?) - insert-computation-before!(then-f, tt-c); + insert-computation-before-reference!(then-f, tt-c, tt-t); else // It's not used in the consequent, so get rid of it. remove-user!(object, tt-c); end