This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] lower-subreg: Decompose multiword shifts
- From: Rask Ingemann Lambertsen <rask at sygehus dot dk>
- To: Andreas Krebbel <Andreas dot Krebbel at de dot ibm dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 2 Aug 2007 20:51:48 +0200
- Subject: Re: [PATCH] lower-subreg: Decompose multiword shifts
- References: <20070802153434.GA24953@blc4eb430604175.ibm.com>
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