src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/OptimizeDivPhase.java
author jwilhelm
Tue, 12 Mar 2019 19:17:42 +0100
changeset 54084 84f10bbf993f
child 58299 6df94ce3ab2f
permissions -rw-r--r--
8218074: Update Graal Reviewed-by: kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
54084
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     1
/*
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     2
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     4
 *
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     8
 *
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    13
 * accompanied this code).
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    14
 *
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    18
 *
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    21
 * questions.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    22
 */
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    23
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    24
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    25
package org.graalvm.compiler.phases.common;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    26
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    27
import jdk.internal.vm.compiler.collections.Pair;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    28
import org.graalvm.compiler.core.common.type.IntegerStamp;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    29
import org.graalvm.compiler.nodes.ConstantNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    30
import org.graalvm.compiler.nodes.FixedNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    31
import org.graalvm.compiler.nodes.NodeView;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    32
import org.graalvm.compiler.nodes.StructuredGraph;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    33
import org.graalvm.compiler.nodes.ValueNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    34
import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    35
import org.graalvm.compiler.nodes.calc.IntegerDivRemNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    36
import org.graalvm.compiler.nodes.calc.IntegerMulHighNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    37
import org.graalvm.compiler.nodes.calc.MulNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    38
import org.graalvm.compiler.nodes.calc.NarrowNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    39
import org.graalvm.compiler.nodes.calc.RightShiftNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    40
import org.graalvm.compiler.nodes.calc.SignExtendNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    41
import org.graalvm.compiler.nodes.calc.SignedDivNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    42
import org.graalvm.compiler.nodes.calc.SignedRemNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    43
import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    44
import org.graalvm.compiler.phases.Phase;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    45
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    46
import jdk.vm.ci.code.CodeUtil;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    47
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    48
public class OptimizeDivPhase extends Phase {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    49
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    50
    @Override
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    51
    protected void run(StructuredGraph graph) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    52
        for (IntegerDivRemNode rem : graph.getNodes().filter(IntegerDivRemNode.class)) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    53
            if (rem instanceof SignedRemNode && divByNonZeroConstant(rem)) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    54
                optimizeRem(rem);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    55
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    56
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    57
        for (IntegerDivRemNode div : graph.getNodes().filter(IntegerDivRemNode.class)) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    58
            if (div instanceof SignedDivNode && divByNonZeroConstant(div)) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    59
                optimizeSignedDiv((SignedDivNode) div);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    60
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    61
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    62
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    63
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    64
    @Override
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    65
    public float codeSizeIncrease() {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    66
        return 5.0f;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    67
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    68
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    69
    protected static boolean divByNonZeroConstant(IntegerDivRemNode divRemNode) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    70
        return divRemNode.getY().isConstant() && divRemNode.getY().asJavaConstant().asLong() != 0;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    71
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    72
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    73
    protected final void optimizeRem(IntegerDivRemNode rem) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    74
        assert rem.getOp() == IntegerDivRemNode.Op.REM;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    75
        // Java spec 15.17.3.: (a/b)*b+(a%b) == a
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    76
        // so a%b == a-(a/b)*b
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    77
        StructuredGraph graph = rem.graph();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    78
        ValueNode div = findDivForRem(rem);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    79
        ValueNode mul = BinaryArithmeticNode.mul(graph, div, rem.getY(), NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    80
        ValueNode result = BinaryArithmeticNode.sub(graph, rem.getX(), mul, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    81
        graph.replaceFixedWithFloating(rem, result);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    82
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    83
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    84
    private ValueNode findDivForRem(IntegerDivRemNode rem) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    85
        if (rem.next() instanceof IntegerDivRemNode) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    86
            IntegerDivRemNode div = (IntegerDivRemNode) rem.next();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    87
            if (div.getOp() == IntegerDivRemNode.Op.DIV && div.getType() == rem.getType() && div.getX() == rem.getX() && div.getY() == rem.getY()) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    88
                return div;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    89
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    90
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    91
        if (rem.predecessor() instanceof IntegerDivRemNode) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    92
            IntegerDivRemNode div = (IntegerDivRemNode) rem.predecessor();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    93
            if (div.getOp() == IntegerDivRemNode.Op.DIV && div.getType() == rem.getType() && div.getX() == rem.getX() && div.getY() == rem.getY()) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    94
                return div;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    95
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    96
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    97
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    98
        // not found, create a new one (will be optimized away later)
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
    99
        ValueNode div = rem.graph().addOrUniqueWithInputs(createDiv(rem));
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   100
        if (div instanceof FixedNode) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   101
            rem.graph().addAfterFixed(rem, (FixedNode) div);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   102
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   103
        return div;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   104
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   105
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   106
    protected ValueNode createDiv(IntegerDivRemNode rem) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   107
        assert rem instanceof SignedRemNode;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   108
        return SignedDivNode.create(rem.getX(), rem.getY(), rem.getZeroCheck(), NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   109
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   110
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   111
    protected static void optimizeSignedDiv(SignedDivNode div) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   112
        ValueNode forX = div.getX();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   113
        long c = div.getY().asJavaConstant().asLong();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   114
        assert c != 1 && c != -1 && c != 0;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   115
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   116
        IntegerStamp dividendStamp = (IntegerStamp) forX.stamp(NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   117
        int bitSize = dividendStamp.getBits();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   118
        Pair<Long, Integer> nums = magicDivideConstants(c, bitSize);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   119
        long magicNum = nums.getLeft().longValue();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   120
        int shiftNum = nums.getRight().intValue();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   121
        assert shiftNum >= 0;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   122
        ConstantNode m = ConstantNode.forLong(magicNum);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   123
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   124
        ValueNode value;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   125
        if (bitSize == 32) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   126
            value = new MulNode(new SignExtendNode(forX, 64), m);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   127
            if ((c > 0 && magicNum < 0) || (c < 0 && magicNum > 0)) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   128
                // Get upper 32-bits of the result
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   129
                value = NarrowNode.create(new RightShiftNode(value, ConstantNode.forInt(32)), 32, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   130
                if (c > 0) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   131
                    value = BinaryArithmeticNode.add(value, forX, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   132
                } else {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   133
                    value = BinaryArithmeticNode.sub(value, forX, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   134
                }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   135
                if (shiftNum > 0) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   136
                    value = new RightShiftNode(value, ConstantNode.forInt(shiftNum));
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   137
                }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   138
            } else {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   139
                value = new RightShiftNode(value, ConstantNode.forInt(32 + shiftNum));
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   140
                value = new NarrowNode(value, Integer.SIZE);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   141
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   142
        } else {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   143
            assert bitSize == 64;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   144
            value = new IntegerMulHighNode(forX, m);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   145
            if (c > 0 && magicNum < 0) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   146
                value = BinaryArithmeticNode.add(value, forX, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   147
            } else if (c < 0 && magicNum > 0) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   148
                value = BinaryArithmeticNode.sub(value, forX, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   149
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   150
            if (shiftNum > 0) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   151
                value = new RightShiftNode(value, ConstantNode.forInt(shiftNum));
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   152
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   153
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   154
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   155
        if (c < 0) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   156
            ConstantNode s = ConstantNode.forInt(bitSize - 1);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   157
            ValueNode sign = UnsignedRightShiftNode.create(value, s, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   158
            value = BinaryArithmeticNode.add(value, sign, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   159
        } else if (dividendStamp.canBeNegative()) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   160
            ConstantNode s = ConstantNode.forInt(bitSize - 1);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   161
            ValueNode sign = UnsignedRightShiftNode.create(forX, s, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   162
            value = BinaryArithmeticNode.add(value, sign, NodeView.DEFAULT);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   163
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   164
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   165
        StructuredGraph graph = div.graph();
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   166
        graph.replaceFixed(div, graph.addOrUniqueWithInputs(value));
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   167
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   168
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   169
    /**
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   170
     * Borrowed from Hacker's Delight by Henry S. Warren, Jr. Figure 10-1.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   171
     */
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   172
    private static Pair<Long, Integer> magicDivideConstants(long divisor, int size) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   173
        final long twoW = 1L << (size - 1);                // 2 ^ (size - 1).
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   174
        long t = twoW + (divisor >>> 63);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   175
        long ad = Math.abs(divisor);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   176
        long anc = t - 1 - Long.remainderUnsigned(t, ad);  // Absolute value of nc.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   177
        long q1 = Long.divideUnsigned(twoW, anc);          // Init. q1 = 2**p/|nc|.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   178
        long r1 = Long.remainderUnsigned(twoW, anc);       // Init. r1 = rem(2**p, |nc|).
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   179
        long q2 = Long.divideUnsigned(twoW, ad);           // Init. q2 = 2**p/|d|.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   180
        long r2 = Long.remainderUnsigned(twoW, ad);        // Init. r2 = rem(2**p, |d|).
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   181
        long delta;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   182
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   183
        int p = size - 1;                                  // Init. p.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   184
        do {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   185
            p = p + 1;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   186
            q1 = 2 * q1;                                   // Update q1 = 2**p/|nc|.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   187
            r1 = 2 * r1;                                   // Update r1 = rem(2**p, |nc|).
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   188
            if (Long.compareUnsigned(r1, anc) >= 0) {      // Must be an unsigned comparison.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   189
                q1 = q1 + 1;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   190
                r1 = r1 - anc;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   191
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   192
            q2 = 2 * q2;                                   // Update q2 = 2**p/|d|.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   193
            r2 = 2 * r2;                                   // Update r2 = rem(2**p, |d|).
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   194
            if (Long.compareUnsigned(r2, ad) >= 0) {       // Must be an unsigned comparison.
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   195
                q2 = q2 + 1;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   196
                r2 = r2 - ad;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   197
            }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   198
            delta = ad - r2;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   199
        } while (Long.compareUnsigned(q1, delta) < 0 || (q1 == delta && r1 == 0));
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   200
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   201
        long magic = CodeUtil.signExtend(q2 + 1, size);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   202
        if (divisor < 0) {
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   203
            magic = -magic;
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   204
        }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   205
        return Pair.create(magic, p - size);
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   206
    }
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   207
84f10bbf993f 8218074: Update Graal
jwilhelm
parents:
diff changeset
   208
}