• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Const;
7 import com.android.tools.r8.code.Const16;
8 import com.android.tools.r8.code.Const4;
9 import com.android.tools.r8.code.ConstHigh16;
10 import com.android.tools.r8.code.ConstWide;
11 import com.android.tools.r8.code.ConstWide16;
12 import com.android.tools.r8.code.ConstWide32;
13 import com.android.tools.r8.code.ConstWideHigh16;
14 import com.android.tools.r8.dex.Constants;
15 import com.android.tools.r8.graph.AppInfo;
16 import com.android.tools.r8.graph.DexType;
17 import com.android.tools.r8.ir.conversion.DexBuilder;
18 import com.android.tools.r8.ir.optimize.Inliner.Constraint;
19 import com.android.tools.r8.utils.NumberUtils;
20 
21 public class ConstNumber extends ConstInstruction {
22 
23   public final ConstType type;
24   private final long value;
25 
ConstNumber(ConstType type, Value dest, long value)26   public ConstNumber(ConstType type, Value dest, long value) {
27     super(dest);
28     // We create const numbers after register allocation for rematerialization of values. Those
29     // are all for fixed register values. All other values that are used as the destination for
30     // const number instructions should be marked as constants.
31     assert dest.isFixedRegisterValue() || dest.definition.isConstNumber();
32     assert type != ConstType.OBJECT;
33     this.type = type;
34     this.value = value;
35   }
36 
copyOf(IRCode code, ConstNumber original)37   public static ConstNumber copyOf(IRCode code, ConstNumber original) {
38     Value newValue =
39         new Value(
40             code.valueNumberGenerator.next(),
41             original.outType(),
42             original.getDebugInfo());
43     return new ConstNumber(original.type, newValue, original.getRawValue());
44   }
45 
preciseTypeUnknown()46   private boolean preciseTypeUnknown() {
47     return type == ConstType.INT_OR_FLOAT || type == ConstType.LONG_OR_DOUBLE;
48   }
49 
dest()50   public Value dest() {
51     return outValue;
52   }
53 
getIntValue()54   public int getIntValue() {
55     assert type == ConstType.INT || type == ConstType.INT_OR_FLOAT;
56     return (int) value;
57   }
58 
getLongValue()59   public long getLongValue() {
60     assert type == ConstType.LONG || type == ConstType.LONG_OR_DOUBLE;
61     return value;
62   }
63 
getFloatValue()64   public float getFloatValue() {
65     assert type == ConstType.FLOAT || type == ConstType.INT_OR_FLOAT;
66     return Float.intBitsToFloat((int) value);
67   }
68 
getDoubleValue()69   public double getDoubleValue() {
70     assert type == ConstType.DOUBLE || type == ConstType.LONG_OR_DOUBLE;
71     return Double.longBitsToDouble(value);
72   }
73 
getRawValue()74   public long getRawValue() {
75     return value;
76   }
77 
isZero()78   public boolean isZero() {
79     return value == 0;
80   }
81 
isIntegerNegativeOne(NumericType type)82   public boolean isIntegerNegativeOne(NumericType type) {
83     assert type == NumericType.INT || type == NumericType.LONG;
84     if (type == NumericType.INT) {
85       return getIntValue() == -1;
86     }
87     return getLongValue() == -1;
88   }
89 
90   @Override
buildDex(DexBuilder builder)91   public void buildDex(DexBuilder builder) {
92     if (!dest().needsRegister()) {
93       builder.addNop(this);
94       return;
95     }
96 
97     int register = builder.allocatedRegister(dest(), getNumber());
98     if (MoveType.fromConstType(type) == MoveType.SINGLE) {
99       assert NumberUtils.is32Bit(value);
100       if ((register & 0xf) == register && NumberUtils.is4Bit(value)) {
101         builder.add(this, new Const4(register, (int) value));
102       } else if (NumberUtils.is16Bit(value)) {
103         builder.add(this, new Const16(register, (int) value));
104       } else if ((value & 0x0000ffffL) == 0) {
105         builder.add(this, new ConstHigh16(register, ((int) value) >>> 16));
106       } else {
107         builder.add(this, new Const(register, (int) value));
108       }
109     } else {
110       assert MoveType.fromConstType(type) == MoveType.WIDE;
111       if (NumberUtils.is16Bit(value)) {
112         builder.add(this, new ConstWide16(register, (int) value));
113       } else if ((value & 0x0000ffffffffffffL) == 0) {
114         builder.add(this, new ConstWideHigh16(register, (int) (value >>> 48)));
115       } else if (NumberUtils.is32Bit(value)) {
116         builder.add(this, new ConstWide32(register, (int) value));
117       } else {
118         builder.add(this, new ConstWide(register, value));
119       }
120     }
121   }
122 
123   @Override
maxInValueRegister()124   public int maxInValueRegister() {
125     assert false : "Const has no register arguments.";
126     return 0;
127   }
128 
129   @Override
maxOutValueRegister()130   public int maxOutValueRegister() {
131     return Constants.U8BIT_MAX;
132   }
133 
134   @Override
toString()135   public String toString() {
136     return super.toString() + " " + value + " (" + type + ")";
137   }
138 
139   @Override
identicalNonValueParts(Instruction other)140   public boolean identicalNonValueParts(Instruction other) {
141     if (preciseTypeUnknown()) {
142       return false;
143     }
144     ConstNumber o = other.asConstNumber();
145     return o.type == type && o.value == value;
146   }
147 
148   @Override
compareNonValueParts(Instruction other)149   public int compareNonValueParts(Instruction other) {
150     ConstNumber o = other.asConstNumber();
151     int result;
152     result = type.ordinal() - o.type.ordinal();
153     if (result != 0) {
154       return result;
155     }
156     return Long.signum(value - o.value);
157   }
158 
is8Bit()159   public boolean is8Bit() {
160     return NumberUtils.is8Bit(value);
161   }
162 
negativeIs8Bit()163   public boolean negativeIs8Bit() {
164     return NumberUtils.negativeIs8Bit(value);
165   }
166 
is16Bit()167   public boolean is16Bit() {
168     return NumberUtils.is16Bit(value);
169   }
170 
negativeIs16Bit()171   public boolean negativeIs16Bit() {
172     return NumberUtils.negativeIs16Bit(value);
173   }
174 
175   @Override
isOutConstant()176   public boolean isOutConstant() {
177     return true;
178   }
179 
180   @Override
isConstNumber()181   public boolean isConstNumber() {
182     return true;
183   }
184 
185   @Override
asConstNumber()186   public ConstNumber asConstNumber() {
187     return this;
188   }
189 
190   @Override
inliningConstraint(AppInfo info, DexType holder)191   public Constraint inliningConstraint(AppInfo info, DexType holder) {
192     return Constraint.ALWAYS;
193   }
194 }
195