This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] lower-subreg: Decompose multiword shifts


On Thu, Aug 02, 2007 at 05:34:34PM +0200, Andreas Krebbel wrote:
> 
> u64
> foo (u32 high, u32 low)
> {
>   return ((u64)high << 32) | low;
> }
> 
> Although that should be a nop on s390 GCC comes up with:
> 
> foo:
> .LFB2:
>         lr      %r5,%r2
>         lhi     %r4,0
>         sldl    %r4,32
>         or      %r5,%r3
>         lr      %r2,%r4
>         lr      %r3,%r5
>         br      %r14

   Odd, because on ia16, the equivalent multiword shift

u32
foo2 (u16 high, u16 low)
{
  return ((u32)high << 16) | low;
}

produces

foo2:
	pushw	%bp		;# 45	*pushhi1_nonimm
	movw	%sp,	%bp	;# 44	*movhi/1
	movw	6(%bp),	%ax	;# 26	*movhi/1
	movw	4(%bp),	%dx	;# 27	*movhi/1
	popw	%bp		;# 48	*pophi1
	ret			;# 49	*return

which is nearly perfect.

   After the first subreg pass, there is still a shift and two iors:

(note 4 3 9 2 NOTE_INSN_FUNCTION_BEG)

(insn 9 4 37 2 shifttest-lower.c:13 (clobber (reg:HI 32)) -1 (expr_list:REG_LIBCALL_ID (const_int 3 [0x3])
        (nil)))

(insn 37 9 7 2 shifttest-lower.c:13 (clobber (reg:HI 33 [+2 ])) -1 (nil))

(insn 7 37 8 2 shifttest-lower.c:13 (set (reg:HI 32)
        (reg/v:HI 22 [ low ])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 3 [0x3])
        (nil)))

(insn 8 7 12 2 shifttest-lower.c:13 (set (reg:HI 33 [+2 ])
        (const_int 0 [0x0])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 3 [0x3])
        (expr_list:REG_NO_CONFLICT (reg/v:HI 22 [ low ])
            (nil))))

(insn 12 8 38 2 shifttest-lower.c:13 (clobber (reg:HI 34)) -1 (expr_list:REG_LIBCALL_ID (const_int 4 [0x4])
        (nil)))

(insn 38 12 10 2 shifttest-lower.c:13 (clobber (reg:HI 35 [+2 ])) -1 (nil))

(insn 10 38 11 2 shifttest-lower.c:13 (set (reg:HI 34)
        (reg/v:HI 21 [ high ])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 4 [0x4])
        (nil)))

(insn 11 10 13 2 shifttest-lower.c:13 (set (reg:HI 35 [+2 ])
        (const_int 0 [0x0])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 4 [0x4])
        (expr_list:REG_NO_CONFLICT (reg/v:HI 21 [ high ])
            (nil))))

(insn 13 11 16 2 shifttest-lower.c:13 (set (reg:QI 27)
        (const_int 0 [0x0])) 8 {*movqi} (nil))

(insn 16 13 39 2 shifttest-lower.c:13 (clobber (reg:HI 36)) -1 (expr_list:REG_LIBCALL_ID (const_int 5 [0x5])
        (nil)))

(insn 39 16 14 2 shifttest-lower.c:13 (clobber (reg:HI 37 [+2 ])) -1 (nil))

(insn 14 39 15 2 shifttest-lower.c:13 (parallel [
            (set (reg:HI 37 [+2 ])
                (ashift:HI (reg:HI 34)
                    (reg:QI 27)))
            (clobber (reg:CC 13 cc))
        ]) 331 {*ashlhi3} (expr_list:REG_LIBCALL_ID (const_int 5 [0x5])
        (expr_list:REG_EQUAL (ashift:HI (reg:HI 34)
                (const_int 0 [0x0]))
            (nil))))

(insn 15 14 19 2 shifttest-lower.c:13 (set (reg:HI 36)
        (const_int 0 [0x0])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 5 [0x5])
        (nil)))

(insn 19 15 40 2 shifttest-lower.c:13 (clobber (reg:HI 30)) -1 (expr_list:REG_LIBCALL_ID (const_int 6 [0x6])
        (nil)))

(insn 40 19 17 2 shifttest-lower.c:13 (clobber (reg:HI 31 [+2 ])) -1 (nil))

(insn 17 40 18 2 shifttest-lower.c:13 (parallel [
            (set (reg:HI 30)
                (ior:HI (reg:HI 32)
                    (reg:HI 36)))
            (clobber (reg:CC 13 cc))
        ]) 75 {*iorhi3} (expr_list:REG_LIBCALL_ID (const_int 6 [0x6])
        (nil)))

(insn 18 17 22 2 shifttest-lower.c:13 (parallel [
            (set (reg:HI 31 [+2 ])
                (ior:HI (reg:HI 33 [+2 ])
                    (reg:HI 37 [+2 ])))
            (clobber (reg:CC 13 cc))
        ]) 75 {*iorhi3} (expr_list:REG_LIBCALL_ID (const_int 6 [0x6])
        (nil)))

(insn 22 18 41 2 shifttest-lower.c:13 (clobber (reg:HI 28 [ <result> ])) -1 (nil))

(insn 41 22 20 2 shifttest-lower.c:13 (clobber (reg:HI 29 [ <result>+2 ])) -1 (nil))

(insn 20 41 21 2 shifttest-lower.c:13 (set (reg:HI 28 [ <result> ])
        (reg:HI 30)) 6 {*movhi} (nil))

(insn 21 20 26 2 shifttest-lower.c:13 (set (reg:HI 29 [ <result>+2 ])
        (reg:HI 31 [+2 ])) 6 {*movhi} (nil))

(insn 26 21 27 2 shifttest-lower.c:15 (set (reg:HI 2 a)
        (reg:HI 28 [ <result> ])) 6 {*movhi} (nil))

(insn 27 26 33 2 shifttest-lower.c:15 (set (reg:HI 4 d [+2 ])
        (reg:HI 29 [ <result>+2 ])) 6 {*movhi} (nil))

(insn 33 27 0 2 shifttest-lower.c:15 (use (reg/i:SI 2 a)) -1 (nil))


   The shift and iors are gone already at cse1:

(note 4 3 9 2 NOTE_INSN_FUNCTION_BEG)

(insn 9 4 7 2 shifttest-lower.c:13 (clobber (reg:HI 32 [ low ])) -1 (expr_list:REG_LIBCALL_ID (const_int 3 [0x3])
        (nil)))

(insn 7 9 8 2 shifttest-lower.c:13 (set (reg:HI 32 [ low ])
        (reg/v:HI 22 [ low ])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 3 [0x3])
        (nil)))

(insn 8 7 12 2 shifttest-lower.c:13 (set (reg:HI 33 [+2 ])
        (const_int 0 [0x0])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 3 [0x3])
        (expr_list:REG_NO_CONFLICT (reg/v:HI 22 [ low ])
            (nil))))

(insn 12 8 10 2 shifttest-lower.c:13 (clobber (reg:HI 34 [ high ])) -1 (expr_list:REG_LIBCALL_ID (const_int 4 [0x4])
        (nil)))

(insn 10 12 11 2 shifttest-lower.c:13 (set (reg:HI 34 [ high ])
        (reg/v:HI 21 [ high ])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 4 [0x4])
        (nil)))

(insn 11 10 13 2 shifttest-lower.c:13 (set (reg:HI 35 [+2 ])
        (reg:HI 33 [+2 ])) 6 {*movhi} (expr_list:REG_EQUAL (const_int 0 [0x0])
        (expr_list:REG_LIBCALL_ID (const_int 4 [0x4])
            (expr_list:REG_NO_CONFLICT (reg/v:HI 21 [ high ])
                (nil)))))

(insn 13 11 16 2 shifttest-lower.c:13 (set (reg:QI 27)
        (subreg:QI (reg:HI 33 [+2 ]) 0)) 8 {*movqi} (expr_list:REG_EQUAL (const_int 0 [0x0])
        (nil)))

(insn 16 13 14 2 shifttest-lower.c:13 (clobber (reg:HI 36)) -1 (expr_list:REG_LIBCALL_ID (const_int 5 [0x5])
        (nil)))

(insn 14 16 15 2 shifttest-lower.c:13 (set (reg:HI 37 [+2 ])
        (reg/v:HI 21 [ high ])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 5 [0x5])
        (expr_list:REG_EQUAL (reg/v:HI 21 [ high ])
            (nil))))

(insn 15 14 19 2 shifttest-lower.c:13 (set (reg:HI 36)
        (reg:HI 33 [+2 ])) 6 {*movhi} (expr_list:REG_EQUAL (const_int 0 [0x0])
        (expr_list:REG_LIBCALL_ID (const_int 5 [0x5])
            (nil))))

(insn 19 15 17 2 shifttest-lower.c:13 (clobber (reg:HI 30)) -1 (expr_list:REG_LIBCALL_ID (const_int 6 [0x6])
        (nil)))

(insn 17 19 18 2 shifttest-lower.c:13 (set (reg:HI 30)
        (reg/v:HI 22 [ low ])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 6 [0x6])
        (nil)))

(insn 18 17 20 2 shifttest-lower.c:13 (set (reg:HI 31 [+2 ])
        (reg/v:HI 21 [ high ])) 6 {*movhi} (expr_list:REG_LIBCALL_ID (const_int 6 [0x6])
        (nil)))

(insn 20 18 21 2 shifttest-lower.c:13 (set (reg:HI 28 [ <result> ])
        (reg/v:HI 22 [ low ])) 6 {*movhi} (nil))

(insn 21 20 26 2 shifttest-lower.c:13 (set (reg:HI 29 [ <result>+2 ])
        (reg/v:HI 21 [ high ])) 6 {*movhi} (nil))

(insn 26 21 27 2 shifttest-lower.c:15 (set (reg:HI 2 a [ <result> ])
        (reg/v:HI 22 [ low ])) 6 {*movhi} (nil))

(insn 27 26 33 2 shifttest-lower.c:15 (set (reg:HI 4 d [+2 ])
        (reg/v:HI 21 [ high ])) 6 {*movhi} (nil))

(insn 33 27 0 2 shifttest-lower.c:15 (use (reg/i:SI 2 a)) -1 (nil))


   After fwprop1, only this is left:

(note 4 3 9 2 NOTE_INSN_FUNCTION_BEG)

(insn 9 4 12 2 shifttest-lower.c:13 (clobber (reg:HI 32 [ low ])) -1 (expr_list:REG_LIBCALL_ID (const_int 3 [0x3])
        (nil)))

(insn 12 9 16 2 shifttest-lower.c:13 (clobber (reg:HI 34 [ high ])) -1 (expr_list:REG_LIBCALL_ID (const_int 4 [0x4])
        (nil)))

(insn 16 12 19 2 shifttest-lower.c:13 (clobber (reg:HI 36)) -1 (expr_list:REG_LIBCALL_ID (const_int 5 [0x5])
        (nil)))

(insn 19 16 26 2 shifttest-lower.c:13 (clobber (reg:HI 30)) -1 (expr_list:REG_LIBCALL_ID (const_int 6 [0x6])
        (nil)))

(insn 26 19 27 2 shifttest-lower.c:15 (set (reg:HI 2 a [ <result> ])
        (reg/v:HI 22 [ low ])) 6 {*movhi} (nil))

(insn 27 26 33 2 shifttest-lower.c:15 (set (reg:HI 4 d [+2 ])
        (reg/v:HI 21 [ high ])) 6 {*movhi} (nil))

(insn 33 27 0 2 shifttest-lower.c:15 (use (reg/i:SI 2 a)) -1 (nil))


   Why isn't the same magic happening on s390?

> Index: gcc/testsuite/gcc.dg/multiword-shifts.c
> ===================================================================
> *** /dev/null	1970-01-01 00:00:00.000000000 +0000
> --- gcc/testsuite/gcc.dg/multiword-shifts.c	2007-08-02 11:48:02.000000000 +0200
> ***************
> *** 0 ****
> --- 1,40 ----
> + /* { dg-do run } */
> + /* { dg-options "-O3" } */
> + 
> + typedef unsigned int u32;
> + typedef unsigned long long u64;

   Please use uint32_t and uint64_t from stdint.h (or some other reliable
means of getting types of the sizes you want).

-- 
Rask Ingemann Lambertsen


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]