Closed
Bug 1053788
Opened 11 years ago
Closed 11 years ago
IonMonkey: Specialize MMinMax for Float32
Categories
(Core :: JavaScript Engine: JIT, defect)
Core
JavaScript Engine: JIT
Tracking
()
RESOLVED
FIXED
mozilla35
People
(Reporter: bbouvier, Assigned: bbouvier)
Details
Attachments
(5 files, 1 obsolete file)
|
2.51 KB,
patch
|
sunfish
:
review+
|
Details | Diff | Splinter Review |
|
14.08 KB,
patch
|
sunfish
:
review+
|
Details | Diff | Splinter Review |
|
4.55 KB,
patch
|
Details | Diff | Splinter Review | |
|
15.07 KB,
patch
|
luke
:
review+
|
Details | Diff | Splinter Review |
|
6.29 KB,
patch
|
nbp
:
review+
|
Details | Diff | Splinter Review |
There are minss and maxss instructions for x86, and I don't see any reason why MMinMax wouldn't be float32-commutative (comparisons are float32 commutative), so we could specialize it.
Will do unless somebody beats me to it.
| Assignee | ||
Updated•11 years ago
|
Flags: needinfo?(benj)
| Assignee | ||
Comment 1•11 years ago
|
||
A small refactoring before the main patch.
Updated•11 years ago
|
Attachment #8483600 -
Flags: review?(sunfish) → review+
| Assignee | ||
Comment 2•11 years ago
|
||
This implements codegen for all tier-1 platforms.
Attachment #8484238 -
Flags: review?(sunfish)
| Assignee | ||
Comment 3•11 years ago
|
||
Attachment #8484240 -
Flags: review?(nicolas.b.pierron)
| Assignee | ||
Comment 4•11 years ago
|
||
Attachment #8484241 -
Flags: review?(sstangl)
| Assignee | ||
Comment 5•11 years ago
|
||
Attachment #8484242 -
Flags: review?(luke)
Flags: needinfo?(benj)
| Assignee | ||
Comment 6•11 years ago
|
||
Modified test files all pass with --tbpl. --ion test pass with a x64 build. Try run for sanity:
https://tbpl.mozilla.org/?tree=Try&rev=75cc74cbb606
Comment 7•11 years ago
|
||
Comment on attachment 8484242 [details] [diff] [review]
Part 5: Add float32 specialization of Math.min/max in Odin
Review of attachment 8484242 [details] [diff] [review]:
-----------------------------------------------------------------
::: js/src/asmjs/AsmJSValidate.cpp
@@ +4305,1 @@
> bool opIsInteger = firstType.isInt();
I was thinking, perhaps we should finally just add a:
bool operator<=(Type lhs, Type rhs);
overload so that we can remove these 3 bools and have a single T argType and check below with:
if (!(nextType <= argType))
We could reuse this to avoid this same situation in CheckMathBuiltinCall. Up to you.
Attachment #8484242 -
Flags: review?(luke) → review+
Comment 8•11 years ago
|
||
Comment on attachment 8484238 [details] [diff] [review]
Part 2: Backends for x86, x64, ARM
Review of attachment 8484238 [details] [diff] [review]:
-----------------------------------------------------------------
LGTM.
::: js/src/jit/Lowering.cpp
@@ +1278,5 @@
>
> + if (ins->specialization() == MIRType_Float32) {
> + LMinMaxF *lir = new(alloc()) LMinMaxF(useRegisterAtStart(first), useRegister(second));
> + return defineReuseInput(lir, ins, 0);
> + }
This is a comment on the original code, but there should probably be an assert that ins->specialization() == MIRType_Double here.
Attachment #8484238 -
Flags: review?(sunfish) → review+
Comment 9•11 years ago
|
||
Comment on attachment 8484240 [details] [diff] [review]
Part 3: Update the recover instruction RMinMax
Review of attachment 8484240 [details] [diff] [review]:
-----------------------------------------------------------------
::: js/src/jit/Recover.cpp
@@ +761,5 @@
>
> + // MIRType_Float32 is a specialization embedding the fact that the result is
> + // rounded to a Float32.
> + if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
> + return false;
As the operands are already float32, does it make sense to have a roundFloat32 here?
I am fine for adding the tests cases (r=me), but I do not see the point into adding the code.
Attachment #8484240 -
Flags: review?(nicolas.b.pierron)
Updated•11 years ago
|
Attachment #8484241 -
Flags: review?(sstangl) → review+
| Assignee | ||
Comment 10•11 years ago
|
||
Sorry Sean, I had a little epiphany: we don't need to look at consumers of Math.min/max when deciding whether to specialize or not. As Math.min/max is semantically equivalent to a comparison and an assignment, the output doesn't need to be validated.
Even better: Math.min/max with more than 2 arguments creates several MMinMax, so we can specialize the trySpecializeFloat32 function so that it looks at inputs which also are MMinMax that have been specialized for float32. So e.g. Math.min(f32[0], f32[1], f32[2]) can entirely be carried on with single precision instructions.
Attachment #8484241 -
Attachment is obsolete: true
Attachment #8487917 -
Flags: review?(sstangl)
| Assignee | ||
Comment 11•11 years ago
|
||
(In reply to Nicolas B. Pierron [:nbp] from comment #9)
> As the operands are already float32, does it make sense to have a
> roundFloat32 here?
You're right. I've modified the patch to just add the test cases and r=you.
Comment 12•11 years ago
|
||
Comment on attachment 8487917 [details] [diff] [review]
Part 4: Activate float32 specialization of MMinMax
Review of attachment 8487917 [details] [diff] [review]:
-----------------------------------------------------------------
::: js/src/jit-test/tests/ion/testFloat32-correctness.js
@@ +103,5 @@
> + f32[9] = Math.pow(2,31) - 1;
> +}
> +function minMax() {
> + for(var i = 0; i < 9; ++i) {
> + var minf = Math.fround(Math.min(f32[i], f32[i+1]));
nit:
for(var i = 0; i < 9; ++i) {
for(var j = 0; j < 9; ++j) {
var minf = Math.fround(Math.min(f32[i], f32[j]));
::: js/src/jit-test/tests/ion/testFloat32.js
@@ +210,5 @@
> + var res = Math.max(f32[0], 42.13 + f32[1]);
> + assertFloat32(res, false);
> + f64[0] = res;
> +}
> +test(refuseMax);
Add additional test case, where you check that the output of MinMax can fit as any other Math.fround(…) result:
function acceptMinAdd() {
var res = Math.min(f32[0], f32[1]) + f32[2];
assertFloat32(res, true);
f32[3] = res;
}
Attachment #8487917 -
Flags: review?(sstangl) → review+
| Assignee | ||
Comment 13•11 years ago
|
||
(In reply to Nicolas B. Pierron [:nbp] from comment #12)
> ::: js/src/jit-test/tests/ion/testFloat32.js
> @@ +210,5 @@
> > + var res = Math.max(f32[0], 42.13 + f32[1]);
> > + assertFloat32(res, false);
> > + f64[0] = res;
> > +}
> > +test(refuseMax);
>
> Add additional test case, where you check that the output of MinMax can fit
> as any other Math.fround(…) result:
>
> function acceptMinAdd() {
> var res = Math.min(f32[0], f32[1]) + f32[2];
> assertFloat32(res, true);
> f32[3] = res;
> }
This last test wouldn't work, as MMinMax isn't a float32 producer. However, MMinMax behaves like a Phi (which makes sense, as it's a comparison and an assignment): it is a producer if the inputs are producers, and it is a consumer if all uses are consumers. While the concept is pretty simple, the implementation would involve caching these two values, as otherwise chains of MMinMax would involve a lot of recursive calls (MMinMax::canProduceFloat32 would just consist in calling canProduceFloat32 on its two inputs). nbp and I agreed AFK this wasn't worth it, at least in the scope of this bug.
| Assignee | ||
Comment 14•11 years ago
|
||
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/8ac587fb9cda
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/5f142d472a26
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/bad63e9d0b19
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/4dda6de2f09a
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/b1b54c2c8785
Comment 15•11 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/8ac587fb9cda
https://hg.mozilla.org/mozilla-central/rev/5f142d472a26
https://hg.mozilla.org/mozilla-central/rev/bad63e9d0b19
https://hg.mozilla.org/mozilla-central/rev/4dda6de2f09a
https://hg.mozilla.org/mozilla-central/rev/b1b54c2c8785
Status: ASSIGNED → RESOLVED
Closed: 11 years ago
Flags: in-testsuite+
Resolution: --- → FIXED
Target Milestone: --- → mozilla35
You need to log in
before you can comment on or make changes to this bug.
Description
•