summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/b3/B3LowerMacros.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/b3/B3LowerMacros.cpp')
-rw-r--r--Source/JavaScriptCore/b3/B3LowerMacros.cpp377
1 files changed, 0 insertions, 377 deletions
diff --git a/Source/JavaScriptCore/b3/B3LowerMacros.cpp b/Source/JavaScriptCore/b3/B3LowerMacros.cpp
deleted file mode 100644
index f71ca62ab..000000000
--- a/Source/JavaScriptCore/b3/B3LowerMacros.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "B3LowerMacros.h"
-
-#if ENABLE(B3_JIT)
-
-#include "B3BasicBlockInlines.h"
-#include "B3BlockInsertionSet.h"
-#include "B3CCallValue.h"
-#include "B3ConstPtrValue.h"
-#include "B3ControlValue.h"
-#include "B3InsertionSetInlines.h"
-#include "B3PhaseScope.h"
-#include "B3ProcedureInlines.h"
-#include "B3SwitchValue.h"
-#include "B3UpsilonValue.h"
-#include "B3ValueInlines.h"
-#include <cmath>
-
-namespace JSC { namespace B3 {
-
-namespace {
-
-class LowerMacros {
-public:
- LowerMacros(Procedure& proc)
- : m_proc(proc)
- , m_blockInsertionSet(proc)
- , m_insertionSet(proc)
- {
- }
-
- bool run()
- {
- for (BasicBlock* block : m_proc) {
- m_block = block;
- processCurrentBlock();
- }
- m_changed |= m_blockInsertionSet.execute();
- if (m_changed) {
- m_proc.resetReachability();
- m_proc.invalidateCFG();
- }
- return m_changed;
- }
-
-private:
- void processCurrentBlock()
- {
- for (m_index = 0; m_index < m_block->size(); ++m_index) {
- m_value = m_block->at(m_index);
- m_origin = m_value->origin();
- switch (m_value->opcode()) {
- case Mod: {
- double (*fmodDouble)(double, double) = fmod;
- if (m_value->type() == Double) {
- Value* functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, fmodDouble);
- Value* result = m_insertionSet.insert<CCallValue>(m_index, Double, m_origin,
- Effects::none(),
- functionAddress,
- m_value->child(0),
- m_value->child(1));
- m_value->replaceWithIdentity(result);
- m_changed = true;
- } else if (m_value->type() == Float) {
- Value* numeratorAsDouble = m_insertionSet.insert<Value>(m_index, FloatToDouble, m_origin, m_value->child(0));
- Value* denominatorAsDouble = m_insertionSet.insert<Value>(m_index, FloatToDouble, m_origin, m_value->child(1));
- Value* functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, fmodDouble);
- Value* doubleMod = m_insertionSet.insert<CCallValue>(m_index, Double, m_origin,
- Effects::none(),
- functionAddress,
- numeratorAsDouble,
- denominatorAsDouble);
- Value* result = m_insertionSet.insert<Value>(m_index, DoubleToFloat, m_origin, doubleMod);
- m_value->replaceWithIdentity(result);
- m_changed = true;
- } else if (isARM64()) {
- Value* divResult = m_insertionSet.insert<Value>(m_index, ChillDiv, m_origin, m_value->child(0), m_value->child(1));
- Value* multipliedBack = m_insertionSet.insert<Value>(m_index, Mul, m_origin, divResult, m_value->child(1));
- Value* result = m_insertionSet.insert<Value>(m_index, Sub, m_origin, m_value->child(0), multipliedBack);
- m_value->replaceWithIdentity(result);
- m_changed = true;
- }
- break;
- }
- case ChillDiv: {
- makeDivisionChill(Div);
- break;
- }
-
- case ChillMod: {
- if (isARM64()) {
- BasicBlock* before = m_blockInsertionSet.splitForward(m_block, m_index, &m_insertionSet);
- BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* normalModCase = m_blockInsertionSet.insertBefore(m_block);
-
- before->replaceLastWithNew<ControlValue>(
- m_proc, Branch, m_origin, m_value->child(1),
- FrequentedBlock(normalModCase, FrequencyClass::Normal),
- FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
-
- Value* divResult = normalModCase->appendNew<Value>(m_proc, ChillDiv, m_origin, m_value->child(0), m_value->child(1));
- Value* multipliedBack = normalModCase->appendNew<Value>(m_proc, Mul, m_origin, divResult, m_value->child(1));
- Value* result = normalModCase->appendNew<Value>(m_proc, Sub, m_origin, m_value->child(0), multipliedBack);
- UpsilonValue* normalResult = normalModCase->appendNew<UpsilonValue>(m_proc, m_origin, result);
- normalModCase->appendNew<ControlValue>(m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- UpsilonValue* zeroResult = zeroDenCase->appendNew<UpsilonValue>(
- m_proc, m_origin,
- zeroDenCase->appendIntConstant(m_proc, m_value, 0));
- zeroDenCase->appendNew<ControlValue>(m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- Value* phi = m_insertionSet.insert<Value>(m_index, Phi, m_value->type(), m_origin);
- normalResult->setPhi(phi);
- zeroResult->setPhi(phi);
- m_value->replaceWithIdentity(phi);
- m_changed = true;
- } else
- makeDivisionChill(Mod);
- break;
- }
-
- case Switch: {
- SwitchValue* switchValue = m_value->as<SwitchValue>();
- Vector<SwitchCase> cases;
- for (const SwitchCase& switchCase : *switchValue)
- cases.append(switchCase);
- std::sort(
- cases.begin(), cases.end(),
- [] (const SwitchCase& left, const SwitchCase& right) {
- return left.caseValue() < right.caseValue();
- });
- m_block->values().removeLast();
- recursivelyBuildSwitch(cases, 0, false, cases.size(), m_block);
- m_proc.deleteValue(switchValue);
- m_block->updatePredecessorsAfter();
- m_changed = true;
- break;
- }
-
- default:
- break;
- }
- }
- m_insertionSet.execute(m_block);
- }
-
- void makeDivisionChill(Opcode nonChillOpcode)
- {
- ASSERT(nonChillOpcode == Div || nonChillOpcode == Mod);
-
- // ARM supports this instruction natively.
- if (isARM64())
- return;
-
- // We implement "res = ChillDiv/ChillMod(num, den)" as follows:
- //
- // if (den + 1 <=_unsigned 1) {
- // if (!den) {
- // res = 0;
- // goto done;
- // }
- // if (num == -2147483648) {
- // res = isDiv ? num : 0;
- // goto done;
- // }
- // }
- // res = num (/ or %) dev;
- // done:
- m_changed = true;
-
- Value* num = m_value->child(0);
- Value* den = m_value->child(1);
-
- Value* one = m_insertionSet.insertIntConstant(m_index, m_value, 1);
- Value* isDenOK = m_insertionSet.insert<Value>(
- m_index, Above, m_origin,
- m_insertionSet.insert<Value>(m_index, Add, m_origin, den, one),
- one);
-
- BasicBlock* before = m_blockInsertionSet.splitForward(m_block, m_index, &m_insertionSet);
-
- BasicBlock* normalDivCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* shadyDenCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block);
-
- before->replaceLastWithNew<ControlValue>(
- m_proc, Branch, m_origin, isDenOK,
- FrequentedBlock(normalDivCase, FrequencyClass::Normal),
- FrequentedBlock(shadyDenCase, FrequencyClass::Rare));
-
- UpsilonValue* normalResult = normalDivCase->appendNew<UpsilonValue>(
- m_proc, m_origin,
- normalDivCase->appendNew<Value>(m_proc, nonChillOpcode, m_origin, num, den));
- normalDivCase->appendNew<ControlValue>(
- m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- shadyDenCase->appendNew<ControlValue>(
- m_proc, Branch, m_origin, den,
- FrequentedBlock(neg1DenCase, FrequencyClass::Normal),
- FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
-
- UpsilonValue* zeroResult = zeroDenCase->appendNew<UpsilonValue>(
- m_proc, m_origin,
- zeroDenCase->appendIntConstant(m_proc, m_value, 0));
- zeroDenCase->appendNew<ControlValue>(
- m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- int64_t badNumeratorConst = 0;
- switch (m_value->type()) {
- case Int32:
- badNumeratorConst = std::numeric_limits<int32_t>::min();
- break;
- case Int64:
- badNumeratorConst = std::numeric_limits<int64_t>::min();
- break;
- default:
- ASSERT_NOT_REACHED();
- badNumeratorConst = 0;
- }
-
- Value* badNumerator =
- neg1DenCase->appendIntConstant(m_proc, m_value, badNumeratorConst);
-
- neg1DenCase->appendNew<ControlValue>(
- m_proc, Branch, m_origin,
- neg1DenCase->appendNew<Value>(
- m_proc, Equal, m_origin, num, badNumerator),
- FrequentedBlock(intMinCase, FrequencyClass::Rare),
- FrequentedBlock(normalDivCase, FrequencyClass::Normal));
-
- Value* intMinResult = nonChillOpcode == Div ? badNumerator : intMinCase->appendIntConstant(m_proc, m_value, 0);
- UpsilonValue* intMinResultUpsilon = intMinCase->appendNew<UpsilonValue>(
- m_proc, m_origin, intMinResult);
- intMinCase->appendNew<ControlValue>(
- m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- Value* phi = m_insertionSet.insert<Value>(
- m_index, Phi, m_value->type(), m_origin);
- normalResult->setPhi(phi);
- zeroResult->setPhi(phi);
- intMinResultUpsilon->setPhi(phi);
-
- m_value->replaceWithIdentity(phi);
- before->updatePredecessorsAfter();
- }
-
- void recursivelyBuildSwitch(
- const Vector<SwitchCase>& cases, unsigned start, bool hardStart, unsigned end,
- BasicBlock* before)
- {
- // FIXME: Add table-based switch lowering.
- // https://bugs.webkit.org/show_bug.cgi?id=151141
-
- // See comments in jit/BinarySwitch.cpp for a justification of this algorithm. The only
- // thing we do differently is that we don't use randomness.
-
- const unsigned leafThreshold = 3;
-
- unsigned size = end - start;
-
- if (size <= leafThreshold) {
- bool allConsecutive = false;
-
- if ((hardStart || (start && cases[start - 1].caseValue() == cases[start].caseValue() - 1))
- && end < cases.size()
- && cases[end - 1].caseValue() == cases[end].caseValue() - 1) {
- allConsecutive = true;
- for (unsigned i = 0; i < size - 1; ++i) {
- if (cases[start + i].caseValue() + 1 != cases[start + i + 1].caseValue()) {
- allConsecutive = false;
- break;
- }
- }
- }
-
- unsigned limit = allConsecutive ? size - 1 : size;
-
- for (unsigned i = 0; i < limit; ++i) {
- BasicBlock* nextCheck = m_blockInsertionSet.insertAfter(m_block);
- before->appendNew<ControlValue>(
- m_proc, Branch, m_origin,
- before->appendNew<Value>(
- m_proc, Equal, m_origin, m_value->child(0),
- before->appendIntConstant(
- m_proc, m_origin, m_value->child(0)->type(),
- cases[start + i].caseValue())),
- cases[start + i].target(), FrequentedBlock(nextCheck));
-
- before = nextCheck;
- }
-
- if (allConsecutive) {
- before->appendNew<ControlValue>(
- m_proc, Jump, m_origin, cases[end - 1].target());
- } else {
- before->appendNew<ControlValue>(
- m_proc, Jump, m_origin, m_value->as<SwitchValue>()->fallThrough());
- }
- return;
- }
-
- unsigned medianIndex = (start + end) / 2;
-
- BasicBlock* left = m_blockInsertionSet.insertAfter(m_block);
- BasicBlock* right = m_blockInsertionSet.insertAfter(m_block);
-
- before->appendNew<ControlValue>(
- m_proc, Branch, m_origin,
- before->appendNew<Value>(
- m_proc, LessThan, m_origin, m_value->child(0),
- before->appendIntConstant(
- m_proc, m_origin, m_value->child(0)->type(),
- cases[medianIndex].caseValue())),
- FrequentedBlock(left), FrequentedBlock(right));
-
- recursivelyBuildSwitch(cases, start, hardStart, medianIndex, left);
- recursivelyBuildSwitch(cases, medianIndex, true, end, right);
- }
-
- Procedure& m_proc;
- BlockInsertionSet m_blockInsertionSet;
- InsertionSet m_insertionSet;
- BasicBlock* m_block;
- unsigned m_index;
- Value* m_value;
- Origin m_origin;
- bool m_changed { false };
-};
-
-bool lowerMacrosImpl(Procedure& proc)
-{
- LowerMacros lowerMacros(proc);
- return lowerMacros.run();
-}
-
-} // anonymous namespace
-
-bool lowerMacros(Procedure& proc)
-{
- PhaseScope phaseScope(proc, "lowerMacros");
- bool result = lowerMacrosImpl(proc);
- if (shouldValidateIR())
- RELEASE_ASSERT(!lowerMacrosImpl(proc));
- return result;
-}
-
-} } // namespace JSC::B3
-
-#endif // ENABLE(B3_JIT)
-