From 338eb33a72a17d56b2800b9e4ac763c2cac00526 Mon Sep 17 00:00:00 2001 From: "Peter S. Housel" Date: Tue, 18 Jun 2024 20:40:00 -0700 Subject: [PATCH 1/2] dfmc-optimization: Fix missed if-computation optimizations These changes fix missed cases where type-constrained values in if tests and instance? tests were substituted in the left (consequent) side of the if body computations, but not in the left side of the if merge. * sources/dfmc/optimization/assignment.dylan (maybe-rename-temporaries-in-conditional): Substitute the type-constrained value when the test value appears in the left side of the . * sources/dfmc/optimization/calls.dylan (do-optimize-instance?-user): Substitute the type-constrained value when the instance? test value appears in the left side of the . --- sources/dfmc/optimization/assignment.dylan | 10 ++++++++-- sources/dfmc/optimization/calls.dylan | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sources/dfmc/optimization/assignment.dylan b/sources/dfmc/optimization/assignment.dylan index 254833bffb..af2b44503d 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 3ad03bfd22..9f53b3910d 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 From a023760364ed5bd39ba6698a051db62eb7404c79 Mon Sep 17 00:00:00 2001 From: "Peter S. Housel" Date: Wed, 19 Jun 2024 12:42:25 -0700 Subject: [PATCH 2/2] documentation: Note if-expression optimization in release notes * documentation/source/release-notes/2024.2.rst: Add entry to Compiler section. --- documentation/source/release-notes/2024.2.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/documentation/source/release-notes/2024.2.rst b/documentation/source/release-notes/2024.2.rst index 2d7715a16d..258fb9f6a9 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 =====