1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/* -*- 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/EagerSimdUnbox.h"
#include "jit/MIR.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
namespace js {
namespace jit {
// Do not optimize any Phi instruction which has conflicting Unbox operations,
// as this might imply some intended polymorphism.
static bool
CanUnboxSimdPhi(const JitCompartment* jitCompartment, MPhi* phi, SimdType unboxType)
{
MOZ_ASSERT(phi->type() == MIRType::Object);
// If we are unboxing, we are more than likely to have boxed this SIMD type
// once in baseline, otherwise, we cannot create a MSimdBox as we have no
// template object to use.
if (!jitCompartment->maybeGetSimdTemplateObjectFor(unboxType))
return false;
MResumePoint* entry = phi->block()->entryResumePoint();
MIRType mirType = SimdTypeToMIRType(unboxType);
for (MUseIterator i(phi->usesBegin()), e(phi->usesEnd()); i != e; i++) {
// If we cannot recover the Simd object at the entry of the basic block,
// then we would have to box the content anyways.
if ((*i)->consumer() == entry && !entry->isRecoverableOperand(*i))
return false;
if (!(*i)->consumer()->isDefinition())
continue;
MDefinition* def = (*i)->consumer()->toDefinition();
if (def->isSimdUnbox() && def->toSimdUnbox()->type() != mirType)
return false;
}
return true;
}
static void
UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, SimdType unboxType)
{
TempAllocator& alloc = graph.alloc();
// Unbox and replace all operands.
for (size_t i = 0, e = phi->numOperands(); i < e; i++) {
MDefinition* op = phi->getOperand(i);
MSimdUnbox* unbox = MSimdUnbox::New(alloc, op, unboxType);
op->block()->insertAtEnd(unbox);
phi->replaceOperand(i, unbox);
}
// Change the MIRType of the Phi.
MIRType mirType = SimdTypeToMIRType(unboxType);
phi->setResultType(mirType);
MBasicBlock* phiBlock = phi->block();
MInstruction* atRecover = phiBlock->safeInsertTop(nullptr, MBasicBlock::IgnoreRecover);
MInstruction* at = phiBlock->safeInsertTop(atRecover);
// Note, we capture the uses-list now, as new instructions are not visited.
MUseIterator i(phi->usesBegin()), e(phi->usesEnd());
// Add a MSimdBox, and replace all the Phi uses with it.
JSObject* templateObject = jitCompartment->maybeGetSimdTemplateObjectFor(unboxType);
InlineTypedObject* inlineTypedObject = &templateObject->as<InlineTypedObject>();
MSimdBox* recoverBox = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
recoverBox->setRecoveredOnBailout();
phiBlock->insertBefore(atRecover, recoverBox);
MSimdBox* box = nullptr;
while (i != e) {
MUse* use = *i++;
MNode* ins = use->consumer();
if ((ins->isDefinition() && ins->toDefinition()->isRecoveredOnBailout()) ||
(ins->isResumePoint() && ins->toResumePoint()->isRecoverableOperand(use)))
{
use->replaceProducer(recoverBox);
continue;
}
if (!box) {
box = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
phiBlock->insertBefore(at, box);
}
use->replaceProducer(box);
}
}
bool
EagerSimdUnbox(MIRGenerator* mir, MIRGraph& graph)
{
const JitCompartment* jitCompartment = GetJitContext()->compartment->jitCompartment();
for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
if (mir->shouldCancel("Eager Simd Unbox"))
return false;
for (MInstructionReverseIterator ins = block->rbegin(); ins != block->rend(); ins++) {
if (!ins->isSimdUnbox())
continue;
MSimdUnbox* unbox = ins->toSimdUnbox();
if (!unbox->input()->isPhi())
continue;
MPhi* phi = unbox->input()->toPhi();
if (!CanUnboxSimdPhi(jitCompartment, phi, unbox->simdType()))
continue;
UnboxSimdPhi(jitCompartment, graph, phi, unbox->simdType());
}
}
return true;
}
} /* namespace jit */
} /* namespace js */
|