Bug 51428 - Some code after SSA expand does nothing
Summary: Some code after SSA expand does nothing
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-12-05 23:52 UTC by Andrew Pinski
Modified: 2017-07-08 17:32 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-03-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2011-12-05 23:52:42 UTC
While looking into PR 45416, I came across:
	/* Check for |= or &= of a bitfield of size one into another bitfield
	   of size 1.  In this case, (unless we need the result of the
	   assignment) we can do this more efficiently with a
	   test followed by an assignment, if necessary.

From what I am reading, this code does nothing any more as TREE_CODE (rhs) will never be BIT_IOR_EXPR or BIT_AND_EXPR.
Comment 1 Martin Sebor 2017-03-16 03:06:56 UTC
After some grepping I found the comment you are referring to in gcc/expr.c.  It sounds to me as though you are suggesting that the whole if statement below is dead and should be removed.  Some light testing seems to confirm that removing it has no effect on the C test suite.  The comment that starts with ??? below the part you quoted seems to imply it's intentional, so I'm not sure what to make of this report.

Andrew, before I close this bug, would you like to shed some light on what you had in mind here?  What sort of a resolution are you looking for?

rtx
expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
                    enum expand_modifier modifier, rtx *alt_rtl,
                    bool inner_reference_p)
{
  ...
    case MODIFY_EXPR:
      {
        tree lhs = treeop0;
        tree rhs = treeop1;
        gcc_assert (ignore);

        /* Check for |= or &= of a bitfield of size one into another bitfield
           of size 1.  In this case, (unless we need the result of the
           assignment) we can do this more efficiently with a
           test followed by an assignment, if necessary.

           ??? At this point, we can't get a BIT_FIELD_REF here.  But if
           things change so we do, this code should be enhanced to
           support it.  */
        if (TREE_CODE (lhs) == COMPONENT_REF
            && (TREE_CODE (rhs) == BIT_IOR_EXPR
                || TREE_CODE (rhs) == BIT_AND_EXPR)
            && TREE_OPERAND (rhs, 0) == lhs
            && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
            && integer_onep (DECL_SIZE (TREE_OPERAND (lhs, 1)))
            && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
          {
            rtx_code_label *label = gen_label_rtx ();
            int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
            do_jump (TREE_OPERAND (rhs, 1),
                     value ? label : 0,
                     value ? 0 : label, -1);
            expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value),
                               false);
            do_pending_stack_adjust ();
            emit_label (label);
            return const0_rtx;
          }

        expand_assignment (lhs, rhs, false);
        return const0_rtx;
      }
Comment 2 Andrew Pinski 2017-07-08 17:32:06 UTC
(In reply to Martin Sebor from comment #1) 
> Andrew, before I close this bug, would you like to shed some light on what
> you had in mind here?  What sort of a resolution are you looking for?

So the reason why I said it was dead is because:
TREE_CODE (lhs) == COMPONENT_REF
&& (TREE_CODE (rhs) == BIT_IOR_EXPR
    || TREE_CODE (rhs) == BIT_AND_EXPR)

Can never be true after gimplification.

What this optimization is trying to do is the following:

struct f{
  int i0:1;
  int i1:1;
};

void or0(struct f *a)
{
  a->i0 = a->i0 | a->i1;
}
into:
void or1(struct f *a)
{
  if (a->i1 != 0)
    a->i0 = 1;
}

And:

void and0(struct f *a)
{
  a->i0 = a->i0 & a->i1;
}
into:
void and0(struct f *a)
{
  if (a->i1 == 0)
    a->i0 = 0;
}

------ CUT -----

Now this optimization has been disabled for ~8 years now and it might be better if just removed.