Skip to content

Commit fe6daed

Browse files
aartbikcommit-bot@chromium.org
authored andcommitted
[vm/compiler] "fast"-path for x64 division
Rationale: Since 64-bit division requires twice as many cycles and has much higher latency compared to the 32-bit division, even for a non-speculative 64-bit path, a 32-bit "fast path" makes sense. Speedup: About 2x for cases that fit 32-bits. No noticable slowdown for the 64-bit cases. flutter/flutter#19677 #33967 Change-Id: I0d3b44564fee2cda03fc36f089a4424084732de0 Reviewed-on: https://dart-review.googlesource.com/69200 Commit-Queue: Aart Bik <[email protected]> Reviewed-by: Vyacheslav Egorov <[email protected]>
1 parent 508751c commit fe6daed

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

runtime/vm/compiler/backend/il_x64.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5326,9 +5326,32 @@ static void EmitInt64ModTruncDiv(FlowGraphCompiler* compiler,
53265326
// out = left % right
53275327
// or
53285328
// out = left / right.
5329+
//
5330+
// Note that since 64-bit division requires twice as many cycles
5331+
// and has much higher latency compared to the 32-bit division,
5332+
// even for this non-speculative 64-bit path we add a "fast path".
5333+
// Integers are untagged at this stage, so testing if sign extending
5334+
// the lower half of each operand equals the full operand, effectively
5335+
// tests if the values fit in 32-bit operands (and the slightly
5336+
// dangerous division by -1 has been handled above already).
53295337
ASSERT(left == RAX);
5338+
ASSERT(right != RDX); // available at this stage
5339+
Label div_64;
5340+
Label div_merge;
5341+
__ movsxd(RDX, left);
5342+
__ cmpq(RDX, left);
5343+
__ j(NOT_EQUAL, &div_64, Assembler::kNearJump);
5344+
__ movsxd(RDX, right);
5345+
__ cmpq(RDX, right);
5346+
__ j(NOT_EQUAL, &div_64, Assembler::kNearJump);
5347+
__ cdq(); // sign-ext eax into edx:eax
5348+
__ idivl(right); // quotient eax, remainder edx
5349+
__ movsxd(out, out);
5350+
__ jmp(&div_merge, Assembler::kNearJump);
5351+
__ Bind(&div_64);
53305352
__ cqo(); // sign-ext rax into rdx:rax
53315353
__ idivq(right); // quotient rax, remainder rdx
5354+
__ Bind(&div_merge);
53325355
if (op_kind == Token::kMOD) {
53335356
ASSERT(out == RDX);
53345357
ASSERT(tmp == RAX);

tests/language_2/vm/modtruncdiv_int_test.dart

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,34 @@ main() {
176176
doModVars((3 << 32) - 1, (3 << 32) + 1, (3 << 32) - 1, (3 << 32) + 1);
177177
Expect.equals(38654705666, acc);
178178

179+
acc = 0;
180+
doModVars(minInt32 - 4, minInt32 + 4, -11, -1);
181+
Expect.equals(239, acc);
182+
183+
acc = 0;
184+
doModVars(minInt32 - 4, minInt32 + 4, 2, 7);
185+
Expect.equals(85, acc);
186+
187+
acc = 0;
188+
doModVars(minInt32 - 4, minInt32 + 4, minInt32 - 4, minInt32 + 4);
189+
Expect.equals(77309411268, acc);
190+
191+
acc = 0;
192+
doModVars(minInt32 - 4, minInt32 + 4, maxInt32 - 4, maxInt32 + 4);
193+
Expect.equals(96636763974, acc);
194+
195+
acc = 0;
196+
doModVars(maxInt32 - 4, maxInt32 + 4, 2, 7);
197+
Expect.equals(104, acc);
198+
199+
acc = 0;
200+
doModVars(maxInt32 - 4, maxInt32 + 4, minInt32 - 4, minInt32 + 4);
201+
Expect.equals(96636764139, acc);
202+
203+
acc = 0;
204+
doModVars(maxInt32 - 4, maxInt32 + 4, maxInt32 - 4, maxInt32 + 4);
205+
Expect.equals(77309411352, acc);
206+
179207
acc = 0;
180208
doTruncDivVars(3, 5, 2, 6);
181209
Expect.equals(11, acc);
@@ -200,6 +228,38 @@ main() {
200228
doTruncDivVars(minInt64, minInt64, -1, -1);
201229
Expect.equals(minInt64, acc);
202230

231+
acc = 0;
232+
doTruncDivVars(minInt32 - 4, minInt32 + 4, -11, -1);
233+
Expect.equals(58366234918, acc);
234+
235+
acc = 0;
236+
doTruncDivVars(minInt32 - 4, minInt32 + 4, 2, 7);
237+
Expect.equals(-30785711991, acc);
238+
239+
acc = 0;
240+
doTruncDivVars(minInt32 - 4, minInt32 + 4, minInt32 - 4, minInt32 + 4);
241+
Expect.equals(45, acc);
242+
243+
acc = 0;
244+
doTruncDivVars(minInt32 - 4, minInt32 + 4, maxInt32 - 4, maxInt32 + 4);
245+
Expect.equals(-53, acc);
246+
247+
acc = 0;
248+
doTruncDivVars(maxInt32 - 4, maxInt32 + 4, 2, 7);
249+
Expect.equals(30785711975, acc);
250+
251+
acc = 0;
252+
doTruncDivVars(maxInt32 - 4, maxInt32 + 4, minInt32 - 4, minInt32 + 4);
253+
Expect.equals(-36, acc);
254+
255+
acc = 0;
256+
doTruncDivVars(maxInt32 - 4, maxInt32 + 4, maxInt32 - 4, maxInt32 + 4);
257+
Expect.equals(45, acc);
258+
259+
acc = 0;
260+
doTruncDivVars(maxInt32 - 4, maxInt32 + 4, 1, 7);
261+
Expect.equals(50113064798, acc);
262+
203263
// Exceptions at the right time.
204264

205265
acc = 0;

0 commit comments

Comments
 (0)