diff options
author | 2023-11-30 09:47:03 +0000 | |
---|---|---|
committer | 2023-12-01 07:33:24 +0000 | |
commit | ee12ff26f3413dee84c963af15dd1018b58466bb (patch) | |
tree | 61212c0cf6b2f3e389b8eae99cc421158b9fcb73 /compiler/optimizing/intrinsics_riscv64.cc | |
parent | 502d277b38adb65d65ec9c88e8d5317303dc4035 (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.cc | 23 |
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); |