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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|target                      |middle-end

--- Comment #13 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
So this is a middle-end issue.


So expand_binop does:
```
  /* Record where to delete back to if we backtrack.  */
  last = get_last_insn ();

...
      if (otheroptab
          && (icode = optab_handler (otheroptab, mode)) != CODE_FOR_nothing)
        {
          /* The scalar may have been extended to be too wide.  Truncate
             it back to the proper size to fit in the broadcast vector.  */
          scalar_mode inner_mode = GET_MODE_INNER (mode);
          if (!CONST_INT_P (op1)
              && (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (op1)))
                  > GET_MODE_BITSIZE (inner_mode)))
            op1 = force_reg (inner_mode,
                             simplify_gen_unary (TRUNCATE, inner_mode, op1,
                                                 GET_MODE (op1)));
          rtx vop1 = expand_vector_broadcast (mode, op1);
          if (vop1)
            {
              temp = expand_binop_directly (icode, mode, otheroptab, op0, vop1,
                                            target, unsignedp, methods, last);
              if (temp)
                return temp;
            }
```

But then inside expand_binop_directly, does:
```
      /* If PAT is composed of more than one insn, try to add an appropriate
         REG_EQUAL note to it.  If we can't because TEMP conflicts with an
         operand, call expand_binop again, this time without a target.  */
      if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
          && ! add_equal_note (pat, ops[0].value,
                               optab_to_code (binoptab),
                               ops[1].value, ops[2].value, mode0))
        {
          delete_insns_since (last);
          return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
                               unsignedp, methods);
        }
```

And then the expand_vector_broadcast is lost because last points to right
before the dup.
But last here is wrong, it deletes too much. It should have been the last insn
at the entry of expand_binop_directly instead of last argument.

Reply via email to