Optimizes integral divide operations to be fewer instructions. Specially optimizes division by powers of two into shr ops. Suggested by: knorton Review by: spoon git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2210 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java index 1e7cecb..3dd6b4f 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -374,8 +374,7 @@ } /** - * Explicitly cast all integral divide operations to trigger replacements with - * narrowing calls in the next pass. + * Handle integral divide operations which may have floating point results. */ private class DivVisitor extends JModVisitor { @@ -385,10 +384,18 @@ if (x.getOp() == JBinaryOperator.DIV && type != program.getTypePrimitiveFloat() && type != program.getTypePrimitiveDouble()) { + /* + * If the numerator was already in range, we can assume the output is + * also in range. Therefore, we don't need to do the full conversion, + * but rather a narrowing int conversion instead. + */ + String methodName = "Cast.narrow_" + type.getName(); + JMethod castMethod = program.getIndexedMethod(methodName); + JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null, + castMethod, type); x.setType(program.getTypePrimitiveDouble()); - JCastOperation cast = new JCastOperation(program, x.getSourceInfo(), - type, x); - ctx.replaceMe(cast); + call.getArgs().add(x); + ctx.replaceMe(call); } } }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java index af6da97..9a15320 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.jjs.impl; +import com.google.gwt.dev.jjs.SourceInfo; import com.google.gwt.dev.jjs.ast.Context; import com.google.gwt.dev.jjs.ast.JBinaryOperation; import com.google.gwt.dev.jjs.ast.JBinaryOperator; @@ -137,7 +138,14 @@ break; case ADD: if (x.getType() == program.getTypeJavaLangString()) { - evalConcat(ctx, lhs, rhs); + evalConcat(lhs, rhs, ctx); + } + break; + case DIV: + case ASG_DIV: + if (x.getType() != program.getTypePrimitiveFloat() + && x.getType() != program.getTypePrimitiveDouble()) { + divToShift(x, lhs, rhs, ctx); } break; default: @@ -650,7 +658,41 @@ return true; } - private void evalConcat(Context ctx, JExpression lhs, JExpression rhs) { + private void divToShift(JBinaryOperation x, JExpression lhs, + JExpression rhs, Context ctx) { + long divisor; + if (rhs instanceof JIntLiteral) { + divisor = ((JIntLiteral) rhs).getValue(); + } else if (rhs instanceof JLongLiteral) { + divisor = ((JLongLiteral) rhs).getValue(); + } else { + return; + } + + if (divisor == 1) { + ctx.replaceMe(lhs); + return; + } else if (divisor == -1 && !x.getOp().isAssignment()) { + JPrefixOperation negOp = new JPrefixOperation(program, + x.getSourceInfo(), JUnaryOperator.NEG, lhs); + ctx.replaceMe(negOp); + return; + } + + if (divisor > 1 && divisor == Long.highestOneBit(divisor)) { + // It's a power of two, convert to a shift operation. + int shift = Long.numberOfTrailingZeros(divisor); + JBinaryOperator op = x.getOp().isAssignment() ? JBinaryOperator.ASG_SHR + : JBinaryOperator.SHR; + JBinaryOperation binOp = new JBinaryOperation(program, + x.getSourceInfo(), lhs.getType(), op, lhs, + program.getLiteralInt(shift)); + ctx.replaceMe(binOp); + return; + } + } + + private void evalConcat(JExpression lhs, JExpression rhs, Context ctx) { if (lhs instanceof JValueLiteral && rhs instanceof JValueLiteral) { Object lhsObj = ((JValueLiteral) lhs).getValueObj(); Object rhsObj = ((JValueLiteral) rhs).getValueObj();