| Submitter | Alan Modra |
|---|---|
| Date | Feb. 4, 2012, 5:46 a.m. |
| Message ID | <20120204054652.GC4832@bubble.grove.modra.org> |
| Download | mbox | patch |
| Permalink | /patch/139530/ |
| State | New |
| Headers | show |
Comments
On Sat, Feb 4, 2012 at 12:46 AM, Alan Modra <amodra@gmail.com> wrote: > http://gcc.gnu.org/ml/gcc-patches/2007-01/msg01835.html changed the > code I'm tweaking here to use DFmode subregs when loading a TFmode > constant into regs for e500. This just extends that change to all > rs6000 targets, the simplest fix I found for PR52107, a problem I > discovered when looking at powerpc64-linux libgcc. > It would also be possible to fix this in the rs6000.md movdi splitter > dealing with large constants, at least for this testcase when we know > we are dealing with a hard float reg. However, I think it's better > not to generate DImode fp values in the first place. Bootstrapped and > regression tested powerpc64-linux. OK to apply everywhere? > PR target/52107 > * config/rs6000/rs6000.c (rs6000_emit_move): Don't create DImode > subregs of TFmode. This fix is okay in trunk and 4.6. I am more reluctant to approve backporting it to GCC 4.5 at this late date. Thanks, David
Patch
Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 183781) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -7006,17 +7006,14 @@ rs6000_emit_move (rtx dest, rtx source, if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE) { - /* DImode is used, not DFmode, because simplify_gen_subreg doesn't - know how to get a DFmode SUBREG of a TFmode. */ - enum machine_mode imode = (TARGET_E500_DOUBLE ? DFmode : DImode); - rs6000_emit_move (simplify_gen_subreg (imode, operands[0], mode, 0), - simplify_gen_subreg (imode, operands[1], mode, 0), - imode); - rs6000_emit_move (simplify_gen_subreg (imode, operands[0], mode, - GET_MODE_SIZE (imode)), - simplify_gen_subreg (imode, operands[1], mode, - GET_MODE_SIZE (imode)), - imode); + rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode, 0), + simplify_gen_subreg (DFmode, operands[1], mode, 0), + DFmode); + rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode, + GET_MODE_SIZE (DFmode)), + simplify_gen_subreg (DFmode, operands[1], mode, + GET_MODE_SIZE (DFmode)), + DFmode); return; }
http://gcc.gnu.org/ml/gcc-patches/2007-01/msg01835.html changed the code I'm tweaking here to use DFmode subregs when loading a TFmode constant into regs for e500. This just extends that change to all rs6000 targets, the simplest fix I found for PR52107, a problem I discovered when looking at powerpc64-linux libgcc. If we leave these constant loads as DImode, here's what happens at various stages of rtl optimisation: .expand (insn 7 6 8 (set (reg:DI 35 3) (mem/u/c:DI (unspec:DI [ (symbol_ref/u:DI ("*.LC1") [flags 0x2]) (reg:DI 2 2) ] UNSPEC_TOCREL) [5 S8 A8])) /src/tmp/floatconst.c:10 -1 (nil)) .cse1 (insn 7 6 8 2 (set (reg:DI 35 3) (const_int 4318952042648305664 [0x3bf0000000000000])) /src/tmp/floatconst.c:10 401 {*movdi_internal64} (nil)) .split1 (insn 21 3 22 2 (set (reg:DI 35 3) (mem/u/c:DI (unspec:DI [ (symbol_ref/u:DI ("*.LC3") [flags 0x2]) (reg:DI 2 2) ] UNSPEC_TOCREL) [5 S8 A8])) /src/tmp/floatconst.c:10 -1 (expr_list:REG_EQUAL (const_int 1005584384 [0x3bf00000]) (nil))) (insn 22 21 8 2 (set (reg:DI 35 3) (ashift:DI (reg:DI 35 3) (const_int 32 [0x20]))) /src/tmp/floatconst.c:10 -1 (expr_list:REG_EQUAL (const_int 4318952042648305664 [0x3bf0000000000000]) (nil))) It would also be possible to fix this in the rs6000.md movdi splitter dealing with large constants, at least for this testcase when we know we are dealing with a hard float reg. However, I think it's better not to generate DImode fp values in the first place. Bootstrapped and regression tested powerpc64-linux. OK to apply everywhere? Note that the comment I remove is no longer true. PR target/52107 * config/rs6000/rs6000.c (rs6000_emit_move): Don't create DImode subregs of TFmode.