re PR tree-optimization/63747 (icf mis-compares switch gimple)
[gcc.git] / gcc / lto-compress.c
1 /* LTO IL compression streams.
2
3 Copyright (C) 2009-2014 Free Software Foundation, Inc.
4 Contributed by Simon Baldwin <simonb@google.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 /* zlib.h includes other system headers. Those headers may test feature
25 test macros. config.h may define feature test macros. For this reason,
26 zlib.h needs to be included after, rather than before, config.h and
27 system.h. */
28 #include <zlib.h>
29 #include "coretypes.h"
30 #include "tree.h"
31 #include "predict.h"
32 #include "vec.h"
33 #include "hashtab.h"
34 #include "hash-set.h"
35 #include "machmode.h"
36 #include "tm.h"
37 #include "hard-reg-set.h"
38 #include "input.h"
39 #include "function.h"
40 #include "basic-block.h"
41 #include "tree-ssa-alias.h"
42 #include "internal-fn.h"
43 #include "gimple-expr.h"
44 #include "is-a.h"
45 #include "gimple.h"
46 #include "diagnostic-core.h"
47 #include "langhooks.h"
48 #include "hash-map.h"
49 #include "plugin-api.h"
50 #include "ipa-ref.h"
51 #include "cgraph.h"
52 #include "lto-streamer.h"
53 #include "lto-compress.h"
54
55 /* Compression stream structure, holds the flush callback and opaque token,
56 the buffered data, and a note of whether compressing or uncompressing. */
57
58 struct lto_compression_stream
59 {
60 void (*callback) (const char *, unsigned, void *);
61 void *opaque;
62 char *buffer;
63 size_t bytes;
64 size_t allocation;
65 bool is_compression;
66 };
67
68 /* Overall compression constants for zlib. */
69
70 static const size_t Z_BUFFER_LENGTH = 4096;
71 static const size_t MIN_STREAM_ALLOCATION = 1024;
72
73 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
74 is unused. */
75
76 static void *
77 lto_zalloc (void *opaque, unsigned items, unsigned size)
78 {
79 gcc_assert (opaque == Z_NULL);
80 return xmalloc (items * size);
81 }
82
83 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
84
85 static void
86 lto_zfree (void *opaque, void *address)
87 {
88 gcc_assert (opaque == Z_NULL);
89 free (address);
90 }
91
92 /* Return a zlib compression level that zlib will not reject. Normalizes
93 the compression level from the command line flag, clamping non-default
94 values to the appropriate end of their valid range. */
95
96 static int
97 lto_normalized_zlib_level (void)
98 {
99 int level = flag_lto_compression_level;
100
101 if (level != Z_DEFAULT_COMPRESSION)
102 {
103 if (level < Z_NO_COMPRESSION)
104 level = Z_NO_COMPRESSION;
105 else if (level > Z_BEST_COMPRESSION)
106 level = Z_BEST_COMPRESSION;
107 }
108
109 return level;
110 }
111
112 /* Create a new compression stream, with CALLBACK flush function passed
113 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
114
115 static struct lto_compression_stream *
116 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
117 void *opaque, bool is_compression)
118 {
119 struct lto_compression_stream *stream
120 = (struct lto_compression_stream *) xmalloc (sizeof (*stream));
121
122 memset (stream, 0, sizeof (*stream));
123 stream->callback = callback;
124 stream->opaque = opaque;
125 stream->is_compression = is_compression;
126
127 return stream;
128 }
129
130 /* Append NUM_CHARS from address BASE to STREAM. */
131
132 static void
133 lto_append_to_compression_stream (struct lto_compression_stream *stream,
134 const char *base, size_t num_chars)
135 {
136 size_t required = stream->bytes + num_chars;
137
138 if (stream->allocation < required)
139 {
140 if (stream->allocation == 0)
141 stream->allocation = MIN_STREAM_ALLOCATION;
142 while (stream->allocation < required)
143 stream->allocation *= 2;
144
145 stream->buffer = (char *) xrealloc (stream->buffer, stream->allocation);
146 }
147
148 memcpy (stream->buffer + stream->bytes, base, num_chars);
149 stream->bytes += num_chars;
150 }
151
152 /* Free the buffer and memory associated with STREAM. */
153
154 static void
155 lto_destroy_compression_stream (struct lto_compression_stream *stream)
156 {
157 free (stream->buffer);
158 free (stream);
159 }
160
161 /* Return a new compression stream, with CALLBACK flush function passed
162 OPAQUE token. */
163
164 struct lto_compression_stream *
165 lto_start_compression (void (*callback) (const char *, unsigned, void *),
166 void *opaque)
167 {
168 return lto_new_compression_stream (callback, opaque, true);
169 }
170
171 /* Append NUM_CHARS from address BASE to STREAM. */
172
173 void
174 lto_compress_block (struct lto_compression_stream *stream,
175 const char *base, size_t num_chars)
176 {
177 gcc_assert (stream->is_compression);
178
179 lto_append_to_compression_stream (stream, base, num_chars);
180 lto_stats.num_output_il_bytes += num_chars;
181 }
182
183 /* Finalize STREAM compression, and free stream allocations. */
184
185 void
186 lto_end_compression (struct lto_compression_stream *stream)
187 {
188 unsigned char *cursor = (unsigned char *) stream->buffer;
189 size_t remaining = stream->bytes;
190 const size_t outbuf_length = Z_BUFFER_LENGTH;
191 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
192 z_stream out_stream;
193 size_t compressed_bytes = 0;
194 int status;
195
196 gcc_assert (stream->is_compression);
197
198 out_stream.next_out = outbuf;
199 out_stream.avail_out = outbuf_length;
200 out_stream.next_in = cursor;
201 out_stream.avail_in = remaining;
202 out_stream.zalloc = lto_zalloc;
203 out_stream.zfree = lto_zfree;
204 out_stream.opaque = Z_NULL;
205
206 status = deflateInit (&out_stream, lto_normalized_zlib_level ());
207 if (status != Z_OK)
208 internal_error ("compressed stream: %s", zError (status));
209
210 do
211 {
212 size_t in_bytes, out_bytes;
213
214 status = deflate (&out_stream, Z_FINISH);
215 if (status != Z_OK && status != Z_STREAM_END)
216 internal_error ("compressed stream: %s", zError (status));
217
218 in_bytes = remaining - out_stream.avail_in;
219 out_bytes = outbuf_length - out_stream.avail_out;
220
221 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
222 lto_stats.num_compressed_il_bytes += out_bytes;
223 compressed_bytes += out_bytes;
224
225 cursor += in_bytes;
226 remaining -= in_bytes;
227
228 out_stream.next_out = outbuf;
229 out_stream.avail_out = outbuf_length;
230 out_stream.next_in = cursor;
231 out_stream.avail_in = remaining;
232 }
233 while (status != Z_STREAM_END);
234
235 status = deflateEnd (&out_stream);
236 if (status != Z_OK)
237 internal_error ("compressed stream: %s", zError (status));
238
239 lto_destroy_compression_stream (stream);
240 free (outbuf);
241 }
242
243 /* Return a new uncompression stream, with CALLBACK flush function passed
244 OPAQUE token. */
245
246 struct lto_compression_stream *
247 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
248 void *opaque)
249 {
250 return lto_new_compression_stream (callback, opaque, false);
251 }
252
253 /* Append NUM_CHARS from address BASE to STREAM. */
254
255 void
256 lto_uncompress_block (struct lto_compression_stream *stream,
257 const char *base, size_t num_chars)
258 {
259 gcc_assert (!stream->is_compression);
260
261 lto_append_to_compression_stream (stream, base, num_chars);
262 lto_stats.num_input_il_bytes += num_chars;
263 }
264
265 /* Finalize STREAM uncompression, and free stream allocations.
266
267 Because of the way LTO IL streams are compressed, there may be several
268 concatenated compressed segments in the accumulated data, so for this
269 function we iterate decompressions until no data remains. */
270
271 void
272 lto_end_uncompression (struct lto_compression_stream *stream)
273 {
274 unsigned char *cursor = (unsigned char *) stream->buffer;
275 size_t remaining = stream->bytes;
276 const size_t outbuf_length = Z_BUFFER_LENGTH;
277 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
278 size_t uncompressed_bytes = 0;
279
280 gcc_assert (!stream->is_compression);
281
282 while (remaining > 0)
283 {
284 z_stream in_stream;
285 size_t out_bytes;
286 int status;
287
288 in_stream.next_out = outbuf;
289 in_stream.avail_out = outbuf_length;
290 in_stream.next_in = cursor;
291 in_stream.avail_in = remaining;
292 in_stream.zalloc = lto_zalloc;
293 in_stream.zfree = lto_zfree;
294 in_stream.opaque = Z_NULL;
295
296 status = inflateInit (&in_stream);
297 if (status != Z_OK)
298 internal_error ("compressed stream: %s", zError (status));
299
300 do
301 {
302 size_t in_bytes;
303
304 status = inflate (&in_stream, Z_SYNC_FLUSH);
305 if (status != Z_OK && status != Z_STREAM_END)
306 internal_error ("compressed stream: %s", zError (status));
307
308 in_bytes = remaining - in_stream.avail_in;
309 out_bytes = outbuf_length - in_stream.avail_out;
310
311 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
312 lto_stats.num_uncompressed_il_bytes += out_bytes;
313 uncompressed_bytes += out_bytes;
314
315 cursor += in_bytes;
316 remaining -= in_bytes;
317
318 in_stream.next_out = outbuf;
319 in_stream.avail_out = outbuf_length;
320 in_stream.next_in = cursor;
321 in_stream.avail_in = remaining;
322 }
323 while (!(status == Z_STREAM_END && out_bytes == 0));
324
325 status = inflateEnd (&in_stream);
326 if (status != Z_OK)
327 internal_error ("compressed stream: %s", zError (status));
328 }
329
330 lto_destroy_compression_stream (stream);
331 free (outbuf);
332 }