summaryrefslogtreecommitdiff
path: root/compiler/optimizing/intrinsics_riscv64.cc
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2023-11-30 09:47:03 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2023-12-01 07:33:24 +0000
commitee12ff26f3413dee84c963af15dd1018b58466bb (patch)
tree61212c0cf6b2f3e389b8eae99cc421158b9fcb73 /compiler/optimizing/intrinsics_riscv64.cc
parent502d277b38adb65d65ec9c88e8d5317303dc4035 (diff)
riscv64: Fix VarHandle GetAndUpdate intrinsic.
Fix the byte-swap CAS case for narrow types (short, char). Note that these cases are not currently supported by libcore and we therefore take the slow path during the access mode check. However, the ART VarHandle implementation is ready to handle them in case this arbitrary libcore (or upstream?) decision changes and it generates code for them. This fix avoids a `DCHECK` failure in `GenerateByteSwapAndExtract()` by doing the `DCHECK` in two of its three callers and generates the correct (and smaller) code in all cases. Extend the run-test 712 to test offsets that would lead to non-zero shift in `GenerateByteSwapAndExtract()`. To test this code path, one needs to modify the libcore method `VarHandle.unalignedAccessModesBitMask()` to permit the `NUMERIC_ATOMIC_UPDATE_ACCESS_MODES_BIT_MASK` for `short` (and maybe `char` but that makes less sense than `short`). Test: testrunner.py --target --64 --ndebug --optimizing Bug: 283082089 Change-Id: I23926bbafc9eff21e094b00f36357d629cc550a9
Diffstat (limited to 'compiler/optimizing/intrinsics_riscv64.cc')
-rw-r--r--compiler/optimizing/intrinsics_riscv64.cc23
1 files changed, 10 insertions, 13 deletions
diff --git a/compiler/optimizing/intrinsics_riscv64.cc b/compiler/optimizing/intrinsics_riscv64.cc
index 7bd7faf482..10539f95f4 100644
--- a/compiler/optimizing/intrinsics_riscv64.cc
+++ b/compiler/optimizing/intrinsics_riscv64.cc
@@ -2322,22 +2322,15 @@ static void GenerateByteSwapAndExtract(CodeGeneratorRISCV64* codegen,
XRegister rs1,
XRegister shift,
DataType::Type type) {
- Riscv64Assembler* assembler = codegen->GetAssembler();
- // Do not apply shift in `GenerateReverseBytes()` for small types.
+ // Apply shift before `GenerateReverseBytes()` for small types.
DCHECK_EQ(shift != kNoXRegister, DataType::Size(type) < 4u);
- DataType::Type swap_type = (shift != kNoXRegister) ? DataType::Type::kInt32 : type;
- // Also handles moving to FP registers.
- GenerateReverseBytes(codegen, rd, rs1, swap_type);
if (shift != kNoXRegister) {
- DCHECK_EQ(rs1, rd.AsRegister<XRegister>());
- __ Sllw(rs1, rs1, shift);
- if (type == DataType::Type::kUint16) {
- __ Srliw(rs1, rs1, 16);
- } else {
- DCHECK_EQ(type, DataType::Type::kInt16);
- __ Sraiw(rs1, rs1, 16);
- }
+ Riscv64Assembler* assembler = codegen->GetAssembler();
+ __ Srlw(rd.AsRegister<XRegister>(), rs1, shift);
+ rs1 = rd.AsRegister<XRegister>();
}
+ // Also handles moving to FP registers.
+ GenerateReverseBytes(codegen, rd, rs1, type);
}
static void GenerateVarHandleCompareAndSetOrExchange(HInvoke* invoke,
@@ -2527,6 +2520,8 @@ static void GenerateVarHandleCompareAndSetOrExchange(HInvoke* invoke,
if (return_success) {
// Nothing to do, the result register already contains 1 on success and 0 on failure.
} else if (byte_swap) {
+ DCHECK_IMPLIES(is_small, out.AsRegister<XRegister>() == old_value)
+ << " " << value_type << " " << out.AsRegister<XRegister>() << "!=" << old_value;
GenerateByteSwapAndExtract(codegen, out, old_value, shift, value_type);
} else if (is_fp) {
codegen->MoveLocation(out, Location::RegisterLocation(old_value), value_type);
@@ -2909,6 +2904,8 @@ static void GenerateVarHandleGetAndUpdate(HInvoke* invoke,
GenerateGetAndUpdate(
codegen, get_and_update_op, op_type, order, tmp_ptr, arg_reg, old_value, mask, temp);
if (byte_swap) {
+ DCHECK_IMPLIES(is_small, out.AsRegister<XRegister>() == old_value)
+ << " " << value_type << " " << out.AsRegister<XRegister>() << "!=" << old_value;
GenerateByteSwapAndExtract(codegen, out, old_value, shift, value_type);
} else if (is_fp) {
codegen->MoveLocation(out, Location::RegisterLocation(old_value), value_type);