Implement OR abstract function

Bug: b/302483644
Change-Id: I83657149ae8defd3786ef4218534979dc870c058
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/arithmetic/AbstractCalculator.java b/src/main/java/com/android/tools/r8/ir/analysis/value/arithmetic/AbstractCalculator.java
new file mode 100644
index 0000000..741efd0
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/arithmetic/AbstractCalculator.java
@@ -0,0 +1,174 @@
+// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.ir.analysis.value.arithmetic;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.utils.BitUtils;
+
+public class AbstractCalculator {
+
+  public static AbstractValue andIntegers(
+      AbstractValue left, AbstractValue right, AppView<?> appView) {
+    if (left.isZero()) {
+      return left;
+    }
+    if (right.isZero()) {
+      return right;
+    }
+    if (left.isSingleNumberValue() && right.isSingleNumberValue()) {
+      int result =
+          left.asSingleNumberValue().getIntValue() & right.asSingleNumberValue().getIntValue();
+      return appView.abstractValueFactory().createUncheckedSingleNumberValue(result);
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation()
+        && right.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(
+              left.getDefinitelySetIntBits() & right.getDefinitelySetIntBits(),
+              left.getDefinitelyUnsetIntBits() | right.getDefinitelyUnsetIntBits());
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(0, left.getDefinitelyUnsetIntBits());
+    }
+    if (right.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(0, right.getDefinitelyUnsetIntBits());
+    }
+    return AbstractValue.unknown();
+  }
+
+  public static AbstractValue orIntegers(
+      AbstractValue left, AbstractValue right, AppView<?> appView) {
+    if (left.isZero()) {
+      return right;
+    }
+    if (right.isZero()) {
+      return left;
+    }
+    if (left.isSingleNumberValue() && right.isSingleNumberValue()) {
+      int result =
+          left.asSingleNumberValue().getIntValue() | right.asSingleNumberValue().getIntValue();
+      return appView.abstractValueFactory().createUncheckedSingleNumberValue(result);
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation()
+        && right.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(
+              left.getDefinitelySetIntBits() | right.getDefinitelySetIntBits(),
+              left.getDefinitelyUnsetIntBits() & right.getDefinitelyUnsetIntBits());
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(left.getDefinitelySetIntBits(), 0);
+    }
+    if (right.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(right.getDefinitelySetIntBits(), 0);
+    }
+    return AbstractValue.unknown();
+  }
+
+  public static AbstractValue shlIntegers(
+      AbstractValue left, AbstractValue right, AppView<?> appView) {
+    if (!right.isSingleNumberValue()) {
+      return AbstractValue.unknown();
+    }
+    int rightConst = right.asSingleNumberValue().getIntValue();
+    if (rightConst == 0) {
+      return left;
+    }
+    if (left.isSingleNumberValue()) {
+      int result = left.asSingleNumberValue().getIntValue() << rightConst;
+      return appView.abstractValueFactory().createUncheckedSingleNumberValue(result);
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation() && rightConst > 0) {
+      // Shift the known bits and add that we now know that the lowermost n bits are definitely
+      // unset. Note that when rightConst is 31, 1 << rightConst is Integer.MIN_VALUE. When
+      // subtracting 1 we overflow and get 0111...111, as desired.
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(
+              left.getDefinitelySetIntBits() << rightConst,
+              (left.getDefinitelyUnsetIntBits() << rightConst) | ((1 << rightConst) - 1));
+    }
+    return AbstractValue.unknown();
+  }
+
+  public static AbstractValue shrIntegers(
+      AbstractValue left, AbstractValue right, AppView<?> appView) {
+    if (!right.isSingleNumberValue()) {
+      return AbstractValue.unknown();
+    }
+    int rightConst = right.asSingleNumberValue().getIntValue();
+    if (rightConst == 0) {
+      return left;
+    }
+    if (left.isSingleNumberValue()) {
+      int result = left.asSingleNumberValue().getIntValue() >> rightConst;
+      return appView.abstractValueFactory().createUncheckedSingleNumberValue(result);
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(
+              left.getDefinitelySetIntBits() >> rightConst,
+              left.getDefinitelyUnsetIntBits() >> rightConst);
+    }
+    return AbstractValue.unknown();
+  }
+
+  public static AbstractValue ushrIntegers(
+      AbstractValue left, AbstractValue right, AppView<?> appView) {
+    if (!right.isSingleNumberValue()) {
+      return AbstractValue.unknown();
+    }
+    int rightConst = right.asSingleNumberValue().getIntValue();
+    if (rightConst == 0) {
+      return left;
+    }
+    if (left.isSingleNumberValue()) {
+      int result = left.asSingleNumberValue().getIntValue() >>> rightConst;
+      return appView.abstractValueFactory().createUncheckedSingleNumberValue(result);
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation() && rightConst > 0) {
+      // Shift the known bits information and add that we now know that the uppermost n bits are
+      // definitely unset.
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(
+              left.getDefinitelySetIntBits() >>> rightConst,
+              (left.getDefinitelyUnsetIntBits() >>> rightConst)
+                  | (BitUtils.ONLY_SIGN_BIT_SET_MASK >> (rightConst - 1)));
+    }
+    return AbstractValue.unknown();
+  }
+
+  public static AbstractValue xorIntegers(
+      AbstractValue left, AbstractValue right, AppView<?> appView) {
+    if (left.isSingleNumberValue() && right.isSingleNumberValue()) {
+      int result =
+          left.asSingleNumberValue().getIntValue() ^ right.asSingleNumberValue().getIntValue();
+      return appView.abstractValueFactory().createUncheckedSingleNumberValue(result);
+    }
+    if (left.hasDefinitelySetAndUnsetBitsInformation()
+        && right.hasDefinitelySetAndUnsetBitsInformation()) {
+      return appView
+          .abstractValueFactory()
+          .createDefiniteBitsNumberValue(
+              (left.getDefinitelySetIntBits() & right.getDefinitelyUnsetIntBits())
+                  | (left.getDefinitelyUnsetIntBits() & right.getDefinitelySetIntBits()),
+              (left.getDefinitelySetIntBits() & right.getDefinitelySetIntBits())
+                  | (left.getDefinitelyUnsetIntBits() & right.getDefinitelyUnsetIntBits()));
+    }
+    return AbstractValue.unknown();
+  }
+}
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 2639a9d..08b399f 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
@@ -14,6 +14,7 @@
 import com.android.tools.r8.dex.code.DexInstruction;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.analysis.value.arithmetic.AbstractCalculator;
 import java.util.Set;
 
 public class And extends LogicalBinop {
@@ -104,37 +105,7 @@
 
   @Override
   AbstractValue foldIntegers(AbstractValue left, AbstractValue right, AppView<?> appView) {
-    if (left.isZero()) {
-      return left;
-    }
-    if (right.isZero()) {
-      return right;
-    }
-    if (left.isSingleNumberValue() && right.isSingleNumberValue()) {
-      int result =
-          foldIntegers(
-              left.asSingleNumberValue().getIntValue(), right.asSingleNumberValue().getIntValue());
-      return appView.abstractValueFactory().createSingleNumberValue(result, getOutType());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation()
-        && right.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(
-              foldIntegers(left.getDefinitelySetIntBits(), right.getDefinitelySetIntBits()),
-              left.getDefinitelyUnsetIntBits() | right.getDefinitelyUnsetIntBits());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(0, left.getDefinitelyUnsetIntBits());
-    }
-    if (right.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(0, right.getDefinitelyUnsetIntBits());
-    }
-    return AbstractValue.unknown();
+    return AbstractCalculator.andIntegers(left, right, appView);
   }
 
   @Override
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 0cc297a..c098fe2 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
@@ -13,6 +13,7 @@
 import com.android.tools.r8.dex.code.DexOrLong2Addr;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.analysis.value.arithmetic.AbstractCalculator;
 import java.util.Set;
 
 public class Or extends LogicalBinop {
@@ -103,37 +104,7 @@
 
   @Override
   AbstractValue foldIntegers(AbstractValue left, AbstractValue right, AppView<?> appView) {
-    if (left.isZero()) {
-      return right;
-    }
-    if (right.isZero()) {
-      return left;
-    }
-    if (left.isSingleNumberValue() && right.isSingleNumberValue()) {
-      int result =
-          foldIntegers(
-              left.asSingleNumberValue().getIntValue(), right.asSingleNumberValue().getIntValue());
-      return appView.abstractValueFactory().createSingleNumberValue(result, getOutType());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation()
-        && right.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(
-              foldIntegers(left.getDefinitelySetIntBits(), right.getDefinitelySetIntBits()),
-              left.getDefinitelyUnsetIntBits() & right.getDefinitelyUnsetIntBits());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(left.getDefinitelySetIntBits(), 0);
-    }
-    if (right.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(right.getDefinitelySetIntBits(), 0);
-    }
-    return AbstractValue.unknown();
+    return AbstractCalculator.orIntegers(left, right, appView);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Shl.java b/src/main/java/com/android/tools/r8/ir/code/Shl.java
index a9d9ee4..5977cad 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Shl.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Shl.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.analysis.value.arithmetic.AbstractCalculator;
 
 public class Shl extends LogicalBinop {
 
@@ -98,28 +99,7 @@
 
   @Override
   AbstractValue foldIntegers(AbstractValue left, AbstractValue right, AppView<?> appView) {
-    if (!right.isSingleNumberValue()) {
-      return AbstractValue.unknown();
-    }
-    int rightConst = right.asSingleNumberValue().getIntValue();
-    if (rightConst == 0) {
-      return left;
-    }
-    if (left.isSingleNumberValue()) {
-      int result = foldIntegers(left.asSingleNumberValue().getIntValue(), rightConst);
-      return appView.abstractValueFactory().createSingleNumberValue(result, getOutType());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation() && rightConst > 0) {
-      // Shift the known bits and add that we now know that the lowermost n bits are definitely
-      // unset. Note that when rightConst is 31, 1 << rightConst is Integer.MIN_VALUE. When
-      // subtracting 1 we overflow and get 0111...111, as desired.
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(
-              foldIntegers(left.getDefinitelySetIntBits(), rightConst),
-              foldIntegers(left.getDefinitelyUnsetIntBits(), rightConst) | ((1 << rightConst) - 1));
-    }
-    return AbstractValue.unknown();
+    return AbstractCalculator.shlIntegers(left, right, appView);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Shr.java b/src/main/java/com/android/tools/r8/ir/code/Shr.java
index bc59c79..d1b6a1c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Shr.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Shr.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.analysis.value.arithmetic.AbstractCalculator;
 
 public class Shr extends LogicalBinop {
 
@@ -98,25 +99,7 @@
 
   @Override
   AbstractValue foldIntegers(AbstractValue left, AbstractValue right, AppView<?> appView) {
-    if (!right.isSingleNumberValue()) {
-      return AbstractValue.unknown();
-    }
-    int rightConst = right.asSingleNumberValue().getIntValue();
-    if (rightConst == 0) {
-      return left;
-    }
-    if (left.isSingleNumberValue()) {
-      int result = foldIntegers(left.asSingleNumberValue().getIntValue(), rightConst);
-      return appView.abstractValueFactory().createSingleNumberValue(result, getOutType());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(
-              foldIntegers(left.getDefinitelySetIntBits(), rightConst),
-              foldIntegers(left.getDefinitelyUnsetIntBits(), rightConst));
-    }
-    return AbstractValue.unknown();
+    return AbstractCalculator.shrIntegers(left, right, appView);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Ushr.java b/src/main/java/com/android/tools/r8/ir/code/Ushr.java
index 104b90d..88eb857 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Ushr.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Ushr.java
@@ -13,7 +13,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.utils.BitUtils;
+import com.android.tools.r8.ir.analysis.value.arithmetic.AbstractCalculator;
 
 public class Ushr extends LogicalBinop {
 
@@ -99,28 +99,7 @@
 
   @Override
   AbstractValue foldIntegers(AbstractValue left, AbstractValue right, AppView<?> appView) {
-    if (!right.isSingleNumberValue()) {
-      return AbstractValue.unknown();
-    }
-    int rightConst = right.asSingleNumberValue().getIntValue();
-    if (rightConst == 0) {
-      return left;
-    }
-    if (left.isSingleNumberValue()) {
-      int result = foldIntegers(left.asSingleNumberValue().getIntValue(), rightConst);
-      return appView.abstractValueFactory().createSingleNumberValue(result, getOutType());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation() && rightConst > 0) {
-      // Shift the known bits information and add that we now know that the uppermost n bits are
-      // definitely unset.
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(
-              foldIntegers(left.getDefinitelySetIntBits(), rightConst),
-              foldIntegers(left.getDefinitelyUnsetIntBits(), rightConst)
-                  | (BitUtils.ONLY_SIGN_BIT_SET_MASK >> (rightConst - 1)));
-    }
-    return AbstractValue.unknown();
+    return AbstractCalculator.ushrIntegers(left, right, appView);
   }
 
   @Override
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 5116990..fff451f 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
@@ -13,6 +13,7 @@
 import com.android.tools.r8.dex.code.DexXorLong2Addr;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.analysis.value.arithmetic.AbstractCalculator;
 import java.util.Set;
 
 public class Xor extends LogicalBinop {
@@ -98,23 +99,7 @@
 
   @Override
   AbstractValue foldIntegers(AbstractValue left, AbstractValue right, AppView<?> appView) {
-    if (left.isSingleNumberValue() && right.isSingleNumberValue()) {
-      int result =
-          foldIntegers(
-              left.asSingleNumberValue().getIntValue(), right.asSingleNumberValue().getIntValue());
-      return appView.abstractValueFactory().createSingleNumberValue(result, getOutType());
-    }
-    if (left.hasDefinitelySetAndUnsetBitsInformation()
-        && right.hasDefinitelySetAndUnsetBitsInformation()) {
-      return appView
-          .abstractValueFactory()
-          .createDefiniteBitsNumberValue(
-              (left.getDefinitelySetIntBits() & right.getDefinitelyUnsetIntBits())
-                  | (left.getDefinitelyUnsetIntBits() & right.getDefinitelySetIntBits()),
-              (left.getDefinitelySetIntBits() & right.getDefinitelySetIntBits())
-                  | (left.getDefinitelyUnsetIntBits() & right.getDefinitelyUnsetIntBits()));
-    }
-    return AbstractValue.unknown();
+    return AbstractCalculator.xorIntegers(left, right, appView);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java
index 0893be8..7b390d6 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java
@@ -3,6 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize.argumentpropagation.codescanner;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
 public interface AbstractFunction extends InFlow {
 
   static IdentityAbstractFunction identity() {
@@ -25,7 +28,10 @@
    * {@param flowGraphStateProvider}. Attempting to lookup the state of a non-declared input is an
    * error.
    */
-  ValueState apply(FlowGraphStateProvider flowGraphStateProvider, ConcreteValueState state);
+  ValueState apply(
+      AppView<AppInfoWithLiveness> appView,
+      FlowGraphStateProvider flowGraphStateProvider,
+      ConcreteValueState inState);
 
   /** Returns true if the given {@param inFlow} is a declared input of this abstract function. */
   boolean containsBaseInFlow(BaseInFlow inFlow);
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java
index 2d53523..fbd733b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java
@@ -29,16 +29,20 @@
     assert !isEffectivelyUnknown() : "Must use UnknownParameterState instead";
   }
 
-  public static NonEmptyValueState create(AbstractValue abstractValue) {
-    return abstractValue.isUnknown()
-        ? ValueState.unknown()
-        : new ConcretePrimitiveTypeValueState(abstractValue);
-  }
-
   public ConcretePrimitiveTypeValueState(InFlow inFlow) {
     this(AbstractValue.bottom(), SetUtils.newHashSet(inFlow));
   }
 
+  public static NonEmptyValueState create(AbstractValue abstractValue) {
+    return create(abstractValue, Collections.emptySet());
+  }
+
+  public static NonEmptyValueState create(AbstractValue abstractValue, Set<InFlow> inFlow) {
+    return abstractValue.isUnknown()
+        ? ValueState.unknown()
+        : new ConcretePrimitiveTypeValueState(abstractValue, inFlow);
+  }
+
   @Override
   public ValueState clearInFlow() {
     if (hasInFlow()) {
@@ -52,7 +56,7 @@
   }
 
   @Override
-  public ValueState mutableCopy() {
+  public ConcretePrimitiveTypeValueState mutableCopy() {
     return new ConcretePrimitiveTypeValueState(abstractValue, copyInFlow());
   }
 
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/IdentityAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/IdentityAbstractFunction.java
index e3818a9..1545a75 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/IdentityAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/IdentityAbstractFunction.java
@@ -4,6 +4,8 @@
 package com.android.tools.r8.optimize.argumentpropagation.codescanner;
 
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class IdentityAbstractFunction implements AbstractFunction {
 
@@ -16,8 +18,11 @@
   }
 
   @Override
-  public ValueState apply(FlowGraphStateProvider flowGraphStateProvider, ConcreteValueState state) {
-    return state;
+  public ValueState apply(
+      AppView<AppInfoWithLiveness> appView,
+      FlowGraphStateProvider flowGraphStateProvider,
+      ConcreteValueState inState) {
+    return inState;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
index 59a3a7f..bd97c0b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
@@ -3,8 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize.argumentpropagation.codescanner;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.Lists;
 
 public class InstanceFieldReadAbstractFunction implements AbstractFunction {
@@ -19,7 +21,9 @@
 
   @Override
   public ValueState apply(
-      FlowGraphStateProvider flowGraphStateProvider, ConcreteValueState predecessorState) {
+      AppView<AppInfoWithLiveness> appView,
+      FlowGraphStateProvider flowGraphStateProvider,
+      ConcreteValueState predecessorState) {
     ValueState state = flowGraphStateProvider.getState(receiver, () -> ValueState.bottom(field));
     if (state.isBottom()) {
       return ValueState.bottom(field);
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/OrAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/OrAbstractFunction.java
index 93ac577..3c02dd2 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/OrAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/OrAbstractFunction.java
@@ -3,6 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize.argumentpropagation.codescanner;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.analysis.value.SingleNumberValue;
+import com.android.tools.r8.ir.analysis.value.arithmetic.AbstractCalculator;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.IterableUtils;
 import java.util.Objects;
 
@@ -14,18 +19,22 @@
 public class OrAbstractFunction implements AbstractFunction {
 
   public final BaseInFlow inFlow;
-  public final long constant;
+  public final SingleNumberValue constant;
 
-  public OrAbstractFunction(BaseInFlow inFlow, long constant) {
+  public OrAbstractFunction(BaseInFlow inFlow, SingleNumberValue constant) {
     this.inFlow = inFlow;
     this.constant = constant;
   }
 
   @Override
-  public ValueState apply(FlowGraphStateProvider flowGraphStateProvider, ConcreteValueState state) {
-    // TODO(b/302483644): Implement this abstract function to allow correct value propagation of
-    //  updateChangedFlags(x | 1).
-    return state;
+  public ValueState apply(
+      AppView<AppInfoWithLiveness> appView,
+      FlowGraphStateProvider flowGraphStateProvider,
+      ConcreteValueState inState) {
+    ConcretePrimitiveTypeValueState inPrimitiveState = inState.asPrimitiveState();
+    AbstractValue result =
+        AbstractCalculator.orIntegers(inPrimitiveState.getAbstractValue(), constant, appView);
+    return ConcretePrimitiveTypeValueState.create(result, inPrimitiveState.copyInFlow());
   }
 
   @Override
@@ -55,7 +64,7 @@
       return false;
     }
     OrAbstractFunction fn = (OrAbstractFunction) obj;
-    return inFlow.equals(fn.inFlow) && constant == fn.constant;
+    return inFlow.equals(fn.inFlow) && constant.equals(fn.constant);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownAbstractFunction.java
index 7ddc238..f9ffd98 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownAbstractFunction.java
@@ -4,6 +4,8 @@
 package com.android.tools.r8.optimize.argumentpropagation.codescanner;
 
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class UnknownAbstractFunction implements AbstractFunction {
 
@@ -16,7 +18,10 @@
   }
 
   @Override
-  public ValueState apply(FlowGraphStateProvider flowGraphStateProvider, ConcreteValueState state) {
+  public ValueState apply(
+      AppView<AppInfoWithLiveness> appView,
+      FlowGraphStateProvider flowGraphStateProvider,
+      ConcreteValueState inState) {
     return ValueState.unknown();
   }
 
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
index 894a54c..952b3a2 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
@@ -149,7 +149,8 @@
           for (AbstractFunction transferFunction : transferFunctions) {
             FlowGraphStateProvider flowGraphStateProvider =
                 FlowGraphStateProvider.create(flowGraph, transferFunction);
-            ValueState transferState = transferFunction.apply(flowGraphStateProvider, state);
+            ValueState transferState =
+                transferFunction.apply(appView, flowGraphStateProvider, state);
             if (transferState.isBottom()) {
               // Nothing to propagate.
             } else if (transferState.isUnknown()) {
diff --git a/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorComposeModeling.java b/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorComposeModeling.java
index ebba6d5..332b695 100644
--- a/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorComposeModeling.java
+++ b/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorComposeModeling.java
@@ -13,6 +13,8 @@
 import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
+import com.android.tools.r8.ir.analysis.value.SingleNumberValue;
 import com.android.tools.r8.ir.code.InstanceGet;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InvokeMethod;
@@ -203,9 +205,11 @@
         argument = otherOperand;
         // Update the model from bottom to a special value that effectively throws away any known
         // information about the lowermost bit of $$changed.
+        SingleNumberValue one =
+            appView.abstractValueFactory().createSingleNumberValue(1, TypeElement.getInt());
         inFlow =
             new UpdateChangedFlagsAbstractFunction(
-                new OrAbstractFunction(new FieldValue(expectedField), 1));
+                new OrAbstractFunction(new FieldValue(expectedField), one));
       } else {
         inFlow = new UpdateChangedFlagsAbstractFunction(new FieldValue(expectedField));
       }
diff --git a/src/main/java/com/android/tools/r8/optimize/compose/UpdateChangedFlagsAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/compose/UpdateChangedFlagsAbstractFunction.java
index 8bf3c0d..ee25e29 100644
--- a/src/main/java/com/android/tools/r8/optimize/compose/UpdateChangedFlagsAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/compose/UpdateChangedFlagsAbstractFunction.java
@@ -3,12 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize.compose;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.AbstractFunction;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.BaseInFlow;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteValueState;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.FlowGraphStateProvider;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.InFlow;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.OrAbstractFunction;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.IterableUtils;
 import java.util.Objects;
 
@@ -21,10 +24,21 @@
   }
 
   @Override
-  public ValueState apply(FlowGraphStateProvider flowGraphStateProvider, ConcreteValueState state) {
+  public ValueState apply(
+      AppView<AppInfoWithLiveness> appView,
+      FlowGraphStateProvider flowGraphStateProvider,
+      ConcreteValueState baseInState) {
+    ValueState inState;
+    if (inFlow.isAbstractFunction()) {
+      AbstractFunction orFunction = inFlow.asAbstractFunction();
+      assert orFunction instanceof OrAbstractFunction;
+      inState = orFunction.apply(appView, flowGraphStateProvider, baseInState);
+    } else {
+      inState = baseInState;
+    }
     // TODO(b/302483644): Implement this abstract function to allow correct value propagation of
     //  updateChangedFlags(x | 1).
-    return state;
+    return inState;
   }
 
   @Override