• 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 static com.android.tools.r8.dex.Constants.U4BIT_MAX;
7 import static com.android.tools.r8.dex.Constants.U8BIT_MAX;
8 
9 import com.android.tools.r8.errors.Unreachable;
10 import com.android.tools.r8.ir.conversion.DexBuilder;
11 import com.android.tools.r8.utils.CfgPrinter;
12 import java.util.List;
13 
14 public class If extends JumpInstruction {
15 
16   public enum Type {
17     EQ, GE, GT, LE, LT, NE;
18 
19     // Returns the comparison type if the operands are swapped.
forSwappedOperands()20     public Type forSwappedOperands() {
21       switch (this) {
22         case EQ:
23         case NE:
24           return this;
25         case GE:
26           return Type.LE;
27         case GT:
28           return Type.LT;
29         case LE:
30           return Type.GE;
31         case LT:
32           return Type.GT;
33         default:
34           throw new Unreachable("Unknown if condition type.");
35       }
36     }
37 
inverted()38     public Type inverted() {
39       switch (this) {
40         case EQ:
41           return Type.NE;
42         case GE:
43           return Type.LT;
44         case GT:
45           return Type.LE;
46         case LE:
47           return Type.GT;
48         case LT:
49           return Type.GE;
50         case NE:
51           return Type.EQ;
52         default:
53           throw new Unreachable("Unknown if condition type.");
54       }
55     }
56   }
57 
58   private Type type;
59 
If(Type type, Value value)60   public If(Type type, Value value) {
61     super(null, value);
62     this.type = type;
63   }
64 
If(Type type, List<Value> values)65   public If(Type type, List<Value> values) {
66     super(null, values);
67     this.type = type;
68   }
69 
isZeroTest()70   public boolean isZeroTest() {
71     return inValues.size() == 1;
72   }
73 
getType()74   public Type getType() {
75     return type;
76   }
77 
invert()78   public void invert() {
79     BasicBlock tmp = getTrueTarget();
80     setTrueTarget(fallthroughBlock());
81     setFallthroughBlock(tmp);
82     type = type.inverted();
83   }
84 
getTrueTarget()85   public BasicBlock getTrueTarget() {
86     assert getBlock().exit() == this;
87     List<BasicBlock> successors = getBlock().getSuccessors();
88     assert successors.size() >= 2;
89     return successors.get(successors.size() - 2);
90   }
91 
setTrueTarget(BasicBlock block)92   public void setTrueTarget(BasicBlock block) {
93     assert getBlock().exit() == this;
94     List<BasicBlock> successors = getBlock().getSuccessors();
95     assert successors.size() >= 2;
96     successors.set(successors.size() - 2, block);
97   }
98 
99   @Override
fallthroughBlock()100   public BasicBlock fallthroughBlock() {
101     assert getBlock().exit() == this;
102     List<BasicBlock> successors = getBlock().getSuccessors();
103     assert successors.size() >= 2;
104     return successors.get(successors.size() - 1);
105   }
106 
107   @Override
setFallthroughBlock(BasicBlock block)108   public void setFallthroughBlock(BasicBlock block) {
109     List<BasicBlock> successors = getBlock().getSuccessors();
110     successors.set(successors.size() - 1, block);
111   }
112 
113   @Override
buildDex(DexBuilder builder)114   public void buildDex(DexBuilder builder) {
115     builder.addIf(this);
116   }
117 
118   @Override
toString()119   public String toString() {
120     return super.toString() + " " + type + " block " + getTrueTarget().getNumber()
121         + " (fallthrough " + fallthroughBlock().getNumber() + ")";
122   }
123 
124   @Override
maxInValueRegister()125   public int maxInValueRegister() {
126     return isZeroTest() ? U8BIT_MAX : U4BIT_MAX;
127   }
128 
129   @Override
maxOutValueRegister()130   public int maxOutValueRegister() {
131     assert false : "If instructions define no values.";
132     return 0;
133   }
134 
135   @Override
print(CfgPrinter printer)136   public void print(CfgPrinter printer) {
137     super.print(printer);
138     printer.append(" B").append(getTrueTarget().getNumber());
139   }
140 
141   @Override
identicalNonValueParts(Instruction other)142   public boolean identicalNonValueParts(Instruction other) {
143     If o = other.asIf();
144     return o.getTrueTarget() == getTrueTarget()
145         && o.fallthroughBlock() == fallthroughBlock()
146         && o.type == type;
147   }
148 
149   @Override
compareNonValueParts(Instruction other)150   public int compareNonValueParts(Instruction other) {
151     assert other.isIf();
152     assert false : "Not supported";
153     return 0;
154   }
155 
156 
targetFromCondition(int cond)157   public BasicBlock targetFromCondition(int cond) {
158     switch (type) {
159       case EQ:
160         return cond == 0 ? getTrueTarget() : fallthroughBlock();
161       case NE:
162         return cond != 0 ? getTrueTarget() : fallthroughBlock();
163       case GE:
164         return cond >= 0 ? getTrueTarget() : fallthroughBlock();
165       case GT:
166         return cond > 0 ? getTrueTarget() : fallthroughBlock();
167       case LE:
168         return cond <= 0 ? getTrueTarget() : fallthroughBlock();
169       case LT:
170         return cond < 0 ? getTrueTarget() : fallthroughBlock();
171     }
172     throw new Unreachable("Unexpected condition type " + type);
173   }
174 
175   @Override
isIf()176   public boolean isIf() {
177     return true;
178   }
179 
180   @Override
asIf()181   public If asIf() {
182     return this;
183   }
184 }
185