annotate gcc/d/dmd/optimize.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 /* Compiler implementation of the D programming language
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 * written by Walter Bright
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 * http://www.digitalmars.com
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 * Distributed under the Boost Software License, Version 1.0
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 * http://www.boost.org/LICENSE_1_0.txt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/optimize.c
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11 #include "root/dsystem.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 #include "root/checkedint.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 #include "lexer.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 #include "mtype.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 #include "expression.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 #include "declaration.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 #include "aggregate.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 #include "init.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20 #include "enum.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 #include "ctfe.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 Expression *semantic(Expression *e, Scope *sc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 /*************************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 * If variable has a const initializer,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 * return that initializer.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 Expression *expandVar(int result, VarDeclaration *v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v->toChars() : "null");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 Expression *e = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 if (!v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 return e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 if (!v->originalType && v->semanticRun < PASSsemanticdone) // semantic() not yet run
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 v->semantic(NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 if (!v->type)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 return e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 Type *tb = v->type->toBasetype();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 if (v->storage_class & STCmanifest ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 v->type->toBasetype()->isscalar() ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 ((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 )
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 if (v->_init)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 if (v->inuse)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 if (v->storage_class & STCmanifest)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 v->error("recursive initialization of constant");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 goto Lerror;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 Expression *ei = v->getConstInitializer();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 if (!ei)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 if (v->storage_class & STCmanifest)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 v->error("enum cannot be initialized with %s", v->_init->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 goto Lerror;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 if (ei->op == TOKconstruct || ei->op == TOKblit)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 AssignExp *ae = (AssignExp *)ei;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 ei = ae->e2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 if (ei->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 else if (ei->op == TOKstring)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 // Bugzilla 14459: We should not constfold the string literal
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 // if it's typed as a C string, because the value expansion
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 // will drop the pointer identity.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 if (!(result & WANTexpand) && ei->type->toBasetype()->ty == Tpointer)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 if (ei->type == v->type)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 // const variable initialized with const expression
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 else if (ei->implicitConvTo(v->type) >= MATCHconst)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 // const var initialized with non-const expression
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 ei = ei->implicitCastTo(NULL, v->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 ei = semantic(ei, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 else if (!(v->storage_class & STCmanifest) &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 ei->isConst() != 1 && ei->op != TOKstring &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 ei->op != TOKaddress)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 if (!ei->type)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 // Should remove the copy() operation by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 // making all mods to expressions copy-on-write
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 e = ei->copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 if (e->type != v->type)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 e = e->castTo(NULL, v->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 v->inuse++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 e = e->optimize(result);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 v->inuse--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 L1:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 //if (e) printf("\te = %p, %s, e->type = %d, %s\n", e, e->toChars(), e->type->ty, e->type->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 return e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 Lerror:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 return new ErrorExp();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 Expression *fromConstInitializer(int result, Expression *e1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 //printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 //static int xx; if (xx++ == 10) assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 Expression *e = e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 if (e1->op == TOKvar)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 VarExp *ve = (VarExp *)e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 VarDeclaration *v = ve->var->isVarDeclaration();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 e = expandVar(result, v);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 if (e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 // If it is a comma expression involving a declaration, we mustn't
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 // perform a copy -- we'd get two declarations of the same variable.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 // See bugzilla 4465.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 if (e->op == TOKcomma && ((CommaExp *)e)->e1->op == TOKdeclaration)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 e = e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 if (e->type != e1->type && e1->type && e1->type->ty != Tident)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 // Type 'paint' operation
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 e = e->copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 e->type = e1->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 e->loc = e1->loc;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 e = e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 return e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 class OptimizeVisitor : public Visitor
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 int result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 bool keepLvalue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 Expression *ret;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 OptimizeVisitor(int result, bool keepLvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 : result(result), keepLvalue(keepLvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 void error()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 ret = new ErrorExp();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 bool expOptimize(Expression *&e, int flags, bool keepLvalue = false)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 if (!e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 Expression *ex = e->optimize(flags, keepLvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 if (ex->op == TOKerror)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 ret = ex; // store error result
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 e = ex; // modify original
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214 bool unaOptimize(UnaExp *e, int flags)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 return expOptimize(e->e1, flags);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 bool binOptimize(BinExp *e, int flags)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 expOptimize(e->e1, flags);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 expOptimize(e->e2, flags);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223 return ret->op == TOKerror;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 void visit(Expression *)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 //printf("Expression::optimize(result = x%x) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 void visit(VarExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 if (keepLvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235 VarDeclaration *v = e->var->isVarDeclaration();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 if (v && !(v->storage_class & STCmanifest))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239 ret = fromConstInitializer(result, e);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 void visit(TupleExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 expOptimize(e->e0, WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 for (size_t i = 0; i < e->exps->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 expOptimize((*e->exps)[i], WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 void visit(ArrayLiteralExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 if (e->elements)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 expOptimize(e->basis, result & WANTexpand);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 for (size_t i = 0; i < e->elements->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 expOptimize((*e->elements)[i], result & WANTexpand);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 void visit(AssocArrayLiteralExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 assert(e->keys->dim == e->values->dim);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 for (size_t i = 0; i < e->keys->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 expOptimize((*e->keys)[i], result & WANTexpand);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269 expOptimize((*e->values)[i], result & WANTexpand);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 void visit(StructLiteralExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275 if (e->stageflags & stageOptimize) return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 int old = e->stageflags;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 e->stageflags |= stageOptimize;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 if (e->elements)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 for (size_t i = 0; i < e->elements->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282 expOptimize((*e->elements)[i], result & WANTexpand);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 e->stageflags = old;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 void visit(UnaExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 //printf("UnaExp::optimize() %s\n", e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 if (unaOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 void visit(NegExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 if (unaOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 if (e->e1->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 ret = Neg(e->type, e->e1).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 void visit(ComExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308 if (unaOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 if (e->e1->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 ret = Com(e->type, e->e1).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 void visit(NotExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319 if (unaOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 if (e->e1->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 ret = Not(e->type, e->e1).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 void visit(SymOffExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 assert(e->var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 void visit(AddrExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 //printf("AddrExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 /* Rewrite &(a,b) as (a,&b)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 if (e->e1->op == TOKcomma)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 CommaExp *ce = (CommaExp *)e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 AddrExp *ae = new AddrExp(e->loc, ce->e2, e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 ret = new CommaExp(ce->loc, ce->e1, ae);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 // Keep lvalue-ness
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 if (expOptimize(e->e1, result, true))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 // Convert &*ex to ex
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 if (e->e1->op == TOKstar)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355 Expression *ex = ((PtrExp *)e->e1)->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 if (e->type->equals(ex->type))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 ret = ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 else if (e->type->toBasetype()->equivalent(ex->type->toBasetype()))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 ret = ex->copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365 if (e->e1->op == TOKvar)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367 VarExp *ve = (VarExp *)e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 if (!ve->var->isOut() && !ve->var->isRef() &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369 !ve->var->isImportedSymbol())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371 ret = new SymOffExp(e->loc, ve->var, 0, ve->hasOverloads);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376 if (e->e1->op == TOKindex)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 // Convert &array[n] to &array+n
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379 IndexExp *ae = (IndexExp *)e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381 if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383 sinteger_t index = ae->e2->toInteger();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 VarExp *ve = (VarExp *)ae->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 if (ve->type->ty == Tsarray
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 && !ve->var->isImportedSymbol())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388 TypeSArray *ts = (TypeSArray *)ve->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389 sinteger_t dim = ts->dim->toInteger();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390 if (index < 0 || index >= dim)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392 e->error("array index %lld is out of bounds [0..%lld]", index, dim);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393 return error();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 bool overflow = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397 const d_uns64 offset = mulu(index, ts->nextOf()->size(e->loc), overflow);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 if (overflow)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400 e->error("array offset overflow");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401 return error();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404 ret = new SymOffExp(e->loc, ve->var, offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 void visit(PtrExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 //printf("PtrExp::optimize(result = x%x) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415 if (expOptimize(e->e1, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417 // Convert *&ex to ex
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418 // But only if there is no type punning involved
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419 if (e->e1->op == TOKaddress)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 Expression *ex = ((AddrExp *)e->e1)->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 if (e->type->equals(ex->type))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 ret = ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424 else if (e->type->toBasetype()->equivalent(ex->type->toBasetype()))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426 ret = ex->copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430 if (keepLvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433 // Constant fold *(&structliteral + offset)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434 if (e->e1->op == TOKadd)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436 Expression *ex = Ptr(e->type, e->e1).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 if (!CTFEExp::isCantExp(ex))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439 ret = ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444 if (e->e1->op == TOKsymoff)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446 SymOffExp *se = (SymOffExp *)e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 VarDeclaration *v = se->var->isVarDeclaration();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 Expression *ex = expandVar(result, v);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 if (ex && ex->op == TOKstructliteral)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451 StructLiteralExp *sle = (StructLiteralExp *)ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452 ex = sle->getField(e->type, (unsigned)se->offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453 if (ex && !CTFEExp::isCantExp(ex))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
455 ret = ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
456 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
457 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 void visit(DotVarExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464 //printf("DotVarExp::optimize(result = x%x) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465 if (expOptimize(e->e1, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467 if (keepLvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470 Expression *ex = e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472 if (ex->op == TOKvar)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474 VarExp *ve = (VarExp *)ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475 VarDeclaration *v = ve->var->isVarDeclaration();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476 ex = expandVar(result, v);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 if (ex && ex->op == TOKstructliteral)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481 StructLiteralExp *sle = (StructLiteralExp *)ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 VarDeclaration *vf = e->var->isVarDeclaration();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 if (vf && !vf->overlapped)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485 /* Bugzilla 13021: Prevent optimization if vf has overlapped fields.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487 ex = sle->getField(e->type, vf->offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488 if (ex && !CTFEExp::isCantExp(ex))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 ret = ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 void visit(NewExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499 expOptimize(e->thisexp, WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 // Optimize parameters
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 if (e->newargs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 for (size_t i = 0; i < e->newargs->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506 expOptimize((*e->newargs)[i], WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510 if (e->arguments)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512 for (size_t i = 0; i < e->arguments->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514 expOptimize((*e->arguments)[i], WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519 void visit(CallExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521 //printf("CallExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523 // Optimize parameters with keeping lvalue-ness
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524 if (expOptimize(e->e1, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526 if (e->arguments)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 Type *t1 = e->e1->type->toBasetype();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529 if (t1->ty == Tdelegate) t1 = t1->nextOf();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530 assert(t1->ty == Tfunction);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531 TypeFunction *tf = (TypeFunction *)t1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 for (size_t i = 0; i < e->arguments->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
533 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
534 Parameter *p = Parameter::getNth(tf->parameters, i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
535 bool keep = p && (p->storageClass & (STCref | STCout)) != 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
536 expOptimize((*e->arguments)[i], WANTvalue, keep);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
537 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
538 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
539 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
540
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
541 void visit(CastExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
542 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
543 //printf("CastExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
544 //printf("from %s to %s\n", e->type->toChars(), e->to->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
545 //printf("from %s\n", e->type->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
546 //printf("e1->type %s\n", e->e1->type->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
547 //printf("type = %p\n", e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
548 assert(e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
549 TOK op1 = e->e1->op;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
550
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
551 Expression *e1old = e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
552 if (expOptimize(e->e1, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
553 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
554 e->e1 = fromConstInitializer(result, e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
555
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
556 if (e->e1 == e1old &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
557 e->e1->op == TOKarrayliteral &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
558 e->type->toBasetype()->ty == Tpointer &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
559 e->e1->type->toBasetype()->ty != Tsarray)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
560 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
561 // Casting this will result in the same expression, and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
562 // infinite loop because of Expression::implicitCastTo()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
563 return; // no change
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
564 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
565
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
566 if ((e->e1->op == TOKstring || e->e1->op == TOKarrayliteral) &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
567 (e->type->ty == Tpointer || e->type->ty == Tarray))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
568 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
569 const d_uns64 esz = e->type->nextOf()->size(e->loc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
570 const d_uns64 e1sz = e->e1->type->toBasetype()->nextOf()->size(e->e1->loc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
571 if (esz == SIZE_INVALID || e1sz == SIZE_INVALID)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
572 return error();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
573
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
574 if (e1sz == esz)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
575 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
576 // Bugzilla 12937: If target type is void array, trying to paint
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
577 // e->e1 with that type will cause infinite recursive optimization.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
578 if (e->type->nextOf()->ty == Tvoid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
579 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
580
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
581 ret = e->e1->castTo(NULL, e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
582 //printf(" returning1 %s\n", ret->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
583 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
584 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
585 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
586
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
587 if (e->e1->op == TOKstructliteral &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
588 e->e1->type->implicitConvTo(e->type) >= MATCHconst)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
589 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
590 //printf(" returning2 %s\n", e->e1->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
591 L1: // Returning e1 with changing its type
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
592 ret = (e1old == e->e1 ? e->e1->copy() : e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
593 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
594 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
595 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
596
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
597 /* The first test here is to prevent infinite loops
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
598 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
599 if (op1 != TOKarrayliteral && e->e1->op == TOKarrayliteral)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
600 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
601 ret = e->e1->castTo(NULL, e->to);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
602 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
603 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
604 if (e->e1->op == TOKnull &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
605 (e->type->ty == Tpointer || e->type->ty == Tclass || e->type->ty == Tarray))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
606 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
607 //printf(" returning3 %s\n", e->e1->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
608 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
609 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
610
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
611 if (e->type->ty == Tclass && e->e1->type->ty == Tclass)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
612 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
613 // See if we can remove an unnecessary cast
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
614 ClassDeclaration *cdfrom = e->e1->type->isClassHandle();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
615 ClassDeclaration *cdto = e->type->isClassHandle();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
616 if (cdto == ClassDeclaration::object && !cdfrom->isInterfaceDeclaration())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
617 goto L1; // can always convert a class to Object
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
618 // Need to determine correct offset before optimizing away the cast.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
619 // https://issues.dlang.org/show_bug.cgi?id=16980
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
620 cdfrom->size(e->loc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
621 assert(cdfrom->sizeok == SIZEOKdone);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
622 assert(cdto->sizeok == SIZEOKdone || !cdto->isBaseOf(cdfrom, NULL));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
623 int offset;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
624 if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
625 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
626 //printf(" returning4 %s\n", e->e1->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
627 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
628 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
629 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
630
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
631 // We can convert 'head const' to mutable
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
632 if (e->to->mutableOf()->constOf()->equals(e->e1->type->mutableOf()->constOf()))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
633 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
634 //printf(" returning5 %s\n", e->e1->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
635 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
636 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
637
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
638 if (e->e1->isConst())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
639 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
640 if (e->e1->op == TOKsymoff)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
641 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
642 if (e->type->toBasetype()->ty != Tsarray)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
643 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
644 const d_uns64 esz = e->type->size(e->loc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
645 const d_uns64 e1sz = e->e1->type->size(e->e1->loc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
646 if (esz == SIZE_INVALID ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
647 e1sz == SIZE_INVALID)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
648 return error();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
649
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
650 if (esz == e1sz)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
651 goto L1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
652 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
653 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
654 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
655 if (e->to->toBasetype()->ty != Tvoid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
656 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
657 if (e->e1->type->equals(e->type) && e->type->equals(e->to))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
658 ret = e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
659 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
660 ret = Cast(e->loc, e->type, e->to, e->e1).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
661 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
662 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
663 //printf(" returning6 %s\n", ret->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
664 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
665
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
666 void visit(BinExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
667 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
668 //printf("BinExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
669 // don't replace const variable with its initializer in e1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
670 bool e2only = (e->op == TOKconstruct || e->op == TOKblit);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
671 if (e2only ? expOptimize(e->e2, result) : binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
672 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
673
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
674 if (e->op == TOKshlass || e->op == TOKshrass || e->op == TOKushrass)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
675 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
676 if (e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
677 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
678 sinteger_t i2 = e->e2->toInteger();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
679 d_uns64 sz = e->e1->type->size(e->e1->loc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
680 assert(sz != SIZE_INVALID);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
681 sz *= 8;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
682 if (i2 < 0 || (d_uns64)i2 >= sz)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
683 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
684 e->error("shift assign by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
685 return error();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
686 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
687 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
688 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
689 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
690
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
691 void visit(AddExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
692 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
693 //printf("AddExp::optimize(%s)\n", e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
694
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
695 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
696 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
697
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
698 if (e->e1->isConst() && e->e2->isConst())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
699 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
700 if (e->e1->op == TOKsymoff && e->e2->op == TOKsymoff)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
701 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
702 ret = Add(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
703 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
704 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
705
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
706 void visit(MinExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
707 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
708 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
709 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
710
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
711 if (e->e1->isConst() && e->e2->isConst())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
712 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
713 if (e->e2->op == TOKsymoff)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
714 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
715 ret = Min(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
716 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
717 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
718
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
719 void visit(MulExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
720 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
721 //printf("MulExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
722
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
723 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
724 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
725
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
726 if (e->e1->isConst() == 1 && e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
727 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
728 ret = Mul(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
729 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
730 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
731
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
732 void visit(DivExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
733 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
734 //printf("DivExp::optimize(%s)\n", e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
735
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
736 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
737 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
738
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
739 if (e->e1->isConst() == 1 && e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
740 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
741 ret = Div(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
742 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
743 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
744
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
745 void visit(ModExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
746 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
747 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
748 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
749
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
750 if (e->e1->isConst() == 1 && e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
751 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
752 ret = Mod(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
753 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
754 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
755
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
756 void shift_optimize(BinExp *e, UnionExp (*shift)(Loc, Type *, Expression *, Expression *))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
757 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
758 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
759 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
760
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
761 if (e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
762 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
763 sinteger_t i2 = e->e2->toInteger();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
764 d_uns64 sz = e->e1->type->size();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
765 assert(sz != SIZE_INVALID);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
766 sz *= 8;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
767 if (i2 < 0 || (d_uns64)i2 >= sz)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
768 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
769 e->error("shift by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
770 return error();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
771 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
772 if (e->e1->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
773 ret = (*shift)(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
774 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
775 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
776
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
777 void visit(ShlExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
778 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
779 //printf("ShlExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
780 shift_optimize(e, &Shl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
781 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
782
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
783 void visit(ShrExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
784 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
785 //printf("ShrExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
786 shift_optimize(e, &Shr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
787 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
788
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
789 void visit(UshrExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
790 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
791 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
792 shift_optimize(e, &Ushr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
793 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
794
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
795 void visit(AndExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
796 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
797 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
798 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
799
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
800 if (e->e1->isConst() == 1 && e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
801 ret = And(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
802 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
803
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
804 void visit(OrExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
805 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
806 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
807 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
808
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
809 if (e->e1->isConst() == 1 && e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
810 ret = Or(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
811 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
812
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
813 void visit(XorExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
814 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
815 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
816 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
817
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
818 if (e->e1->isConst() == 1 && e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
819 ret = Xor(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
820 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
821
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
822 void visit(PowExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
823 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
824 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
825 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
826
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
827 // Replace 1 ^^ x or 1.0^^x by (x, 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
828 if ((e->e1->op == TOKint64 && e->e1->toInteger() == 1) ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
829 (e->e1->op == TOKfloat64 && e->e1->toReal() == CTFloat::one))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
830 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
831 ret = new CommaExp(e->loc, e->e2, e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
832 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
833 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
834 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
835
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
836 // Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
837 if (e->e2->type->isintegral() && e->e1->op == TOKint64 && (sinteger_t)e->e1->toInteger() == -1L)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
838 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
839 ret = new AndExp(e->loc, e->e2, new IntegerExp(e->loc, 1, e->e2->type));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
840 ret->type = e->e2->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
841 ret = new CondExp(e->loc, ret, new IntegerExp(e->loc, -1L, e->type), new IntegerExp(e->loc, 1L, e->type));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
842 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
843 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
844 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
845
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
846 // Replace x ^^ 0 or x^^0.0 by (x, 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
847 if ((e->e2->op == TOKint64 && e->e2->toInteger() == 0) ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
848 (e->e2->op == TOKfloat64 && e->e2->toReal() == CTFloat::zero))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
849 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
850 if (e->e1->type->isintegral())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
851 ret = new IntegerExp(e->loc, 1, e->e1->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
852 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
853 ret = new RealExp(e->loc, CTFloat::one, e->e1->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
854
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
855 ret = new CommaExp(e->loc, e->e1, ret);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
856 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
857 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
858 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
859
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
860 // Replace x ^^ 1 or x^^1.0 by (x)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
861 if ((e->e2->op == TOKint64 && e->e2->toInteger() == 1) ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
862 (e->e2->op == TOKfloat64 && e->e2->toReal() == CTFloat::one))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
863 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
864 ret = e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
865 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
866 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
867
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
868 // Replace x ^^ -1.0 by (1.0 / x)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
869 if ((e->e2->op == TOKfloat64 && e->e2->toReal() == CTFloat::minusone))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
870 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
871 ret = new DivExp(e->loc, new RealExp(e->loc, CTFloat::one, e->e2->type), e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
872 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
873 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
874 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
875
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
876 // All other negative integral powers are illegal
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
877 if ((e->e1->type->isintegral()) && (e->e2->op == TOKint64) && (sinteger_t)e->e2->toInteger() < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
878 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
879 e->error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
880 e->e1->type->toBasetype()->toChars(), e->e1->toChars(), e->e2->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
881 return error();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
882 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
883
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
884 // If e2 *could* have been an integer, make it one.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
885 if (e->e2->op == TOKfloat64 && (e->e2->toReal() == ldouble((sinteger_t)e->e2->toReal())))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
886 e->e2 = new IntegerExp(e->loc, e->e2->toInteger(), Type::tint64);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
887
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
888 if (e->e1->isConst() == 1 && e->e2->isConst() == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
889 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
890 Expression *ex = Pow(e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
891 if (!CTFEExp::isCantExp(ex))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
892 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
893 ret = ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
894 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
895 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
896 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
897
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
898 // (2 ^^ n) ^^ p -> 1 << n * p
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
899 if (e->e1->op == TOKint64 && e->e1->toInteger() > 0 &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
900 !((e->e1->toInteger() - 1) & e->e1->toInteger()) &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
901 e->e2->type->isintegral() && e->e2->type->isunsigned())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
902 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
903 dinteger_t i = e->e1->toInteger();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
904 dinteger_t mul = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
905 while ((i >>= 1) > 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
906 mul++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
907 Expression *shift = new MulExp(e->loc, e->e2, new IntegerExp(e->loc, mul, e->e2->type));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
908 shift->type = e->e2->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
909 shift = shift->castTo(NULL, Type::tshiftcnt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
910 ret = new ShlExp(e->loc, new IntegerExp(e->loc, 1, e->e1->type), shift);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
911 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
912 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
913 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
914 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
915
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
916 void visit(CommaExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
917 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
918 //printf("CommaExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
919 // Comma needs special treatment, because it may
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
920 // contain compiler-generated declarations. We can interpret them, but
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
921 // otherwise we must NOT attempt to constant-fold them.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
922 // In particular, if the comma returns a temporary variable, it needs
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
923 // to be an lvalue (this is particularly important for struct constructors)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
924
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
925 expOptimize(e->e1, WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
926 expOptimize(e->e2, result, keepLvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
927 if (ret->op == TOKerror)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
928 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
929
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
930 if (!e->e1 || e->e1->op == TOKint64 || e->e1->op == TOKfloat64 || !hasSideEffect(e->e1))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
931 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
932 ret = e->e2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
933 if (ret)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
934 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
935 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
936
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
937 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
938 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
939
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
940 void visit(ArrayLengthExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
941 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
942 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
943
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
944 if (unaOptimize(e, WANTexpand))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
945 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
946
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
947 // CTFE interpret static immutable arrays (to get better diagnostics)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
948 if (e->e1->op == TOKvar)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
949 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
950 VarDeclaration *v = ((VarExp *)e->e1)->var->isVarDeclaration();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
951 if (v && (v->storage_class & STCstatic) && (v->storage_class & STCimmutable) && v->_init)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
952 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
953 if (Expression *ci = v->getConstInitializer())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
954 e->e1 = ci;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
955 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
956 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
957
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
958 if (e->e1->op == TOKstring || e->e1->op == TOKarrayliteral || e->e1->op == TOKassocarrayliteral ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
959 e->e1->type->toBasetype()->ty == Tsarray)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
960 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
961 ret = ArrayLength(e->type, e->e1).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
962 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
963 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
964
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
965 void visit(EqualExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
966 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
967 //printf("EqualExp::optimize(result = %x) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
968 if (binOptimize(e, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
969 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
970
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
971 Expression *e1 = fromConstInitializer(result, e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
972 Expression *e2 = fromConstInitializer(result, e->e2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
973 if (e1->op == TOKerror)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
974 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
975 ret = e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
976 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
977 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
978 if (e2->op == TOKerror)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
979 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
980 ret = e2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
981 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
982 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
983
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
984 ret = Equal(e->op, e->loc, e->type, e1, e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
985 if (CTFEExp::isCantExp(ret))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
986 ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
987 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
988
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
989 void visit(IdentityExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
990 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
991 //printf("IdentityExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
992
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
993 if (binOptimize(e, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
994 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
995
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
996 if ((e->e1->isConst() && e->e2->isConst()) ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
997 (e->e1->op == TOKnull && e->e2->op == TOKnull)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
998 )
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
999 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1000 ret = Identity(e->op, e->loc, e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1001 if (CTFEExp::isCantExp(ret))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1002 ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1003 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1004 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1005
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1006 /* It is possible for constant folding to change an array expression of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1007 * unknown length, into one where the length is known.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1008 * If the expression 'arr' is a literal, set lengthVar to be its length.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1009 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1010 static void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1011 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1012 if (!lengthVar)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1013 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1014 if (lengthVar->_init && !lengthVar->_init->isVoidInitializer())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1015 return; // we have previously calculated the length
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1016 size_t len;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1017 if (arr->op == TOKstring)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1018 len = ((StringExp *)arr)->len;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1019 else if (arr->op == TOKarrayliteral)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1020 len = ((ArrayLiteralExp *)arr)->elements->dim;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1021 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1022 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1023 Type *t = arr->type->toBasetype();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1024 if (t->ty == Tsarray)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1025 len = (size_t)((TypeSArray *)t)->dim->toInteger();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1026 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1027 return; // we don't know the length yet
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1028 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1029
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1030 Expression *dollar = new IntegerExp(Loc(), len, Type::tsize_t);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1031 lengthVar->_init = new ExpInitializer(Loc(), dollar);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1032 lengthVar->storage_class |= STCstatic | STCconst;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1033 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1034
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1035 void visit(IndexExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1036 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1037 //printf("IndexExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1038 if (expOptimize(e->e1, result & WANTexpand))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1039 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1040
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1041 Expression *ex = fromConstInitializer(result, e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1042
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1043 // We might know $ now
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1044 setLengthVarIfKnown(e->lengthVar, ex);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1045
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1046 if (expOptimize(e->e2, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1047 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1048 if (keepLvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1049 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1050 ret = Index(e->type, ex, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1051 if (CTFEExp::isCantExp(ret))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1052 ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1053 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1054
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1055 void visit(SliceExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1056 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1057 //printf("SliceExp::optimize(result = %d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1058 if (expOptimize(e->e1, result & WANTexpand))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1059 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1060 if (!e->lwr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1061 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1062 if (e->e1->op == TOKstring)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1063 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1064 // Convert slice of string literal into dynamic array
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1065 Type *t = e->e1->type->toBasetype();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1066 if (Type *tn = t->nextOf())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1067 ret = e->e1->castTo(NULL, tn->arrayOf());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1068 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1069 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1070 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1071 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1072 e->e1 = fromConstInitializer(result, e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1073 // We might know $ now
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1074 setLengthVarIfKnown(e->lengthVar, e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1075 expOptimize(e->lwr, WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1076 expOptimize(e->upr, WANTvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1077 if (ret->op == TOKerror)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1078 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1079 ret = Slice(e->type, e->e1, e->lwr, e->upr).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1080 if (CTFEExp::isCantExp(ret))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1081 ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1082 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1083
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1084 // Bugzilla 14649: We need to leave the slice form so it might be
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1085 // a part of array operation.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1086 // Assume that the backend codegen will handle the form `e[]`
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1087 // as an equal to `e` itself.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1088 if (ret->op == TOKstring)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1089 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1090 e->e1 = ret;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1091 e->lwr = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1092 e->upr = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1093 ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1094 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1095 //printf("-SliceExp::optimize() %s\n", ret->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1096 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1097
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1098 void visit(AndAndExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1099 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1100 //printf("AndAndExp::optimize(%d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1101 if (expOptimize(e->e1, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1102 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1103
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1104 if (e->e1->isBool(false))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1105 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1106 // Replace with (e1, false)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1107 ret = new IntegerExp(e->loc, 0, Type::tbool);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1108 ret = Expression::combine(e->e1, ret);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1109 if (e->type->toBasetype()->ty == Tvoid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1110 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1111 ret = new CastExp(e->loc, ret, Type::tvoid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1112 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1113 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1114 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1115 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1116
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1117 if (expOptimize(e->e2, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1118 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1119
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1120 if (e->e1->isConst())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1121 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1122 if (e->e2->isConst())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1123 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1124 bool n1 = e->e1->isBool(true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1125 bool n2 = e->e2->isBool(true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1126 ret = new IntegerExp(e->loc, n1 && n2, e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1127 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1128 else if (e->e1->isBool(true))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1129 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1130 if (e->type->toBasetype()->ty == Tvoid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1131 ret = e->e2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1132 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1133 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1134 ret = new CastExp(e->loc, e->e2, e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1135 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1136 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1137 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1138 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1139 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1140
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1141 void visit(OrOrExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1142 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1143 //printf("OrOrExp::optimize(%d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1144 if (expOptimize(e->e1, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1145 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1146
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1147 if (e->e1->isBool(true))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1148 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1149 // Replace with (e1, true)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1150 ret = new IntegerExp(e->loc, 1, Type::tbool);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1151 ret = Expression::combine(e->e1, ret);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1152 if (e->type->toBasetype()->ty == Tvoid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1153 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1154 ret = new CastExp(e->loc, ret, Type::tvoid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1155 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1156 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1157 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1158 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1159
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1160 if (expOptimize(e->e2, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1161 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1162
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1163 if (e->e1->isConst())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1164 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1165 if (e->e2->isConst())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1166 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1167 bool n1 = e->e1->isBool(true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1168 bool n2 = e->e2->isBool(true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1169 ret = new IntegerExp(e->loc, n1 || n2, e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1170 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1171 else if (e->e1->isBool(false))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1172 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1173 if (e->type->toBasetype()->ty == Tvoid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1174 ret = e->e2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1175 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1176 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1177 ret = new CastExp(e->loc, e->e2, e->type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1178 ret->type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1179 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1180 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1181 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1182 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1183
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1184 void visit(CmpExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1185 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1186 //printf("CmpExp::optimize() %s\n", e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1187 if (binOptimize(e, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1188 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1189
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1190 Expression *e1 = fromConstInitializer(result, e->e1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1191 Expression *e2 = fromConstInitializer(result, e->e2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1192
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1193 ret = Cmp(e->op, e->loc, e->type, e1, e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1194 if (CTFEExp::isCantExp(ret))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1195 ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1196 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1197
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1198 void visit(CatExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1199 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1200 //printf("CatExp::optimize(%d) %s\n", result, e->toChars());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1201
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1202 if (binOptimize(e, result))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1203 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1204
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1205 if (e->e1->op == TOKcat)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1206 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1207 // Bugzilla 12798: optimize ((expr ~ str1) ~ str2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1208 CatExp *ce1 = (CatExp *)e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1209 CatExp cex(e->loc, ce1->e2, e->e2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1210 cex.type = e->type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1211 Expression *ex = cex.optimize(result);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1212 if (ex != &cex)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1213 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1214 e->e1 = ce1->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1215 e->e2 = ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1216 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1217 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1218
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1219 // optimize "str"[] -> "str"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1220 if (e->e1->op == TOKslice)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1221 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1222 SliceExp *se1 = (SliceExp *)e->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1223 if (se1->e1->op == TOKstring && !se1->lwr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1224 e->e1 = se1->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1225 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1226 if (e->e2->op == TOKslice)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1227 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1228 SliceExp *se2 = (SliceExp *)e->e2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1229 if (se2->e1->op == TOKstring && !se2->lwr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1230 e->e2 = se2->e1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1231 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1232
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1233 ret = Cat(e->type, e->e1, e->e2).copy();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1234 if (CTFEExp::isCantExp(ret))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1235 ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1236 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1237
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1238 void visit(CondExp *e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1239 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1240 if (expOptimize(e->econd, WANTvalue))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1241 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1242 if (e->econd->isBool(true))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1243 ret = e->e1->optimize(result, keepLvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1244 else if (e->econd->isBool(false))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1245 ret = e->e2->optimize(result, keepLvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1246 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1247 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1248 expOptimize(e->e1, result, keepLvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1249 expOptimize(e->e2, result, keepLvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1250 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1251 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1252 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1253
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1254 OptimizeVisitor v(result, keepLvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1255 Expression *ex = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1256 v.ret = e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1257
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1258 // Optimize the expression until it can no longer be simplified.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1259 while (ex != v.ret)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1260 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1261 ex = v.ret;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1262 ex->accept(&v);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1263 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1264 return ex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1265 }