]>
Commit | Line | Data |
---|---|---|
de56f95a XL |
1 | /* { dg-do compile } */ |
2 | /* { dg-options "-O2 -fdump-tree-sink-stats" } */ | |
42d6b7d5 | 3 | /* { dg-require-effective-target int32plus } */ |
de56f95a XL |
4 | |
5 | #include <stdint.h> | |
6 | ||
7 | #define HLOG 16 | |
8 | #define MAX_LIT (1 << 5) | |
9 | typedef const uint8_t *LZF_HSLOT; | |
10 | typedef LZF_HSLOT LZF_STATE[1 << (HLOG)]; | |
11 | ||
12 | int | |
13 | compute_on_bytes (uint8_t *in_data, int in_len, uint8_t *out_data, int out_len) | |
14 | { | |
15 | LZF_STATE htab; | |
16 | ||
17 | uint8_t *ip = in_data; | |
18 | uint8_t *op = out_data; | |
19 | uint8_t *in_end = ip + in_len; | |
20 | uint8_t *out_end = op + out_len; | |
21 | uint8_t *ref; | |
22 | ||
23 | unsigned long off; | |
24 | unsigned int hval; | |
25 | int lit; | |
26 | ||
27 | if (!in_len || !out_len) | |
28 | return 0; | |
29 | ||
30 | lit = 0; | |
31 | op++; | |
32 | hval = (((ip[0]) << 8) | ip[1]); | |
33 | ||
34 | while (ip < in_end - 2) | |
35 | { | |
36 | uint8_t *hslot; | |
37 | ||
38 | hval = (((hval) << 8) | ip[2]); | |
39 | hslot = (uint8_t*)(htab + (((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))); | |
40 | ||
41 | ref = *hslot + in_data; | |
42 | *hslot = ip - in_data; | |
43 | ||
44 | if (1 && (off = ip - ref - 1) < (1 << 13) && ref > in_data | |
45 | && ref[2] == ip[2] | |
46 | && ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0])) | |
47 | { | |
48 | unsigned int len = 2; | |
49 | unsigned int maxlen = in_end - ip - len; | |
50 | maxlen | |
51 | = maxlen > ((1 << 8) + (1 << 3)) ? ((1 << 8) + (1 << 3)) : maxlen; | |
52 | ||
53 | if ((op + 3 + 1 >= out_end) != 0) | |
54 | if (op - !lit + 3 + 1 >= out_end) | |
55 | return 0; | |
56 | ||
57 | op[-lit - 1] = lit - 1; | |
58 | op -= !lit; | |
59 | ||
60 | for (;;) | |
61 | { | |
62 | if (maxlen > 16) | |
63 | { | |
64 | len++; | |
65 | if (ref[len] != ip[len]) | |
66 | break; | |
67 | len++; | |
68 | if (ref[len] != ip[len]) | |
69 | break; | |
70 | len++; | |
71 | if (ref[len] != ip[len]) | |
72 | break; | |
73 | len++; | |
74 | if (ref[len] != ip[len]) | |
75 | break; | |
76 | ||
77 | len++; | |
78 | if (ref[len] != ip[len]) | |
79 | break; | |
80 | len++; | |
81 | if (ref[len] != ip[len]) | |
82 | break; | |
83 | len++; | |
84 | if (ref[len] != ip[len]) | |
85 | break; | |
86 | len++; | |
87 | if (ref[len] != ip[len]) | |
88 | break; | |
89 | ||
90 | len++; | |
91 | if (ref[len] != ip[len]) | |
92 | break; | |
93 | len++; | |
94 | if (ref[len] != ip[len]) | |
95 | break; | |
96 | len++; | |
97 | if (ref[len] != ip[len]) | |
98 | break; | |
99 | len++; | |
100 | if (ref[len] != ip[len]) | |
101 | break; | |
102 | ||
103 | len++; | |
104 | if (ref[len] != ip[len]) | |
105 | break; | |
106 | len++; | |
107 | if (ref[len] != ip[len]) | |
108 | break; | |
109 | len++; | |
110 | if (ref[len] != ip[len]) | |
111 | break; | |
112 | len++; | |
113 | if (ref[len] != ip[len]) | |
114 | break; | |
115 | } | |
116 | ||
117 | do | |
118 | { | |
119 | len++; | |
120 | } | |
121 | while (len < maxlen && ip[len] == ref[len]); | |
122 | ||
123 | break; | |
124 | } | |
125 | ||
126 | len -= 2; | |
127 | ip++; | |
128 | ||
129 | if (len < 7) | |
130 | { | |
131 | *op++ = (off >> 8) + (len << 5); | |
132 | } | |
133 | else | |
134 | { | |
135 | *op++ = (off >> 8) + (7 << 5); | |
136 | *op++ = len - 7; | |
137 | } | |
138 | *op++ = off; | |
139 | lit = 0; | |
140 | op++; | |
141 | ip += len + 1; | |
142 | ||
143 | if (ip >= in_end - 2) | |
144 | break; | |
145 | ||
146 | --ip; | |
147 | --ip; | |
148 | ||
149 | hval = (((ip[0]) << 8) | ip[1]); | |
150 | hval = (((hval) << 8) | ip[2]); | |
151 | htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))] | |
152 | = (LZF_HSLOT)(ip - in_data); | |
153 | ip++; | |
154 | ||
155 | hval = (((hval) << 8) | ip[2]); | |
156 | htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))] | |
157 | = (LZF_HSLOT)(ip - in_data); | |
158 | ip++; | |
159 | } | |
160 | else | |
161 | { | |
162 | if (op >= out_end) | |
163 | return 0; | |
164 | ||
165 | lit++; | |
166 | *op++ = *ip++; | |
167 | ||
168 | if (lit == (1 << 5)) | |
169 | { | |
170 | op[-lit - 1] = lit - 1; | |
171 | lit = 0; | |
172 | op++; | |
173 | } | |
174 | } | |
175 | } | |
176 | if (op + 3 > out_end) /* at most 3 bytes can be missing here */ | |
177 | return 0; | |
178 | ||
179 | while (ip < in_end) | |
180 | { | |
181 | lit++; | |
182 | *op++ = *ip++; | |
183 | if (lit == MAX_LIT) | |
184 | { | |
185 | op[-lit - 1] = lit - 1; /* stop run */ | |
186 | lit = 0; | |
187 | op++; /* start run */ | |
188 | } | |
189 | } | |
190 | ||
191 | op[-lit - 1] = lit - 1; /* end run */ | |
192 | op -= !lit; /* undo run if length is zero */ | |
193 | ||
194 | return op - out_data; | |
195 | } | |
196 | ||
197 | /* For this case, pass sink2 sinks statements from hot loop header to loop | |
198 | exits after gimple loop optimizations, which generates instructions executed | |
199 | each iteration in loop, but the results are used outside of loop: | |
200 | With -m64, | |
201 | "Sinking _367 = (uint8_t *) _320; | |
202 | from bb 31 to bb 90 | |
203 | Sinking _320 = _321 + ivtmp.25_326; | |
204 | from bb 31 to bb 90 | |
205 | Sinking _321 = (unsigned long) ip_229; | |
206 | from bb 31 to bb 90 | |
207 | Sinking len_158 = _322 + 4294967295; | |
208 | from bb 31 to bb 33" | |
209 | When -m32, Power and X86 will sink 3 instructions, but arm ilp32 couldn't | |
210 | sink due to ivopts chooses two IV candidates instead of one, which is | |
93574914 AO |
211 | expected, so this case is restricted to lp64 only so far. This different |
212 | ivopts choice affects riscv64 as well, probably because it also lacks | |
213 | base+index addressing modes, so the ip[len] address computation can't be | |
214 | made from the IV computation above. */ | |
de56f95a | 215 | |
93574914 | 216 | /* { dg-final { scan-tree-dump-times "Sunk statements: 4" 1 "sink2" { target lp64 xfail { riscv64-*-* } } } } */ |