Hello,

I've been investigating the failure of namelist_14.f90 -O0,
the last s390x-ibm-linux Fortran regression.

A much reduced test case is:
program test
  type             ::  mt
    integer        ::  ii(4)
  end type mt

  type(mt) :: t
  t = mt ((/1,1,1,1/))
end program test

Compiling this program without optimization fails with
test.f90:9: internal compiler error: in expand_assignment, at expr.c:3929
(Note that *with* optimization everything is fine.)

The ICE in expand_assignment results from expanding the
following line of code (from test.f90.t24.fixupcfg):
  mt.0.ii[S.6] = D.557;

"mt.0" is a temporary of type "mt" generated by the gimplifier.  As the
size of mt is 16, the expander uses TImode to hold the variable.

The ICE occurs because the expander tries to use a *register* to hold
that variable, and indexing a *variable* slot inside an array held in
a register is not supported by expand_assignment.

The decision whether to use a register or a stack slot is made in the
function use_register_for_decl (function.c):

bool
use_register_for_decl (tree decl)
{
  /* Honor volatile.  */
  if (TREE_SIDE_EFFECTS (decl))
    return false;

  /* Honor addressability.  */
  if (TREE_ADDRESSABLE (decl))
    return false;

  /* Only register-like things go in registers.  */
  if (DECL_MODE (decl) == BLKmode)
    return false;

  /* If -ffloat-store specified, don't put explicit float variables
     into registers.  */
  /* ??? This should be checked after DECL_ARTIFICIAL, but tree-ssa
     propagates values across these stores, and it probably shouldn't.  */
  if (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (decl)))
    return false;

  /* If we're not interested in tracking debugging information for
     this decl, then we can certainly put it in a register.  */
  if (DECL_IGNORED_P (decl))
    return true;

  return (optimize || DECL_REGISTER (decl));
}

As the variable is a temporary generated by the gimplifier, it has
its DECL_IGNORED_P flag set, which is why use_register_for_decl
decides to put it into a register, causing the ICE.  I was unable
to reproduce this in C, because I don't get such temporaries there.

Now, the interesting point is that when opimization is on, this 
routine would return true anyway, so why does it work then?  This
is because then the TREE_ADDRESSABLE flag is set, so it will always
be placed onto the stack.

However, the routine mark_array_ref_addressable (tree-cfg.c) which
sets the TREE_ADDRESSABLE flag is only ever called from the routine
execute_cleanup_cfg_post_optimizing (tree-optimize.c), which is never
called when not optimizing ...


Now, I'm not sure how to fix this.  One fix would be to always make
sure mark_array_ref_addressable is called, even when not optimizing.
I don't know what the right call point would be.

The other fix would be to remove the special treatment of 
DECL_IGNORED_P from use_register_for_decl.  This may cause somewhat
worse code generation, but only in the -O0 case, which I'm not
particularly concerned about ...


Any suggestions what the proper fix should be?

Thanks,
Ulrich


-- 
  Dr. Ulrich Weigand
  Linux on zSeries Development
  [EMAIL PROTECTED]

Reply via email to