Support Baklava float16 to float conversions

Bug: b/413588305
Change-Id: I7d6299562707af45dcfd8f814ccc0dad99b4f14f
diff --git a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
index 3787398..f385e6a 100644
--- a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
+++ b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
@@ -811,6 +811,12 @@
       Paths.get("third_party", "openjdk", "jdk-11-test").toFile(),
       Paths.get("third_party", "openjdk", "jdk-11-test.tar.gz.sha1").toFile(),
     )
+  val jdk21Float16Test =
+    ThirdPartyDependency(
+      "float16-test",
+      Paths.get("third_party", "openjdk", "float16-test").toFile(),
+      Paths.get("third_party", "openjdk", "float16-test.tar.gz.sha1").toFile(),
+    )
   val junit =
     ThirdPartyDependency(
       "junit",
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 ec6544c..947d140 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
@@ -1808,6 +1808,22 @@
           new MethodWithForwardingGenerator(
               method, BackportedMethods::ObjectsMethods_toIdentityString));
 
+      // short java.lang.Float.floatToFloat16(float)
+      // float java.lang.Float.float16ToFloat(short)
+      type = factory.boxedFloatType;
+      name = factory.createString("floatToFloat16");
+      proto = factory.createProto(factory.shortType, factory.floatType);
+      method = factory.createMethod(type, proto, name);
+      addProvider(
+          new MethodWithForwardingGenerator(
+              method, BackportedMethods::FloatMethods_floatToFloat16));
+      name = factory.createString("float16ToFloat");
+      proto = factory.createProto(factory.floatType, factory.shortType);
+      method = factory.createMethod(type, proto, name);
+      addProvider(
+          new MethodWithForwardingGenerator(
+              method, BackportedMethods::FloatMethods_float16ToFloat));
+
       // android.os.Build
       type = factory.androidOsBuildType;
 
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 1feeccb..15743f4 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
@@ -2861,6 +2861,691 @@
         ImmutableList.of());
   }
 
+  public static CfCode FloatMethods_float16ToFloat(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();
+    CfLabel label16 = new CfLabel();
+    CfLabel label17 = new CfLabel();
+    CfLabel label18 = new CfLabel();
+    CfLabel label19 = new CfLabel();
+    CfLabel label20 = new CfLabel();
+    CfLabel label21 = new CfLabel();
+    CfLabel label22 = new CfLabel();
+    CfLabel label23 = new CfLabel();
+    CfLabel label24 = new CfLabel();
+    CfLabel label25 = new CfLabel();
+    CfLabel label26 = new CfLabel();
+    CfLabel label27 = new CfLabel();
+    CfLabel label28 = new CfLabel();
+    CfLabel label29 = new CfLabel();
+    CfLabel label30 = new CfLabel();
+    CfLabel label31 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        18,
+        ImmutableList.of(
+            label0,
+            new CfConstNumber(32768, ValueType.INT),
+            new CfStore(ValueType.INT, 1),
+            label1,
+            new CfConstNumber(10, ValueType.INT),
+            new CfStore(ValueType.INT, 2),
+            label2,
+            new CfConstNumber(31, ValueType.INT),
+            new CfStore(ValueType.INT, 3),
+            label3,
+            new CfConstNumber(1023, ValueType.INT),
+            new CfStore(ValueType.INT, 4),
+            label4,
+            new CfConstNumber(1056964608, ValueType.INT),
+            new CfStore(ValueType.INT, 5),
+            label5,
+            new CfLoad(ValueType.INT, 5),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Float;"),
+                    factory.createProto(factory.floatType, factory.intType),
+                    factory.createString("intBitsToFloat")),
+                false),
+            new CfStore(ValueType.FLOAT, 6),
+            label6,
+            new CfConstNumber(4194304, ValueType.INT),
+            new CfStore(ValueType.INT, 7),
+            label7,
+            new CfConstNumber(15, ValueType.INT),
+            new CfStore(ValueType.INT, 8),
+            label8,
+            new CfConstNumber(127, ValueType.INT),
+            new CfStore(ValueType.INT, 9),
+            label9,
+            new CfConstNumber(23, ValueType.INT),
+            new CfStore(ValueType.INT, 10),
+            label10,
+            new CfLoad(ValueType.INT, 0),
+            new CfConstNumber(65535, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfStore(ValueType.INT, 11),
+            label11,
+            new CfLoad(ValueType.INT, 11),
+            new CfLoad(ValueType.INT, 1),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfStore(ValueType.INT, 12),
+            label12,
+            new CfLoad(ValueType.INT, 11),
+            new CfLoad(ValueType.INT, 2),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Ushr, NumericType.INT),
+            new CfLoad(ValueType.INT, 3),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfStore(ValueType.INT, 13),
+            label13,
+            new CfLoad(ValueType.INT, 11),
+            new CfLoad(ValueType.INT, 4),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfStore(ValueType.INT, 14),
+            label14,
+            new CfConstNumber(0, ValueType.INT),
+            new CfStore(ValueType.INT, 15),
+            label15,
+            new CfConstNumber(0, ValueType.INT),
+            new CfStore(ValueType.INT, 16),
+            label16,
+            new CfLoad(ValueType.INT, 13),
+            new CfIf(IfType.NE, ValueType.INT, label23),
+            label17,
+            new CfLoad(ValueType.INT, 14),
+            new CfIf(IfType.EQ, ValueType.INT, label29),
+            label18,
+            new CfLoad(ValueType.INT, 5),
+            new CfLoad(ValueType.INT, 14),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Float;"),
+                    factory.createProto(factory.floatType, factory.intType),
+                    factory.createString("intBitsToFloat")),
+                false),
+            new CfStore(ValueType.FLOAT, 17),
+            label19,
+            new CfLoad(ValueType.FLOAT, 17),
+            new CfLoad(ValueType.FLOAT, 6),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.FLOAT),
+            new CfStore(ValueType.FLOAT, 17),
+            label20,
+            new CfLoad(ValueType.INT, 12),
+            new CfIf(IfType.NE, ValueType.INT, label21),
+            new CfLoad(ValueType.FLOAT, 17),
+            new CfGoto(label22),
+            label21,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.floatType()
+                    })),
+            new CfLoad(ValueType.FLOAT, 17),
+            new CfNeg(NumericType.FLOAT),
+            label22,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.floatType()
+                    }),
+                new ArrayDeque<>(Arrays.asList(FrameType.floatType()))),
+            new CfReturn(ValueType.FLOAT),
+            label23,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 14),
+            new CfConstNumber(13, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shl, NumericType.INT),
+            new CfStore(ValueType.INT, 16),
+            label24,
+            new CfLoad(ValueType.INT, 13),
+            new CfConstNumber(31, ValueType.INT),
+            new CfIfCmp(IfType.NE, ValueType.INT, label28),
+            label25,
+            new CfConstNumber(255, ValueType.INT),
+            new CfStore(ValueType.INT, 15),
+            label26,
+            new CfLoad(ValueType.INT, 16),
+            new CfIf(IfType.EQ, ValueType.INT, label29),
+            label27,
+            new CfLoad(ValueType.INT, 16),
+            new CfLoad(ValueType.INT, 7),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
+            new CfStore(ValueType.INT, 16),
+            new CfGoto(label29),
+            label28,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 13),
+            new CfLoad(ValueType.INT, 8),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfLoad(ValueType.INT, 9),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+            new CfStore(ValueType.INT, 15),
+            label29,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+                    new FrameType[] {
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 12),
+            new CfConstNumber(16, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shl, NumericType.INT),
+            new CfLoad(ValueType.INT, 15),
+            new CfLoad(ValueType.INT, 10),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shl, NumericType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
+            new CfLoad(ValueType.INT, 16),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
+            new CfStore(ValueType.INT, 17),
+            label30,
+            new CfLoad(ValueType.INT, 17),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Float;"),
+                    factory.createProto(factory.floatType, factory.intType),
+                    factory.createString("intBitsToFloat")),
+                false),
+            new CfReturn(ValueType.FLOAT),
+            label31),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode FloatMethods_floatToFloat16(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();
+    CfLabel label16 = new CfLabel();
+    CfLabel label17 = new CfLabel();
+    CfLabel label18 = new CfLabel();
+    CfLabel label19 = new CfLabel();
+    CfLabel label20 = new CfLabel();
+    CfLabel label21 = new CfLabel();
+    CfLabel label22 = new CfLabel();
+    CfLabel label23 = new CfLabel();
+    CfLabel label24 = new CfLabel();
+    CfLabel label25 = new CfLabel();
+    CfLabel label26 = new CfLabel();
+    CfLabel label27 = new CfLabel();
+    CfLabel label28 = new CfLabel();
+    CfLabel label29 = new CfLabel();
+    CfLabel label30 = new CfLabel();
+    CfLabel label31 = new CfLabel();
+    CfLabel label32 = new CfLabel();
+    CfLabel label33 = new CfLabel();
+    CfLabel label34 = new CfLabel();
+    CfLabel label35 = new CfLabel();
+    CfLabel label36 = new CfLabel();
+    CfLabel label37 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        18,
+        ImmutableList.of(
+            label0,
+            new CfConstNumber(10, ValueType.INT),
+            new CfStore(ValueType.INT, 1),
+            label1,
+            new CfConstNumber(15, ValueType.INT),
+            new CfStore(ValueType.INT, 2),
+            label2,
+            new CfConstNumber(15, ValueType.INT),
+            new CfStore(ValueType.INT, 3),
+            label3,
+            new CfConstNumber(127, ValueType.INT),
+            new CfStore(ValueType.INT, 4),
+            label4,
+            new CfConstNumber(23, ValueType.INT),
+            new CfStore(ValueType.INT, 5),
+            label5,
+            new CfConstNumber(31, ValueType.INT),
+            new CfStore(ValueType.INT, 6),
+            label6,
+            new CfConstNumber(255, ValueType.INT),
+            new CfStore(ValueType.INT, 7),
+            label7,
+            new CfConstNumber(8388607, ValueType.INT),
+            new CfStore(ValueType.INT, 8),
+            label8,
+            new CfLoad(ValueType.FLOAT, 0),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Float;"),
+                    factory.createProto(factory.intType, factory.floatType),
+                    factory.createString("floatToRawIntBits")),
+                false),
+            new CfStore(ValueType.INT, 9),
+            label9,
+            new CfLoad(ValueType.INT, 9),
+            new CfLoad(ValueType.INT, 6),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Ushr, NumericType.INT),
+            new CfStore(ValueType.INT, 10),
+            label10,
+            new CfLoad(ValueType.INT, 9),
+            new CfLoad(ValueType.INT, 5),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Ushr, NumericType.INT),
+            new CfLoad(ValueType.INT, 7),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfStore(ValueType.INT, 11),
+            label11,
+            new CfLoad(ValueType.INT, 9),
+            new CfLoad(ValueType.INT, 8),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfStore(ValueType.INT, 12),
+            label12,
+            new CfConstNumber(0, ValueType.INT),
+            new CfStore(ValueType.INT, 13),
+            label13,
+            new CfConstNumber(0, ValueType.INT),
+            new CfStore(ValueType.INT, 14),
+            label14,
+            new CfLoad(ValueType.INT, 11),
+            new CfConstNumber(255, ValueType.INT),
+            new CfIfCmp(IfType.NE, ValueType.INT, label19),
+            label15,
+            new CfConstNumber(31, ValueType.INT),
+            new CfStore(ValueType.INT, 13),
+            label16,
+            new CfLoad(ValueType.INT, 12),
+            new CfIf(IfType.EQ, ValueType.INT, label17),
+            new CfConstNumber(512, ValueType.INT),
+            new CfGoto(label18),
+            label17,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfConstNumber(0, ValueType.INT),
+            label18,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    }),
+                new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
+            new CfStore(ValueType.INT, 14),
+            new CfGoto(label36),
+            label19,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 11),
+            new CfLoad(ValueType.INT, 4),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfLoad(ValueType.INT, 3),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+            new CfStore(ValueType.INT, 11),
+            label20,
+            new CfLoad(ValueType.INT, 11),
+            new CfConstNumber(31, ValueType.INT),
+            new CfIfCmp(IfType.LT, ValueType.INT, label22),
+            label21,
+            new CfConstNumber(31, ValueType.INT),
+            new CfStore(ValueType.INT, 13),
+            new CfGoto(label36),
+            label22,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 11),
+            new CfIf(IfType.GT, ValueType.INT, label32),
+            label23,
+            new CfLoad(ValueType.INT, 11),
+            new CfConstNumber(-10, ValueType.INT),
+            new CfIfCmp(IfType.GE, ValueType.INT, label24),
+            new CfGoto(label36),
+            label24,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 12),
+            new CfConstNumber(8388608, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
+            new CfStore(ValueType.INT, 12),
+            label25,
+            new CfConstNumber(14, ValueType.INT),
+            new CfLoad(ValueType.INT, 11),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfStore(ValueType.INT, 15),
+            label26,
+            new CfLoad(ValueType.INT, 12),
+            new CfLoad(ValueType.INT, 15),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.INT),
+            new CfStore(ValueType.INT, 14),
+            label27,
+            new CfLoad(ValueType.INT, 12),
+            new CfConstNumber(1, ValueType.INT),
+            new CfLoad(ValueType.INT, 15),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shl, NumericType.INT),
+            new CfConstNumber(1, ValueType.INT),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfStore(ValueType.INT, 16),
+            label28,
+            new CfConstNumber(1, ValueType.INT),
+            new CfLoad(ValueType.INT, 15),
+            new CfConstNumber(1, ValueType.INT),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shl, NumericType.INT),
+            new CfStore(ValueType.INT, 17),
+            label29,
+            new CfLoad(ValueType.INT, 16),
+            new CfLoad(ValueType.INT, 14),
+            new CfConstNumber(1, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+            new CfLoad(ValueType.INT, 17),
+            new CfIfCmp(IfType.LE, ValueType.INT, label31),
+            label30,
+            new CfIinc(14, 1),
+            label31,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfGoto(label36),
+            label32,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 11),
+            new CfStore(ValueType.INT, 13),
+            label33,
+            new CfLoad(ValueType.INT, 12),
+            new CfConstNumber(13, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shr, NumericType.INT),
+            new CfStore(ValueType.INT, 14),
+            label34,
+            new CfLoad(ValueType.INT, 12),
+            new CfConstNumber(8191, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfLoad(ValueType.INT, 14),
+            new CfConstNumber(1, ValueType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+            new CfConstNumber(4096, ValueType.INT),
+            new CfIfCmp(IfType.LE, ValueType.INT, label36),
+            label35,
+            new CfIinc(14, 1),
+            label36,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
+                    new FrameType[] {
+                      FrameType.floatType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType(),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.INT, 10),
+            new CfLoad(ValueType.INT, 2),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shl, NumericType.INT),
+            new CfLoad(ValueType.INT, 13),
+            new CfLoad(ValueType.INT, 1),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Shl, NumericType.INT),
+            new CfLoad(ValueType.INT, 14),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+            new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
+            new CfNumberConversion(NumericType.INT, NumericType.SHORT),
+            new CfReturn(ValueType.INT),
+            label37),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode FloatMethods_isFinite(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java
index a452fea..0be353e 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java
@@ -9,4 +9,117 @@
   public static boolean isFinite(float f) {
     return !Float.isInfinite(f) && !Float.isNaN(f);
   }
+
+  /*
+   * Source: The Android Open Source Project
+   * License: the Apache License, Version 2.0
+   * Github: https://github.com/caoccao/Javet/blob/main/src/main/java/com/caoccao/javet/utils/Float16.java
+   */
+  public static float float16ToFloat(short float16) {
+    // The float16 format has 1 sign bit, 5 exponent bits, and 10 mantissa bits.
+    // The exponent bias is 15.
+    int signMask = 0x8000;
+    int exponentShift = 10;
+    int shiftedExponentMask = 0x1f;
+    int significandMask = 0x3ff;
+    int fp32DenormalMagic = 126 << 23;
+    float fp32DenormalFloat = Float.intBitsToFloat(fp32DenormalMagic);
+    int fp32QnanMask = 0x400000;
+    int exponentBias = 15;
+    int fp32ExponentBias = 127;
+    int fp32ExponentShift = 23;
+
+    int bits = float16 & 0xffff;
+    int s = bits & signMask;
+    int e = (bits >>> exponentShift) & shiftedExponentMask;
+    int m = (bits) & significandMask;
+    int outE = 0;
+    int outM = 0;
+    if (e == 0) { // Denormal or 0
+      if (m != 0) {
+        // Convert denorm fp16 into normalized fp32
+        float o = Float.intBitsToFloat(fp32DenormalMagic + m);
+        o -= fp32DenormalFloat;
+        return s == 0 ? o : -o;
+      }
+    } else {
+      outM = m << 13;
+      if (e == 0x1f) { // Infinite or NaN
+        outE = 0xff;
+        if (outM != 0) { // SNaNs are quieted
+          outM |= fp32QnanMask;
+        }
+      } else {
+        outE = e - exponentBias + fp32ExponentBias;
+      }
+    }
+    int out = (s << 16) | (outE << fp32ExponentShift) | outM;
+    return Float.intBitsToFloat(out);
+  }
+
+  /*
+   * Source: The Android Open Source Project
+   * License: the Apache License, Version 2.0
+   * Github: https://github.com/caoccao/Javet/blob/main/src/main/java/com/caoccao/javet/utils/Float16.java
+   */
+  public static short floatToFloat16(float flt) {
+    // The float16 format has 1 sign bit, 5 exponent bits, and 10 mantissa bits.
+    // The exponent bias is 15.
+    int exponentShift = 10;
+    int signShift = 15;
+    int exponentBias = 15;
+    int fp32ExponentBias = 127;
+    int fp32ExponentShift = 23;
+    int fp32SignShift = 31;
+    int fp32ShiftedExponentMask = 0xff;
+    int fp32SignificandMask = 0x7fffff;
+
+    int bits = Float.floatToRawIntBits(flt);
+    int s = (bits >>> fp32SignShift);
+    int e = (bits >>> fp32ExponentShift) & fp32ShiftedExponentMask;
+    int m = (bits) & fp32SignificandMask;
+    int outE = 0;
+    int outM = 0;
+    if (e == 0xff) { // Infinite or NaN
+      outE = 0x1f;
+      outM = m != 0 ? 0x200 : 0;
+    } else {
+      e = e - fp32ExponentBias + exponentBias;
+      if (e >= 0x1f) { // Overflow
+        outE = 0x1f;
+      } else if (e <= 0) { // Underflow
+        if (e < -10) {
+          // The absolute fp32 value is less than MIN_VALUE, flush to +/-0
+        } else {
+          // The fp32 value is a normalized float less than MIN_NORMAL,
+          // we convert to a denorm fp16
+          m = m | 0x800000;
+          int shift = 14 - e;
+          outM = m >> shift;
+          int lowm = m & ((1 << shift) - 1);
+          int hway = 1 << (shift - 1);
+          // if above halfway or exactly halfway and outM is odd
+          if (lowm + (outM & 1) > hway) {
+            // Round to nearest even
+            // Can overflow into exponent bit, which surprisingly is OK.
+            // This increment relies on the +outM in the return statement below
+            outM++;
+          }
+        }
+      } else {
+        outE = e;
+        outM = m >> 13;
+        // if above halfway or exactly halfway and outM is odd
+        if ((m & 0x1fff) + (outM & 0x1) > 0x1000) {
+          // Round to nearest even
+          // Can overflow into exponent bit, which surprisingly is OK.
+          // This increment relies on the +outM in the return statement below
+          outM++;
+        }
+      }
+    }
+    // The outM is added here as the +1 increments for outM above can
+    // cause an overflow in the exponent bit which is OK.
+    return (short) ((s << signShift) | (outE << exponentShift) + outM);
+  }
 }
diff --git a/src/test/java21/com/android/tools/r8/jdk21/backport/Jdk21Float16Test.java b/src/test/java21/com/android/tools/r8/jdk21/backport/Jdk21Float16Test.java
new file mode 100644
index 0000000..23b00dd
--- /dev/null
+++ b/src/test/java21/com/android/tools/r8/jdk21/backport/Jdk21Float16Test.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2025, 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.jdk21.backport;
+
+import static com.android.tools.r8.utils.FileUtils.CLASS_EXTENSION;
+import static com.android.tools.r8.utils.FileUtils.JAVA_EXTENSION;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class Jdk21Float16Test extends TestBase {
+
+  private static final String FLOAT_16_TEST_NAME = "Binary16Conversion";
+  private static final String FLOAT_16_NAN_TEST_NAME = "Binary16ConversionNaN";
+
+  private static Path getTestPath(String name) {
+    return Paths.get(ToolHelper.THIRD_PARTY_DIR, "openjdk", "float16-test", name + JAVA_EXTENSION);
+  }
+
+  private static final Path[] JDK_21_FLOAT_16_TEST_JAVA_FILES =
+      new Path[] {getTestPath(FLOAT_16_TEST_NAME), getTestPath(FLOAT_16_NAN_TEST_NAME)};
+
+  private static Path[] JDK_21_FLOAT_16_TEST_CLASS_FILES;
+
+  @Parameter(0)
+  public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withDexRuntimesAndAllApiLevels().withCfRuntime(CfVm.JDK21).build();
+  }
+
+  @BeforeClass
+  public static void compileTestClasses() throws Exception {
+    // Build test constants.
+    Path output = getStaticTemp().newFolder("output").toPath();
+    javac(TestRuntime.getCheckedInJdk21(), getStaticTemp())
+        .addSourceFiles(JDK_21_FLOAT_16_TEST_JAVA_FILES)
+        .setOutputPath(output)
+        .compile();
+    JDK_21_FLOAT_16_TEST_CLASS_FILES =
+        new Path[] {
+          output.resolve(FLOAT_16_TEST_NAME + CLASS_EXTENSION),
+          output.resolve(FLOAT_16_TEST_NAME + "$Binary16" + CLASS_EXTENSION),
+          output.resolve(FLOAT_16_NAN_TEST_NAME + CLASS_EXTENSION)
+        };
+  }
+
+  @Test
+  public void testFloat16() throws Exception {
+    testForD8(parameters)
+        .addProgramFiles(JDK_21_FLOAT_16_TEST_CLASS_FILES)
+        .run(parameters.getRuntime(), FLOAT_16_TEST_NAME)
+        .assertSuccessWithOutput("");
+  }
+
+  @Test
+  public void testFloat16NaN() throws Exception {
+    Assume.assumeTrue("The test fails also on jdk21", false);
+    testForD8(parameters)
+        .addProgramFiles(JDK_21_FLOAT_16_TEST_CLASS_FILES)
+        .run(parameters.getRuntime(), FLOAT_16_NAN_TEST_NAME)
+        .assertSuccessWithOutput("");
+  }
+}
diff --git a/third_party/openjdk/float16-test.tar.gz.sha1 b/third_party/openjdk/float16-test.tar.gz.sha1
new file mode 100644
index 0000000..ded34fa
--- /dev/null
+++ b/third_party/openjdk/float16-test.tar.gz.sha1
@@ -0,0 +1 @@
+166f74a089e05b71c4b7d8da71b3f2c1e25cda59
\ No newline at end of file