expmed costs and i386.c cost for widening mul (PR81444)

Georg-Johann Lay avr@gjlay.de
Mon Jul 17 12:11:00 GMT 2017


On 17.07.2017 10:53, Georg-Johann Lay wrote:
> Hi, while testing a patch to fix PR81444, I came across a new FAIL due
> to the patch in i386.c/pr71321.c
> 
> PR81444 is about wrong modes used by expmed.c as it computes costs for
> widening operations like widening mul.  It uses  GET_MODE_WIDER_MODE
> for the wider mode where is should use GET_MODE_2XWIDER_MODE (the
> internals specify a mode 2 times as wide for the wider mode).
> 
> Applying the patch from below then leads to the following change in
> code generated for PR71321.c:
> 
> Without patch:
> 
> 
> 
> cvt_to_2digit_ascii:
>      movzbl    %dil, %eax    # 7    *zero_extendqihi2/1    [length = 4]
>      leal    (%rax,%rax,4), %edx    # 46    *leasi    [length = 3]
>      leal    (%rax,%rdx,8), %edx    # 47    *leasi    [length = 3]
>      leal    (%rdx,%rdx,4), %edx    # 48    *leasi    [length = 3]
>      shrw    $11, %dx    # 16    *lshrhi3_1    [length = 4]
>      leal    (%rdx,%rdx,4), %eax    # 49    *leasi    [length = 3]
>      movzbl    %dl, %edx    # 35    *zero_extendqisi2/1    [length = 3]
>      addl    %eax, %eax    # 50    *ashlsi3_1/1    [length = 2]
>      subl    %eax, %edi    # 51    *subsi_1/1    [length = 2]
>      movzbl    %dil, %eax    # 23    *zero_extendqisi2/1    [length = 4]
>      sall    $8, %eax    # 24    *ashlsi3_1/1    [length = 3]
>      orl    %edx, %eax    # 36    *iorsi_1/1    [length = 2]
>      addl    $667696, %eax    # 37    *addsi_1/1    [length = 5]
>      ret    # 55    simple_return_internal    [length = 1]
> 
> 
> With patch applied:
> 
> cvt_to_2digit_ascii:
>      movl    $-51, %edx    # 7    *movqi_internal/2    [length = 5]
>      movl    %edx, %eax    # 35    *movqi_internal/1    [length = 2]
>      mulb    %dil    # 8    *umulqihi3_1    [length = 3]
>      movl    %eax, %edx    # 36    *movhi_internal/1    [length = 2]
> 
> (Following code is the same)
> 
>      shrw    $11, %dx    # 10    *lshrhi3_1    [length = 4]
>      leal    (%rdx,%rdx,4), %eax    # 37    *leasi    [length = 3]
>      movzbl    %dl, %edx    # 23    *zero_extendqisi2/1    [length = 3]
>      addl    %eax, %eax    # 38    *ashlsi3_1/1    [length = 2]
>      subl    %eax, %edi    # 39    *subsi_1/1    [length = 2]
>      movzbl    %dil, %eax    # 17    *zero_extendqisi2/1    [length = 4]
>      sall    $8, %eax    # 18    *ashlsi3_1/1    [length = 3]
>      orl    %edx, %eax    # 24    *iorsi_1/1    [length = 2]
>      addl    $667696, %eax    # 25    *addsi_1/1    [length = 5]
>      ret    # 43    simple_return_internal    [length = 1]
> 
> Is this actually a performance regression or did the code improve 
> actually? (compiled with -O2 on x86_64).
> 
> What would be the proposed fix:  Adjust the test case or is this some
> problem in the i386.c cost computation?


...some more information. Looking into what ix86_rtx_costs is coming
up with. The unchanged version sees the strange modes an computes,
for example:

cost 4 (speed=1, outer=set) =
(zero_extend:HI (reg:XI 87))

cost 4 (speed=1, outer=set) =
(zero_extend:HI (reg:XI 87))

cost 24 (speed=1, outer=set) =
(mult:HI (zero_extend:HI (reg:XI 87))
     (zero_extend:HI (reg:XI 87)))

cost 4 (speed=1, outer=truncate) =
(lshiftrt:HI (mult:HI (zero_extend:HI (reg:XI 87))
         (zero_extend:HI (reg:XI 87)))
     (const_int 8 [0x8]))

cost 0 (speed=1, outer=lshiftrt) =
(const_int 8 [0x8])

cost 4 (speed=1, outer=lshiftrt) =
(zero_extend:HI (reg:XI 87))

cost 4 (speed=1, outer=lshiftrt) =
(zero_extend:HI (reg:XI 87))

cost 24 (speed=1, outer=lshiftrt) =
(mult:HI (zero_extend:HI (reg:XI 87))
     (zero_extend:HI (reg:XI 87)))


The patched version doesn't go into the sub-expressions and comes up
with smaller costs of 12 / 12 instead of the 24 / 24 from above:

cost 12 (speed=1, outer=set) =
(mult:HI (zero_extend:HI (reg:QI 87))
     (zero_extend:HI (reg:QI 87)))

cost 4 (speed=1, outer=truncate) =
(lshiftrt:HI (mult:HI (zero_extend:HI (reg:QI 87))
         (zero_extend:HI (reg:QI 87)))
     (const_int 8 [0x8]))

cost 0 (speed=1, outer=lshiftrt) =
(const_int 8 [0x8])

cost 12 (speed=1, outer=lshiftrt) =
(mult:HI (zero_extend:HI (reg:QI 87))
     (zero_extend:HI (reg:QI 87)))

Hence, with the proper expressions, costs for widening mul are cheaper
than with the XImode.  XImode is artefact of clobbering mode of
all->reg in expmed.c::init_expmed_one_conv().


> Johann
> 
> 
> 
> Index: expmed.c
> ===================================================================
> --- expmed.c    (revision 250090)
> +++ expmed.c    (working copy)
> @@ -119,6 +119,7 @@ init_expmed_one_conv (struct init_expmed
>   {
>     int to_size, from_size;
>     rtx which;
> +  machine_mode orig_mode = GET_MODE (all->reg);
> 
>     to_size = GET_MODE_PRECISION (to_mode);
>     from_size = GET_MODE_PRECISION (from_mode);
> @@ -140,6 +141,8 @@ init_expmed_one_conv (struct init_expmed
>     PUT_MODE (all->reg, from_mode);
>     set_convert_cost (to_mode, from_mode, speed,
>               set_src_cost (which, to_mode, speed));
> +  // Unclobber the mode, callers still use it.
> +  PUT_MODE (all->reg, orig_mode);
>   }
> 
>   static void
> @@ -210,7 +213,7 @@ init_expmed_one_mode (struct init_expmed
>       }
>     if (GET_MODE_CLASS (mode) == MODE_INT)
>       {
> -      machine_mode  wider_mode = GET_MODE_WIDER_MODE (mode);
> +      machine_mode wider_mode = GET_MODE_2XWIDER_MODE (mode);
>         if (wider_mode != VOIDmode)
>       {
>         PUT_MODE (all->zext, wider_mode);
> 



More information about the Gcc mailing list