Optimizing: Simplify consecutive type conversions.
Merge two consecutive type conversions to one if the result
of such merged conversion is guaranteed to be the same and
remove all implicit conversions, not just conversions to the
same type. Improve codegens to handle conversions from long
to integral types smaller than int.
This will make it easier to simplify `(byte) (x & 0xffL)` to
`(byte) x` where the conversion from long to byte is done by
two dex instructions, long-to-int and in int-to-byte.
Bug: 23965701
Change-Id: I833f193556671136ad2cd3f5b31cdfbc2d99c19d
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 71d65e8..119084e 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -3943,18 +3943,26 @@
__ Andi(dst, src, 0xFFFF);
break;
case Primitive::kPrimByte:
- // long is never converted into types narrower than int directly,
- // so SEB and SEH can be used without ever causing unpredictable results
- // on 64-bit inputs
- DCHECK(input_type != Primitive::kPrimLong);
- __ Seb(dst, src);
+ if (input_type == Primitive::kPrimLong) {
+ // Type conversion from long to types narrower than int is a result of code
+ // transformations. To avoid unpredictable results for SEB and SEH, we first
+ // need to sign-extend the low 32-bit value into bits 32 through 63.
+ __ Sll(dst, src, 0);
+ __ Seb(dst, dst);
+ } else {
+ __ Seb(dst, src);
+ }
break;
case Primitive::kPrimShort:
- // long is never converted into types narrower than int directly,
- // so SEB and SEH can be used without ever causing unpredictable results
- // on 64-bit inputs
- DCHECK(input_type != Primitive::kPrimLong);
- __ Seh(dst, src);
+ if (input_type == Primitive::kPrimLong) {
+ // Type conversion from long to types narrower than int is a result of code
+ // transformations. To avoid unpredictable results for SEB and SEH, we first
+ // need to sign-extend the low 32-bit value into bits 32 through 63.
+ __ Sll(dst, src, 0);
+ __ Seh(dst, dst);
+ } else {
+ __ Seh(dst, src);
+ }
break;
case Primitive::kPrimInt:
case Primitive::kPrimLong: