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

--- Comment #10 from Xi Ruoyao <xry111 at gcc dot gnu.org> ---
(In reply to Xi Ruoyao from comment #9)

>  (define_insn "<optab>di3_fake"
>    [(set (match_operand:DI 0 "register_operand" "=r,&r,&r")
> -     (sign_extend:DI
> -       (any_div:SI (match_operand:DI 1 "register_operand" "r,r,0")
> -                   (match_operand:DI 2 "register_operand" "r,r,r"))))]
> -  ""
> +     (if_then_else
> +       (and (eq (match_operand:DI 1 "register_operand" "r,r,0")
> +                (sign_extend:DI (subreg:SI (match_dup 1) 0)))
> +            (eq (match_operand:DI 2 "register_operand" "r,r,r")
> +                (sign_extend:DI (subreg:SI (match_dup 2) 0))))
> +       (sign_extend:DI
> +         (any_div:SI (subreg:SI (match_dup 1) 0)
> +                     (subreg:SI (match_dup 2) 0)))
> +       (unspec:DI [(const_int 0)] UNSPEC_BAD_DIVW)))]

With this the compiler will still believe all bad {div,mod}.w{,u} instructions
generate the exactly same unspecified value.  But I don't think this is really
relevant: if a program depends on the unspecified value (no matter one value or
multiple values) it's already wrong.

If we are really "paranoid" about this we can make 4 UNSPEC_BAD_* constants and
use [(match_dup 1) (match_dup 2)] instead of [(const_int 0)].

> +  "TARGET_64BIT"
>  {
>    return loongarch_output_division ("<insn>.w<u>\t%0,%1,%2", operands);
>  }

Reply via email to