https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114985

Aldy Hernandez <aldyh at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
   Last reconfirmed|                            |2024-05-08
             Status|UNCONFIRMED                 |NEW
                 CC|                            |amacleod at redhat dot com,
                   |                            |hubicka at gcc dot gnu.org,
                   |                            |jamborm at gcc dot gnu.org

--- Comment #4 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
Confirmed.

Here is some background on tracking discriminator failures.

The sanity check in the range_op dispatch code has noticed that it has an
unsupported pointer range combination.  This is the sanity check:

bool
range_op_handler::fold_range (vrange &r, tree type,
                              const vrange &lh,
                              const vrange &rh,
                              relation_trio rel) const
...
...
  if (has_pointer_operand_p (r, lh, rh)
      && !m_operator->pointers_handled_p (DISPATCH_FOLD_RANGE,
                                          dispatch_kind (r, lh, rh)))
    discriminator_fail (r, lh, rh);

The above code fails if the operator cannot handle the pointer combo it was
passed, and the operator at hand is op_equal:

(gdb) p *this
$11 = {m_operator = 0x1463a590 <op_equal>}

What's being attempted is a <POINTER> = <POINTER> == <POINTER> as per the
somewhat cryptic error:

DISCRIMINATOR FAIL.  Dispatch ====> RO_PPP <====

This is because for operator_equal::fold_range(), we only handle INTEGER =
POINTER OP_EQUAL POINTER.  That is, the result must be an integer:

bool
operator_equal::pointers_handled_p (range_op_dispatch_type type,
                                    unsigned dispatch) const
{
  switch (type)
    {
    case DISPATCH_FOLD_RANGE:
      return dispatch == RO_IPP;
...
...
}


This all comes from ipa_value_range_from_jfunc() which is trying to calculate
the equality of two pointer ranges and store the result in a pointer.  I
believe this is incorrect, as the result of equality should be a
boolean_type_node, or at least an integer.

This is where IPA is trying to call fold_range with the invalid combo:

         Value_Range op_res (vr_type);
          Value_Range res (vr_type);
          tree op = ipa_get_jf_pass_through_operand (jfunc);
          Value_Range op_vr (TREE_TYPE (op));
          range_op_handler handler (operation);

          ipa_range_set_and_normalize (op_vr, op);

          if (!handler
              || !op_res.supports_type_p (vr_type)
=>            || !handler.fold_range (op_res, vr_type, srcvr, op_vr))
            op_res.set_varying (vr_type);


It is trying to call fold_range() with EQ_EXPR for two pointer operands, but
storing the result in a pointer:

(gdb) p operation
$18 = EQ_EXPR
(gdb) p debug(srcvr)
[prange] union tree_node * * [0, +INF] MASK 0xfffffffffffffff8 VALUE 0x0
$14 = void
(gdb) p debug(op_vr)
[prange] union tree_node * * [0, 0] MASK 0x0 VALUE 0x0
$15 = void

IMO op_res should have an integer type, but it is a pointer:

(gdb) p debug_generic_stmt(vr_type)
union tree_node * *

...causing op_res to be a pointer:

(gdb) p debug(op_res)
[prange] UNDEFINED

If <POINTER> = <POINTER> OP_EQUAL <POINTER> is valid gimple, then we should
change operator_equal::fold_range() to accept all pointer operands.  If not,
then we need to change the IPA pass.

I would appreciate if an IL expert could opine here.

Reply via email to