Add Math.div methods

Bug: b/388147728
Change-Id: I2c3bd5bea211be4e5400a765a7b3a1e048229d9c
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 3553629..b52dbf0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -2022,6 +2022,44 @@
         addProvider(
             new MethodGenerator(
                 method, BackportedMethods::MathMethods_ceilModLongInt, "ceilModLongInt"));
+
+        // int divideExact(int, int)
+        // long divideExact(long, long)
+        name = factory.createString("divideExact");
+        proto = factory.createProto(factory.intType, factory.intType, factory.intType);
+        method = factory.createMethod(mathType, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method, BackportedMethods::MathMethods_divideExactInt, "divideExactInt"));
+        proto = factory.createProto(factory.longType, factory.longType, factory.longType);
+        method = factory.createMethod(mathType, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method, BackportedMethods::MathMethods_divideExactLong, "divideExactLong"));
+
+        // int floorDivExact(int, int)
+        // long floorDivExact(long, long)
+        name = factory.createString("floorDivExact");
+        proto = factory.createProto(factory.intType, factory.intType, factory.intType);
+        method = factory.createMethod(mathType, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method, BackportedMethods::MathMethods_floorDivExactInt, "floorDivExactInt"));
+        proto = factory.createProto(factory.longType, factory.longType, factory.longType);
+        method = factory.createMethod(mathType, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method, BackportedMethods::MathMethods_floorDivExactLong, "floorDivExactLong"));
+
+        // long unsignedMultiplyHigh(long, long)
+        name = factory.createString("unsignedMultiplyHigh");
+        proto = factory.createProto(factory.longType, factory.longType, factory.longType);
+        method = factory.createMethod(mathType, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method,
+                BackportedMethods::MathMethods_unsignedMultiplyHigh,
+                "unsignedMultiplyHigh"));
       }
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index 89ca871..24224c7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -6193,6 +6193,348 @@
         ImmutableList.of());
   }
 
+  public static CfCode MathMethods_divideExactInt(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        2,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.INT, 0),
+            new CfConstNumber(-2147483648, ValueType.INT),
+            new CfIfCmp(IfType.NE, ValueType.INT, label2),
+            new CfLoad(ValueType.INT, 1),
+            new CfConstNumber(-1, ValueType.INT),
+            new CfIfCmp(IfType.NE, ValueType.INT, label2),
+            label1,
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfConstString(factory.createString("integer overflow")),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1}, new FrameType[] {FrameType.intType(), FrameType.intType()})),
+            new CfLoad(ValueType.INT, 0),
+            new CfLoad(ValueType.INT, 1),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Div, NumericType.INT),
+            new CfReturn(ValueType.INT),
+            label3),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode MathMethods_divideExactLong(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        4,
+        4,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.LONG, 0),
+            new CfConstNumber(-9223372036854775808L, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.NE, ValueType.INT, label2),
+            new CfLoad(ValueType.LONG, 2),
+            new CfConstNumber(-1, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.NE, ValueType.INT, label2),
+            label1,
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfConstString(factory.createString("long overflow")),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.LONG, 0),
+            new CfLoad(ValueType.LONG, 2),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Div, NumericType.LONG),
+            new CfReturn(ValueType.LONG),
+            label3),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode MathMethods_floorDivExactInt(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    CfLabel label6 = new CfLabel();
+    CfLabel label7 = new CfLabel();
+    CfLabel label8 = new CfLabel();
+    CfLabel label9 = new CfLabel();
+    CfLabel label10 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        5,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.INT, 0),
+            new CfConstNumber(-2147483648, ValueType.INT),
+            new CfIfCmp(IfType.NE, ValueType.INT, label2),
+            new CfLoad(ValueType.INT, 1),
+            new CfConstNumber(-1, ValueType.INT),
+            new CfIfCmp(IfType.NE, ValueType.INT, label2),
+            label1,
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfConstString(factory.createString("integer overflow")),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1}, new FrameType[] {FrameType.intType(), FrameType.intType()})),
+            new CfLoad(ValueType.INT, 0),
+            new CfLoad(ValueType.INT, 1),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Div, NumericType.INT),
+            new CfStore(ValueType.INT, 2),
+            label3,
+            new CfLoad(ValueType.INT, 0),
+            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 2),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.INT),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfStore(ValueType.INT, 3),
+            label4,
+            new CfLoad(ValueType.INT, 3),
+            new CfIf(IfType.NE, ValueType.INT, label6),
+            label5,
+            new CfLoad(ValueType.INT, 2),
+            new CfReturn(ValueType.INT),
+            label6,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfConstNumber(1, ValueType.INT),
+            new CfLoad(ValueType.INT, 0),
+            new CfLoad(ValueType.INT, 1),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Xor, NumericType.INT),
+            new CfConstNumber(31, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
+            new CfStore(ValueType.INT, 4),
+            label7,
+            new CfLoad(ValueType.INT, 4),
+            new CfIf(IfType.GE, ValueType.INT, label8),
+            new CfLoad(ValueType.INT, 2),
+            new CfConstNumber(1, ValueType.INT),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfGoto(label9),
+            label8,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 2),
+            label9,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    }),
+                new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
+            new CfReturn(ValueType.INT),
+            label10),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode MathMethods_floorDivExactLong(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    CfLabel label6 = new CfLabel();
+    CfLabel label7 = new CfLabel();
+    CfLabel label8 = new CfLabel();
+    CfLabel label9 = new CfLabel();
+    CfLabel label10 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
+        10,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.LONG, 0),
+            new CfConstNumber(-9223372036854775808L, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.NE, ValueType.INT, label2),
+            new CfLoad(ValueType.LONG, 2),
+            new CfConstNumber(-1, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.NE, ValueType.INT, label2),
+            label1,
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfConstString(factory.createString("long overflow")),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.LONG, 0),
+            new CfLoad(ValueType.LONG, 2),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Div, NumericType.LONG),
+            new CfStore(ValueType.LONG, 4),
+            label3,
+            new CfLoad(ValueType.LONG, 0),
+            new CfLoad(ValueType.LONG, 2),
+            new CfLoad(ValueType.LONG, 4),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.LONG),
+            new CfStore(ValueType.LONG, 6),
+            label4,
+            new CfLoad(ValueType.LONG, 6),
+            new CfConstNumber(0, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.NE, ValueType.INT, label6),
+            label5,
+            new CfLoad(ValueType.LONG, 4),
+            new CfReturn(ValueType.LONG),
+            label6,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7},
+                    new FrameType[] {
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfConstNumber(1, ValueType.LONG),
+            new CfLoad(ValueType.LONG, 0),
+            new CfLoad(ValueType.LONG, 2),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Xor, NumericType.LONG),
+            new CfConstNumber(63, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.LONG),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.LONG),
+            new CfStore(ValueType.LONG, 8),
+            label7,
+            new CfLoad(ValueType.LONG, 8),
+            new CfConstNumber(0, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.GE, ValueType.INT, label8),
+            new CfLoad(ValueType.LONG, 4),
+            new CfConstNumber(1, ValueType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.LONG),
+            new CfGoto(label9),
+            label8,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+                    new FrameType[] {
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.LONG, 4),
+            label9,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+                    new FrameType[] {
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    }),
+                new ArrayDeque<>(Arrays.asList(FrameType.longType()))),
+            new CfReturn(ValueType.LONG),
+            label10),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode MathMethods_floorDivInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
@@ -7451,6 +7793,176 @@
         ImmutableList.of());
   }
 
+  public static CfCode MathMethods_unsignedMultiplyHigh(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    CfLabel label6 = new CfLabel();
+    CfLabel label7 = new CfLabel();
+    CfLabel label8 = new CfLabel();
+    CfLabel label9 = new CfLabel();
+    CfLabel label10 = new CfLabel();
+    CfLabel label11 = new CfLabel();
+    CfLabel label12 = new CfLabel();
+    CfLabel label13 = new CfLabel();
+    CfLabel label14 = new CfLabel();
+    CfLabel label15 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
+        22,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.LONG, 0),
+            new CfConstNumber(32, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.LONG),
+            new CfStore(ValueType.LONG, 4),
+            label1,
+            new CfLoad(ValueType.LONG, 0),
+            new CfConstNumber(4294967295L, ValueType.LONG),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.LONG),
+            new CfStore(ValueType.LONG, 6),
+            label2,
+            new CfLoad(ValueType.LONG, 2),
+            new CfConstNumber(32, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.LONG),
+            new CfStore(ValueType.LONG, 8),
+            label3,
+            new CfLoad(ValueType.LONG, 2),
+            new CfConstNumber(4294967295L, ValueType.LONG),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.LONG),
+            new CfStore(ValueType.LONG, 10),
+            label4,
+            new CfLoad(ValueType.LONG, 6),
+            new CfLoad(ValueType.LONG, 10),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfStore(ValueType.LONG, 12),
+            label5,
+            new CfLoad(ValueType.LONG, 4),
+            new CfLoad(ValueType.LONG, 10),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfLoad(ValueType.LONG, 12),
+            new CfConstNumber(32, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Ushr, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 14),
+            label6,
+            new CfLoad(ValueType.LONG, 14),
+            new CfConstNumber(4294967295L, ValueType.LONG),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.LONG),
+            new CfStore(ValueType.LONG, 16),
+            label7,
+            new CfLoad(ValueType.LONG, 14),
+            new CfConstNumber(32, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.LONG),
+            new CfStore(ValueType.LONG, 18),
+            label8,
+            new CfLoad(ValueType.LONG, 16),
+            new CfLoad(ValueType.LONG, 6),
+            new CfLoad(ValueType.LONG, 8),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 16),
+            label9,
+            new CfLoad(ValueType.LONG, 4),
+            new CfLoad(ValueType.LONG, 8),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfLoad(ValueType.LONG, 18),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfLoad(ValueType.LONG, 16),
+            new CfConstNumber(32, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 20),
+            label10,
+            new CfLoad(ValueType.LONG, 0),
+            new CfConstNumber(0, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.GE, ValueType.INT, label12),
+            label11,
+            new CfLoad(ValueType.LONG, 20),
+            new CfLoad(ValueType.LONG, 2),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 20),
+            label12,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {
+                      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
+                    },
+                    new FrameType[] {
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.LONG, 2),
+            new CfConstNumber(0, ValueType.LONG),
+            new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
+            new CfIf(IfType.GE, ValueType.INT, label14),
+            label13,
+            new CfLoad(ValueType.LONG, 20),
+            new CfLoad(ValueType.LONG, 0),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 20),
+            label14,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {
+                      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
+                    },
+                    new FrameType[] {
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.LONG, 20),
+            new CfReturn(ValueType.LONG),
+            label15),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode MethodMethods_getParameterCount(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
diff --git a/src/test/examplesJava21/backport/MathJava21Test.java b/src/test/examplesJava21/backport/MathJava21Test.java
index ae6e48a..1c34ed9 100644
--- a/src/test/examplesJava21/backport/MathJava21Test.java
+++ b/src/test/examplesJava21/backport/MathJava21Test.java
@@ -25,7 +25,7 @@
 
   public MathJava21Test(TestParameters parameters) {
     super(parameters, Math.class, Main.class);
-    registerTarget(AndroidApiLevel.V, 70);
+    registerTarget(AndroidApiLevel.V, 92);
   }
 
   static final class Main extends MiniAssert {
@@ -45,6 +45,14 @@
       testCeilModIntInt();
       testCeilModLongLong();
       testCeilModLongInt();
+
+      testDivideExactInt();
+      testDivideExactLong();
+
+      testFloorDivExactInt();
+      testFloorDivExactLong();
+
+      testUnsignedMultiplyHigh();
     }
 
     private static void testClampInt() {
@@ -200,5 +208,64 @@
       assertEquals(-3L, Math.ceilMod(-3L, 7));
       assertEquals(0L, Math.ceilMod(Long.MIN_VALUE, -1));
     }
+
+    private static void testDivideExactInt() {
+      assertEquals(1, Math.divideExact(7, 7));
+      assertEquals(-1, Math.divideExact(-7, 7));
+      assertEquals(0, Math.divideExact(3, 7));
+      assertEquals(0, Math.divideExact(-3, 7));
+      try {
+        Math.divideExact(Integer.MIN_VALUE, -1);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testDivideExactLong() {
+      assertEquals(1L, Math.divideExact(7L, 7L));
+      assertEquals(-1L, Math.divideExact(-7L, 7L));
+      assertEquals(0, Math.divideExact(3L, 7L));
+      assertEquals(0, Math.divideExact(-3L, 7L));
+      try {
+        Math.divideExact(Long.MIN_VALUE, -1L);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testFloorDivExactInt() {
+      assertEquals(1, Math.floorDivExact(7, 7));
+      assertEquals(-1, Math.floorDivExact(-7, 7));
+      assertEquals(0, Math.floorDivExact(3, 7));
+      assertEquals(-1, Math.floorDivExact(-3, 7));
+      try {
+        Math.floorDivExact(Integer.MIN_VALUE, -1);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testFloorDivExactLong() {
+      assertEquals(1L, Math.floorDivExact(7L, 7L));
+      assertEquals(-1L, Math.floorDivExact(-7L, 7L));
+      assertEquals(0L, Math.floorDivExact(3L, 7L));
+      assertEquals(-1L, Math.floorDivExact(-3L, 7L));
+      try {
+        Math.floorDivExact(Long.MIN_VALUE, -1L);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testUnsignedMultiplyHigh() {
+      assertEquals(
+          31696182030193L, Math.unsignedMultiplyHigh(8222222222222222L, 71111111111111111L));
+      assertEquals(
+          71079414929080917L, Math.unsignedMultiplyHigh(-8222222222222222L, 71111111111111111L));
+    }
   }
 }
diff --git a/src/test/examplesJava21/backport/StrictMathJava21Test.java b/src/test/examplesJava21/backport/StrictMathJava21Test.java
index 95f5d0e..e39d818 100644
--- a/src/test/examplesJava21/backport/StrictMathJava21Test.java
+++ b/src/test/examplesJava21/backport/StrictMathJava21Test.java
@@ -25,7 +25,7 @@
 
   public StrictMathJava21Test(TestParameters parameters) {
     super(parameters, StrictMath.class, Main.class);
-    registerTarget(AndroidApiLevel.V, 70);
+    registerTarget(AndroidApiLevel.V, 92);
   }
 
   static final class Main extends MiniAssert {
@@ -45,6 +45,14 @@
       testCeilModIntInt();
       testCeilModLongLong();
       testCeilModLongInt();
+
+      testDivideExactInt();
+      testDivideExactLong();
+
+      testFloorDivExactInt();
+      testFloorDivExactLong();
+
+      testUnsignedMultiplyHigh();
     }
 
     private static void testClampInt() {
@@ -200,5 +208,65 @@
       assertEquals(-3L, StrictMath.ceilMod(-3L, 7));
       assertEquals(0L, StrictMath.ceilMod(Long.MIN_VALUE, -1));
     }
+
+    private static void testDivideExactInt() {
+      assertEquals(1, StrictMath.divideExact(7, 7));
+      assertEquals(-1, StrictMath.divideExact(-7, 7));
+      assertEquals(0, StrictMath.divideExact(3, 7));
+      assertEquals(0, StrictMath.divideExact(-3, 7));
+      try {
+        StrictMath.divideExact(Integer.MIN_VALUE, -1);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testDivideExactLong() {
+      assertEquals(1L, StrictMath.divideExact(7L, 7L));
+      assertEquals(-1L, StrictMath.divideExact(-7L, 7L));
+      assertEquals(0, StrictMath.divideExact(3L, 7L));
+      assertEquals(0, StrictMath.divideExact(-3L, 7L));
+      try {
+        StrictMath.divideExact(Long.MIN_VALUE, -1L);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testFloorDivExactInt() {
+      assertEquals(1, StrictMath.floorDivExact(7, 7));
+      assertEquals(-1, StrictMath.floorDivExact(-7, 7));
+      assertEquals(0, StrictMath.floorDivExact(3, 7));
+      assertEquals(-1, StrictMath.floorDivExact(-3, 7));
+      try {
+        StrictMath.floorDivExact(Integer.MIN_VALUE, -1);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testFloorDivExactLong() {
+      assertEquals(1L, StrictMath.floorDivExact(7L, 7L));
+      assertEquals(-1L, StrictMath.floorDivExact(-7L, 7L));
+      assertEquals(0L, StrictMath.floorDivExact(3L, 7L));
+      assertEquals(-1L, StrictMath.floorDivExact(-3L, 7L));
+      try {
+        StrictMath.floorDivExact(Long.MIN_VALUE, -1L);
+        fail("Should have thrown");
+      } catch (ArithmeticException ae) {
+
+      }
+    }
+
+    private static void testUnsignedMultiplyHigh() {
+      assertEquals(
+          31696182030193L, StrictMath.unsignedMultiplyHigh(8222222222222222L, 71111111111111111L));
+      assertEquals(
+          71079414929080917L,
+          StrictMath.unsignedMultiplyHigh(-8222222222222222L, 71111111111111111L));
+    }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java
index 16df7e5..86995f4 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java
@@ -365,4 +365,68 @@
     }
     return rem;
   }
+
+  public static int divideExactInt(int x, int y) {
+    if (x == Integer.MIN_VALUE && y == -1) {
+      throw new ArithmeticException("integer overflow");
+    }
+    return x / y;
+  }
+
+  public static long divideExactLong(long x, long y) {
+    if (x == Long.MIN_VALUE && y == -1) {
+      throw new ArithmeticException("long overflow");
+    }
+    return x / y;
+  }
+
+  public static int floorDivExactInt(int x, int y) {
+    if (x == Integer.MIN_VALUE && y == -1) {
+      throw new ArithmeticException("integer overflow");
+    }
+    // Inlined: return Math.floorDiv(x,y);
+    int div = x / y;
+    int rem = x - y * div;
+    if (rem == 0) {
+      return div;
+    }
+    int signum = 1 | ((x ^ y) >> (Integer.SIZE - 1));
+    return signum < 0 ? div - 1 : div;
+  }
+
+  public static long floorDivExactLong(long x, long y) {
+    if (x == Long.MIN_VALUE && y == -1) {
+      throw new ArithmeticException("long overflow");
+    }
+    // Inlined: return Math.floorDiv(x,y);
+    long div = x / y;
+    long rem = x - y * div;
+    if (rem == 0L) {
+      return div;
+    }
+    long signum = 1L | ((x ^ y) >> (Long.SIZE - 1));
+    return signum < 0L ? div - 1L : div;
+  }
+
+  public static long unsignedMultiplyHigh(long x, long y) {
+    long x1 = x >> 32;
+    long x2 = x & 0xFFFFFFFFL;
+    long y1 = y >> 32;
+    long y2 = y & 0xFFFFFFFFL;
+
+    long z2 = x2 * y2;
+    long t = x1 * y2 + (z2 >>> 32);
+    long z1 = t & 0xFFFFFFFFL;
+    long z0 = t >> 32;
+    z1 += x2 * y1;
+
+    long result = x1 * y1 + z0 + (z1 >> 32);
+    if (x < 0) {
+      result += y;
+    }
+    if (y < 0) {
+      result += x;
+    }
+    return result;
+  }
 }