ping
On 8/26/26 11:08 AM, Jerry D wrote:
Hi all,
The attached patch recovers most of the slowdown identified in the subject PR.
Test results from the original version of tonto SPEC benchmark are also
described in the PR126964 Comment #7:
"For the configuration in the initial report, I am getting roughly 2% slower
than the baseline before the blamed commit, meaning that most of the performance
has been recovered."
To develop this patch I used claude to analyze an archived open source copy of
tonto and generate an input "deck" to produce a local bench mark. This was
couple by multiple runs using callgrind to identify the "hot paths"
With the patch applied for a rank two dummy passed on from a loop calling it
120000 times, with a non-contiguous actual argument, the instructions executed
fall from 17151636793 to 11676814, against 10478570 before r17-3342.
As I stated above, this recovers most of the performance regression. It also has
peaked my curiosity so I plan some followup explorations.
Regression tested with full testsuite on x86_64.
OK for mainline?
Regards,
Jerry
---
fortran: [PR126964] Reduce the cost of a span addressed dummy
Assisted-by: Claude Opus 5
r17-3342 made a TARGET assumed shape or assumed rank dummy be addressed
through the span of its descriptor, so that a pointer to it stays valid
when its elements are subobjects of larger ones. That costs in two ways,
and SPEC 465.tonto pays both.
First, is_subref_array became true for such a dummy, so passing one on to
another procedure takes the copy-in/copy-out path, with the copy made
conditional on the actual argument being contiguous. That is more than
the receiving dummy needs: a dummy that has a descriptor of its own
addresses its elements by the strides held in it, so it accepts an actual
argument of any stride; the one thing it cannot do is address elements
that are subobjects of larger ones, which is what a span differing from
the element length means. Narrow the condition to the span alone when the
dummy has a descriptor and is not CONTIGUOUS. A dummy that needs the
argument packed still gets the full test.
Second, addressing every element as offset * span leaves the step of a
data reference symbolic, so loop versioning cannot prove that the accesses
stay aligned and the loop is never vectorized. Fold the spacing into the
strides and the offset on entry instead, so that the elements are
addressed by the constant element length as usual. The element length
divides the spacing whenever the element size equals the element
alignment, which covers integer, real and logical elements of an assumed
shape dummy; elsewhere the span is still used to address them.
PR fortran/126964
gcc/fortran/ChangeLog:
* trans.h (struct lang_decl): Add span_normalized.
(GFC_DECL_SPAN_NORMALIZED): New macro.
(gfc_conv_subref_array_arg): Add span_only argument.
(gfc_conv_is_contiguous_expr): Likewise.
* trans-array.h (gfc_span_folds_into_stride): New prototype.
* trans-array.cc (gfc_span_folds_into_stride): New function.
(gfc_trans_dummy_array_bias): Fold the element spacing of a span
normalized dummy into its strides and its offset on entry.
* trans-decl.cc (gfc_build_dummy_array_decl): Mark such a dummy
span normalized.
(gfc_get_symbol_decl): Do not set GFC_DECL_PTR_ARRAY_P for it.
* trans-intrinsic.cc (gfc_conv_is_contiguous_expr): Take span_only
and, with it, test that the span of the descriptor is the element
length without testing the strides.
* trans-expr.cc (is_whole_span_addressed_dummy): New function.
(dummy_accepts_strided_arg): New function.
(gfc_conv_procedure_call): Ask for the span test when a span
addressed dummy is passed on to a dummy that has a descriptor.
gcc/testsuite/ChangeLog:
* gfortran.dg/target_dummy_repack_1.f90: New test.
* gfortran.dg/target_dummy_span_1.f90: New test.
* gfortran.dg/gomp/target-span-1.f90: New test.
* gfortran.dg/c_loc_test_22.f90: Update for addressing by the
element length.
* gfortran.dg/class_to_type_9.f90: Likewise, and expect an
assumed shape dummy to take no copy of a strided actual argument.