[aarch64-port-dev ] Unnecessary branch in MacroAssembler::corrected_idivl

Andrew Haley aph at redhat.com
Mon Mar 31 14:29:49 UTC 2014


Hi,

On 03/26/2014 01:08 AM, D.Sturm wrote:

> since I'm checking special cases, etc. in the Graal compiler generated code
> I generally also check the HotSpot code to see if it does equivalent
> things. Is it actually useful if I report small discrepances where it seems
> HotSpot generates inefficient code such as the following?
> 
> Anyhow, since we're already at it - according to the ARMv8 ISA for division:
> "If a signed integer division (INT_MIN ÷ -1) is performed, where INT_MIN is
> the most negative integer value representable in the selected register
> size, then the result will overflow the signed integer range. No indication
> of this overflow is produced and the result written to the destination
> register will be INT_MIN."
> 
> So the special case for INT_MIN / -1 in MacroAssembler::corrected_idivl is
> unnecessary since that fits exactly the JLS definition for division.

Corrected thusly.

Thanks,
Andrew.



-------------- next part --------------
# HG changeset patch
# User aph
# Date 1396275626 14400
#      Mon Mar 31 10:20:26 2014 -0400
# Node ID e176eb39c5f53127fe18a7e528ca6bc6f0c23cea
# Parent  f2658ddb105cfbc1ca275609fe71e54d852c0624
Remove special-case handling of division arguments.  AArch64 doesn't need it.

diff -r f2658ddb105c -r e176eb39c5f5 src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Mar 27 08:02:20 2014 +0000
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Mon Mar 31 10:20:26 2014 -0400
@@ -1437,40 +1437,22 @@
 int MacroAssembler::corrected_idivl(Register result, Register ra, Register rb,
 				    bool want_remainder, Register scratch)
 {
-  // Full implementation of Java idiv and irem; checks for special
-  // case as described in JVM spec., p.243 & p.271.  The function
-  // returns the (pc) offset of the idivl instruction - may be needed
+  // Full implementation of Java idiv and irem.  The function
+  // returns the (pc) offset of the div instruction - may be needed
   // for implicit exceptions.
   //
   // constraint : ra/rb =/= scratch
-  //         normal case                          special case
+  //         normal case
   //
-  // input : ra: dividend                         min_long
-  //         rb: divisor                          -1
+  // input : ra: dividend
+  //         rb: divisor
   //
   // result: either
-  //         quotient  (= ra idiv rb)         min_long
-  //         remainder (= ra irem rb)         0
+  //         quotient  (= ra idiv rb)
+  //         remainder (= ra irem rb)
 
   assert(ra != scratch && rb != scratch, "reg cannot be scratch");
-  static const int64_t min_long = 0x80000000;
-  Label normal_case, special_case;
-
-  // check for special cases
-  movw(scratch, min_long);
-  cmpw(ra, scratch);
-  br(Assembler::NE, normal_case);
-  // check for -1 in rb
-  cmnw(rb, 1);
-  br(Assembler::NE, normal_case);
-  if (! want_remainder)
-    mov(result, ra);
-  else
-    mov(result, zr);
-  b(special_case);
-
-  // handle normal case
-  bind(normal_case);
+
   int idivl_offset = offset();
   if (! want_remainder) {
     sdivw(result, ra, rb);
@@ -1479,49 +1461,28 @@
     msubw(result, scratch, rb, ra);
   }
 
-  // normal and special case exit
-  bind(special_case);
-
   return idivl_offset;
 }
 
 int MacroAssembler::corrected_idivq(Register result, Register ra, Register rb,
 				    bool want_remainder, Register scratch)
 {
-  // Full implementation of Java idiv and irem; checks for special
-  // case as described in JVM spec., p.243 & p.271.  The function
-  // returns the (pc) offset of the idivq instruction - may be needed
+  // Full implementation of Java ldiv and lrem.  The function
+  // returns the (pc) offset of the div instruction - may be needed
   // for implicit exceptions.
   //
   // constraint : ra/rb =/= scratch
-  //         normal case                          special case
+  //         normal case
   //
-  // input : ra: dividend                         min_long
-  //         rb: divisor                          -1
+  // input : ra: dividend
+  //         rb: divisor
   //
   // result: either
-  //         quotient  (= ra idiv rb)         min_long
-  //         remainder (= ra irem rb)         0
+  //         quotient  (= ra idiv rb)
+  //         remainder (= ra irem rb)
 
   assert(ra != scratch && rb != scratch, "reg cannot be scratch");
-  static const int64_t min_long = 0x8000000000000000ULL;
-  Label normal_case, special_case, nonzero;
-
-  // check for special cases
-  mov(scratch, min_long);
-  cmp(ra, scratch);
-  br(Assembler::NE, normal_case);
-  // check for -1 in rb
-  cmn(rb, 1);
-  br(Assembler::NE, normal_case);
-  if (! want_remainder)
-    mov(result, ra);
-  else
-    mov(result, zr);
-  b(special_case);
-
-  // handle normal case
-  bind(normal_case);
+
   int idivq_offset = offset();
   if (! want_remainder) {
     sdiv(result, ra, rb);
@@ -1530,9 +1491,6 @@
     msub(result, scratch, rb, ra);
   }
 
-  // normal and special case exit
-  bind(special_case);
-
   return idivq_offset;
 }
 


More information about the aarch64-port-dev mailing list