changeset 21448:545cd6b3b377

Make ShiftNode narrowable under certain conditions.
author Roland Schatz <roland.schatz@oracle.com>
date Thu, 21 May 2015 13:25:44 +0200
parents f172a195a8a9
children 006d8ddb7ef9
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowableArithmeticNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java
diffstat 4 files changed, 57 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowableArithmeticNode.java	Thu May 07 14:47:27 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowableArithmeticNode.java	Thu May 21 13:25:44 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,4 +28,14 @@
  * result.
  */
 public interface NarrowableArithmeticNode {
+
+    /**
+     * Check whether this operation can be narrowed to {@code resultBits} bit without loss of
+     * precision.
+     *
+     * @param resultBits
+     */
+    default boolean isNarrowable(int resultBits) {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu May 07 14:47:27 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu May 21 13:25:44 2015 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.Shr;
 import com.oracle.graal.graph.*;
@@ -98,4 +99,19 @@
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
         builder.setResult(this, gen.emitShr(builder.operand(getX()), builder.operand(getY())));
     }
+
+    @Override
+    public boolean isNarrowable(int resultBits) {
+        if (super.isNarrowable(resultBits)) {
+            /*
+             * For signed right shifts, the narrow can be done before the shift if the cut off bits
+             * are all equal to the sign bit of the input. That's equivalent to the condition that
+             * the input is in the signed range of the narrow type.
+             */
+            IntegerStamp inputStamp = (IntegerStamp) getX().stamp();
+            return CodeUtil.minValue(resultBits) <= inputStamp.lowerBound() && inputStamp.upperBound() <= CodeUtil.maxValue(resultBits);
+        } else {
+            return false;
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Thu May 07 14:47:27 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Thu May 21 13:25:44 2015 +0200
@@ -25,6 +25,7 @@
 import java.io.*;
 import java.util.function.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp;
@@ -38,7 +39,7 @@
  * The {@code ShiftOp} class represents shift operations.
  */
 @NodeInfo
-public abstract class ShiftNode<OP> extends BinaryNode implements ArithmeticLIRLowerable {
+public abstract class ShiftNode<OP> extends BinaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     @SuppressWarnings("rawtypes") public static final NodeClass<ShiftNode> TYPE = NodeClass.create(ShiftNode.class);
 
@@ -82,4 +83,18 @@
         return getOp(getX()).getShiftAmountMask(stamp());
     }
 
+    public boolean isNarrowable(int resultBits) {
+        assert CodeUtil.isPowerOf2(resultBits);
+        int narrowMask = resultBits - 1;
+        int wideMask = getShiftAmountMask();
+        assert (wideMask & narrowMask) == narrowMask : String.format("wideMask %x should be wider than narrowMask %x", wideMask, narrowMask);
+
+        /*
+         * Shifts are special because narrowing them also changes the implicit mask of the shift
+         * amount. We can narrow only if (y & wideMask) == (y & narrowMask) for all possible values
+         * of y.
+         */
+        IntegerStamp yStamp = (IntegerStamp) getY().stamp();
+        return (yStamp.upMask() & (wideMask & ~narrowMask)) == 0;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu May 07 14:47:27 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu May 21 13:25:44 2015 +0200
@@ -87,4 +87,18 @@
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
         builder.setResult(this, gen.emitUShr(builder.operand(getX()), builder.operand(getY())));
     }
+
+    @Override
+    public boolean isNarrowable(int resultBits) {
+        if (super.isNarrowable(resultBits)) {
+            /*
+             * For unsigned right shifts, the narrow can be done before the shift if the cut off
+             * bits are all zero.
+             */
+            IntegerStamp inputStamp = (IntegerStamp) getX().stamp();
+            return (inputStamp.upMask() & ~(resultBits - 1)) == 0;
+        } else {
+            return false;
+        }
+    }
 }