Refactor normalization of commutative binops.

This is a refactoring to allow allocating binops without normalization
which is needed for the one-pass building of lightweight IR.

Bug: b/225838009
Change-Id: Iebc9cccab0801145dc678e4bf2836e0fed18db6b
diff --git a/src/main/java/com/android/tools/r8/ir/code/Add.java b/src/main/java/com/android/tools/r8/ir/code/Add.java
index dc8cb05..98e4cf2 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Add.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Add.java
@@ -19,7 +19,17 @@
 
 public class Add extends ArithmeticBinop {
 
-  public Add(NumericType type, Value dest, Value left, Value right) {
+  public static Add create(NumericType type, Value dest, Value left, Value right) {
+    Add add = createNonNormalized(type, dest, left, right);
+    add.normalizeArgumentsForCommutativeBinop();
+    return add;
+  }
+
+  public static Add createNonNormalized(NumericType type, Value dest, Value left, Value right) {
+    return new Add(type, dest, left, right);
+  }
+
+  private Add(NumericType type, Value dest, Value left, Value right) {
     super(type, dest, left, right);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/And.java b/src/main/java/com/android/tools/r8/ir/code/And.java
index f7aac6c..d7cd98c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/And.java
+++ b/src/main/java/com/android/tools/r8/ir/code/And.java
@@ -16,7 +16,17 @@
 
 public class And extends LogicalBinop {
 
-  public And(NumericType type, Value dest, Value left, Value right) {
+  public static And create(NumericType type, Value dest, Value left, Value right) {
+    And and = new And(type, dest, left, right);
+    and.normalizeArgumentsForCommutativeBinop();
+    return and;
+  }
+
+  public static And createNonNormalized(NumericType type, Value dest, Value left, Value right) {
+    return new And(type, dest, left, right);
+  }
+
+  private And(NumericType type, Value dest, Value left, Value right) {
     super(type, dest, left, right);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
index f2aa7cf..92f7380 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
@@ -17,7 +17,7 @@
 
 public abstract class ArithmeticBinop extends Binop {
 
-  public ArithmeticBinop(NumericType type, Value dest, Value left, Value right) {
+  ArithmeticBinop(NumericType type, Value dest, Value left, Value right) {
     super(type, dest, left, right);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/Binop.java b/src/main/java/com/android/tools/r8/ir/code/Binop.java
index 613ff5b..1629cda 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Binop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Binop.java
@@ -20,15 +20,19 @@
 
   protected final NumericType type;
 
-  public Binop(NumericType type, Value dest, Value left, Value right) {
+  Binop(NumericType type, Value dest, Value left, Value right) {
     super(dest);
     this.type = type;
-    if (isCommutative() && (!right.isConstNumber() && left.isConstNumber())) {
-      addInValue(right);
-      addInValue(left);
-    } else {
-      addInValue(left);
-      addInValue(right);
+    addInValue(left);
+    addInValue(right);
+  }
+
+  public void normalizeArgumentsForCommutativeBinop() {
+    assert isCommutative();
+    if (isCommutative() && !rightValue().isConstNumber() && leftValue().isConstNumber()) {
+      Value tmp = inValues.get(0);
+      inValues.set(0, inValues.get(1));
+      inValues.set(1, tmp);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
index c9a1b03..cfc2ee7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
@@ -16,7 +16,7 @@
 
 public abstract class LogicalBinop extends Binop {
 
-  public LogicalBinop(NumericType type, Value dest, Value left, Value right) {
+  LogicalBinop(NumericType type, Value dest, Value left, Value right) {
     super(type, dest, left, right);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/Mul.java b/src/main/java/com/android/tools/r8/ir/code/Mul.java
index ccddf6a..41e4b35 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Mul.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Mul.java
@@ -19,7 +19,17 @@
 
 public class Mul extends ArithmeticBinop {
 
-  public Mul(NumericType type, Value dest, Value left, Value right) {
+  public static Mul create(NumericType type, Value dest, Value left, Value right) {
+    Mul mul = new Mul(type, dest, left, right);
+    mul.normalizeArgumentsForCommutativeBinop();
+    return mul;
+  }
+
+  public static Mul createNonNormalized(NumericType type, Value dest, Value left, Value right) {
+    return new Mul(type, dest, left, right);
+  }
+
+  private Mul(NumericType type, Value dest, Value left, Value right) {
     super(type, dest, left, right);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/Or.java b/src/main/java/com/android/tools/r8/ir/code/Or.java
index 3fd1a77..f0ce553 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Or.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Or.java
@@ -15,7 +15,17 @@
 
 public class Or extends LogicalBinop {
 
-  public Or(NumericType type, Value dest, Value left, Value right) {
+  public static Or create(NumericType type, Value dest, Value left, Value right) {
+    Or or = new Or(type, dest, left, right);
+    or.normalizeArgumentsForCommutativeBinop();
+    return or;
+  }
+
+  public static Or createNonNormalized(NumericType type, Value dest, Value left, Value right) {
+    return new Or(type, dest, left, right);
+  }
+
+  private Or(NumericType type, Value dest, Value left, Value right) {
     super(type, dest, left, right);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/Xor.java b/src/main/java/com/android/tools/r8/ir/code/Xor.java
index 657374a..db92998 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Xor.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Xor.java
@@ -15,7 +15,17 @@
 
 public class Xor extends LogicalBinop {
 
-  public Xor(NumericType type, Value dest, Value left, Value right) {
+  public static Xor create(NumericType type, Value dest, Value left, Value right) {
+    Xor xor = new Xor(type, dest, left, right);
+    xor.normalizeArgumentsForCommutativeBinop();
+    return xor;
+  }
+
+  public static Xor createNonNormalized(NumericType type, Value dest, Value left, Value right) {
+    return new Xor(type, dest, left, right);
+  }
+
+  private Xor(NumericType type, Value dest, Value left, Value right) {
     super(type, dest, left, right);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 3dfe55f..81f5c14 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -321,7 +321,7 @@
 
         // Replace Not with Xor.
         it.replaceCurrentInstruction(
-            new Xor(current.asNot().type, current.outValue(), inValue, constValue));
+            Xor.create(current.asNot().type, current.outValue(), inValue, constValue));
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 779beba..e28dba3 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -1086,7 +1086,7 @@
     Value in1 = readNumericRegister(left, type);
     Value in2 = readNumericRegister(right, type);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    Add instruction = new Add(type, out, in1, in2);
+    Add instruction = Add.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -1096,7 +1096,7 @@
     Value in1 = readNumericRegister(value, type);
     Value in2 = readIntLiteral(constant);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    Add instruction = new Add(type, out, in1, in2);
+    Add instruction = Add.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -1106,7 +1106,7 @@
     Value in1 = readNumericRegister(left, type);
     Value in2 = readNumericRegister(right, type);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    And instruction = new And(type, out, in1, in2);
+    And instruction = And.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -1116,7 +1116,7 @@
     Value in1 = readNumericRegister(value, type);
     Value in2 = readIntLiteral(constant);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    And instruction = new And(type, out, in1, in2);
+    And instruction = And.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -1323,7 +1323,7 @@
     Value in1 = readNumericRegister(left, type);
     Value in2 = readNumericRegister(right, type);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    Mul instruction = new Mul(type, out, in1, in2);
+    Mul instruction = Mul.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -1333,7 +1333,7 @@
     Value in1 = readNumericRegister(value, type);
     Value in2 = readIntLiteral(constant);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    Mul instruction = new Mul(type, out, in1, in2);
+    Mul instruction = Mul.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -1774,7 +1774,7 @@
       instruction = new Not(type, out, in);
     } else {
       Value minusOne = readLiteral(ValueTypeConstraint.fromNumericType(type), -1);
-      instruction = new Xor(type, out, in, minusOne);
+      instruction = Xor.create(type, out, in, minusOne);
     }
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
@@ -1991,7 +1991,7 @@
     Value in1 = readNumericRegister(left, type);
     Value in2 = readNumericRegister(right, type);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    Or instruction = new Or(type, out, in1, in2);
+    Or instruction = Or.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -2001,7 +2001,7 @@
     Value in1 = readNumericRegister(value, type);
     Value in2 = readIntLiteral(constant);
     Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-    Or instruction = new Or(type, out, in1, in2);
+    Or instruction = Or.create(type, out, in1, in2);
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
   }
@@ -2077,7 +2077,7 @@
         && in2.getConstInstruction().asConstNumber().isIntegerNegativeOne(type)) {
       instruction = new Not(type, out, in1);
     } else {
-      instruction = new Xor(type, out, in1, in2);
+      instruction = Xor.create(type, out, in1, in2);
     }
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
@@ -2093,7 +2093,7 @@
     } else {
       Value in2 = readIntLiteral(constant);
       Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
-      instruction = new Xor(type, out, in1, in2);
+      instruction = Xor.create(type, out, in1, in2);
     }
     assert !instruction.instructionTypeCanThrow();
     addInstruction(instruction);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 9f985e9..692eeee 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -3567,8 +3567,8 @@
                   phiBlock.getInstructions().add(insertIndex++, cstToUse);
                 }
                 phi.replaceUsers(newOutValue);
-                Instruction newInstruction = new Xor(NumericType.INT, newOutValue, testValue,
-                    cstToUse.outValue());
+                Instruction newInstruction =
+                    Xor.create(NumericType.INT, newOutValue, testValue, cstToUse.outValue());
                 newInstruction.setBlock(phiBlock);
                 // The xor is replacing a phi so it does not have an actual position.
                 newInstruction.setPosition(phiPosition);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
index ef163ad..3b0caa2 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
@@ -300,10 +300,10 @@
       Instruction newInstruction = null;
       switch (type) {
         case ADD:
-          newInstruction = new Add(numericType, outValue, inValues.get(0), inValues.get(1));
+          newInstruction = Add.create(numericType, outValue, inValues.get(0), inValues.get(1));
           break;
         case MUL:
-          newInstruction = new Mul(numericType, outValue, inValues.get(0), inValues.get(1));
+          newInstruction = Mul.create(numericType, outValue, inValues.get(0), inValues.get(1));
           break;
         case SUB:
           newInstruction = new Sub(numericType, outValue, inValues.get(0), inValues.get(1));
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
index 70c442b..4eea25d 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -344,7 +344,8 @@
     @Override
     public void onAdd(NumericType type, EV leftValueIndex, EV rightValueIndex) {
       Value dest = getOutValueForNextInstruction(TypeElement.getInt());
-      addInstruction(new Add(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
+      addInstruction(
+          Add.createNonNormalized(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
     }
 
     @Override
@@ -356,7 +357,8 @@
     @Override
     public void onMul(NumericType type, EV leftValueIndex, EV rightValueIndex) {
       Value dest = getOutValueForNextInstruction(TypeElement.getInt());
-      addInstruction(new Mul(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
+      addInstruction(
+          Mul.createNonNormalized(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
     }
 
     @Override
diff --git a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
index a376a2e..66adde9 100644
--- a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
+++ b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
@@ -380,7 +380,7 @@
       newReturnBlock.iterator().next().asReturn().returnValue().replaceUsers(newReturnValue);
       Instruction constInstruction = new ConstNumber(newConstValue, 10);
       Instruction addInstruction =
-          new Add(NumericType.INT, newReturnValue, oldReturnValue, newConstValue);
+          Add.create(NumericType.INT, newReturnValue, oldReturnValue, newConstValue);
       iterator.previous();
       iterator.add(constInstruction);
       iterator.add(addInstruction);
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
index 5db89dc..983dfdb 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
@@ -110,9 +110,9 @@
     Value value2 = new Value(2, TypeElement.getInt(), null);
     ConstNumber const2 = new ConstNumber(value2, 2);
     Value value3 = new Value(2, TypeElement.getInt(), null);
-    Add add0 = new Add(NumericType.INT, value3, value0, value1);
+    Add add0 = Add.create(NumericType.INT, value3, value0, value1);
     add0.setPosition(Position.none());
-    Add add1 = new Add(NumericType.INT, value3, value0, value2);
+    Add add1 = Add.create(NumericType.INT, value3, value0, value2);
     add1.setPosition(Position.none());
     value0.computeNeedsRegister();
     assertTrue(value0.needsRegister());