Bug 1137573 - OdinMonkey: Alignment Mask Analysis r=luke

This commit is contained in:
Dan Gohman 2015-02-26 22:17:51 -08:00
parent 74b74f6f58
commit ebb2d05ec1
11 changed files with 149 additions and 30 deletions

View File

@ -0,0 +1,89 @@
/* -*- 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, 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.
if (!ptr->isBitAnd())
return;
MDefinition *lhs = ptr->toBitAnd()->getOperand(0);
MDefinition *rhs = ptr->toBitAnd()->getOperand(1);
int lhsIndex = 0;
if (lhs->isConstantValue()) {
mozilla::Swap(lhs, rhs);
lhsIndex = 1;
}
if (!lhs->isAdd() || !lhs->hasOneUse() || !rhs->isConstantValue())
return;
MDefinition *op0 = lhs->toAdd()->getOperand(0);
MDefinition *op1 = lhs->toAdd()->getOperand(1);
int op0Index = 0;
if (op0->isConstantValue()) {
mozilla::Swap(op0, op1);
op0Index = 1;
}
if (!op1->isConstantValue())
return;
uint32_t i = op1->constantValue().toInt32();
uint32_t m = rhs->constantValue().toInt32();
if (!IsAlignmentMask(m) || ((i & m) != i))
return;
ptr->replaceAllUsesWith(lhs);
ptr->toBitAnd()->replaceOperand(lhsIndex, op0);
lhs->toAdd()->replaceOperand(op0Index, ptr);
MInstructionIterator iter = ptr->block()->begin(ptr->toBitAnd());
++iter;
lhs->block()->moveBefore(*iter, lhs->toAdd());
}
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;
}

View File

@ -0,0 +1,30 @@
/* -*- 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/. */
#ifndef jit_AlignmentMaskAnalysis_h
#define jit_AlignmentMaskAnalysis_h
namespace js {
namespace jit {
class MIRGraph;
class AlignmentMaskAnalysis
{
MIRGraph &graph_;
public:
explicit AlignmentMaskAnalysis(MIRGraph &graph)
: graph_(graph)
{}
bool analyze();
};
} /* namespace jit */
} /* namespace js */
#endif /* jit_AlignmentMaskAnalysis_h */

View File

@ -89,13 +89,6 @@ AnalyzeLsh(TempAllocator &alloc, MLsh *lsh)
last->block()->insertAfter(last, eaddr);
}
static bool
IsAlignmentMask(uint32_t m)
{
// Test whether m is just leading ones and trailing zeros.
return (-m & ~m) == 0;
}
template<typename MAsmJSHeapAccessType>
static void
AnalyzeAsmHeapAccess(MAsmJSHeapAccessType *ins, MIRGraph &graph)
@ -116,6 +109,8 @@ AnalyzeAsmHeapAccess(MAsmJSHeapAccessType *ins, MIRGraph &graph)
}
} else if (ptr->isAdd()) {
// Look for heap[a+i] where i is a constant offset, and fold the offset.
// Alignment masks have already been moved out of the way by the
// Alignment Mask Analysis pass.
MDefinition *op0 = ptr->toAdd()->getOperand(0);
MDefinition *op1 = ptr->toAdd()->getOperand(1);
if (op0->isConstantValue())
@ -125,29 +120,6 @@ AnalyzeAsmHeapAccess(MAsmJSHeapAccessType *ins, MIRGraph &graph)
if (ins->tryAddDisplacement(imm))
ins->replacePtr(op0);
}
} else if (ptr->isBitAnd() && ptr->hasOneUse()) {
// Transform heap[(a+i)&m] to heap[(a&m)+i] so that we can fold i into
// the access. Since we currently just mutate the BitAnd in place, this
// requires that we are its only user.
MDefinition *lhs = ptr->toBitAnd()->getOperand(0);
MDefinition *rhs = ptr->toBitAnd()->getOperand(1);
int lhsIndex = 0;
if (lhs->isConstantValue()) {
mozilla::Swap(lhs, rhs);
lhsIndex = 1;
}
if (lhs->isAdd() && rhs->isConstantValue()) {
MDefinition *op0 = lhs->toAdd()->getOperand(0);
MDefinition *op1 = lhs->toAdd()->getOperand(1);
if (op0->isConstantValue())
mozilla::Swap(op0, op1);
if (op1->isConstantValue()) {
uint32_t i = op1->constantValue().toInt32();
uint32_t m = rhs->constantValue().toInt32();
if (IsAlignmentMask(m) && ((i & m) == i) && ins->tryAddDisplacement(i))
ptr->toBitAnd()->replaceOperand(lhsIndex, op0);
}
}
}
}

View File

@ -14,6 +14,7 @@
#include "gc/Marking.h"
#include "jit/AliasAnalysis.h"
#include "jit/AlignmentMaskAnalysis.h"
#include "jit/BacktrackingAllocator.h"
#include "jit/BaselineFrame.h"
#include "jit/BaselineInspector.h"
@ -1248,6 +1249,18 @@ OptimizeMIR(MIRGenerator *mir)
return false;
}
if (mir->optimizationInfo().amaEnabled()) {
AutoTraceLog log(logger, TraceLogger_AlignmentMaskAnalysis);
AlignmentMaskAnalysis ama(graph);
if (!ama.analyze())
return false;
IonSpewPass("Alignment Mask Analysis");
AssertExtendedGraphCoherency(graph);
if (mir->shouldCancel("Alignment Mask Analysis"))
return false;
}
ValueNumberer gvn(mir, graph);
if (!gvn.init())
return false;

View File

@ -55,6 +55,7 @@ OptimizationInfo::initAsmjsOptimizationInfo()
// Take normal option values for not specified values.
initNormalOptimizationInfo();
ama_ = true;
level_ = Optimization_AsmJS;
edgeCaseAnalysis_ = false;
eliminateRedundantChecks_ = false;

View File

@ -49,6 +49,9 @@ class OptimizationInfo
// Toggles whether Effective Address Analysis is performed.
bool eaa_;
// Toggles whether Alignment Mask Analysis is performed.
bool ama_;
// Toggles whether Edge Case Analysis is used.
bool edgeCaseAnalysis_;
@ -167,6 +170,10 @@ class OptimizationInfo
return eaa_ && !js_JitOptions.disableEaa;
}
bool amaEnabled() const {
return ama_ && !js_JitOptions.disableAma;
}
bool edgeCaseAnalysisEnabled() const {
return edgeCaseAnalysis_ && !js_JitOptions.disableEdgeCaseAnalysis;
}

View File

@ -105,6 +105,9 @@ JitOptions::JitOptions()
// Toggles whether Effective Address Analysis is globally disabled.
SET_DEFAULT(disableEaa, false);
// Toggles whether Alignment Mask Analysis is globally disabled.
SET_DEFAULT(disableAma, false);
// Whether functions are compiled immediately.
SET_DEFAULT(eagerCompilation, false);

View File

@ -55,6 +55,7 @@ struct JitOptions
bool disableSink;
bool disableLoopUnrolling;
bool disableEaa;
bool disableAma;
bool eagerCompilation;
mozilla::Maybe<uint32_t> forcedDefaultIonWarmUpThreshold;
mozilla::Maybe<IonRegisterAllocator> forcedRegisterAllocator;

View File

@ -140,6 +140,7 @@ UNIFIED_SOURCES += [
'irregexp/RegExpParser.cpp',
'irregexp/RegExpStack.cpp',
'jit/AliasAnalysis.cpp',
'jit/AlignmentMaskAnalysis.cpp',
'jit/BacktrackingAllocator.cpp',
'jit/Bailouts.cpp',
'jit/BaselineBailouts.cpp',

View File

@ -683,6 +683,7 @@ TraceLoggerThreadState::init()
enabledTextIds[TraceLogger_RangeAnalysis] = true;
enabledTextIds[TraceLogger_LoopUnrolling] = true;
enabledTextIds[TraceLogger_EffectiveAddressAnalysis] = true;
enabledTextIds[TraceLogger_AlignmentMaskAnalysis] = true;
enabledTextIds[TraceLogger_EliminateDeadCode] = true;
enabledTextIds[TraceLogger_EdgeCaseAnalysis] = true;
enabledTextIds[TraceLogger_EliminateRedundantChecks] = true;

View File

@ -50,6 +50,7 @@
_(RangeAnalysis) \
_(LoopUnrolling) \
_(EffectiveAddressAnalysis) \
_(AlignmentMaskAnalysis) \
_(EliminateDeadCode) \
_(EdgeCaseAnalysis) \
_(EliminateRedundantChecks) \