mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1135039: Generalize swizzle MIR node to SimdGeneralShuffle; r=sunfish
This commit is contained in:
parent
85af73e764
commit
6a2263406f
@ -2732,7 +2732,7 @@ class FunctionCompiler
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MSimdSwizzle *ins = MSimdSwizzle::NewAsmJS(alloc(), vector, type, X, Y, Z, W);
|
||||
MSimdSwizzle *ins = MSimdSwizzle::New(alloc(), vector, type, X, Y, Z, W);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@ -2743,7 +2743,7 @@ class FunctionCompiler
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MInstruction *ins = MSimdShuffle::NewAsmJS(alloc(), lhs, rhs, type, X, Y, Z, W);
|
||||
MInstruction *ins = MSimdShuffle::New(alloc(), lhs, rhs, type, X, Y, Z, W);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
@ -242,13 +242,13 @@
|
||||
_(not) \
|
||||
_(neg) \
|
||||
_(swizzle) \
|
||||
_(shuffle) \
|
||||
_(load) \
|
||||
_(store) \
|
||||
_(check)
|
||||
#define FOREACH_COMMONX4_SIMD_OP(_) \
|
||||
ION_COMMONX4_SIMD_OP(_) \
|
||||
COMP_COMMONX4_TO_INT32X4_SIMD_OP(_) \
|
||||
_(shuffle) \
|
||||
_(loadX) \
|
||||
_(loadXY) \
|
||||
_(loadXYZ) \
|
||||
|
81
js/src/jit-test/tests/SIMD/shuffle.js
Normal file
81
js/src/jit-test/tests/SIMD/shuffle.js
Normal file
@ -0,0 +1,81 @@
|
||||
if (!this.hasOwnProperty("SIMD"))
|
||||
quit();
|
||||
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var i1 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var i2 = SIMD.int32x4(5, 6, 7, 8);
|
||||
|
||||
var leet = Math.fround(13.37);
|
||||
var f1 = SIMD.float32x4(-.5, -0, Infinity, leet);
|
||||
var f2 = SIMD.float32x4(42, .5, 23, -10);
|
||||
|
||||
// computes all rotations of a given array
|
||||
function *gen(arr) {
|
||||
var previous = arr.slice().splice(0, 4);
|
||||
var i = 4;
|
||||
for (var j = 0; j < 8; j++) {
|
||||
yield previous.slice();
|
||||
previous = previous.splice(1, previous.length - 1);
|
||||
previous.push(arr[i]);
|
||||
i = (i + 1) % arr.length;
|
||||
}
|
||||
}
|
||||
|
||||
var compI = [];
|
||||
for (var k of gen([i1.x, i1.y, i1.z, i1.w, i2.x, i2.y, i2.z, i2.w]))
|
||||
compI.push(k);
|
||||
|
||||
var compF = [];
|
||||
for (var k of gen([f1.x, f1.y, f1.z, f1.w, f2.x, f2.y, f2.z, f2.w]))
|
||||
compF.push(k);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
// Variable lanes
|
||||
var r = SIMD.float32x4.shuffle(f1, f2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8);
|
||||
assertEqX4(r, compF[i % 8]);
|
||||
|
||||
// Constant lanes
|
||||
assertEqX4(SIMD.float32x4.shuffle(f1, f2, 3, 2, 4, 5), [leet, Infinity, 42, .5]);
|
||||
|
||||
// Variable lanes
|
||||
var r = SIMD.int32x4.shuffle(i1, i2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8);
|
||||
assertEqX4(r, compI[i % 8]);
|
||||
|
||||
// Constant lanes
|
||||
assertEqX4(SIMD.int32x4.shuffle(i1, i2, 3, 2, 4, 5), [4, 3, 5, 6]);
|
||||
}
|
||||
}
|
||||
|
||||
function testBailouts(uglyDuckling) {
|
||||
var i1 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var i2 = SIMD.int32x4(5, 6, 7, 8);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
// Test bailouts
|
||||
var value = i == 149 ? uglyDuckling : 3;
|
||||
var caught = false;
|
||||
try {
|
||||
assertEqX4(SIMD.int32x4.shuffle(i1, i2, value, 2, 4, 5), [4, 3, 5, 6]);
|
||||
} catch(e) {
|
||||
print(e);
|
||||
caught = true;
|
||||
assertEq(i, 149);
|
||||
assertEq(e instanceof TypeError, true);
|
||||
}
|
||||
assertEq(i < 149 || caught, true);
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
testBailouts(-1);
|
||||
testBailouts(8);
|
||||
testBailouts(2.5);
|
||||
testBailouts(undefined);
|
||||
testBailouts(null);
|
||||
testBailouts({});
|
||||
testBailouts('one');
|
||||
testBailouts(true);
|
@ -832,7 +832,8 @@ class IonBuilder
|
||||
InliningStatus inlineSimdWith(CallInfo &callInfo, JSNative native, SimdLane lane,
|
||||
SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdSplat(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdSwizzle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdShuffle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type,
|
||||
unsigned numVectors, unsigned numLanes);
|
||||
InliningStatus inlineSimdCheck(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdConvert(CallInfo &callInfo, JSNative native, bool isCast,
|
||||
SimdTypeDescr::Type from, SimdTypeDescr::Type to);
|
||||
|
@ -374,46 +374,43 @@ class LSimdSwizzleF : public LSimdSwizzleBase
|
||||
{}
|
||||
};
|
||||
|
||||
class LSimdGeneralSwizzleBase : public LInstructionHelper<1, 5, 1>
|
||||
class LSimdGeneralShuffleBase : public LVariadicInstruction<1, 1>
|
||||
{
|
||||
public:
|
||||
LSimdGeneralSwizzleBase(const LAllocation &base, const LAllocation lanes[4],
|
||||
const LDefinition &temp)
|
||||
{
|
||||
setOperand(0, base);
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
setOperand(1 + i, lanes[i]);
|
||||
explicit LSimdGeneralShuffleBase(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation *base() {
|
||||
return getOperand(0);
|
||||
const LAllocation *vector(unsigned i) {
|
||||
MOZ_ASSERT(i < mir()->numVectors());
|
||||
return getOperand(i);
|
||||
}
|
||||
const LAllocation *lane(size_t i) {
|
||||
return getOperand(1 + i);
|
||||
const LAllocation *lane(unsigned i) {
|
||||
MOZ_ASSERT(i < mir()->numLanes());
|
||||
return getOperand(mir()->numVectors() + i);
|
||||
}
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
MSimdGeneralShuffle *mir() const {
|
||||
return mir_->toSimdGeneralShuffle();
|
||||
}
|
||||
};
|
||||
|
||||
class LSimdGeneralSwizzleI : public LSimdGeneralSwizzleBase
|
||||
class LSimdGeneralShuffleI : public LSimdGeneralShuffleBase
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SimdGeneralSwizzleI);
|
||||
LSimdGeneralSwizzleI(const LAllocation &base, const LAllocation lanes[4],
|
||||
const LDefinition &temp)
|
||||
: LSimdGeneralSwizzleBase(base, lanes, temp)
|
||||
LIR_HEADER(SimdGeneralShuffleI);
|
||||
explicit LSimdGeneralShuffleI(const LDefinition &temp)
|
||||
: LSimdGeneralShuffleBase(temp)
|
||||
{}
|
||||
};
|
||||
|
||||
class LSimdGeneralSwizzleF : public LSimdGeneralSwizzleBase
|
||||
class LSimdGeneralShuffleF : public LSimdGeneralShuffleBase
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SimdGeneralSwizzleF);
|
||||
LSimdGeneralSwizzleF(const LAllocation &base, const LAllocation lanes[4],
|
||||
const LDefinition &temp)
|
||||
: LSimdGeneralSwizzleBase(base, lanes, temp)
|
||||
LIR_HEADER(SimdGeneralShuffleF);
|
||||
explicit LSimdGeneralShuffleF(const LDefinition &temp)
|
||||
: LSimdGeneralShuffleBase(temp)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -28,8 +28,8 @@
|
||||
_(SimdInsertElementI) \
|
||||
_(SimdInsertElementF) \
|
||||
_(SimdSignMaskX4) \
|
||||
_(SimdGeneralSwizzleI) \
|
||||
_(SimdGeneralSwizzleF) \
|
||||
_(SimdGeneralShuffleI) \
|
||||
_(SimdGeneralShuffleF) \
|
||||
_(SimdSwizzleI) \
|
||||
_(SimdSwizzleF) \
|
||||
_(SimdShuffle) \
|
||||
|
@ -3957,28 +3957,33 @@ LIRGenerator::visitSimdSwizzle(MSimdSwizzle *ins)
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitSimdGeneralSwizzle(MSimdGeneralSwizzle *ins)
|
||||
LIRGenerator::visitSimdGeneralShuffle(MSimdGeneralShuffle*ins)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(ins->input()->type()));
|
||||
MOZ_ASSERT(IsSimdType(ins->type()));
|
||||
|
||||
LAllocation lanesUses[4];
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
lanesUses[i] = use(ins->lane(i));
|
||||
LSimdGeneralShuffleBase *lir;
|
||||
if (ins->type() == MIRType_Int32x4)
|
||||
lir = new (alloc()) LSimdGeneralShuffleI(temp());
|
||||
else if (ins->type() == MIRType_Float32x4)
|
||||
lir = new (alloc()) LSimdGeneralShuffleF(temp());
|
||||
else
|
||||
MOZ_CRASH("Unknown SIMD kind when doing a shuffle");
|
||||
|
||||
if (ins->input()->type() == MIRType_Int32x4) {
|
||||
LSimdGeneralSwizzleI *lir = new (alloc()) LSimdGeneralSwizzleI(useRegister(ins->input()),
|
||||
lanesUses, temp());
|
||||
assignSnapshot(lir, Bailout_BoundsCheck);
|
||||
define(lir, ins);
|
||||
} else if (ins->input()->type() == MIRType_Float32x4) {
|
||||
LSimdGeneralSwizzleF *lir = new (alloc()) LSimdGeneralSwizzleF(useRegister(ins->input()),
|
||||
lanesUses, temp());
|
||||
assignSnapshot(lir, Bailout_BoundsCheck);
|
||||
define(lir, ins);
|
||||
} else {
|
||||
MOZ_CRASH("Unknown SIMD kind when getting lane");
|
||||
if (!lir->init(alloc(), ins->numVectors() + ins->numLanes()))
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < ins->numVectors(); i++) {
|
||||
MOZ_ASSERT(IsSimdType(ins->vector(i)->type()));
|
||||
lir->setOperand(i, useRegister(ins->vector(i)));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < ins->numLanes(); i++) {
|
||||
MOZ_ASSERT(ins->lane(i)->type() == MIRType_Int32);
|
||||
lir->setOperand(i + ins->numVectors(), useRegister(ins->lane(i)));
|
||||
}
|
||||
|
||||
assignSnapshot(lir, Bailout_BoundsCheck);
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -269,7 +269,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitSimdInsertElement(MSimdInsertElement *ins);
|
||||
void visitSimdSignMask(MSimdSignMask *ins);
|
||||
void visitSimdSwizzle(MSimdSwizzle *ins);
|
||||
void visitSimdGeneralSwizzle(MSimdGeneralSwizzle *ins);
|
||||
void visitSimdGeneralShuffle(MSimdGeneralShuffle *ins);
|
||||
void visitSimdShuffle(MSimdShuffle *ins);
|
||||
void visitSimdUnaryArith(MSimdUnaryArith *ins);
|
||||
void visitSimdBinaryComp(MSimdBinaryComp *ins);
|
||||
|
@ -351,9 +351,13 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target)
|
||||
return inlineSimdSelect(callInfo, native, IsElementWise(false), SimdTypeDescr::TYPE_FLOAT32);
|
||||
|
||||
if (native == js::simd_int32x4_swizzle)
|
||||
return inlineSimdSwizzle(callInfo, native, SimdTypeDescr::TYPE_INT32);
|
||||
return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_INT32, 1, 4);
|
||||
if (native == js::simd_float32x4_swizzle)
|
||||
return inlineSimdSwizzle(callInfo, native, SimdTypeDescr::TYPE_FLOAT32);
|
||||
return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_FLOAT32, 1, 4);
|
||||
if (native == js::simd_int32x4_shuffle)
|
||||
return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_INT32, 2, 4);
|
||||
if (native == js::simd_float32x4_shuffle)
|
||||
return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_FLOAT32, 2, 4);
|
||||
|
||||
if (native == js::simd_int32x4_load)
|
||||
return inlineSimdLoad(callInfo, native, SimdTypeDescr::TYPE_INT32);
|
||||
@ -3113,18 +3117,24 @@ IonBuilder::inlineSimdCheck(CallInfo &callInfo, JSNative native, SimdTypeDescr::
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdSwizzle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type)
|
||||
IonBuilder::inlineSimdShuffle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type,
|
||||
unsigned numVectors, unsigned numLanes)
|
||||
{
|
||||
InlineTypedObject *templateObj = nullptr;
|
||||
if (!checkInlineSimd(callInfo, native, type, 5, &templateObj))
|
||||
if (!checkInlineSimd(callInfo, native, type, numVectors + numLanes, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition *lanes[4];
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
lanes[i] = callInfo.getArg(1 + i);
|
||||
|
||||
MIRType mirType = SimdTypeDescrToMIRType(type);
|
||||
MSimdGeneralSwizzle *ins = MSimdGeneralSwizzle::New(alloc(), callInfo.getArg(0), lanes, mirType);
|
||||
MSimdGeneralShuffle *ins = MSimdGeneralShuffle::New(alloc(), numVectors, numLanes, mirType);
|
||||
|
||||
if (!ins->init(alloc()))
|
||||
return InliningStatus_Error;
|
||||
|
||||
for (unsigned i = 0; i < numVectors; i++)
|
||||
ins->setVector(i, callInfo.getArg(i));
|
||||
for (size_t i = 0; i < numLanes; i++)
|
||||
ins->setLane(i, callInfo.getArg(numVectors + i));
|
||||
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
|
@ -965,17 +965,26 @@ MSimdSwizzle::foldsTo(TempAllocator &alloc)
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
MSimdGeneralSwizzle::foldsTo(TempAllocator &alloc)
|
||||
MSimdGeneralShuffle::foldsTo(TempAllocator &alloc)
|
||||
{
|
||||
int32_t lanes[4];
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
FixedList<uint32_t> lanes;
|
||||
if (!lanes.init(alloc, numLanes()))
|
||||
return this;
|
||||
|
||||
for (size_t i = 0; i < numLanes(); i++) {
|
||||
if (!lane(i)->isConstant() || lane(i)->type() != MIRType_Int32)
|
||||
return this;
|
||||
lanes[i] = lane(i)->toConstant()->value().toInt32();
|
||||
if (lanes[i] < 0 || lanes[i] >= 4)
|
||||
int32_t temp = lane(i)->toConstant()->value().toInt32();
|
||||
if (temp < 0 || uint32_t(temp) >= numLanes() * numVectors())
|
||||
return this;
|
||||
lanes[i] = uint32_t(temp);
|
||||
}
|
||||
return MSimdSwizzle::New(alloc, input(), type(), lanes[0], lanes[1], lanes[2], lanes[3]);
|
||||
|
||||
if (numVectors() == 1)
|
||||
return MSimdSwizzle::New(alloc, vector(0), type(), lanes[0], lanes[1], lanes[2], lanes[3]);
|
||||
|
||||
MOZ_ASSERT(numVectors() == 2);
|
||||
return MSimdShuffle::New(alloc, vector(0), vector(1), type(), lanes[0], lanes[1], lanes[2], lanes[3]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -1814,12 +1814,6 @@ class MSimdSwizzle
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdSwizzle)
|
||||
|
||||
static MSimdSwizzle *NewAsmJS(TempAllocator &alloc, MDefinition *obj, MIRType type,
|
||||
uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
|
||||
{
|
||||
return new(alloc) MSimdSwizzle(obj, type, laneX, laneY, laneZ, laneW);
|
||||
}
|
||||
|
||||
static MSimdSwizzle *New(TempAllocator &alloc, MDefinition *obj, MIRType type,
|
||||
uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
|
||||
{
|
||||
@ -1842,23 +1836,24 @@ class MSimdSwizzle
|
||||
ALLOW_CLONE(MSimdSwizzle)
|
||||
};
|
||||
|
||||
// A "general swizzle" is a swizzle with non-constant lane indices. This is the
|
||||
// one that Ion inlines and it can be folded into a MSimdSwizzle if lane indices
|
||||
// are constant. Performance of general swizzle does not really matter, as we
|
||||
// expect to always get constant indices.
|
||||
class MSimdGeneralSwizzle :
|
||||
public MAryInstruction<5>,
|
||||
public SimdSwizzlePolicy::Data
|
||||
// A "general swizzle" is a swizzle or a shuffle with non-constant lane
|
||||
// indices. This is the one that Ion inlines and it can be folded into a
|
||||
// MSimdSwizzle/MSimdShuffle if lane indices are constant. Performance of
|
||||
// general swizzle/shuffle does not really matter, as we expect to get
|
||||
// constant indices most of the time.
|
||||
class MSimdGeneralShuffle :
|
||||
public MVariadicInstruction,
|
||||
public SimdShufflePolicy::Data
|
||||
{
|
||||
unsigned numVectors_;
|
||||
unsigned numLanes_;
|
||||
|
||||
protected:
|
||||
MSimdGeneralSwizzle(MDefinition *vec, MDefinition *lanes[4], MIRType type)
|
||||
MSimdGeneralShuffle(unsigned numVectors, unsigned numLanes, MIRType type)
|
||||
: numVectors_(numVectors), numLanes_(numLanes)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
MOZ_ASSERT(SimdTypeToLength(type) == 4);
|
||||
|
||||
initOperand(0, vec);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
initOperand(1 + i, lanes[i]);
|
||||
MOZ_ASSERT(SimdTypeToLength(type) == numLanes_);
|
||||
|
||||
setResultType(type);
|
||||
specialization_ = type;
|
||||
@ -1866,24 +1861,48 @@ class MSimdGeneralSwizzle :
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdGeneralSwizzle);
|
||||
ALLOW_CLONE(MSimdGeneralSwizzle);
|
||||
INSTRUCTION_HEADER(SimdGeneralShuffle);
|
||||
|
||||
static MSimdGeneralSwizzle *New(TempAllocator &alloc, MDefinition *vec, MDefinition *lanes[4],
|
||||
static MSimdGeneralShuffle *New(TempAllocator &alloc, unsigned numVectors, unsigned numLanes,
|
||||
MIRType type)
|
||||
{
|
||||
return new(alloc) MSimdGeneralSwizzle(vec, lanes, type);
|
||||
return new(alloc) MSimdGeneralShuffle(numVectors, numLanes, type);
|
||||
}
|
||||
|
||||
MDefinition *input() const {
|
||||
return getOperand(0);
|
||||
bool init(TempAllocator &alloc) {
|
||||
return MVariadicInstruction::init(alloc, numVectors_ + numLanes_);
|
||||
}
|
||||
MDefinition *lane(size_t i) const {
|
||||
return getOperand(1 + i);
|
||||
void setVector(unsigned i, MDefinition* vec) {
|
||||
MOZ_ASSERT(i < numVectors_);
|
||||
initOperand(i, vec);
|
||||
}
|
||||
void setLane(unsigned i, MDefinition* laneIndex) {
|
||||
MOZ_ASSERT(i < numLanes_);
|
||||
initOperand(numVectors_ + i, laneIndex);
|
||||
}
|
||||
|
||||
unsigned numVectors() const {
|
||||
return numVectors_;
|
||||
}
|
||||
unsigned numLanes() const {
|
||||
return numLanes_;
|
||||
}
|
||||
MDefinition *vector(unsigned i) const {
|
||||
MOZ_ASSERT(i < numVectors_);
|
||||
return getOperand(i);
|
||||
}
|
||||
MDefinition *lane(unsigned i) const {
|
||||
MOZ_ASSERT(i < numLanes_);
|
||||
return getOperand(numVectors_ + i);
|
||||
}
|
||||
|
||||
bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
if (!ins->isSimdGeneralShuffle())
|
||||
return false;
|
||||
const MSimdGeneralShuffle *other = ins->toSimdGeneralShuffle();
|
||||
return numVectors_ == other->numVectors() &&
|
||||
numLanes_ == other->numLanes() &&
|
||||
congruentIfOperandsEqual(other);
|
||||
}
|
||||
|
||||
MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
@ -1918,9 +1937,9 @@ class MSimdShuffle
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdShuffle)
|
||||
|
||||
static MInstruction *NewAsmJS(TempAllocator &alloc, MDefinition *lhs, MDefinition *rhs,
|
||||
MIRType type, uint32_t laneX, uint32_t laneY, uint32_t laneZ,
|
||||
uint32_t laneW)
|
||||
static MInstruction *New(TempAllocator &alloc, MDefinition *lhs, MDefinition *rhs,
|
||||
MIRType type, uint32_t laneX, uint32_t laneY, uint32_t laneZ,
|
||||
uint32_t laneW)
|
||||
{
|
||||
// Swap operands so that new lanes come from LHS in majority.
|
||||
// In the balanced case, swap operands if needs be, in order to be able
|
||||
@ -1936,7 +1955,7 @@ class MSimdShuffle
|
||||
|
||||
// If all lanes come from the same vector, just use swizzle instead.
|
||||
if (laneX < 4 && laneY < 4 && laneZ < 4 && laneW < 4)
|
||||
return MSimdSwizzle::NewAsmJS(alloc, lhs, type, laneX, laneY, laneZ, laneW);
|
||||
return MSimdSwizzle::New(alloc, lhs, type, laneX, laneY, laneZ, laneW);
|
||||
|
||||
return new(alloc) MSimdShuffle(lhs, rhs, type, laneX, laneY, laneZ, laneW);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace jit {
|
||||
_(SimdInsertElement) \
|
||||
_(SimdSignMask) \
|
||||
_(SimdSwizzle) \
|
||||
_(SimdGeneralSwizzle) \
|
||||
_(SimdGeneralShuffle) \
|
||||
_(SimdShuffle) \
|
||||
_(SimdUnaryArith) \
|
||||
_(SimdBinaryComp) \
|
||||
|
@ -786,23 +786,26 @@ template bool
|
||||
SimdPolicy<0>::adjustInputs(TempAllocator &alloc, MInstruction *ins);
|
||||
|
||||
bool
|
||||
SimdSwizzlePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
SimdShufflePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
{
|
||||
MIRType specialization = ins->typePolicySpecialization();
|
||||
|
||||
// First input is the vector input.
|
||||
if (!MaybeSimdUnbox(alloc, ins, specialization, 0))
|
||||
return false;
|
||||
MSimdGeneralShuffle *s = ins->toSimdGeneralShuffle();
|
||||
|
||||
for (unsigned i = 0; i < s->numVectors(); i++) {
|
||||
if (!MaybeSimdUnbox(alloc, ins, specialization, i))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Next inputs are the lanes, which need to be int32
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
MDefinition *in = ins->getOperand(i + 1);
|
||||
for (unsigned i = 0; i < s->numLanes(); i++) {
|
||||
MDefinition *in = ins->getOperand(s->numVectors() + i);
|
||||
if (in->type() == MIRType_Int32)
|
||||
continue;
|
||||
|
||||
MInstruction *replace = MToInt32::New(alloc, in, MacroAssembler::IntConversion_NumbersOnly);
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(i + 1, replace);
|
||||
ins->replaceOperand(s->numVectors() + i, replace);
|
||||
if (!replace->typePolicy()->adjustInputs(alloc, replace))
|
||||
return false;
|
||||
}
|
||||
@ -1115,7 +1118,7 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
_(PowPolicy) \
|
||||
_(SimdAllPolicy) \
|
||||
_(SimdSelectPolicy) \
|
||||
_(SimdSwizzlePolicy) \
|
||||
_(SimdShufflePolicy) \
|
||||
_(StoreTypedArrayElementStaticPolicy) \
|
||||
_(StoreTypedArrayHolePolicy) \
|
||||
_(StoreUnboxedScalarPolicy) \
|
||||
|
@ -330,7 +330,7 @@ class SimdSelectPolicy MOZ_FINAL : public TypePolicy
|
||||
virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class SimdSwizzlePolicy MOZ_FINAL : public TypePolicy
|
||||
class SimdShufflePolicy MOZ_FINAL : public TypePolicy
|
||||
{
|
||||
public:
|
||||
SPECIALIZATION_DATA_;
|
||||
|
@ -245,8 +245,8 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
||||
void visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralShuffleI(LSimdGeneralShuffleI *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralShuffleF(LSimdGeneralShuffleF *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSwizzleI(LSimdSwizzleI *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSwizzleF(LSimdSwizzleF *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
|
@ -290,8 +290,8 @@ class CodeGeneratorMIPS : public CodeGeneratorShared
|
||||
void visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralShuffleI(LSimdGeneralShuffleI *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdGeneralShuffleF(LSimdGeneralShuffleF *lir) { MOZ_CRASH("NYI"); }
|
||||
};
|
||||
|
||||
typedef CodeGeneratorMIPS CodeGeneratorSpecific;
|
||||
|
@ -2386,24 +2386,28 @@ CodeGeneratorX86Shared::visitSimdSignMaskX4(LSimdSignMaskX4 *ins)
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorX86Shared::visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *ins)
|
||||
CodeGeneratorX86Shared::visitSimdGeneralShuffleI(LSimdGeneralShuffleI *ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->base());
|
||||
MSimdGeneralShuffle *mir = ins->mir();
|
||||
unsigned numVectors = mir->numVectors();
|
||||
|
||||
Register temp = ToRegister(ins->temp());
|
||||
|
||||
// This won't generate fast code, but it's fine because we expect users
|
||||
// to have used constant indices (and thus MSimdGeneralSwizzle to be fold
|
||||
// into MSimdSwizzle, which are fast).
|
||||
masm.reserveStack(Simd128DataSize * 2);
|
||||
// to have used constant indices (and thus MSimdGeneralShuffle to be fold
|
||||
// into MSimdSwizzle/MSimdShuffle, which are fast).
|
||||
masm.reserveStack(Simd128DataSize * numVectors);
|
||||
|
||||
masm.storeAlignedInt32x4(input, Address(StackPointer, Simd128DataSize));
|
||||
for (unsigned i = 0; i < numVectors; i++)
|
||||
masm.storeAlignedInt32x4(ToFloatRegister(ins->vector(i)),
|
||||
Address(StackPointer, Simd128DataSize * (1 + i)));
|
||||
|
||||
Label bail;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t i = 0; i < mir->numLanes(); i++) {
|
||||
Operand lane = ToOperand(ins->lane(i));
|
||||
|
||||
masm.cmp32(lane, Imm32(3));
|
||||
masm.cmp32(lane, Imm32(mir->numVectors() * mir->numLanes() - 1));
|
||||
masm.j(Assembler::Above, &bail);
|
||||
|
||||
if (lane.kind() == Operand::REG) {
|
||||
@ -2425,37 +2429,43 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *ins)
|
||||
|
||||
{
|
||||
masm.bind(&bail);
|
||||
masm.freeStack(Simd128DataSize * 2);
|
||||
masm.freeStack(Simd128DataSize * numVectors);
|
||||
bailout(ins->snapshot());
|
||||
}
|
||||
|
||||
masm.bind(&join);
|
||||
masm.setFramePushed(masm.framePushed() + Simd128DataSize * 2);
|
||||
masm.freeStack(Simd128DataSize * 2);
|
||||
masm.setFramePushed(masm.framePushed() + Simd128DataSize * numVectors);
|
||||
masm.freeStack(Simd128DataSize * numVectors);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorX86Shared::visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *ins)
|
||||
CodeGeneratorX86Shared::visitSimdGeneralShuffleF(LSimdGeneralShuffleF *ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->base());
|
||||
MSimdGeneralShuffle *mir = ins->mir();
|
||||
unsigned numVectors = mir->numVectors();
|
||||
|
||||
Register temp = ToRegister(ins->temp());
|
||||
|
||||
// See comment in the visitSimdGeneralSwizzleI.
|
||||
masm.reserveStack(Simd128DataSize * 2);
|
||||
// This won't generate fast code, but it's fine because we expect users
|
||||
// to have used constant indices (and thus MSimdGeneralShuffle to be fold
|
||||
// into MSimdSwizzle/MSimdShuffle, which are fast).
|
||||
masm.reserveStack(Simd128DataSize * numVectors);
|
||||
|
||||
masm.storeAlignedFloat32x4(input, Address(StackPointer, Simd128DataSize));
|
||||
for (unsigned i = 0; i < numVectors; i++)
|
||||
masm.storeAlignedFloat32x4(ToFloatRegister(ins->vector(i)),
|
||||
Address(StackPointer, Simd128DataSize * (1 + i)));
|
||||
|
||||
Label bail;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t i = 0; i < mir->numLanes(); i++) {
|
||||
Operand lane = ToOperand(ins->lane(i));
|
||||
|
||||
masm.cmp32(lane, Imm32(3));
|
||||
masm.cmp32(lane, Imm32(mir->numVectors() * mir->numLanes() - 1));
|
||||
masm.j(Assembler::Above, &bail);
|
||||
|
||||
if (lane.kind() == Operand::REG) {
|
||||
masm.loadFloat32(Operand(StackPointer, ToRegister(ins->lane(i)), TimesFour, Simd128DataSize),
|
||||
ScratchFloat32Reg);
|
||||
ScratchFloat32Reg);
|
||||
} else {
|
||||
masm.load32(lane, temp);
|
||||
masm.loadFloat32(Operand(StackPointer, temp, TimesFour, Simd128DataSize), ScratchFloat32Reg);
|
||||
@ -2472,13 +2482,13 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *ins)
|
||||
|
||||
{
|
||||
masm.bind(&bail);
|
||||
masm.freeStack(Simd128DataSize * 2);
|
||||
masm.freeStack(Simd128DataSize * numVectors);
|
||||
bailout(ins->snapshot());
|
||||
}
|
||||
|
||||
masm.bind(&join);
|
||||
masm.setFramePushed(masm.framePushed() + Simd128DataSize * 2);
|
||||
masm.freeStack(Simd128DataSize * 2);
|
||||
masm.setFramePushed(masm.framePushed() + Simd128DataSize * numVectors);
|
||||
masm.freeStack(Simd128DataSize * numVectors);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -258,8 +258,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||
void visitSimdInsertElementI(LSimdInsertElementI *lir);
|
||||
void visitSimdInsertElementF(LSimdInsertElementF *lir);
|
||||
void visitSimdSignMaskX4(LSimdSignMaskX4 *ins);
|
||||
void visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *lir);
|
||||
void visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *lir);
|
||||
void visitSimdGeneralShuffleI(LSimdGeneralShuffleI *lir);
|
||||
void visitSimdGeneralShuffleF(LSimdGeneralShuffleF *lir);
|
||||
void visitSimdSwizzleI(LSimdSwizzleI *lir);
|
||||
void visitSimdSwizzleF(LSimdSwizzleF *lir);
|
||||
void visitSimdShuffle(LSimdShuffle *lir);
|
||||
|
Loading…
Reference in New Issue
Block a user