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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
From 0de967c51189535f8d00943ccc91a3ad07e50ef2 Mon Sep 17 00:00:00 2001
From: wangchunyang <wangchunyang15@huawei.com>
Date: Wed, 11 Sep 2024 17:27:19 +0800
Subject: [PATCH 4/5] add flag -flto-try enable LTO and automatically skip in
inapplicable situation.
---
gcc/collect2.cc | 51 ++++++++++++++++++++++++++++++++++++++++++-
gcc/common.opt | 8 +++++++
gcc/opts-common.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++-
gcc/opts.cc | 20 +++++++++++++++++
4 files changed, 131 insertions(+), 2 deletions(-)
diff --git a/gcc/collect2.cc b/gcc/collect2.cc
index 9715e8eee..690363880 100644
--- a/gcc/collect2.cc
+++ b/gcc/collect2.cc
@@ -200,6 +200,7 @@ static enum lto_mode_d lto_mode = LTO_MODE_WHOPR;
#else
static enum lto_mode_d lto_mode = LTO_MODE_NONE;
#endif
+static bool maybe_relink_without_lto = false;
bool helpflag; /* true if --help */
@@ -751,7 +752,53 @@ do_link (char **ld_argv, const char *atsuffix)
PEX_LAST | PEX_SEARCH,
HAVE_GNU_LD && at_file_supplied, atsuffix);
int ret = collect_wait (prog, pex);
- if (ret)
+ if (ret && maybe_relink_without_lto)
+ {
+ bool link_with_lto_plugin_before = false;
+ for (int i = 0, j = -1; ld_argv[i]; ++i)
+ {
+ if (endswith (ld_argv[i], "liblto_plugin.so"))
+ {
+ link_with_lto_plugin_before = true;
+ for (j = i + 1; ld_argv[j]; ++j)
+ {
+ if (!startswith (ld_argv[j], "-plugin-opt="))
+ break;
+ }
+ for (i = i - 1; ; ++i, ++j)
+ {
+ ld_argv[i] = ld_argv[j];
+ if (ld_argv[j] == NULL)
+ break;
+ }
+ break;
+ }
+ }
+ int ret2 = 0;
+ if (link_with_lto_plugin_before)
+ {
+ fprintf (stderr, "lto link fail, relinking without lto");
+ lto_mode = LTO_MODE_NONE;
+ pex = collect_execute (prog, ld_argv, NULL, NULL,
+ PEX_LAST | PEX_SEARCH,
+ HAVE_GNU_LD && at_file_supplied, atsuffix);
+ ret2 = collect_wait (prog, pex);
+ }
+ else
+ ret2 = ret;
+ if (ret2)
+ {
+ error ("ld returned %d exit status", ret);
+ exit (ret);
+ }
+ else
+ {
+ /* We have just successfully produced an output file, so assume that
+ we may unlink it if need be for now on. */
+ may_unlink_output_file = true;
+ }
+ }
+ else if (ret)
{
error ("ld returned %d exit status", ret);
exit (ret);
@@ -1009,6 +1056,8 @@ main (int argc, char **argv)
num_c_args++;
if (startswith (q, "-flto-partition=none"))
no_partition = true;
+ else if (startswith (q, "-flto-try"))
+ maybe_relink_without_lto = true;
else if (startswith (q, "-fno-lto"))
lto_mode = LTO_MODE_NONE;
else if (startswith (q, "-save-temps"))
diff --git a/gcc/common.opt b/gcc/common.opt
index 96888cf1b..0895c6114 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -70,6 +70,10 @@ bool flag_warn_unused_result = false
Variable
int flag_generate_lto
+; Nonzero if we should write GIMPLE bytecode for link-time optimization.
+Variable
+int flag_relink_whthout_lto = 0
+
; Nonzero if we should write GIMPLE bytecode for offload compilation.
Variable
int flag_generate_offload = 0
@@ -2161,6 +2165,10 @@ flto
Common
Enable link-time optimization.
+flto-try
+Common Var(flag_lto_try) Init(0)
+Do link-time optimization as much as possible.
+
flto=
Common RejectNegative Joined Var(flag_lto)
Link-time optimization with number of parallel jobs or jobserver.
diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
index 33c696f3d..176041bfe 100644
--- a/gcc/opts-common.cc
+++ b/gcc/opts-common.cc
@@ -1162,7 +1162,50 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv,
struct cl_decoded_option *opt_array;
unsigned int num_decoded_options;
- int opt_array_len = argc;
+ enum LTO_SKIP_STAT
+ {
+ NO_NEED_TO_SKIP,
+ NEED_TO_SKIP,
+ ALREADY_SKIP,
+ };
+ LTO_SKIP_STAT lto_skip_stat = NO_NEED_TO_SKIP;
+ bool try_use_lto = false;
+ const char* lto_option_conflict = NULL;
+ const char* wrap_option = "-Wl,--wrap=";
+ const char* start_lib_option = "-Wl,--start-lib";
+ for (i = 1; i < argc; i += 1)
+ {
+ if (startswith (argv[i], "-flto-try"))
+ {
+ try_use_lto = true;
+ }
+
+ if (startswith (argv[i], wrap_option)
+ && (lto_skip_stat == NO_NEED_TO_SKIP))
+ {
+ lto_option_conflict = wrap_option;
+ lto_skip_stat = NEED_TO_SKIP;
+ }
+ else if (startswith (argv[i], start_lib_option)
+ && (lto_skip_stat == NO_NEED_TO_SKIP))
+ {
+ lto_option_conflict = start_lib_option;
+ lto_skip_stat = NEED_TO_SKIP;
+ }
+ else if (startswith (argv[i], "-fno-lto"))
+ {
+ lto_option_conflict = NULL;
+ lto_skip_stat = ALREADY_SKIP;
+ break;
+ }
+ }
+ if (!try_use_lto)
+ {
+ lto_skip_stat = NO_NEED_TO_SKIP;
+ lto_option_conflict = NULL;
+ }
+
+ int opt_array_len = lto_skip_stat == NEED_TO_SKIP ? argc + 1 : argc;
opt_array = XNEWVEC (struct cl_decoded_option, opt_array_len);
opt_array[0].opt_index = OPT_SPECIAL_program_name;
@@ -1244,6 +1287,15 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv,
num_decoded_options += handle_machine_option (lang_mask, num_decoded_options,
argc, argv, opt_array);
+ if (lto_skip_stat == NEED_TO_SKIP)
+ {
+ const char * nolto = "-fno-lto";
+ fprintf (stderr, "skip lto for %s\n", lto_option_conflict);
+ decode_cmdline_option (&nolto, lang_mask,
+ &opt_array[num_decoded_options]);
+ num_decoded_options++;
+ }
+
*decoded_options = opt_array;
*decoded_options_count = num_decoded_options;
prune_options (decoded_options, decoded_options_count, lang_mask);
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 84dd8925a..9ccc22510 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -1143,6 +1143,26 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
SET_OPTION_IF_UNSET (opts, opts_set, param_stack_frame_growth, 40);
}
+ if (opts->x_flag_lto_try)
+ {
+#ifdef ENABLE_LTO
+ if (opts_set->x_flag_lto && opts->x_flag_lto)
+ {
+ inform (loc, "%<-flto-try%> don't guarantee that lto "
+ "will be enabled.");
+ }
+ opts->x_flag_lto = "";
+ if (opts_set->x_flag_fat_lto_objects && !opts->x_flag_fat_lto_objects)
+ {
+ error_at (loc, "%<-flto-try%> are not supported with "
+ "-fno-fat-lto-objects");
+ }
+ opts->x_flag_fat_lto_objects = 1;
+#else
+ error_at (loc, "LTO support has not been enabled in this configuration");
+#endif
+ }
+
if (opts->x_flag_lto)
{
#ifdef ENABLE_LTO
--
2.33.0
|