1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file 2 // for details. All rights reserved. Use of this source code is governed by a 3 // BSD-style license that can be found in the LICENSE file. 4 package com.android.tools.r8.ir.code; 5 6 import com.android.tools.r8.code.NegDouble; 7 import com.android.tools.r8.code.NegFloat; 8 import com.android.tools.r8.code.NegInt; 9 import com.android.tools.r8.code.NegLong; 10 import com.android.tools.r8.errors.Unreachable; 11 import com.android.tools.r8.ir.conversion.DexBuilder; 12 13 public class Neg extends Unop { 14 15 public final NumericType type; 16 17 public Neg(NumericType type, Value dest, Value source) { 18 super(dest, source); 19 this.type = type; 20 } 21 22 @Override 23 public boolean canBeFolded() { 24 return (type == NumericType.INT || type == NumericType.LONG || type == NumericType.FLOAT 25 || type == NumericType.DOUBLE) 26 && source().isConstant(); 27 } 28 29 @Override 30 public ConstInstruction fold(IRCode code) { 31 assert canBeFolded(); 32 if (type == NumericType.INT) { 33 int result = -source().getConstInstruction().asConstNumber().getIntValue(); 34 Value value = code.createValue(MoveType.SINGLE, getDebugInfo()); 35 return new ConstNumber(ConstType.INT, value, result); 36 } else if (type == NumericType.LONG) { 37 long result = -source().getConstInstruction().asConstNumber().getLongValue(); 38 Value value = code.createValue(MoveType.WIDE, getDebugInfo()); 39 return new ConstNumber(ConstType.LONG, value, result); 40 } else if (type == NumericType.FLOAT) { 41 float result = -source().getConstInstruction().asConstNumber().getFloatValue(); 42 Value value = code.createValue(MoveType.SINGLE, getDebugInfo()); 43 return new ConstNumber(ConstType.FLOAT, value, Float.floatToIntBits(result)); 44 } else { 45 assert type == NumericType.DOUBLE; 46 double result = -source().getConstInstruction().asConstNumber().getDoubleValue(); 47 Value value = code.createValue(MoveType.WIDE, getDebugInfo()); 48 return new ConstNumber(ConstType.DOUBLE, value, Double.doubleToLongBits(result)); 49 } 50 } 51 52 @Override 53 public boolean identicalNonValueParts(Instruction other) { 54 return other.asNeg().type == type; 55 } 56 57 @Override 58 public int compareNonValueParts(Instruction other) { 59 return type.ordinal() - other.asNeg().type.ordinal(); 60 } 61 62 @Override 63 public void buildDex(DexBuilder builder) { 64 com.android.tools.r8.code.Instruction instruction; 65 int dest = builder.allocatedRegister(dest(), getNumber()); 66 int src = builder.allocatedRegister(source(), getNumber()); 67 switch (type) { 68 case INT: 69 instruction = new NegInt(dest, src); 70 break; 71 case LONG: 72 instruction = new NegLong(dest, src); 73 break; 74 case FLOAT: 75 instruction = new NegFloat(dest, src); 76 break; 77 case DOUBLE: 78 instruction = new NegDouble(dest, src); 79 break; 80 default: 81 throw new Unreachable("Unexpected type " + type); 82 } 83 builder.add(this, instruction); 84 } 85 86 @Override 87 public boolean isNeg() { 88 return true; 89 } 90 91 @Override 92 public Neg asNeg() { 93 return this; 94 } 95 } 96