Richard Biener <rguent...@suse.de> writes:
> On Thu, 3 Feb 2022, Richard Sandiford wrote:
>
>> Richard Biener <rguent...@suse.de> writes:
>> > On Wed, 2 Feb 2022, Michael Matz wrote:
>> >
>> >> Hello,
>> >> 
>> >> On Wed, 2 Feb 2022, Richard Biener via Gcc-patches wrote:
>> >> 
>> >> > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this 
>> >> > marks the end-of-life of storage as opposed to just ending the lifetime 
>> >> > of the object that occupied it. The dangling pointer diagnostics uses 
>> >> > CLOBBERs but is confused by those emitted by the C++ frontend for 
>> >> > example which emits them for the second purpose at the start of CTORs.  
>> >> > The issue is also appearant for aarch64 in PR104092.
>> >> > 
>> >> > Distinguishing the two cases is also necessary for the PR90348 fix.
>> >> 
>> >> (Just FWIW: I agree with the plan to have different types of CLOBBERs, in 
>> >> particular those for marking births)
>> >> 
>> >> A style nit:
>> >> 
>> >> >               tree clobber = build_clobber (TREE_TYPE (t));
>> >> > +             CLOBBER_MARKS_EOL (clobber) = 1;
>> >> 
>> >> I think it really were better if build_clobber() gained an additional 
>> >> argument (non-optional!) that sets the type of it.
>> >
>> > It indeed did occur to me as well, so as we're two now I tried to see
>> > how it looks like.  It does like the following (didn't bother to
>> > replace all build_clobber calls but defaulted the parameter - there
>> > are too many).  With CLOBBER_BIRTH added for the fix for PR90348
>> > the enum would be constructed like
>> >
>> > #define CLOBBER_KIND(NODE) \
>> >   ((clobber_kind) (CONSTRUCTOR_CHECK (NODE)->base.private_flag << 1
>> >                    | CONSTRUCTOR_CHECK (NODE)->base.protected_flag))
>> >
>> > or so (maybe different dependent on bitfield endianess to make
>> > extracting the two adjacent bits cheap).  That would leave us space
>> > for a fourth state.
>> >
>> > So do you think that makes it nicer?  What do others think?
>> 
>> This way looks cleaner to me FWIW.
>> 
>> Which arm of tree_base::u do constructors use?  If we need a 2-bit
>> enum then maybe we can carve one out from there.
>
> constructors are tcc_exceptional but since they are used where
> tree operands reside they need to be compatible to EXPR_P and
> thus various things like TREE_SIDE_EFFECTS need to work.
>
> Which means, we can't.

But TREE_SIDE_EFFECTS is part of the main set of flags.  For tree_base::u
we have:

  union {
    /* The bits in the following structure should only be used with
       accessor macros that constrain inputs with tree checking.  */
    struct {
      unsigned lang_flag_0 : 1;
      unsigned lang_flag_1 : 1;
      unsigned lang_flag_2 : 1;
      unsigned lang_flag_3 : 1;
      unsigned lang_flag_4 : 1;
      unsigned lang_flag_5 : 1;
      unsigned lang_flag_6 : 1;
      unsigned saturating_flag : 1;

      unsigned unsigned_flag : 1;
      unsigned packed_flag : 1;
      unsigned user_align : 1;
      unsigned nameless_flag : 1;
      unsigned atomic_flag : 1;
      unsigned unavailable_flag : 1;
      unsigned spare0 : 2;

      unsigned spare1 : 8;

      /* This field is only used with TREE_TYPE nodes; the only reason it is
         present in tree_base instead of tree_type is to save space.  The size
         of the field must be large enough to hold addr_space_t values.  */
      unsigned address_space : 8;
    } bits;

    /* The following fields are present in tree_base to save space.  The
       nodes using them do not require any of the flags above and so can
       make better use of the 4-byte sized word.  */

    /* The number of HOST_WIDE_INTs in an INTEGER_CST.  */
    struct {
      /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
         its native precision.  */
      unsigned char unextended;

      /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to
         wider precisions based on its TYPE_SIGN.  */
      unsigned char extended;

      /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
         offset_int precision, with smaller integers being extended
         according to their TYPE_SIGN.  This is equal to one of the two
         fields above but is cached for speed.  */
      unsigned char offset;
    } int_length;

    /* VEC length.  This field is only used with TREE_VEC.  */
    int length;

    /* This field is only used with VECTOR_CST.  */
    struct {
      /* The value of VECTOR_CST_LOG2_NPATTERNS.  */
      unsigned int log2_npatterns : 8;

      /* The value of VECTOR_CST_NELTS_PER_PATTERN.  */
      unsigned int nelts_per_pattern : 8;

      /* For future expansion.  */
      unsigned int unused : 16;
    } vector_cst;

    /* SSA version number.  This field is only used with SSA_NAME.  */
    unsigned int version;

    /* CHREC_VARIABLE.  This field is only used with POLYNOMIAL_CHREC.  */
    unsigned int chrec_var;

    /* Internal function code.  */
    enum internal_fn ifn;

    /* OMP_ATOMIC* memory order.  */
    enum omp_memory_order omp_atomic_memory_order;

    /* The following two fields are used for MEM_REF and TARGET_MEM_REF
       expression trees and specify known data non-dependences.  For
       two memory references in a function they are known to not
       alias if dependence_info.clique are equal and dependence_info.base
       are distinct.  Clique number zero means there is no information,
       clique number one is populated from function global information
       and thus needs no remapping on transforms like loop unrolling.  */
    struct {
      unsigned short clique;
      unsigned short base;
    } dependence_info;
  } GTY((skip(""))) u;

so there's spare room even if constructors use the general “bits” arm.

Thanks,
Richard

Reply via email to