Hi,

This is another case where GCSE CPROP propagates a global constant
that we don't have exposed in the tree optimizers:

---------------------------
typedef enum
{
  SUCCESS = 1,
  FAILURE
} try;

typedef struct
{
  unsigned entry:1;
  unsigned use_assoc:1;
}
symbol_attribute;

extern try check_conflict (symbol_attribute * attr);
extern try gfc_add_entry (symbol_attribute *);
extern void foo (void);

try
gfc_add_entry (symbol_attribute * attr)
{
  if (attr->use_assoc != 0)
    return FAILURE;

  if (attr->entry)
    {
      foo ();
      return FAILURE;
    }

  return check_conflict (attr);
}
---------------------------

We notice in this case that check_conflict is a tail call, so we
mark it as such (.vars dump):

---------------------------
;; Function gfc_add_entry (gfc_add_entry)

gfc_add_entry (attr)
{
  try D.1580;
  unsigned char D.1578;

  # BLOCK 0
  # PRED: ENTRY [100.0%]  (fallthru,exec)
  D.1578 = BIT_FIELD_REF <*attr, 8, 0>;
  if ((D.1578 & 2) != 0) goto <L6>; else goto <L1>;
  # SUCC: 5 [33.0%]  (true,exec) 1 [67.0%]  (false,exec)

  # BLOCK 5
  # PRED: 0 [33.0%]  (true,exec)
<L6>:;
  D.1580 = 2;
  goto <bb 4> (<L4>);
  # SUCC: 4 [100.0%]  (fallthru)

  # BLOCK 1
  # PRED: 0 [67.0%]  (false,exec)
<L1>:;
  if ((D.1578 & 1) != 0) goto <L2>; else goto <L3>;
  # SUCC: 2 [96.0%]  (true,exec) 3 [4.0%]  (false,exec)

  # BLOCK 2
  # PRED: 1 [96.0%]  (true,exec)
<L2>:;
  foo ();
  D.1580 = 2;
  goto <bb 4> (<L4>);
  # SUCC: 4 [100.0%]  (fallthru,exec)

  # BLOCK 3
  # PRED: 1 [4.0%]  (false,exec)
<L3>:;
  D.1580 = check_conflict (attr) [tail call];
  # SUCC: 4 [100.0%]  (fallthru,exec)

  # BLOCK 4
  # PRED: 5 [100.0%]  (fallthru) 2 [100.0%]  (fallthru,exec) 3 [100.0%]  
(fallthru,exec)
<L4>:;
  return D.1580;
  # SUCC: EXIT [100.0%]

}
---------------------------

Indeed, we succeed in expanding the call to check_conflict as a
tail call, so the edge from BLOCK 2 to BLOCK 4 is redirected to
the functino exit, and suddenly D.1580 == 2 on all paths to it,
and GCSE CPROP propagates this constant.

Question is, can we (and do we want to) expose this constant to
the tree optimizers?  We do not know if the call we marked as a
tail call will indeed be expanded as one, so just adding a return
at the end of BLOCK 3 may pessimize the code.  Maybe we can do it
somewhere late in the tree optimizer path, but before the final
constant propagation pass?

Gr.
Steven

Reply via email to