mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-24 07:29:44 +00:00
90 lines
3.2 KiB
C++
90 lines
3.2 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "jit/AlignmentMaskAnalysis.h"
|
|
#include "jit/MIR.h"
|
|
#include "jit/MIRGraph.h"
|
|
|
|
using namespace js;
|
|
using namespace jit;
|
|
|
|
static bool
|
|
IsAlignmentMask(uint32_t m)
|
|
{
|
|
// Test whether m is just leading ones and trailing zeros.
|
|
return (-m & ~m) == 0;
|
|
}
|
|
|
|
static void
|
|
AnalyzeAsmHeapAddress(MDefinition* ptr, MIRGraph& graph)
|
|
{
|
|
// Fold (a+i)&m to (a&m)+i, provided that this doesn't change the result,
|
|
// since the users of the BitAnd include heap accesses. This will expose
|
|
// the redundancy for GVN when expressions like this:
|
|
// a&m
|
|
// (a+1)&m,
|
|
// (a+2)&m,
|
|
// are transformed into this:
|
|
// a&m
|
|
// (a&m)+1
|
|
// (a&m)+2
|
|
// and it will allow the constants to be folded by the
|
|
// EffectiveAddressAnalysis pass.
|
|
//
|
|
// Putting the add on the outside might seem like it exposes other users of
|
|
// the expression to the possibility of i32 overflow, if we aren't in asm.js
|
|
// and they aren't naturally truncating. However, since we use MAdd::NewAsmJS
|
|
// with MIRType_Int32, we make sure that the value is truncated, just as it
|
|
// would be by the MBitAnd.
|
|
|
|
if (!ptr->isBitAnd())
|
|
return;
|
|
|
|
MDefinition* lhs = ptr->toBitAnd()->getOperand(0);
|
|
MDefinition* rhs = ptr->toBitAnd()->getOperand(1);
|
|
if (lhs->isConstantValue())
|
|
mozilla::Swap(lhs, rhs);
|
|
if (!lhs->isAdd() || !rhs->isConstantValue())
|
|
return;
|
|
|
|
MDefinition* op0 = lhs->toAdd()->getOperand(0);
|
|
MDefinition* op1 = lhs->toAdd()->getOperand(1);
|
|
if (op0->isConstantValue())
|
|
mozilla::Swap(op0, op1);
|
|
if (!op1->isConstantValue())
|
|
return;
|
|
|
|
uint32_t i = op1->constantValue().toInt32();
|
|
uint32_t m = rhs->constantValue().toInt32();
|
|
if (!IsAlignmentMask(m) || (i & m) != i)
|
|
return;
|
|
|
|
// The pattern was matched! Produce the replacement expression.
|
|
MInstruction* and_ = MBitAnd::NewAsmJS(graph.alloc(), op0, rhs);
|
|
ptr->block()->insertBefore(ptr->toBitAnd(), and_);
|
|
MInstruction* add = MAdd::NewAsmJS(graph.alloc(), and_, op1, MIRType_Int32);
|
|
ptr->block()->insertBefore(ptr->toBitAnd(), add);
|
|
ptr->replaceAllUsesWith(add);
|
|
ptr->block()->discard(ptr->toBitAnd());
|
|
}
|
|
|
|
bool
|
|
AlignmentMaskAnalysis::analyze()
|
|
{
|
|
for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
|
|
for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
|
|
// Note that we don't check for MAsmJSCompareExchangeHeap
|
|
// or MAsmJSAtomicBinopHeap, because the backend and the OOB
|
|
// mechanism don't support non-zero offsets for them yet.
|
|
if (i->isAsmJSLoadHeap())
|
|
AnalyzeAsmHeapAddress(i->toAsmJSLoadHeap()->ptr(), graph_);
|
|
else if (i->isAsmJSStoreHeap())
|
|
AnalyzeAsmHeapAddress(i->toAsmJSStoreHeap()->ptr(), graph_);
|
|
}
|
|
}
|
|
return true;
|
|
}
|