On Wed, 14 Nov 2018, Jakub Jelinek wrote:

> Hi!
> 
> As mentioned in the PR, it is unclear if zero_extract is well defined
> if the second argument is 0.  x86 intrinsic require bzhi and bextr to be
> well defined in those cases (extraction of 0 bits results in 0), but
> e.g. combiner hapilly transforms that into << 64 >> 64, simplify-rtx.c,
> while it folds it into 0, might invoke UB in the compiler etc.

So where do the zero_extracts come from?  Can we somehow avoid
zero-sized bit-extracts at expansion time by folding them to zero?

> So, is (zero_extract x 0 y) well defined in the middle-end or not?
> If it is well defined, then what about (sign_extract x 0 y), does it also
> yield 0, undefined, something else?

I don't think those should be well-defined.  If we would decide to
nail them down then both should yield zero indeed.

> If neither of those are well defined, the following patch provides a backend
> workaround for that, by making sure the second argument of zero_extract is
> never 0 on x86.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux.
> 
> 2018-11-13  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR rtl-optimization/87817
>       * config/i386/i386.md (nmi2_bzhi_<mode>3, *bmi2_bzhi_<mode>3,
>       *bmi2_bzhi_<mode>3_1, *bmi2_bzhi_<mode>3_1_ccz): Use IF_THEN_ELSE
>       in the pattern to avoid triggering UB when operands[2] is zero.
>       (tbm_bextri_<mode>): New expander.  Renamed the old define_insn to ...
>       (*tbm_bextri_<mode>): ... this.
> 
> --- gcc/config/i386/i386.md.jj        2018-11-09 14:02:00.030267540 +0100
> +++ gcc/config/i386/i386.md   2018-11-13 15:45:33.034870609 +0100
> @@ -13614,12 +13614,15 @@ (define_insn "*bmi_blsr_<mode>_ccz"
>  (define_expand "bmi2_bzhi_<mode>3"
>    [(parallel
>      [(set (match_operand:SWI48 0 "register_operand")
> -       (zero_extract:SWI48
> -         (match_operand:SWI48 1 "nonimmediate_operand")
> -         (umin:SWI48
> -           (and:SWI48 (match_operand:SWI48 2 "register_operand")
> -                      (const_int 255))
> -           (match_dup 3))
> +       (if_then_else:SWI48
> +         (ne:QI (and:SWI48 (match_operand:SWI48 2 "register_operand")
> +                           (const_int 255))
> +                (const_int 0))
> +         (zero_extract:SWI48
> +           (match_operand:SWI48 1 "nonimmediate_operand")
> +           (umin:SWI48 (and:SWI48 (match_dup 2) (const_int 255))
> +                       (match_dup 3))
> +           (const_int 0))
>           (const_int 0)))
>       (clobber (reg:CC FLAGS_REG))])]
>    "TARGET_BMI2"
> @@ -13627,12 +13630,15 @@ (define_expand "bmi2_bzhi_<mode>3"
>  
>  (define_insn "*bmi2_bzhi_<mode>3"
>    [(set (match_operand:SWI48 0 "register_operand" "=r")
> -     (zero_extract:SWI48
> -       (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> -       (umin:SWI48
> -         (and:SWI48 (match_operand:SWI48 2 "register_operand" "r")
> -                    (const_int 255))
> -         (match_operand:SWI48 3 "const_int_operand" "n"))
> +     (if_then_else:SWI48
> +       (ne:QI (and:SWI48 (match_operand:SWI48 2 "register_operand" "r")
> +                         (const_int 255))
> +              (const_int 0))
> +       (zero_extract:SWI48
> +         (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> +         (umin:SWI48 (and:SWI48 (match_dup 2) (const_int 255))
> +                     (match_operand:SWI48 3 "const_int_operand" "n"))
> +         (const_int 0))
>         (const_int 0)))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_BMI2 && INTVAL (operands[3]) == <MODE_SIZE> * BITS_PER_UNIT"
> @@ -13643,11 +13649,13 @@ (define_insn "*bmi2_bzhi_<mode>3"
>  
>  (define_insn "*bmi2_bzhi_<mode>3_1"
>    [(set (match_operand:SWI48 0 "register_operand" "=r")
> -     (zero_extract:SWI48
> -       (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> -       (umin:SWI48
> -         (zero_extend:SWI48 (match_operand:QI 2 "register_operand" "r"))
> -         (match_operand:SWI48 3 "const_int_operand" "n"))
> +     (if_then_else:SWI48
> +       (ne:QI (match_operand:QI 2 "register_operand" "r") (const_int 0))
> +       (zero_extract:SWI48
> +         (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> +         (umin:SWI48 (zero_extend:SWI48 (match_dup 2))
> +                     (match_operand:SWI48 3 "const_int_operand" "n"))
> +         (const_int 0))
>         (const_int 0)))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_BMI2 && INTVAL (operands[3]) == <MODE_SIZE> * BITS_PER_UNIT"
> @@ -13659,11 +13667,13 @@ (define_insn "*bmi2_bzhi_<mode>3_1"
>  (define_insn "*bmi2_bzhi_<mode>3_1_ccz"
>    [(set (reg:CCZ FLAGS_REG)
>       (compare:CCZ
> -       (zero_extract:SWI48
> -         (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> -         (umin:SWI48
> -           (zero_extend:SWI48 (match_operand:QI 2 "register_operand" "r"))
> -           (match_operand:SWI48 3 "const_int_operand" "n"))
> +       (if_then_else:SWI48
> +         (ne:QI (match_operand:QI 2 "register_operand" "r") (const_int 0))
> +         (zero_extract:SWI48
> +           (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> +           (umin:SWI48 (zero_extend:SWI48 (match_dup 2))
> +                       (match_operand:SWI48 3 "const_int_operand" "n"))
> +           (const_int 0))
>           (const_int 0))
>       (const_int 0)))
>     (clobber (match_scratch:SWI48 0 "=r"))]
> @@ -13696,7 +13706,28 @@ (define_insn "bmi2_pext_<mode>3"
>     (set_attr "mode" "<MODE>")])
>  
>  ;; TBM instructions.
> -(define_insn "tbm_bextri_<mode>"
> +(define_expand "tbm_bextri_<mode>"
> +  [(parallel
> +    [(set (match_operand:SWI48 0 "register_operand")
> +       (zero_extract:SWI48
> +         (match_operand:SWI48 1 "nonimmediate_operand")
> +         (match_operand 2 "const_0_to_255_operand" "N")
> +         (match_operand 3 "const_0_to_255_operand" "N")))
> +     (clobber (reg:CC FLAGS_REG))])]
> +  "TARGET_TBM"
> +{
> +  if (operands[2] == const0_rtx
> +      || INTVAL (operands[3]) >= <MODE_SIZE> * BITS_PER_UNIT)
> +    {
> +      emit_move_insn (operands[0], const0_rtx);
> +      DONE;
> +    }
> +  if (INTVAL (operands[2]) + INTVAL (operands[3])
> +      > <MODE_SIZE> * BITS_PER_UNIT)
> +    operands[2] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT - INTVAL 
> (operands[3]));
> +})
> +
> +(define_insn "*tbm_bextri_<mode>"
>    [(set (match_operand:SWI48 0 "register_operand" "=r")
>          (zero_extract:SWI48
>            (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to