summaryrefslogtreecommitdiff
path: root/debian/patches/gcc-rs6000-update.diff
blob: 1069b504b5083fa8dc375222593224c88c85c05c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
when trying to build Ada for powerpc64le-linux, I ran into an ICE
in fixup_args_size_notes.

It turns out that the p8 fusion peephole acts on these two insns
from the epilog sequence:

(insn 1693 1078 1079 91 (set (reg:DI 7 7)
        (plus:DI (reg/f:DI 31 31)
            (const_int 65536 [0x10000]))) 82 {*adddi3_internal1}
     (nil))
(insn 1079 1693 1511 91 (set (reg/f:DI 1 1)
        (mem/c:DI (plus:DI (reg:DI 7 7)
                (const_int -16096 [0xffffffffffffc120])) [233 %sfp+49440 S8 A64])) 519 {*movdi_internal64}
     (expr_list:REG_DEAD (reg:DI 7 7)
        (expr_list:REG_ARGS_SIZE (const_int 0 [0])
            (nil))))

and replaces them by:

(insn 1776 1078 1777 91 (set (reg/f:DI 1 1)
        (plus:DI (reg/f:DI 31 31)          
            (const_int 65536 [0x10000]))) -1
     (nil))                                 

(insn 1777 1776 1511 91 (set (reg/f:DI 1 1)
        (mem/c:DI (plus:DI (reg/f:DI 1 1)  
                (const_int -16096 [0xffffffffffffc120])) [233  S8 A8])) -1
     (expr_list:REG_ARGS_SIZE (const_int 0 [0])                           
        (nil)))                                                           

Then peephole common code thinks it needs to re-create the REG_ARGS_SIZE
note and fails since the code is too complex for it to understand.  (Which
is reasonable since it doesn't know what value is being restored from the
stack here.)

However, the more fundamental problem seems to be that this transformation
should be invalid anyway, since it creates an intermediate state where
the stack pointer points to a location without proper backchain, which
violates the ABI.

The following patch fixes this by disabling the fusion peephole in those
cases where it would introduce a new use of the stack pointer as temporary
register.

Tested on powerpc64le-linux.  OK for mainline (and 4.8 after the big patch
series is committed)?

Bye,
Ulrich

ChangeLog:

	* config/rs6000/rs6000.c (fusion_gpr_load_p): Refuse optimization
	if it would clobber the stack pointer, even temporarily.

--- a/src/gcc/config/rs6000/rs6000.c
+++ b/src/gcc/config/rs6000/rs6000.c
@@ -32519,6 +32519,11 @@
 
       if (!peep2_reg_dead_p (2, addis_reg))
 	return false;
+
+      /* If the target register being loaded is the stack pointer, we must
+         avoid loading any other value into it, even temporarily.  */
+      if (REG_P (target) && REGNO (target) == STACK_POINTER_REGNUM)
+	return false;
     }
 
   base_reg = XEXP (addr, 0);