summaryrefslogtreecommitdiff
path: root/gcc_arm/testsuite/gcc.wendy/gnu17.c
blob: d3b03c1c539911f0172ba7592efca2f99e1b15d3 (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
#if 0
/*
Date: Mon, 17 Aug 87 09:03:50 PDT
From: bruce@stride.stride.com (Bruce Robertson)
To: bug-gcc@prep.ai.mit.edu
Subject: Optimizer bug in gcc 1.x

I found the cause of the optimizer bug that I've been sending you.  It
occurs because you scan for the first and last occurances of registers
before common subexpression processing, but cse can change these
occurances.  The bug appears in the example program because loop
optimization removes a load of "mem" into a pseudo-register, because
based on the information of the register scan it thinks that there are
no more appearances of the pseudo-register.  Cse added a reference,
however, and this information is not placed in regno_last_uid[].  The
solution seems to be to call reg_scan() again after calling
cse_main().  It fixed the bug anyway, and didn't seem to cause
anything bad.

Diffs for the fix, and the original sample program follow.


Diffs:
======================================================================
*** /tmp/,RCSt1a00495	Thu Aug 13 13:09:01 1987
--- toplev.c	Thu Aug 13 13:08:39 1987
***************
*** 776,781 ****
--- 776,786 ----
  
        TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num ()));
  
+       /* We need to scan for registers again, because common subexpression
+ 	 elimination could have rearranged the first and last occurrances
+ 	 of registers. */
+       TIMEVAR (cse_time, reg_scan (insns, max_reg_num ()));
+ 
        if (tem)
  	TIMEVAR (jump_time, jump_optimize (insns, 0, 0));
      }



Sample program:
======================================================================
#endif

typedef unsigned char quarterword;
typedef unsigned short halfword;

typedef union
{ 
    struct { 
        halfword    lh; 
        halfword    rh; 
    } hh1; 
    struct { 
        quarterword b0; 
        quarterword b1; 
        halfword    rh; 
    } hh2; 
}
    two_halves;

typedef struct
{ 
    quarterword b0;
    quarterword b1;
    quarterword b2;
    quarterword b3;
}
    four_quarters;

typedef union
{ 
    int         i;   
    float      gr;  
    two_halves      hh;  
    four_quarters   qqqq;
}
    memory_word;

memory_word     mem[10];

unsigned int fewest_demerits;
unsigned short best_bet = 0;
unsigned short best_line = -1;


void
foo(r)
	unsigned short r;
{

	do {
		if (mem[r].hh.hh2.b0 != 2 &&
		    mem[(r) + 2].i < fewest_demerits) {
                        best_bet = r;
		}
		r = mem[r].hh.hh1.rh;
	} while (r != (65501 - 7));

	/*
	 * This is the statement that is causing trouble.  See the comment
	 * in the assembly code below.
	 */
	best_line = mem[best_bet + 1].hh.hh1.lh;
}

main()
{
	mem[0].hh.hh2.b0 = 0;
	mem[0].hh.hh1.rh = 65501-7;
	mem[1].hh.hh1.lh = 456;
	mem[2].i = 30;
	foo(0);
	if (best_line == 456)
		printf("Test passed\n");
	else
		printf("Test failed, best_line = %d\n", best_line);
}

/*

#NO_APP
.comm _fewest_demerits,4
.comm _best_bet,2
.comm _best_line,2
.globl _foo
.text
	.even
_foo:
	link a6,#0
	moveml #0x3000,sp@-
	movew #1,d0
	clrl d1
	clrl d2
	lea _mem,a0
L2:
	movew d0,d1
	cmpb #2,a0@(d1:l:4)
	jeq L4
	movel a0@(8,d1:l:4),d3
	cmpl _fewest_demerits,d3
	jcc L4
	movew d0,_best_bet
L4:
	movew d0,d2
	movew a0@(2,d2:l:4),d0
	cmpw #65494,d0
	jne L2
	clrl d0
	movew _best_bet,d0

|
|	Where did this reference (below) to A1 come from?  It should be A0,
|	since that still points to "mem".  A1 is never set in the code
|	above.
|
|	When this code fragment is in place in Common Tex (in function
|	"line_break()" in file "par.c") the reference is to -4(fp)
|	rather than A1.
|

	movew a1@(4,d0:l:4),_best_line
	moveml a6@(-8),#0xc
	unlk a6
	rts
*/