B3 should be able to compile a program with ChillDiv
[WebKit-https.git] / Source / JavaScriptCore / b3 / B3Value.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "B3Value.h"
28
29 #if ENABLE(B3_JIT)
30
31 #include "B3ArgumentRegValue.h"
32 #include "B3CCallValue.h"
33 #include "B3ControlValue.h"
34 #include "B3MemoryValue.h"
35 #include "B3ProcedureInlines.h"
36 #include "B3StackSlotValue.h"
37 #include "B3UpsilonValue.h"
38 #include "B3ValueInlines.h"
39 #include "B3ValueKeyInlines.h"
40 #include <wtf/CommaPrinter.h>
41 #include <wtf/StringPrintStream.h>
42
43 namespace JSC { namespace B3 {
44
45 const char* const Value::dumpPrefix = "@";
46
47 Value::~Value()
48 {
49 }
50
51 void Value::replaceWithIdentity(Value* value)
52 {
53     // This is a bit crazy. It does an in-place replacement of whatever Value subclass this is with
54     // a plain Identity Value. We first collect all of the information we need, then we destruct the
55     // previous value in place, and then we construct the Identity Value in place.
56
57     unsigned index = m_index;
58     Type type = m_type;
59     Origin origin = m_origin;
60     BasicBlock* owner = this->owner;
61
62     RELEASE_ASSERT(type == value->type());
63
64     this->Value::~Value();
65
66     new (this) Value(index, Identity, type, origin, value);
67
68     this->owner = owner;
69 }
70
71 void Value::replaceWithNop()
72 {
73     unsigned index = m_index;
74     Origin origin = m_origin;
75     BasicBlock* owner = this->owner;
76
77     this->Value::~Value();
78
79     new (this) Value(index, Nop, Void, origin);
80
81     this->owner = owner;
82 }
83
84 void Value::dump(PrintStream& out) const
85 {
86     out.print(dumpPrefix, m_index);
87 }
88
89 void Value::dumpChildren(CommaPrinter& comma, PrintStream& out) const
90 {
91     for (Value* child : children())
92         out.print(comma, pointerDump(child));
93 }
94
95 void Value::deepDump(PrintStream& out) const
96 {
97     out.print(m_type, " ", *this, " = ", m_opcode);
98
99     out.print("(");
100     CommaPrinter comma;
101     dumpChildren(comma, out);
102
103     if (m_origin)
104         out.print(comma, m_origin);
105
106     dumpMeta(comma, out);
107
108     {
109         CString string = toCString(effects());
110         if (string.length())
111             out.print(comma, string);
112     }
113
114     out.print(")");
115 }
116
117 Value* Value::negConstant(Procedure&) const
118 {
119     return nullptr;
120 }
121
122 Value* Value::addConstant(Procedure&, int32_t) const
123 {
124     return nullptr;
125 }
126
127 Value* Value::addConstant(Procedure&, const Value*) const
128 {
129     return nullptr;
130 }
131
132 Value* Value::subConstant(Procedure&, const Value*) const
133 {
134     return nullptr;
135 }
136
137 Value* Value::divConstant(Procedure&, const Value*) const
138 {
139     return nullptr;
140 }
141
142 Value* Value::bitAndConstant(Procedure&, const Value*) const
143 {
144     return nullptr;
145 }
146
147 Value* Value::bitOrConstant(Procedure&, const Value*) const
148 {
149     return nullptr;
150 }
151
152 Value* Value::bitXorConstant(Procedure&, const Value*) const
153 {
154     return nullptr;
155 }
156
157 Value* Value::shlConstant(Procedure&, const Value*) const
158 {
159     return nullptr;
160 }
161
162 Value* Value::sShrConstant(Procedure&, const Value*) const
163 {
164     return nullptr;
165 }
166
167 Value* Value::zShrConstant(Procedure&, const Value*) const
168 {
169     return nullptr;
170 }
171
172 TriState Value::equalConstant(const Value*) const
173 {
174     return MixedTriState;
175 }
176
177 TriState Value::notEqualConstant(const Value*) const
178 {
179     return MixedTriState;
180 }
181
182 TriState Value::lessThanConstant(const Value*) const
183 {
184     return MixedTriState;
185 }
186
187 TriState Value::greaterThanConstant(const Value*) const
188 {
189     return MixedTriState;
190 }
191
192 TriState Value::lessEqualConstant(const Value*) const
193 {
194     return MixedTriState;
195 }
196
197 TriState Value::greaterEqualConstant(const Value*) const
198 {
199     return MixedTriState;
200 }
201
202 TriState Value::aboveConstant(const Value*) const
203 {
204     return MixedTriState;
205 }
206
207 TriState Value::belowConstant(const Value*) const
208 {
209     return MixedTriState;
210 }
211
212 TriState Value::aboveEqualConstant(const Value*) const
213 {
214     return MixedTriState;
215 }
216
217 TriState Value::belowEqualConstant(const Value*) const
218 {
219     return MixedTriState;
220 }
221
222 Value* Value::invertedCompare(Procedure& proc) const
223 {
224     if (!numChildren())
225         return nullptr;
226     if (Optional<Opcode> invertedOpcode = B3::invertedCompare(opcode(), child(0)->type()))
227         return proc.add<Value>(*invertedOpcode, type(), origin(), children());
228     return nullptr;
229 }
230
231 bool Value::returnsBool() const
232 {
233     if (type() != Int32)
234         return false;
235     switch (opcode()) {
236     case Const32:
237         return asInt32() == 0 || asInt32() == 1;
238     case BitAnd:
239         return child(1)->isInt32(1);
240     case Equal:
241     case NotEqual:
242     case LessThan:
243     case GreaterThan:
244     case LessEqual:
245     case GreaterEqual:
246     case Above:
247     case Below:
248     case AboveEqual:
249     case BelowEqual:
250         return true;
251     case Phi:
252         // FIXME: We should have a story here.
253         // https://bugs.webkit.org/show_bug.cgi?id=150725
254         return false;
255     default:
256         return false;
257     }
258 }
259
260 TriState Value::asTriState() const
261 {
262     switch (opcode()) {
263     case Const32:
264         return triState(!!asInt32());
265     case Const64:
266         return triState(!!asInt64());
267     case ConstDouble:
268         // Use "!= 0" to really emphasize what this mean with respect to NaN and such.
269         return triState(asDouble() != 0);
270     default:
271         return MixedTriState;
272     }
273 }
274
275 Effects Value::effects() const
276 {
277     Effects result;
278     switch (opcode()) {
279     case Nop:
280     case Identity:
281     case Const32:
282     case Const64:
283     case ConstDouble:
284     case StackSlot:
285     case ArgumentReg:
286     case FramePointer:
287     case Add:
288     case Sub:
289     case Mul:
290     case ChillDiv:
291     case Mod:
292     case BitAnd:
293     case BitOr:
294     case BitXor:
295     case Shl:
296     case SShr:
297     case ZShr:
298     case SExt8:
299     case SExt16:
300     case SExt32:
301     case ZExt32:
302     case Trunc:
303     case FRound:
304     case IToD:
305     case DToI32:
306     case Equal:
307     case NotEqual:
308     case LessThan:
309     case GreaterThan:
310     case LessEqual:
311     case GreaterEqual:
312     case Above:
313     case Below:
314     case AboveEqual:
315     case BelowEqual:
316         break;
317     case Div:
318         result.controlDependent = true;
319         break;
320     case Load8Z:
321     case Load8S:
322     case Load16Z:
323     case Load16S:
324     case LoadFloat:
325     case Load:
326         result.reads = as<MemoryValue>()->range();
327         result.controlDependent = true;
328         break;
329     case Store8:
330     case Store16:
331     case StoreFloat:
332     case Store:
333         result.writes = as<MemoryValue>()->range();
334         result.controlDependent = true;
335         break;
336     case CCall:
337         result = as<CCallValue>()->effects;
338         break;
339     case Patchpoint:
340         result = as<PatchpointValue>()->effects;
341         break;
342     case CheckAdd:
343     case CheckSub:
344     case CheckMul:
345     case Check:
346         result.exitsSideways = true;
347         break;
348     case Upsilon:
349         result.writesSSAState = true;
350         break;
351     case Phi:
352         result.readsSSAState = true;
353         break;
354     case Jump:
355     case Branch:
356     case Switch:
357     case Return:
358     case Oops:
359         result.terminal = true;
360         break;
361     }
362     return result;
363 }
364
365 ValueKey Value::key() const
366 {
367     switch (opcode()) {
368     case FramePointer:
369         return ValueKey(opcode(), type());
370     case Identity:
371     case SExt8:
372     case SExt16:
373     case SExt32:
374     case ZExt32:
375     case Trunc:
376     case FRound:
377     case IToD:
378     case DToI32:
379     case Check:
380         return ValueKey(opcode(), type(), child(0));
381     case Add:
382     case Sub:
383     case Mul:
384     case ChillDiv:
385     case Mod:
386     case BitAnd:
387     case BitOr:
388     case BitXor:
389     case Shl:
390     case SShr:
391     case ZShr:
392     case Equal:
393     case NotEqual:
394     case LessThan:
395     case GreaterThan:
396     case Above:
397     case Below:
398     case AboveEqual:
399     case BelowEqual:
400     case Div:
401     case CheckAdd:
402     case CheckSub:
403     case CheckMul:
404         return ValueKey(opcode(), type(), child(0), child(1));
405     case Const32:
406         return ValueKey(Const32, type(), static_cast<int64_t>(asInt32()));
407     case Const64:
408         return ValueKey(Const64, type(), asInt64());
409     case ConstDouble:
410         return ValueKey(ConstDouble, type(), asDouble());
411     case ArgumentReg:
412         return ValueKey(
413             ArgumentReg, type(),
414             static_cast<int64_t>(as<ArgumentRegValue>()->argumentReg().index()));
415     default:
416         return ValueKey();
417     }
418 }
419
420 void Value::performSubstitution()
421 {
422     for (Value*& child : children()) {
423         while (child->opcode() == Identity)
424             child = child->child(0);
425     }
426 }
427
428 void Value::dumpMeta(CommaPrinter&, PrintStream&) const
429 {
430 }
431
432 #if !ASSERT_DISABLED
433 void Value::checkOpcode(Opcode opcode)
434 {
435     ASSERT(!ArgumentRegValue::accepts(opcode));
436     ASSERT(!CCallValue::accepts(opcode));
437     ASSERT(!CheckValue::accepts(opcode));
438     ASSERT(!Const32Value::accepts(opcode));
439     ASSERT(!Const64Value::accepts(opcode));
440     ASSERT(!ConstDoubleValue::accepts(opcode));
441     ASSERT(!ControlValue::accepts(opcode));
442     ASSERT(!MemoryValue::accepts(opcode));
443     ASSERT(!PatchpointValue::accepts(opcode));
444     ASSERT(!StackSlotValue::accepts(opcode));
445     ASSERT(!UpsilonValue::accepts(opcode));
446 }
447 #endif // !ASSERT_DISABLED
448
449 Type Value::typeFor(Opcode opcode, Value* firstChild)
450 {
451     switch (opcode) {
452     case Identity:
453     case Add:
454     case Sub:
455     case Mul:
456     case Div:
457     case ChillDiv:
458     case Mod:
459     case BitAnd:
460     case BitOr:
461     case BitXor:
462     case Shl:
463     case SShr:
464     case ZShr:
465     case CheckAdd:
466     case CheckSub:
467     case CheckMul:
468         return firstChild->type();
469     case FramePointer:
470         return pointerType();
471     case SExt8:
472     case SExt16:
473     case Trunc:
474     case DToI32:
475     case Equal:
476     case NotEqual:
477     case LessThan:
478     case GreaterThan:
479     case LessEqual:
480     case GreaterEqual:
481     case Above:
482     case Below:
483     case AboveEqual:
484     case BelowEqual:
485         return Int32;
486     case SExt32:
487     case ZExt32:
488         return Int64;
489     case FRound:
490     case IToD:
491         return Double;
492     case Nop:
493         return Void;
494     default:
495         RELEASE_ASSERT_NOT_REACHED();
496     }
497 }
498
499 } } // namespace JSC::B3
500
501 #endif // ENABLE(B3_JIT)