Bug 1059733: OdinMonkey SIMD: add support for bitwise operations; r=luke

This commit is contained in:
Benjamin Bouvier 2014-09-02 10:25:43 +02:00
parent a5374b9caf
commit edd045a2f7
4 changed files with 80 additions and 1 deletions

View File

@ -348,6 +348,9 @@ ValidateSimdOperation(JSContext *cx, AsmJSModule::Global &global, HandleValue gl
case AsmJSSimdOperation_lessThan: native = simd_int32x4_lessThan; break;
case AsmJSSimdOperation_greaterThan: native = simd_int32x4_greaterThan; break;
case AsmJSSimdOperation_equal: native = simd_int32x4_equal; break;
case AsmJSSimdOperation_and: native = simd_int32x4_and; break;
case AsmJSSimdOperation_or: native = simd_int32x4_or; break;
case AsmJSSimdOperation_xor: native = simd_int32x4_xor; break;
case AsmJSSimdOperation_lessThanOrEqual:
case AsmJSSimdOperation_greaterThanOrEqual:
case AsmJSSimdOperation_notEqual:
@ -369,6 +372,9 @@ ValidateSimdOperation(JSContext *cx, AsmJSModule::Global &global, HandleValue gl
case AsmJSSimdOperation_notEqual: native = simd_float32x4_notEqual ; break;
case AsmJSSimdOperation_greaterThan: native = simd_float32x4_greaterThan; break;
case AsmJSSimdOperation_greaterThanOrEqual: native = simd_float32x4_greaterThanOrEqual ; break;
case AsmJSSimdOperation_and: native = simd_float32x4_and; break;
case AsmJSSimdOperation_or: native = simd_float32x4_or; break;
case AsmJSSimdOperation_xor: native = simd_float32x4_xor; break;
}
break;
}

View File

@ -86,6 +86,9 @@ enum AsmJSSimdOperation
AsmJSSimdOperation_notEqual,
AsmJSSimdOperation_greaterThan,
AsmJSSimdOperation_greaterThanOrEqual,
AsmJSSimdOperation_and,
AsmJSSimdOperation_or,
AsmJSSimdOperation_xor,
};
// These labels describe positions in the prologue/epilogue of functions while

View File

@ -1374,7 +1374,10 @@ class MOZ_STACK_CLASS ModuleCompiler
!addStandardLibrarySimdOpName("equal", AsmJSSimdOperation_equal) ||
!addStandardLibrarySimdOpName("notEqual", AsmJSSimdOperation_notEqual) ||
!addStandardLibrarySimdOpName("greaterThan", AsmJSSimdOperation_greaterThan) ||
!addStandardLibrarySimdOpName("greaterThanOrEqual", AsmJSSimdOperation_greaterThanOrEqual))
!addStandardLibrarySimdOpName("greaterThanOrEqual", AsmJSSimdOperation_greaterThanOrEqual) ||
!addStandardLibrarySimdOpName("and", AsmJSSimdOperation_and) ||
!addStandardLibrarySimdOpName("or", AsmJSSimdOperation_or) ||
!addStandardLibrarySimdOpName("xor", AsmJSSimdOperation_xor))
{
return false;
}
@ -2407,6 +2410,19 @@ class FunctionCompiler
return ins;
}
MDefinition *binarySimd(MDefinition *lhs, MDefinition *rhs, MSimdBinaryBitwise::Operation op,
MIRType type)
{
if (inDeadCode())
return nullptr;
JS_ASSERT(IsSimdType(lhs->type()) && rhs->type() == lhs->type());
JS_ASSERT(lhs->type() == type);
MSimdBinaryBitwise *ins = MSimdBinaryBitwise::NewAsmJS(alloc(), lhs, rhs, op, type);
curBlock_->add(ins);
return ins;
}
MDefinition *binarySimd(MDefinition *lhs, MDefinition *rhs, MSimdBinaryComp::Operation op)
{
if (inDeadCode())
@ -3477,6 +3493,9 @@ IsSimdValidOperationType(AsmJSSimdType type, AsmJSSimdOperation op)
case AsmJSSimdOperation_lessThan:
case AsmJSSimdOperation_equal:
case AsmJSSimdOperation_greaterThan:
case AsmJSSimdOperation_and:
case AsmJSSimdOperation_or:
case AsmJSSimdOperation_xor:
return true;
case AsmJSSimdOperation_mul:
case AsmJSSimdOperation_div:
@ -4708,6 +4727,18 @@ CheckBinarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Glob
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::greaterThanOrEqual);
*type = Type::Int32x4;
break;
case AsmJSSimdOperation_and:
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::and_, opType);
*type = retType;
break;
case AsmJSSimdOperation_or:
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::or_, opType);
*type = retType;
break;
case AsmJSSimdOperation_xor:
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::xor_, opType);
*type = retType;
break;
}
return true;
@ -4729,6 +4760,9 @@ CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompile
case AsmJSSimdOperation_notEqual:
case AsmJSSimdOperation_greaterThan:
case AsmJSSimdOperation_greaterThanOrEqual:
case AsmJSSimdOperation_and:
case AsmJSSimdOperation_or:
case AsmJSSimdOperation_xor:
return CheckBinarySimd(f, call, global, def, type);
}
MOZ_CRASH("unexpected simd operation in CheckSimdOperationCall");

View File

@ -449,6 +449,8 @@ const GEF32 = 'var ge=f4.greaterThanOrEqual';
const EQF32 = 'var eq=f4.equal';
const NEF32 = 'var ne=f4.notEqual';
assertAsmTypeFail('glob', USE_ASM + F32 + "var lt=f4.lessThan; function f() {var x=f4(1,2,3,4); var y=f4(5,6,7,8); x=lt(x,y);} return f");
CheckF4Comp(LTF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=lt(y,z)', [F, F, F, F]);
CheckF4Comp(LTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=i4(0,0,0,0); x=lt(y,z)', [T, T, T, T]);
CheckF4Comp(LTF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=i4(0,0,0,0); x=lt(y,z)', [F, T, T, F]);
@ -473,6 +475,40 @@ CheckF4Comp(GEF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x
CheckF4Comp(GEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=i4(0,0,0,0); x=ge(y,z)', [F, F, F, F]);
CheckF4Comp(GEF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=i4(0,0,0,0); x=ge(y,z)', [T, F, F, T]);
// Bitwise ops
const ANDI32 = 'var andd=i4.and;';
const ORI32 = 'var orr=i4.or;';
const XORI32 = 'var xorr=i4.xor;';
CheckI4(ANDI32, 'var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=andd(x,y)', [42 & 2, 1337 & 4, -1 & 7, 13 & 15]);
CheckI4(ORI32, ' var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=orr(x,y)', [42 | 2, 1337 | 4, -1 | 7, 13 | 15]);
CheckI4(XORI32, 'var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=xorr(x,y)', [42 ^ 2, 1337 ^ 4, -1 ^ 7, 13 ^ 15]);
const ANDF32 = 'var andd=f4.and;';
const ORF32 = 'var orr=f4.or;';
const XORF32 = 'var xorr=f4.xor;';
var bitwise = (function() {
var asf32 = new Float32Array(2);
var asi32 = new Int32Array(asf32.buffer);
function andd(x, y) { asf32[0] = x; asf32[1] = y; asi32[0] = asi32[0] & asi32[1]; return asf32[0]; }
function orr(x, y) { asf32[0] = x; asf32[1] = y; asi32[0] = asi32[0] | asi32[1]; return asf32[0]; }
function xorr(x, y) { asf32[0] = x; asf32[1] = y; asi32[0] = asi32[0] ^ asi32[1]; return asf32[0]; }
function andx4(x, y) { var res = []; for (var i = 0; i < 4; i++) res[i] = andd(x[i], y[i]); return res; }
function orx4(x, y) { var res = []; for (var i = 0; i < 4; i++) res[i] = orr(x[i], y[i]); return res; }
function xorx4(x, y) { var res = []; for (var i = 0; i < 4; i++) res[i] = xorr(x[i], y[i]); return res; }
return {
and: andx4,
or: orx4,
xor: xorx4
}
})();
CheckF4(ANDF32, 'var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=andd(x,y)', bitwise.and([42, 13.37, -1.42, 23.10], [19.89, 2.4, 8.15, 16.36]));
CheckF4(ORF32, 'var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=orr(x,y)', bitwise.or( [42, 13.37, -1.42, 23.10], [19.89, 2.4, 8.15, 16.36]));
CheckF4(XORF32, 'var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=xorr(x,y)', bitwise.xor([42, 13.37, -1.42, 23.10], [19.89, 2.4, 8.15, 16.36]));
// Dead code
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); return i4(x); x=i4(5,6,7,8); return i4(x);} return f'), this)(), [1, 2, 3, 4]);
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); var c=0; return i4(x); c=x.x|0; return i4(x);} return f'), this)(), [1, 2, 3, 4]);