summaryrefslogtreecommitdiff
path: root/packages/gcc/gcc-4.3.1/debian/pr30961.dpatch
blob: b20fdf5bf58a10ad321e00e4a44b76dc5683b5a2 (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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#! /bin/sh -e

# DP: <your description>

dir=
if [ $# -eq 3 -a "$2" = '-d' ]; then
    pdir="-d $3"
    dir="$3/"
elif [ $# -ne 1 ]; then
    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    exit 1
fi
case "$1" in
    -patch)
        patch $pdir -f --no-backup-if-mismatch -p0 < $0
        ;;
    -unpatch)
        patch $pdir -f --no-backup-if-mismatch -R -p0 < $0
        ;;
    *)
        echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
        exit 1
esac
exit 0

From: "H.J. Lu" <hjl@lucon.org>
Sender: gcc-patches-owner@gcc.gnu.org
To: gcc-patches@gcc.gnu.org
Subject: PATCH: PR target/30961: [4.1/4.2/4.3 regression] redundant reg/mem 	stores/moves
Date: Mon, 27 Aug 2007 11:34:12 -0700

We start with

(note:HI 3 4 22 2 NOTE_INSN_FUNCTION_BEG)

(insn:HI 6 3 10 2 c.c:3 (set (reg:DF 58 [ <result> ])
        (subreg:DF (reg/v:DI 59 [ in ]) 0)) 102 {*movdf_integer_rex64} (expr_list:REG_DEAD (reg/v:DI 59 [ in ])
        (nil)))

(insn:HI 10 6 16 2 c.c:7 (set (reg/i:DF 21 xmm0 [ <result> ])
        (reg:DF 58 [ <result> ])) 102 {*movdf_integer_rex64} (expr_list:REG_DEAD (reg:DF 58 [ <result> ])
        (nil)))

(insn:HI 16 10 0 2 c.c:7 (use (reg/i:DF 21 xmm0 [ <result> ])) -1 (nil))

we are trying to allocate registers for insn 6 and we allocate
xmm0 for the return value. Reload doesn't check if xmm0 can be used for
DF 59, it allocates xmm1 for DF 59 and generates:

Reloads for insn # 6
Reload 0: reload_in (DF) = (reg:DF 5 di)
        SSE_REGS, RELOAD_FOR_INPUT (opnum = 1), can't combine
        reload_in_reg: (subreg:DF (reg/v:DI 5 di [orig:59 in ] [59]) 0)
        reload_reg_rtx: (reg:DF 22 xmm1)
...

(note:HI 4 1 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(note:HI 3 4 22 2 NOTE_INSN_FUNCTION_BEG)

(insn 22 3 23 2 c.c:3 (set (mem/c:DF (plus:DI (reg/f:DI 7 sp)
                (const_int -8 [0xfffffffffffffff8])) [0 S8 A8])
        (reg:DF 5 di)) 102 {*movdf_integer_rex64} (nil))

(insn 23 22 6 2 c.c:3 (set (reg:DF 22 xmm1)
        (mem/c:DF (plus:DI (reg/f:DI 7 sp)
                (const_int -8 [0xfffffffffffffff8])) [0 S8 A8])) 102 {*movdf_integer_rex64} (nil))

(insn:HI 6 23 16 2 c.c:3 (set (reg:DF 21 xmm0 [orig:58 <result> ] [58])
        (reg:DF 22 xmm1)) 102 {*movdf_integer_rex64} (nil))

(insn 16 6 21 2 c.c:7 (use (reg/i:DF 21 xmm0 [ <result> ])) -1 (nil))

This patch tries to use the destination register when reloading for input. It
generates

Reloads for insn # 6
Reload 0: reload_in (DF) = (reg:DF 5 di)
        SSE_REGS, RELOAD_FOR_INPUT (opnum = 1), can't combine
        reload_in_reg: (subreg:DF (reg/v:DI 5 di [orig:59 in ] [59]) 0)
        reload_reg_rtx: (reg:DF 21 xmm0)
...
(note:HI 4 1 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(note:HI 3 4 22 2 NOTE_INSN_FUNCTION_BEG)

(insn 22 3 23 2 c.c:3 (set (mem/c:DF (plus:DI (reg/f:DI 7 sp)
                (const_int -8 [0xfffffffffffffff8])) [0 S8 A8])
        (reg:DF 5 di)) 102 {*movdf_integer_rex64} (nil))

(insn 23 22 6 2 c.c:3 (set (reg:DF 21 xmm0)
        (mem/c:DF (plus:DI (reg/f:DI 7 sp)
                (const_int -8 [0xfffffffffffffff8])) [0 S8 A8])) 102 {*movdf_integer_rex64} (nil))

(insn:HI 6 23 10 2 c.c:3 (set (reg:DF 22 xmm1 [orig:58 <result> ] [58])
        (reg:DF 21 xmm0)) 102 {*movdf_integer_rex64} (nil))

(insn:HI 10 6 16 2 c.c:7 (set (reg/i:DF 21 xmm0 [ <result> ])
        (reg:DF 22 xmm1 [orig:58 <result> ] [58])) 102 {*movdf_integer_rex64} (nil))

(insn 16 10 21 2 c.c:7 (use (reg/i:DF 21 xmm0 [ <result> ])) -1 (nil))


H.J.
----
gcc/

2007-08-27  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/30961
	* reload1.c (find_reg): Favor the hard register in destination
	if it is usable and a memory location is needed for reload
	input.

gcc/testsuite/

2007-08-27  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/30961
	* gcc.target/i386/pr30961-1.c: New.

--- gcc/reload1.c.second	2007-08-27 09:35:08.000000000 -0700
+++ gcc/reload1.c	2007-08-27 09:36:33.000000000 -0700
@@ -1781,6 +1781,20 @@ find_reg (struct insn_chain *chain, int 
   HARD_REG_SET not_usable;
   HARD_REG_SET used_by_other_reload;
   reg_set_iterator rsi;
+#ifdef SECONDARY_MEMORY_NEEDED
+  rtx body = PATTERN (chain->insn);
+  unsigned int dest_reg = FIRST_PSEUDO_REGISTER;
+
+  if (GET_CODE (body) == SET)
+    {
+      rtx dest = SET_DEST (body);
+
+      if ((REG_P (dest)
+	   || (GET_CODE (dest) == SUBREG
+	       && REG_P (SUBREG_REG (dest)))))
+	dest_reg = reg_or_subregno (dest);
+    }
+#endif
 
   COPY_HARD_REG_SET (not_usable, bad_spill_regs);
   IOR_HARD_REG_SET (not_usable, bad_spill_regs_global);
@@ -1821,6 +1835,18 @@ find_reg (struct insn_chain *chain, int 
 	    this_cost--;
 	  if (rl->out && REG_P (rl->out) && REGNO (rl->out) == regno)
 	    this_cost--;
+#ifdef SECONDARY_MEMORY_NEEDED
+	  /* If a memory location is needed for rl->in and dest_reg
+	     is usable, we will favor it.  */
+	  else if (dest_reg == regno
+		   && rl->in
+		   && REG_P (rl->in)
+		   && REGNO (rl->in) < FIRST_PSEUDO_REGISTER
+		   && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (rl->in)),
+					       rl->class,
+					       rl->mode))
+	    this_cost = 0;
+#endif
 	  if (this_cost < best_cost
 	      /* Among registers with equal cost, prefer caller-saved ones, or
 		 use REG_ALLOC_ORDER if it is defined.  */
--- gcc/testsuite/gcc.target/i386/pr30961-1.c.second	2007-08-27 11:01:59.000000000 -0700
+++ gcc/testsuite/gcc.target/i386/pr30961-1.c	2007-08-27 11:02:51.000000000 -0700
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2" } */
+
+double
+convert (long long in)
+{
+  double f;
+  __builtin_memcpy( &f, &in, sizeof( in ) );
+  return f;
+}
+
+/* { dg-final { scan-assembler-not "movapd" } } */