1/*
2 * Copyright (C) 2019 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 "AirCode.h"
27#include "AirInstInlines.h"
28#include "AirValidate.h"
29#include "AllowMacroScratchRegisterUsage.h"
30#include "B3ArgumentRegValue.h"
31#include "B3AtomicValue.h"
32#include "B3BasicBlockInlines.h"
33#include "B3BreakCriticalEdges.h"
34#include "B3CCallValue.h"
35#include "B3Compilation.h"
36#include "B3Compile.h"
37#include "B3ComputeDivisionMagic.h"
38#include "B3Const32Value.h"
39#include "B3Const64Value.h"
40#include "B3ConstPtrValue.h"
41#include "B3Effects.h"
42#include "B3FenceValue.h"
43#include "B3FixSSA.h"
44#include "B3Generate.h"
45#include "B3LowerToAir.h"
46#include "B3MathExtras.h"
47#include "B3MemoryValue.h"
48#include "B3MoveConstants.h"
49#include "B3NativeTraits.h"
50#include "B3Procedure.h"
51#include "B3ReduceLoopStrength.h"
52#include "B3ReduceStrength.h"
53#include "B3SlotBaseValue.h"
54#include "B3StackSlot.h"
55#include "B3StackmapGenerationParams.h"
56#include "B3SwitchValue.h"
57#include "B3UpsilonValue.h"
58#include "B3UseCounts.h"
59#include "B3Validate.h"
60#include "B3ValueInlines.h"
61#include "B3VariableValue.h"
62#include "B3WasmAddressValue.h"
63#include "B3WasmBoundsCheckValue.h"
64#include "CCallHelpers.h"
65#include "FPRInfo.h"
66#include "GPRInfo.h"
67#include "InitializeThreading.h"
68#include "JSCInlines.h"
69#include "LinkBuffer.h"
70#include "PureNaN.h"
71#include <cmath>
72#include <string>
73#include <wtf/FastTLS.h>
74#include <wtf/IndexSet.h>
75#include <wtf/ListDump.h>
76#include <wtf/Lock.h>
77#include <wtf/NumberOfCores.h>
78#include <wtf/StdList.h>
79#include <wtf/Threading.h>
80#include <wtf/text/StringCommon.h>
81
82// We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous.
83inline bool hiddenTruthBecauseNoReturnIsStupid() { return true; }
84
85inline void usage()
86{
87 dataLog("Usage: testb3 [<filter>]\n");
88 if (hiddenTruthBecauseNoReturnIsStupid())
89 exit(1);
90}
91
92#if ENABLE(B3_JIT)
93
94using namespace JSC;
95using namespace JSC::B3;
96
97inline bool shouldBeVerbose()
98{
99 return shouldDumpIR(B3Mode);
100}
101
102extern Lock crashLock;
103
104// Nothing fancy for now; we just use the existing WTF assertion machinery.
105#define CHECK(x) do { \
106 if (!!(x)) \
107 break; \
108 crashLock.lock(); \
109 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #x); \
110 CRASH(); \
111} while (false)
112
113#define CHECK_EQ(x, y) do { \
114 auto __x = (x); \
115 auto __y = (y); \
116 if (__x == __y) \
117 break; \
118 crashLock.lock(); \
119 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(#x " == " #y, " (" #x " == ", __x, ", " #y " == ", __y, ")").data()); \
120 CRASH(); \
121} while (false)
122
123#define PREFIX "O", Options::defaultB3OptLevel(), ": "
124
125#define RUN(test) do { \
126 if (!shouldRun(filter, #test)) \
127 break; \
128 tasks.append( \
129 createSharedTask<void()>( \
130 [&] () { \
131 dataLog(PREFIX #test "...\n"); \
132 test; \
133 dataLog(PREFIX #test ": OK!\n"); \
134 })); \
135 } while (false);
136
137#define RUN_UNARY(test, values) \
138 for (auto a : values) { \
139 CString testStr = toCString(PREFIX #test, "(", a.name, ")"); \
140 if (!shouldRun(filter, testStr.data())) \
141 continue; \
142 tasks.append(createSharedTask<void()>( \
143 [=] () { \
144 dataLog(toCString(testStr, "...\n")); \
145 test(a.value); \
146 dataLog(toCString(testStr, ": OK!\n")); \
147 })); \
148 }
149
150#define RUN_NOW(test) do { \
151 if (!shouldRun(filter, #test)) \
152 break; \
153 dataLog(PREFIX #test "...\n"); \
154 test; \
155 dataLog(PREFIX #test ": OK!\n"); \
156 } while (false)
157
158#define RUN_BINARY(test, valuesA, valuesB) \
159 for (auto a : valuesA) { \
160 for (auto b : valuesB) { \
161 CString testStr = toCString(PREFIX #test, "(", a.name, ", ", b.name, ")"); \
162 if (!shouldRun(filter, testStr.data())) \
163 continue; \
164 tasks.append(createSharedTask<void()>( \
165 [=] () { \
166 dataLog(toCString(testStr, "...\n")); \
167 test(a.value, b.value); \
168 dataLog(toCString(testStr, ": OK!\n")); \
169 })); \
170 } \
171 }
172#define RUN_TERNARY(test, valuesA, valuesB, valuesC) \
173 for (auto a : valuesA) { \
174 for (auto b : valuesB) { \
175 for (auto c : valuesC) { \
176 CString testStr = toCString(#test, "(", a.name, ", ", b.name, ",", c.name, ")"); \
177 if (!shouldRun(filter, testStr.data())) \
178 continue; \
179 tasks.append(createSharedTask<void()>( \
180 [=] () { \
181 dataLog(toCString(testStr, "...\n")); \
182 test(a.value, b.value, c.value); \
183 dataLog(toCString(testStr, ": OK!\n")); \
184 })); \
185 } \
186 } \
187 }
188
189
190inline std::unique_ptr<Compilation> compileProc(Procedure& procedure, unsigned optLevel = Options::defaultB3OptLevel())
191{
192 procedure.setOptLevel(optLevel);
193 return makeUnique<Compilation>(B3::compile(procedure));
194}
195
196template<typename T, typename... Arguments>
197T invoke(MacroAssemblerCodePtr<B3CompilationPtrTag> ptr, Arguments... arguments)
198{
199 void* executableAddress = untagCFunctionPtr<B3CompilationPtrTag>(ptr.executableAddress());
200 T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(executableAddress);
201 return function(arguments...);
202}
203
204template<typename T, typename... Arguments>
205T invoke(const Compilation& code, Arguments... arguments)
206{
207 return invoke<T>(code.code(), arguments...);
208}
209
210template<typename T, typename... Arguments>
211T compileAndRun(Procedure& procedure, Arguments... arguments)
212{
213 return invoke<T>(*compileProc(procedure), arguments...);
214}
215
216inline void lowerToAirForTesting(Procedure& proc)
217{
218 proc.resetReachability();
219
220 if (shouldBeVerbose())
221 dataLog("B3 before lowering:\n", proc);
222
223 validate(proc);
224 lowerToAir(proc);
225
226 if (shouldBeVerbose())
227 dataLog("Air after lowering:\n", proc.code());
228
229 Air::validate(proc.code());
230}
231
232template<typename Func>
233void checkDisassembly(Compilation& compilation, const Func& func, const CString& failText)
234{
235 CString disassembly = compilation.disassembly();
236 if (func(disassembly.data()))
237 return;
238
239 crashLock.lock();
240 dataLog("Bad lowering! ", failText, "\n");
241 dataLog(disassembly);
242 CRASH();
243}
244
245inline void checkUsesInstruction(Compilation& compilation, const char* text)
246{
247 checkDisassembly(
248 compilation,
249 [&] (const char* disassembly) -> bool {
250 return strstr(disassembly, text);
251 },
252 toCString("Expected to find ", text, " but didnt!"));
253}
254
255inline void checkDoesNotUseInstruction(Compilation& compilation, const char* text)
256{
257 checkDisassembly(
258 compilation,
259 [&] (const char* disassembly) -> bool {
260 return !strstr(disassembly, text);
261 },
262 toCString("Did not expected to find ", text, " but it's there!"));
263}
264
265template<typename Type>
266struct Operand {
267 const char* name;
268 Type value;
269};
270
271typedef Operand<int64_t> Int64Operand;
272typedef Operand<int32_t> Int32Operand;
273typedef Operand<int16_t> Int16Operand;
274typedef Operand<int8_t> Int8Operand;
275
276#define MAKE_OPERAND(value) Operand<decltype(value)> { #value, value }
277
278template<typename FloatType>
279void populateWithInterestingValues(Vector<Operand<FloatType>>& operands)
280{
281 operands.append({ "0.", static_cast<FloatType>(0.) });
282 operands.append({ "-0.", static_cast<FloatType>(-0.) });
283 operands.append({ "0.4", static_cast<FloatType>(0.5) });
284 operands.append({ "-0.4", static_cast<FloatType>(-0.5) });
285 operands.append({ "0.5", static_cast<FloatType>(0.5) });
286 operands.append({ "-0.5", static_cast<FloatType>(-0.5) });
287 operands.append({ "0.6", static_cast<FloatType>(0.6) });
288 operands.append({ "-0.6", static_cast<FloatType>(-0.6) });
289 operands.append({ "1.", static_cast<FloatType>(1.) });
290 operands.append({ "-1.", static_cast<FloatType>(-1.) });
291 operands.append({ "2.", static_cast<FloatType>(2.) });
292 operands.append({ "-2.", static_cast<FloatType>(-2.) });
293 operands.append({ "M_PI", static_cast<FloatType>(M_PI) });
294 operands.append({ "-M_PI", static_cast<FloatType>(-M_PI) });
295 operands.append({ "min", std::numeric_limits<FloatType>::min() });
296 operands.append({ "max", std::numeric_limits<FloatType>::max() });
297 operands.append({ "lowest", std::numeric_limits<FloatType>::lowest() });
298 operands.append({ "epsilon", std::numeric_limits<FloatType>::epsilon() });
299 operands.append({ "infiniti", std::numeric_limits<FloatType>::infinity() });
300 operands.append({ "-infiniti", - std::numeric_limits<FloatType>::infinity() });
301 operands.append({ "PNaN", static_cast<FloatType>(PNaN) });
302}
303
304template<typename FloatType>
305Vector<Operand<FloatType>> floatingPointOperands()
306{
307 Vector<Operand<FloatType>> operands;
308 populateWithInterestingValues(operands);
309 return operands;
310};
311
312inline Vector<Int64Operand> int64Operands()
313{
314 Vector<Int64Operand> operands;
315 operands.append({ "0", 0 });
316 operands.append({ "1", 1 });
317 operands.append({ "-1", -1 });
318 operands.append({ "42", 42 });
319 operands.append({ "-42", -42 });
320 operands.append({ "int64-max", std::numeric_limits<int64_t>::max() });
321 operands.append({ "int64-min", std::numeric_limits<int64_t>::min() });
322 operands.append({ "int32-max", std::numeric_limits<int32_t>::max() });
323 operands.append({ "int32-min", std::numeric_limits<int32_t>::min() });
324 operands.append({ "uint64-max", static_cast<int64_t>(std::numeric_limits<uint64_t>::max()) });
325 operands.append({ "uint64-min", static_cast<int64_t>(std::numeric_limits<uint64_t>::min()) });
326 operands.append({ "uint32-max", static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) });
327 operands.append({ "uint32-min", static_cast<int64_t>(std::numeric_limits<uint32_t>::min()) });
328
329 return operands;
330}
331
332inline Vector<Int32Operand> int32Operands()
333{
334 Vector<Int32Operand> operands({
335 { "0", 0 },
336 { "1", 1 },
337 { "-1", -1 },
338 { "42", 42 },
339 { "-42", -42 },
340 { "int32-max", std::numeric_limits<int32_t>::max() },
341 { "int32-min", std::numeric_limits<int32_t>::min() },
342 { "uint32-max", static_cast<int32_t>(std::numeric_limits<uint32_t>::max()) },
343 { "uint32-min", static_cast<int32_t>(std::numeric_limits<uint32_t>::min()) }
344 });
345 return operands;
346}
347
348inline Vector<Int16Operand> int16Operands()
349{
350 Vector<Int16Operand> operands({
351 { "0", 0 },
352 { "1", 1 },
353 { "-1", -1 },
354 { "42", 42 },
355 { "-42", -42 },
356 { "int16-max", std::numeric_limits<int16_t>::max() },
357 { "int16-min", std::numeric_limits<int16_t>::min() },
358 { "uint16-max", static_cast<int16_t>(std::numeric_limits<uint16_t>::max()) },
359 { "uint16-min", static_cast<int16_t>(std::numeric_limits<uint16_t>::min()) }
360 });
361 return operands;
362}
363
364inline Vector<Int8Operand> int8Operands()
365{
366 Vector<Int8Operand> operands({
367 { "0", 0 },
368 { "1", 1 },
369 { "-1", -1 },
370 { "42", 42 },
371 { "-42", -42 },
372 { "int8-max", std::numeric_limits<int8_t>::max() },
373 { "int8-min", std::numeric_limits<int8_t>::min() },
374 { "uint8-max", static_cast<int8_t>(std::numeric_limits<uint8_t>::max()) },
375 { "uint8-min", static_cast<int8_t>(std::numeric_limits<uint8_t>::min()) }
376 });
377 return operands;
378}
379
380inline void add32(CCallHelpers& jit, GPRReg src1, GPRReg src2, GPRReg dest)
381{
382 if (src2 == dest)
383 jit.add32(src1, dest);
384 else {
385 jit.move(src1, dest);
386 jit.add32(src2, dest);
387 }
388}
389
390template<typename LoadedType, typename EffectiveType>
391EffectiveType modelLoad(EffectiveType value);
392
393template<typename LoadedType, typename EffectiveType>
394EffectiveType modelLoad(EffectiveType value)
395{
396 union {
397 EffectiveType original;
398 LoadedType loaded;
399 } u;
400
401 u.original = value;
402 if (std::is_signed<LoadedType>::value)
403 return static_cast<EffectiveType>(u.loaded);
404 return static_cast<EffectiveType>(static_cast<typename std::make_unsigned<EffectiveType>::type>(u.loaded));
405}
406
407template<>
408inline float modelLoad<float, float>(float value) { return value; }
409
410template<>
411inline double modelLoad<double, double>(double value) { return value; }
412
413void run(const char* filter);
414void testBitAndSExt32(int32_t value, int64_t mask);
415void testBasicSelect();
416void testSelectTest();
417void testSelectCompareDouble();
418void testSelectCompareFloat(float, float);
419void testSelectCompareFloatToDouble(float, float);
420void testSelectDouble();
421void testSelectDoubleTest();
422void testSelectDoubleCompareDouble();
423void testSelectDoubleCompareFloat(float, float);
424void testSelectFloatCompareFloat(float, float);
425void testSelectDoubleCompareDoubleWithAliasing();
426void testSelectFloatCompareFloatWithAliasing();
427void testSelectFold(intptr_t value);
428void testSelectInvert();
429void testCheckSelect();
430void testCheckSelectCheckSelect();
431void testCheckSelectAndCSE();
432void testPowDoubleByIntegerLoop(double xOperand, int32_t yOperand);
433double b3Pow(double x, int y);
434void testTruncOrHigh();
435void testTruncOrLow();
436void testBitAndOrHigh();
437void testBitAndOrLow();
438void testBranch64Equal(int64_t left, int64_t right);
439void testBranch64EqualImm(int64_t left, int64_t right);
440void testBranch64EqualMem(int64_t left, int64_t right);
441void testBranch64EqualMemImm(int64_t left, int64_t right);
442void testStore8Load8Z(int32_t value);
443void testStore16Load16Z(int32_t value);
444void testTrivialInfiniteLoop();
445void testFoldPathEqual();
446void testLShiftSelf32();
447void testRShiftSelf32();
448void testURShiftSelf32();
449void testLShiftSelf64();
450void testRShiftSelf64();
451void testURShiftSelf64();
452void testPatchpointDoubleRegs();
453void testSpillDefSmallerThanUse();
454void testSpillUseLargerThanDef();
455void testLateRegister();
456void interpreterPrint(Vector<intptr_t>* stream, intptr_t value);
457void testInterpreter();
458void testReduceStrengthCheckBottomUseInAnotherBlock();
459void testResetReachabilityDanglingReference();
460void testEntrySwitchSimple();
461void testEntrySwitchNoEntrySwitch();
462void testEntrySwitchWithCommonPaths();
463void testEntrySwitchWithCommonPathsAndNonTrivialEntrypoint();
464void testEntrySwitchLoop();
465void testSomeEarlyRegister();
466void testBranchBitAndImmFusion(B3::Opcode valueModifier, Type valueType, int64_t constant, Air::Opcode expectedOpcode, Air::Arg::Kind firstKind);
467void testTerminalPatchpointThatNeedsToBeSpilled();
468void testTerminalPatchpointThatNeedsToBeSpilled2();
469void testPatchpointTerminalReturnValue(bool successIsRare);
470void testMemoryFence();
471void testStoreFence();
472void testLoadFence();
473void testTrappingLoad();
474void testTrappingStore();
475void testTrappingLoadAddStore();
476void testTrappingLoadDCE();
477void testTrappingStoreElimination();
478void testMoveConstants();
479void testPCOriginMapDoesntInsertNops();
480void testBitOrBitOrArgImmImm32(int, int, int c);
481void testBitOrImmBitOrArgImm32(int, int, int c);
482double bitOrDouble(double, double);
483void testBitOrArgDouble(double);
484void testBitOrArgsDouble(double, double);
485void testBitOrArgImmDouble(double, double);
486void testBitOrImmsDouble(double, double);
487float bitOrFloat(float, float);
488void testBitOrArgFloat(float);
489void testBitOrArgsFloat(float, float);
490void testBitOrArgImmFloat(float, float);
491void testBitOrImmsFloat(float, float);
492void testBitOrArgsFloatWithUselessDoubleConversion(float, float);
493void testBitXorArgs(int64_t, int64_t);
494void testBitXorSameArg(int64_t);
495void testBitXorAndAndArgs(int64_t, int64_t, int64_t c);
496void testBitXorAndAndArgs32(int32_t, int32_t, int32_t c);
497void testBitXorAndSameArgs(int64_t, int64_t);
498void testBitXorAndSameArgs32(int32_t, int32_t);
499void testBitXorImms(int64_t, int64_t);
500void testBitXorArgImm(int64_t, int64_t);
501void testBitXorImmArg(int64_t, int64_t);
502void testBitXorBitXorArgImmImm(int64_t, int64_t, int64_t c);
503void testBitXorImmBitXorArgImm(int64_t, int64_t, int64_t c);
504void testBitXorArgs32(int, int);
505void testBitXorSameArg32(int);
506void testBitXorImms32(int, int);
507void testBitXorArgImm32(int, int);
508void testBitXorImmArg32(int, int);
509void testBitXorBitXorArgImmImm32(int, int, int c);
510void testBitXorImmBitXorArgImm32(int, int, int c);
511void testBitNotArg(int64_t);
512void testBitNotImm(int64_t);
513void testBitNotMem(int64_t);
514void testBitNotArg32(int32_t);
515void testBitNotImm32(int32_t);
516void testBitNotMem32(int32_t);
517void testNotOnBooleanAndBranch32(int64_t, int64_t);
518void testBitNotOnBooleanAndBranch32(int64_t, int64_t);
519void testShlArgs(int64_t, int64_t);
520void testShlImms(int64_t, int64_t);
521void testShlArgImm(int64_t, int64_t);
522void testShlSShrArgImm(int64_t, int64_t);
523void testShlArg32(int32_t);
524void testShlArgs32(int32_t, int32_t);
525void testShlImms32(int32_t, int32_t);
526void testShlArgImm32(int32_t, int32_t);
527void testShlZShrArgImm32(int32_t, int32_t);
528void testClzArg64(int64_t);
529void testClzMem64(int64_t);
530void testClzArg32(int32_t);
531void testClzMem32(int32_t);
532void testAbsArg(double);
533void testAbsImm(double);
534void testAbsMem(double);
535void testAbsAbsArg(double);
536void testAbsNegArg(double);
537void testAbsBitwiseCastArg(double);
538void testBitwiseCastAbsBitwiseCastArg(double);
539void testAbsArg(float);
540void testAbsImm(float);
541void testAbsMem(float);
542void testAbsAbsArg(float);
543void testAbsNegArg(float);
544void testAbsBitwiseCastArg(float);
545void testBitwiseCastAbsBitwiseCastArg(float);
546void testAbsArgWithUselessDoubleConversion(float);
547void testAbsArgWithEffectfulDoubleConversion(float);
548void testCeilArg(double);
549void testCeilImm(double);
550void testCeilMem(double);
551void testCeilCeilArg(double);
552void testFloorCeilArg(double);
553void testCeilIToD64(int64_t);
554void testCeilIToD32(int64_t);
555void testCeilArg(float);
556void testCeilImm(float);
557void testCeilMem(float);
558void testCeilCeilArg(float);
559void testFloorCeilArg(float);
560void testCeilArgWithUselessDoubleConversion(float);
561void testCeilArgWithEffectfulDoubleConversion(float);
562void testFloorArg(double);
563void testFloorImm(double);
564void testFloorMem(double);
565void testFloorFloorArg(double);
566void testCeilFloorArg(double);
567void testFloorIToD64(int64_t);
568void testFloorIToD32(int64_t);
569void testFloorArg(float);
570void testFloorImm(float);
571void testFloorMem(float);
572void testFloorFloorArg(float);
573void testCeilFloorArg(float);
574void testFloorArgWithUselessDoubleConversion(float);
575void testFloorArgWithEffectfulDoubleConversion(float);
576double correctSqrt(double value);
577void testSqrtArg(double);
578void testSqrtImm(double);
579void testSqrtMem(double);
580void testSqrtArg(float);
581void testSqrtImm(float);
582void testSqrtMem(float);
583void testSqrtArgWithUselessDoubleConversion(float);
584void testSqrtArgWithEffectfulDoubleConversion(float);
585void testCompareTwoFloatToDouble(float, float);
586void testCompareOneFloatToDouble(float, double);
587void testCompareFloatToDoubleThroughPhi(float, float);
588void testDoubleToFloatThroughPhi(float value);
589void testReduceFloatToDoubleValidates();
590void testDoubleProducerPhiToFloatConversion(float value);
591void testDoubleProducerPhiToFloatConversionWithDoubleConsumer(float value);
592void testDoubleProducerPhiWithNonFloatConst(float value, double constValue);
593void testDoubleArgToInt64BitwiseCast(double value);
594void testDoubleImmToInt64BitwiseCast(double value);
595void testTwoBitwiseCastOnDouble(double value);
596void testBitwiseCastOnDoubleInMemory(double value);
597void testBitwiseCastOnDoubleInMemoryIndexed(double value);
598void testInt64BArgToDoubleBitwiseCast(int64_t value);
599void testInt64BImmToDoubleBitwiseCast(int64_t value);
600void testTwoBitwiseCastOnInt64(int64_t value);
601void testBitwiseCastOnInt64InMemory(int64_t value);
602void testBitwiseCastOnInt64InMemoryIndexed(int64_t value);
603void testFloatImmToInt32BitwiseCast(float value);
604void testBitwiseCastOnFloatInMemory(float value);
605void testInt32BArgToFloatBitwiseCast(int32_t value);
606void testInt32BImmToFloatBitwiseCast(int32_t value);
607void testTwoBitwiseCastOnInt32(int32_t value);
608void testBitwiseCastOnInt32InMemory(int32_t value);
609void testConvertDoubleToFloatArg(double value);
610void testConvertDoubleToFloatImm(double value);
611void testConvertDoubleToFloatMem(double value);
612void testConvertFloatToDoubleArg(float value);
613void testConvertFloatToDoubleImm(float value);
614void testConvertFloatToDoubleMem(float value);
615void testConvertDoubleToFloatToDoubleToFloat(double value);
616void testLoadFloatConvertDoubleConvertFloatStoreFloat(float value);
617void testFroundArg(double value);
618void testFroundMem(double value);
619void testIToD64Arg();
620void testIToF64Arg();
621void testIToD32Arg();
622void testIToF32Arg();
623void testIToD64Mem();
624void testIToF64Mem();
625void testIToD32Mem();
626void testIToF32Mem();
627void testIToD64Imm(int64_t value);
628void testIToF64Imm(int64_t value);
629void testIToD32Imm(int32_t value);
630void testIToF32Imm(int32_t value);
631void testIToDReducedToIToF64Arg();
632void testIToDReducedToIToF32Arg();
633void testStore32(int value);
634void testStoreConstant(int value);
635void testStoreConstantPtr(intptr_t value);
636void testStore8Arg();
637void testStore8Imm();
638void testStorePartial8BitRegisterOnX86();
639void testStore16Arg();
640void testStore16Imm();
641void testTrunc(int64_t value);
642void testAdd1(int value);
643void testAdd1Ptr(intptr_t value);
644void testNeg32(int32_t value);
645void testNegPtr(intptr_t value);
646void testStoreAddLoad32(int amount);
647void testStoreRelAddLoadAcq32(int amount);
648void testStoreAddLoadImm32(int amount);
649void testStoreAddLoad8(int amount, B3::Opcode loadOpcode);
650void testStoreRelAddLoadAcq8(int amount, B3::Opcode loadOpcode);
651void testStoreRelAddFenceLoadAcq8(int amount, B3::Opcode loadOpcode);
652void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode);
653void testStoreAddLoad16(int amount, B3::Opcode loadOpcode);
654void testStoreRelAddLoadAcq16(int amount, B3::Opcode loadOpcode);
655void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode);
656void testStoreAddLoad64(int amount);
657void testStoreRelAddLoadAcq64(int amount);
658void testStoreAddLoadImm64(int64_t amount);
659void testStoreAddLoad32Index(int amount);
660void testStoreAddLoadImm32Index(int amount);
661void testStoreAddLoad8Index(int amount, B3::Opcode loadOpcode);
662void testStoreAddLoadImm8Index(int amount, B3::Opcode loadOpcode);
663void testStoreAddLoad16Index(int amount, B3::Opcode loadOpcode);
664void testStoreAddLoadImm16Index(int amount, B3::Opcode loadOpcode);
665void testStoreAddLoad64Index(int amount);
666void testStoreAddLoadImm64Index(int64_t amount);
667void testStoreSubLoad(int amount);
668void testStoreAddLoadInterference(int amount);
669void testStoreAddAndLoad(int amount, int mask);
670void testStoreNegLoad32(int32_t value);
671void testStoreNegLoadPtr(intptr_t value);
672void testAdd1Uncommuted(int value);
673void testLoadOffset();
674void testLoadOffsetNotConstant();
675void testLoadOffsetUsingAdd();
676void testLoadOffsetUsingAddInterference();
677void testLoadOffsetUsingAddNotConstant();
678void testLoadAddrShift(unsigned shift);
679void testFramePointer();
680void testOverrideFramePointer();
681void testStackSlot();
682void testLoadFromFramePointer();
683void testStoreLoadStackSlot(int value);
684void testStoreFloat(double input);
685void testStoreDoubleConstantAsFloat(double input);
686void testSpillGP();
687void testSpillFP();
688void testInt32ToDoublePartialRegisterStall();
689void testInt32ToDoublePartialRegisterWithoutStall();
690void testBranch();
691void testBranchPtr();
692void testDiamond();
693void testBranchNotEqual();
694void testBranchNotEqualCommute();
695void testBranchNotEqualNotEqual();
696void testBranchEqual();
697void testBranchEqualEqual();
698void testBranchEqualCommute();
699void testBranchEqualEqual1();
700void testBranchEqualOrUnorderedArgs(double, double);
701void testBranchEqualOrUnorderedArgs(float, float);
702void testBranchNotEqualAndOrderedArgs(double, double);
703void testBranchNotEqualAndOrderedArgs(float, float);
704void testBranchEqualOrUnorderedDoubleArgImm(double, double);
705void testBranchEqualOrUnorderedFloatArgImm(float, float);
706void testBranchEqualOrUnorderedDoubleImms(double, double);
707void testBranchEqualOrUnorderedFloatImms(float, float);
708void testBranchEqualOrUnorderedFloatWithUselessDoubleConversion(float, float);
709void testBranchFold(int value);
710void testDiamondFold(int value);
711void testBranchNotEqualFoldPtr(intptr_t value);
712void testBranchEqualFoldPtr(intptr_t value);
713void testBranchLoadPtr();
714void testBranchLoad32();
715void testBranchLoad8S();
716void testBranchLoad8Z();
717void testBranchLoad16S();
718void testBranchLoad16Z();
719void testBranch8WithLoad8ZIndex();
720void testComplex(unsigned numVars, unsigned numConstructs);
721void testBranchBitTest32TmpImm(uint32_t value, uint32_t imm);
722void testBranchBitTest32AddrImm(uint32_t value, uint32_t imm);
723void testBranchBitTest32TmpTmp(uint32_t value, uint32_t value2);
724void testBranchBitTest64TmpTmp(uint64_t value, uint64_t value2);
725void testBranchBitTest64AddrTmp(uint64_t value, uint64_t value2);
726void testBranchBitTestNegation(uint64_t value, uint64_t value2);
727void testBranchBitTestNegation2(uint64_t value, uint64_t value2);
728void testSimplePatchpoint();
729void testSimplePatchpointWithoutOuputClobbersGPArgs();
730void testSimplePatchpointWithOuputClobbersGPArgs();
731void testSimplePatchpointWithoutOuputClobbersFPArgs();
732void testSimplePatchpointWithOuputClobbersFPArgs();
733void testPatchpointWithEarlyClobber();
734void testPatchpointCallArg();
735void testPatchpointFixedRegister();
736void testPatchpointAny(ValueRep rep);
737void testPatchpointGPScratch();
738void testPatchpointFPScratch();
739void testPatchpointLotsOfLateAnys();
740void testPatchpointAnyImm(ValueRep rep);
741void testPatchpointManyWarmAnyImms();
742void testPatchpointManyColdAnyImms();
743void testPatchpointWithRegisterResult();
744void testPatchpointWithStackArgumentResult();
745void testPatchpointWithAnyResult();
746void testSimpleCheck();
747void testCheckFalse();
748void testCheckTrue();
749void testCheckLessThan();
750void testCheckMegaCombo();
751void testCheckTrickyMegaCombo();
752void testCheckTwoMegaCombos();
753void testCheckTwoNonRedundantMegaCombos();
754void testCheckAddImm();
755void testCheckAddImmCommute();
756void testCheckAddImmSomeRegister();
757void testCheckAdd();
758void testCheckAdd64();
759void testCheckAddFold(int, int);
760void testCheckAddFoldFail(int, int);
761void test42();
762void testLoad42();
763void testLoadAcq42();
764void testLoadWithOffsetImpl(int32_t offset64, int32_t offset32);
765void testLoadOffsetImm9Max();
766void testLoadOffsetImm9MaxPlusOne();
767void testLoadOffsetImm9MaxPlusTwo();
768void testLoadOffsetImm9Min();
769void testLoadOffsetImm9MinMinusOne();
770void testLoadOffsetScaledUnsignedImm12Max();
771void testLoadOffsetScaledUnsignedOverImm12Max();
772void testAddTreeArg32(int32_t);
773void testMulTreeArg32(int32_t);
774void testArg(int argument);
775void testReturnConst64(int64_t value);
776void testReturnVoid();
777void testAddArg(int);
778void testAddArgs(int, int);
779void testAddArgImm(int, int);
780void testAddImmArg(int, int);
781void testAddArgMem(int64_t, int64_t);
782void testAddMemArg(int64_t, int64_t);
783void testAddImmMem(int64_t, int64_t);
784void testAddArg32(int);
785void testAddArgs32(int, int);
786void testAddArgMem32(int32_t, int32_t);
787void testAddMemArg32(int32_t, int32_t);
788void testAddImmMem32(int32_t, int32_t);
789void testAddNeg1(int, int);
790void testAddNeg2(int, int);
791void testAddArgZeroImmZDef();
792void testAddLoadTwice();
793void testAddArgDouble(double);
794void testCheckAddArgumentAliasing64();
795void testCheckAddArgumentAliasing32();
796void testCheckAddSelfOverflow64();
797void testCheckAddSelfOverflow32();
798void testCheckAddRemoveCheckWithSExt8(int8_t);
799void testCheckAddRemoveCheckWithSExt16(int16_t);
800void testCheckAddRemoveCheckWithSExt32(int32_t);
801void testCheckAddRemoveCheckWithZExt32(int32_t);
802void testCheckSubImm();
803void testCheckSubBadImm();
804void testCheckSub();
805double doubleSub(double, double);
806void testCheckSub64();
807void testCheckSubFold(int, int);
808void testCheckSubFoldFail(int, int);
809void testCheckNeg();
810void testCheckNeg64();
811void testCheckMul();
812void testCheckMulMemory();
813void testCheckMul2();
814void testCheckMul64();
815void testCheckMulFold(int, int);
816void testCheckMulFoldFail(int, int);
817void testAddArgsDouble(double, double);
818void testAddArgImmDouble(double, double);
819void testAddImmArgDouble(double, double);
820void testAddImmsDouble(double, double);
821void testAddArgFloat(float);
822void testAddArgsFloat(float, float);
823void testAddFPRArgsFloat(float, float);
824void testAddArgImmFloat(float, float);
825void testAddImmArgFloat(float, float);
826void testAddImmsFloat(float, float);
827void testAddArgFloatWithUselessDoubleConversion(float);
828void testAddArgsFloatWithUselessDoubleConversion(float, float);
829void testAddArgsFloatWithEffectfulDoubleConversion(float, float);
830void testAddMulMulArgs(int64_t, int64_t, int64_t c);
831void testMulArg(int);
832void testMulArgStore(int);
833void testMulAddArg(int);
834void testMulArgs(int, int);
835void testMulArgNegArg(int, int);
836void testCheckMulArgumentAliasing64();
837void testCheckMulArgumentAliasing32();
838void testCheckMul64SShr();
839void testCompareImpl(B3::Opcode opcode, int64_t left, int64_t right);
840void testCompare(B3::Opcode opcode, int64_t left, int64_t right);
841void testEqualDouble(double left, double right, bool result);
842void testCallSimple(int, int);
843void testCallRare(int, int);
844void testCallRareLive(int, int, int c);
845void testCallSimplePure(int, int);
846void testCallFunctionWithHellaArguments();
847void testCallFunctionWithHellaArguments2();
848void testCallFunctionWithHellaArguments3();
849void testReturnDouble(double value);
850void testReturnFloat(float value);
851void testMulNegArgArg(int, int);
852void testMulArgImm(int64_t, int64_t);
853void testMulImmArg(int, int);
854void testMulArgs32(int, int);
855void testMulArgs32SignExtend(int, int);
856void testMulImm32SignExtend(const int, int);
857void testMulLoadTwice();
858void testMulAddArgsLeft();
859void testMulAddArgsRight();
860void testMulAddArgsLeft32();
861void testMulAddArgsRight32();
862void testMulSubArgsLeft();
863void testMulSubArgsRight();
864void testMulSubArgsLeft32();
865void testMulSubArgsRight32();
866void testMulNegArgs();
867void testMulNegArgs32();
868void testMulArgDouble(double);
869void testMulArgsDouble(double, double);
870void testCallSimpleDouble(double, double);
871void testCallSimpleFloat(float, float);
872void testCallFunctionWithHellaDoubleArguments();
873void testCallFunctionWithHellaFloatArguments();
874void testLinearScanWithCalleeOnStack();
875void testChillDiv(int num, int den, int res);
876void testChillDivTwice(int num1, int den1, int num2, int den2, int res);
877void testChillDiv64(int64_t num, int64_t den, int64_t res);
878void testModArg(int64_t value);
879void testModArgs(int64_t numerator, int64_t denominator);
880void testModImms(int64_t numerator, int64_t denominator);
881void testMulArgImmDouble(double, double);
882void testMulImmArgDouble(double, double);
883void testMulImmsDouble(double, double);
884void testMulArgFloat(float);
885void testMulArgsFloat(float, float);
886void testMulArgImmFloat(float, float);
887void testMulImmArgFloat(float, float);
888void testMulImmsFloat(float, float);
889void testMulArgFloatWithUselessDoubleConversion(float);
890void testMulArgsFloatWithUselessDoubleConversion(float, float);
891void testMulArgsFloatWithEffectfulDoubleConversion(float, float);
892void testDivArgDouble(double);
893void testDivArgsDouble(double, double);
894void testDivArgImmDouble(double, double);
895void testDivImmArgDouble(double, double);
896void testDivImmsDouble(double, double);
897void testDivArgFloat(float);
898void testDivArgsFloat(float, float);
899void testDivArgImmFloat(float, float);
900void testModArg32(int32_t value);
901void testModArgs32(int32_t numerator, int32_t denominator);
902void testModImms32(int32_t numerator, int32_t denominator);
903void testChillModArg(int64_t value);
904void testChillModArgs(int64_t numerator, int64_t denominator);
905void testChillModImms(int64_t numerator, int64_t denominator);
906void testChillModArg32(int32_t value);
907void testChillModArgs32(int32_t numerator, int32_t denominator);
908void testChillModImms32(int32_t numerator, int32_t denominator);
909void testLoopWithMultipleHeaderEdges();
910void testSwitch(unsigned degree);
911void testSwitch(unsigned degree, unsigned gap);
912void testSwitchSameCaseAsDefault();
913void testSwitchChillDiv(unsigned degree, unsigned gap);
914void testSwitchTargettingSameBlock();
915void testSwitchTargettingSameBlockFoldPathConstant();
916void testTruncFold(int64_t value);
917void testZExt32(int32_t value);
918void testZExt32Fold(int32_t value);
919void testSExt32(int32_t value);
920void testSExt32Fold(int32_t value);
921void testTruncZExt32(int32_t value);
922void testPinRegisters();
923void testX86LeaAddAddShlLeft();
924void testX86LeaAddAddShlRight();
925void testX86LeaAddAdd();
926void testX86LeaAddShlRight();
927void testX86LeaAddShlLeftScale1();
928void testX86LeaAddShlLeftScale2();
929void testX86LeaAddShlLeftScale4();
930void testX86LeaAddShlLeftScale8();
931void testAddShl32();
932void testAddShl64();
933void testAddShl65();
934void testReduceStrengthReassociation(bool flip);
935void testLoadBaseIndexShift2();
936void testLoadBaseIndexShift32();
937void testOptimizeMaterialization();
938void testLICMPure();
939void testLICMPureSideExits();
940void testTruncSExt32(int32_t value);
941void testSExt8(int32_t value);
942void testSExt8Fold(int32_t value);
943void testSExt8SExt8(int32_t value);
944void testSExt8SExt16(int32_t value);
945void testSExt8BitAnd(int32_t value, int32_t mask);
946void testBitAndSExt8(int32_t value, int32_t mask);
947void testSExt16(int32_t value);
948void testSExt16Fold(int32_t value);
949void testSExt16SExt16(int32_t value);
950void testSExt16SExt8(int32_t value);
951void testLICMPureWritesPinned();
952void testLICMPureWrites();
953void testLICMReadsLocalState();
954void testLICMReadsPinned();
955void testLICMReads();
956void testLICMPureNotBackwardsDominant();
957void testLICMPureFoiledByChild();
958void testLICMPureNotBackwardsDominantFoiledByChild();
959void testLICMExitsSideways();
960void testLICMWritesLocalState();
961void testLICMWrites();
962void testLICMFence();
963void testLICMWritesPinned();
964void testLICMControlDependent();
965void testLICMControlDependentNotBackwardsDominant();
966void testLICMControlDependentSideExits();
967void testLICMReadsPinnedWritesPinned();
968void testLICMReadsWritesDifferentHeaps();
969void testLICMReadsWritesOverlappingHeaps();
970void testLICMDefaultCall();
971void testDepend32();
972void testDepend64();
973void testWasmBoundsCheck(unsigned offset);
974void testWasmAddress();
975void testFastTLSLoad();
976void testFastTLSStore();
977void testDoubleLiteralComparison(double, double);
978void testFloatEqualOrUnorderedFolding();
979void testFloatEqualOrUnorderedFoldingNaN();
980void testFloatEqualOrUnorderedDontFold();
981void testSExt16BitAnd(int32_t value, int32_t mask);
982void testBitAndSExt16(int32_t value, int32_t mask);
983void testSExt32BitAnd(int32_t value, int32_t mask);
984void testShuffleDoesntTrashCalleeSaves();
985void testDemotePatchpointTerminal();
986void testReportUsedRegistersLateUseFollowedByEarlyDefDoesNotMarkUseAsDead();
987void testInfiniteLoopDoesntCauseBadHoisting();
988void testDivImmArgFloat(float, float);
989void testDivImmsFloat(float, float);
990void testModArgDouble(double);
991void testModArgsDouble(double, double);
992void testModArgImmDouble(double, double);
993void testModImmArgDouble(double, double);
994void testModImmsDouble(double, double);
995void testModArgFloat(float);
996void testModArgsFloat(float, float);
997void testModArgImmFloat(float, float);
998void testModImmArgFloat(float, float);
999void testModImmsFloat(float, float);
1000void testDivArgFloatWithUselessDoubleConversion(float);
1001void testDivArgsFloatWithUselessDoubleConversion(float, float);
1002void testDivArgsFloatWithEffectfulDoubleConversion(float, float);
1003void testUDivArgsInt32(uint32_t, uint32_t);
1004void testUDivArgsInt64(uint64_t, uint64_t);
1005void testUModArgsInt32(uint32_t, uint32_t);
1006void testUModArgsInt64(uint64_t, uint64_t);
1007void testSubArg(int);
1008void testSubArgs(int, int);
1009void testSubArgImm(int64_t, int64_t);
1010void testSubNeg(int, int);
1011void testNegSub(int, int);
1012void testNegValueSubOne(int);
1013void testSubSub(int, int, int c);
1014void testSubSub2(int, int, int c);
1015void testSubAdd(int, int, int c);
1016void testSubFirstNeg(int, int);
1017void testSubImmArg(int, int);
1018void testSubArgMem(int64_t, int64_t);
1019void testSubMemArg(int64_t, int64_t);
1020void testSubImmMem(int64_t, int64_t);
1021void testSubMemImm(int64_t, int64_t);
1022void testSubArgs32(int, int);
1023void testSubArgImm32(int, int);
1024void testSubImmArg32(int, int);
1025void testSubMemArg32(int32_t, int32_t);
1026void testSubArgMem32(int32_t, int32_t);
1027void testSubImmMem32(int32_t, int32_t);
1028void testSubMemImm32(int32_t, int32_t);
1029void testNegValueSubOne32(int);
1030void testNegMulArgImm(int64_t, int64_t);
1031void testSubMulMulArgs(int64_t, int64_t, int64_t c);
1032void testSubArgDouble(double);
1033void testSubArgsDouble(double, double);
1034void testSubArgImmDouble(double, double);
1035void testSubImmArgDouble(double, double);
1036void testSubImmsDouble(double, double);
1037void testSubArgFloat(float);
1038void testSubArgsFloat(float, float);
1039void testSubArgImmFloat(float, float);
1040void testSubImmArgFloat(float, float);
1041void testSubImmsFloat(float, float);
1042void testSubArgFloatWithUselessDoubleConversion(float);
1043void testSubArgsFloatWithUselessDoubleConversion(float, float);
1044void testSubArgsFloatWithEffectfulDoubleConversion(float, float);
1045void testTernarySubInstructionSelection(B3::Opcode valueModifier, Type valueType, Air::Opcode expectedOpcode);
1046void testNegDouble(double);
1047void testNegFloat(float);
1048void testNegFloatWithUselessDoubleConversion(float);
1049
1050void addArgTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1051void addBitTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1052void addCallTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1053void addSExtTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1054void addSShrShTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1055void addShrTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1056void addAtomicTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1057void addLoadTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1058void addTupleTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1059
1060void testFastForwardCopy32();
1061void testByteCopyLoop();
1062void testByteCopyLoopStartIsLoopDependent();
1063void testByteCopyLoopBoundIsLoopDependent();
1064
1065void addCopyTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>&);
1066
1067bool shouldRun(const char* filter, const char* testName);
1068
1069#endif // ENABLE(B3_JIT)
1070