1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.openjdk.bench.vm.compiler;
  24 
  25 import org.openjdk.jmh.annotations.Benchmark;
  26 import org.openjdk.jmh.annotations.BenchmarkMode;
  27 import org.openjdk.jmh.annotations.Mode;
  28 import org.openjdk.jmh.annotations.OutputTimeUnit;
  29 import org.openjdk.jmh.annotations.Scope;
  30 import org.openjdk.jmh.annotations.Setup;
  31 import org.openjdk.jmh.annotations.State;
  32 
  33 import java.util.Random;
  34 import java.util.concurrent.TimeUnit;
  35 
  36 /**
  37  * Tests speed of division and remainder calculations.
  38  */
  39 @BenchmarkMode(Mode.AverageTime)
  40 @OutputTimeUnit(TimeUnit.NANOSECONDS)
  41 @State(Scope.Thread)
  42 public class DivRem {
  43 
  44     private static final int ARRAYSIZE = 500;
  45 
  46     /* instance fields for the constant int division tests. */
  47     public int[] intValues, intValues2;
  48 
  49     /* instance fields for the constant long division tests. */
  50     public long[] longValues, longValues2;
  51 
  52     /* instance fields for the tests using the testdr-method. */
  53     public long[] drLongValues1, drLongValues2;
  54 
  55     public long[] drLongValuesAsInts1, drLongValuesAsInts2;
  56 
  57     @Setup
  58     public void setupSubclass() {
  59         Random r = new Random(4711);
  60 
  61         intValues = new int[ARRAYSIZE];
  62         intValues2 = new int[ARRAYSIZE];
  63         longValues = new long[ARRAYSIZE];
  64         longValues2 = new long[ARRAYSIZE];
  65 
  66         for (int i = 0; i < ARRAYSIZE; i++) {
  67             intValues[i] = r.nextInt();
  68             if (intValues[i] == 0) {
  69                 intValues[i] = 5353;
  70             }
  71             intValues2[i] = r.nextInt();
  72 
  73             longValues[i] = r.nextLong();
  74             if (longValues[i] == 0) {
  75                 longValues[i] = 5353L;
  76             }
  77             longValues2[i] = r.nextLong();
  78         }
  79 
  80         /* generate random longs for 32-64 tests */
  81 
  82         drLongValues1 = new long[ARRAYSIZE];
  83         drLongValues2 = new long[ARRAYSIZE];
  84         drLongValuesAsInts1 = new long[ARRAYSIZE];
  85         drLongValuesAsInts2 = new long[ARRAYSIZE];
  86         for (int i = 0; i < ARRAYSIZE; i++) {
  87             long l = r.nextLong();
  88             if (l == 0L) {
  89                 l++;
  90             }
  91             drLongValues1[i] = l;
  92             drLongValuesAsInts1[i] = (long) (int) l;
  93             l = r.nextLong();
  94             if (l == 0L) {
  95                 l++;
  96             }
  97             drLongValues2[i] = l;
  98             drLongValuesAsInts2[i] = (long) (int) l;
  99         }
 100     }
 101 
 102     /**
 103      * Tests integer division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to
 104      * a multiplication instead.
 105      */
 106     @Benchmark
 107     public int testIntDivConstantDivisor() {
 108         int dummy = 0;
 109         for (int i = 0; i < intValues.length; i++) {
 110             dummy += intValues[i] / 49;
 111         }
 112         return dummy;
 113     }
 114 
 115     /**
 116      * Tests long division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to a
 117      * multiplication instead.
 118      */
 119     @Benchmark
 120     public long testLongDivConstantDivisor() {
 121         long dummy = 0;
 122         for (int i = 0; i < longValues.length; i++) {
 123             dummy += longValues[i] / 49L + longValues[i] / 0x4949494949L;
 124         }
 125         return dummy;
 126     }
 127 
 128     /**
 129      * Tests integer remainder with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to
 130      * two multiplications instead.
 131      */
 132     @Benchmark
 133     public int testIntRemConstantDivisor() {
 134         int dummy = 0;
 135         for (int i = 0; i < intValues.length; i++) {
 136             dummy += intValues[i] % 49;
 137         }
 138         return dummy;
 139     }
 140 
 141     /**
 142      * Tests long division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to a
 143      * multiplication instead.
 144      */
 145     @Benchmark
 146     public long testLongRemConstantDivisor() {
 147         long dummy = 0;
 148         for (int i = 0; i < longValues.length; i++) {
 149             dummy += longValues[i] % 49L + longValues[i] % 0x4949494949L;
 150         }
 151         return dummy;
 152     }
 153 
 154     /**
 155      * Tests integer division with a variable divisor. This benchmark is mainly here to be a comparison against the
 156      * benchmark that performs both divisions and remainder calculations.
 157      */
 158     @Benchmark
 159     public int testIntDivVariableDivisor() {
 160         int dummy = 0;
 161         for (int i = 0; i < intValues.length; i++) {
 162             dummy += intValues2[i] / intValues[i];
 163         }
 164         return dummy;
 165     }
 166 
 167     /**
 168      * Tests integer division and remainder with a variable divisor. Both calculations are performed with the same
 169      * divisor, so a JVM should not have to perform two complex calculations. Either a division followed by a
 170      * multiplication, or on X86 using idiv, where the reminder is also returned from the idiv instruction.
 171      */
 172     @Benchmark
 173     public int testIntDivRemVariableDivisor() {
 174         int dummy = 0;
 175         for (int i = 0; i < intValues.length; i++) {
 176             dummy += intValues2[i] / intValues[i];
 177             dummy += intValues2[i] % intValues[i];
 178         }
 179         return dummy;
 180     }
 181 
 182     @Benchmark
 183     public long test64DivRem64() {
 184         long dummy = 0;
 185         for (int i = 0; i < drLongValues1.length; i++) {
 186             long l1 = drLongValues1[i];
 187             long l2 = drLongValues2[i];
 188             dummy += l1 / l2;
 189             dummy += l1 % l2;
 190         }
 191         return dummy;
 192     }
 193 
 194     @Benchmark
 195     public long test32DivRem32() {
 196         long dummy = 0;
 197         for (int i = 0; i < drLongValuesAsInts1.length; i++) {
 198             long l1 = drLongValuesAsInts1[i];
 199             long l2 = drLongValuesAsInts2[i];
 200             dummy += l1 / l2;
 201             dummy += l1 % l2;
 202         }
 203         return dummy;
 204     }
 205 
 206     @Benchmark
 207     public long test64DivRem32() {
 208         long dummy = 0;
 209         for (int i = 0; i < drLongValues1.length; i++) {
 210             long l1 = drLongValues1[i];
 211             long l2 = drLongValuesAsInts2[i];
 212             dummy += l1 / l2;
 213             dummy += l1 % l2;
 214         }
 215         return dummy;
 216     }
 217 }