https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113377
--- Comment #2 from anlauf at gcc dot gnu.org --- (In reply to Mikael Morin from comment #1) > (In reply to anlauf from comment #0) > > The dump-tree suggests that the scalarizer sees the loop invariant j, > > unconditionally dereferences it outside the loop, > > Note that the copy to the variable before the loop does NOT dereference the > pointer. You are right: I was mistaken as I was looking at the code generated for PR67277, especially at testcase gfortran.dg/ishftc_optional_size_1.f90, function ishftc4_ref_4, where the scalarization deferences the optional argument size_, D.4389 = *size_; outside of the loop. > This case is explicitly supported by the scalarizer, see > gfc_scalar_elemental_arg_saved_as_reference (and > gfc_walk_elemental_function_args for the initialization of the > can_be_null_ref field). I'll need to have a closer look here. Note that adding a scalar call in function one: r(1) = two (i(1), j) generates sane code: *((integer(kind=4) *) __result.0 + (sizetype) ((offset.1 + NON_LVALUE_EXPR <stride.0>) * 4)) = two (&(*i)[0], j != 0B ? *j : 0, j != 0B); > Normally this is sufficient to support optional dummies (there is also > additional support for class wrappers in gfc_conv_procedure_call), except if > value comes into play. > > > generates code that > > unconditionally dereferences j in the invocation of two, and uses a > > wrong interface: > These are the topics to investigate. > I suppose we need to duplicate (or factor) the code for optional, value > dummies that was added for non-elemental procedures in > gfc_conv_procedure_call. Probably yes. There is another observation: using the value attribute for j also in one, the scalar call from above becomes a straight *((integer(kind=4) *) __result.0 + (sizetype) ((offset.1 + NON_LVALUE_EXPR <stride.0>) * 4)) = two (&(*i)[0], j, .j); while the scalarizer produces: integer(kind=4) * D.4340; ... D.4340 = &j; ... *((integer(kind=4) *) __result.0 + (sizetype) ((S.3 * D.4342 + D.4339) * 4)) = two (&(*i)[S.3 + -1], *D.4340); which looks more complicated (besides being wrong...)