This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix wrong code with autoinc/autodec
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 21 Nov 2008 22:27:38 +0100
- Subject: Fix wrong code with autoinc/autodec
This problem is responsible for the following ACATS regressions on IA-64:
FAIL: cxf3a01
FAIL: cxf3a02
FAIL: cxf3a03
FAIL: cxf3a04
FAIL: cxf3a06
FAIL: cxf3a07
FAIL: cxf3a08
It's a reload issue. We start with:
(insn 1066 1091 1096 4 fxf3a00.ads:88 (set (mem/s/f/j:DI (post_inc:DI
(reg/f:DI 1062)) [14 <variable>.P_ARRAY+0 S8 A128])
(reg/f:DI 566)) 5 {movdi_internal} (expr_list:REG_DEAD (reg/f:DI 566)
(expr_list:REG_INC (reg/f:DI 1062)
(nil))))
Then caller-save adds a new insn right before:
(insn 3852 1091 1066 4 (set (reg:DI 126 out6)
(mem/c:DI (plus:DI (reg/f:DI 328 sfp)
(const_int 192 [0xc0])) [137 S8 A64])) -1 (nil))
(insn 1066 1091 1096 4 fxf3a00.ads:88 (set (mem/s/f/j:DI (post_inc:DI
(reg/f:DI 11 r11 [1062])) [14 <variable>.P_ARRAY+0 S8 A128])
(reg/f:DI 126 out6 [566])) 5 {movdi_internal} (expr_list:REG_DEAD
(reg/f:DI 126 out6 [566])
(expr_list:REG_INC (reg/f:DI 11 r11 [1062])
(nil))))
Then a reload is called for insn 3852:
Reloads for insn # 3852
Reload 0: reload_in (DI) = (plus:DI (reg/f:DI 12 r12)
(const_int 208 [0xd0]))
GR_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 1), can't combine
reload_in_reg: (plus:DI (reg/f:DI 12 r12)
(const_int 208 [0xd0]))
reload_reg_rtx: (reg:DI 11 r11)
The problem is that the reload register r11 is live as it's used in insn 1066.
It's a variant of
http://gcc.gnu.org/ml/gcc-patches/2007-11/msg00838.html
When the new insn 3852 is added in insert_one_insn, we have for its associated
reload chain:
(gdb) p debug_regset(chain->live_throughout)
560 561 564 568 569 571 573 577 579 581 582 583 584 586 590 592 596 597 603
608 614 620 621 625 627 633 639 641 642 644 646 650 652 655 656 657 661 663
664 667 668 672 674 678 679 683 685 686 690 696 701 707 712 718 723 729 734
740 745 749 751 753 755 756 762 767 773 778 784 789 795 800 806 811 815 817
824 830 832 837 843 849 850 856 863 869 877 883 891 897 899 905 911 919 925
932 933 939 947 953 955 960 966 973 979 987 993 1001 1007 1015 1021 1031 1037
1045 1048 1051 1052 1058 1065 1069 1072 1076 1079 1335 1366 1529 1540 1548
1555 1571 1628 1767 1773 1970 1971 1972 1973 1974 1996 1998 2022 2089 2116
2117 2166 2211 2556
$59 = void
(gdb) p debug_regset(chain->dead_or_set)
1062
but, as already pointed out in the linked to discussion, dead_or_set is
disregarded in insert_one_insn and only notes are used to compute the new
live_throughout.
Minimally fixed in the same spirit by scanning REG_INC notes as well.
Tested on ia64-suse-linux, applied on the mainline.
2008-11-21 ?Eric Botcazou ?<ebotcazou@adacore.com>
* caller-save.c (insert_one_insn): Take into account REG_INC notes
for the liveness computation of the new insn.
--
Eric Botcazou
Index: caller-save.c
===================================================================
--- caller-save.c (revision 141915)
+++ caller-save.c (working copy)
@@ -1216,10 +1216,12 @@ insert_one_insn (struct insn_chain *chai
/* ??? It would be nice if we could exclude the already / still saved
registers from the live sets. */
COPY_REG_SET (&new_chain->live_throughout, &chain->live_throughout);
- /* Registers that die in CHAIN->INSN still live in the new insn. */
+ /* Registers that die in CHAIN->INSN still live in the new insn.
+ Likewise for those which are autoincremented or autodecremented. */
for (link = REG_NOTES (chain->insn); link; link = XEXP (link, 1))
{
- if (REG_NOTE_KIND (link) == REG_DEAD)
+ enum reg_note kind = REG_NOTE_KIND (link);
+ if (kind == REG_DEAD || kind == REG_INC)
{
rtx reg = XEXP (link, 0);
int regno, i;