Skip to content

Commit 57d35f9

Browse files
committedNov 26, 2024
8344382: RISC-V: CASandCAEwithNegExpected fails with Zacas
Reviewed-by: fyang, mli
1 parent 0105203 commit 57d35f9

File tree

2 files changed

+68
-52
lines changed

2 files changed

+68
-52
lines changed
 

‎src/hotspot/cpu/riscv/macroAssembler_riscv.cpp

+66-49
Original file line numberDiff line numberDiff line change
@@ -3313,14 +3313,11 @@ void MacroAssembler::store_conditional(Register dst,
33133313
}
33143314

33153315

3316-
void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expected,
3317-
Register new_val,
3316+
void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expected, Register new_val,
33183317
enum operand_size size,
3319-
Register tmp1, Register tmp2, Register tmp3) {
3318+
Register shift, Register mask, Register aligned_addr) {
33203319
assert(size == int8 || size == int16, "unsupported operand size");
33213320

3322-
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3;
3323-
33243321
andi(shift, addr, 3);
33253322
slli(shift, shift, 3);
33263323

@@ -3335,8 +3332,6 @@ void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expecte
33353332
}
33363333
sll(mask, mask, shift);
33373334

3338-
notr(not_mask, mask);
3339-
33403335
sll(expected, expected, shift);
33413336
andr(expected, expected, mask);
33423337

@@ -3353,35 +3348,46 @@ void MacroAssembler::cmpxchg_narrow_value(Register addr, Register expected,
33533348
Assembler::Aqrl acquire, Assembler::Aqrl release,
33543349
Register result, bool result_as_bool,
33553350
Register tmp1, Register tmp2, Register tmp3) {
3356-
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0;
3357-
assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp);
3358-
cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3);
3351+
assert_different_registers(addr, expected, new_val, result, tmp1, tmp2, tmp3, t0, t1);
33593352

3360-
Label retry, fail, done;
3353+
Register scratch0 = t0, aligned_addr = t1;
3354+
Register shift = tmp1, mask = tmp2, scratch1 = tmp3;
3355+
3356+
cmpxchg_narrow_value_helper(addr, expected, new_val, size, shift, mask, aligned_addr);
33613357

3362-
bind(retry);
3358+
Label retry, fail, done;
33633359

33643360
if (UseZacas) {
3365-
lw(old, aligned_addr);
3361+
lw(result, aligned_addr);
3362+
3363+
bind(retry); // amocas loads the current value into result
3364+
notr(scratch1, mask);
33663365

3367-
// if old & mask != expected
3368-
andr(tmp, old, mask);
3369-
bne(tmp, expected, fail);
3366+
andr(scratch0, result, scratch1); // scratch0 = word - cas bits
3367+
orr(scratch1, expected, scratch0); // scratch1 = non-cas bits + cas bits
3368+
bne(result, scratch1, fail); // cas bits differ, cas failed
33703369

3371-
andr(tmp, old, not_mask);
3372-
orr(tmp, tmp, new_val);
3370+
// result is the same as expected, use as expected value.
33733371

3374-
atomic_cas(old, tmp, aligned_addr, operand_size::int32, acquire, release);
3375-
bne(tmp, old, retry);
3372+
// scratch0 is still = word - cas bits
3373+
// Or in the new value to create complete new value.
3374+
orr(scratch0, scratch0, new_val);
3375+
3376+
mv(scratch1, result); // save our expected value
3377+
atomic_cas(result, scratch0, aligned_addr, operand_size::int32, acquire, release);
3378+
bne(scratch1, result, retry);
33763379
} else {
3377-
lr_w(old, aligned_addr, acquire);
3378-
andr(tmp, old, mask);
3379-
bne(tmp, expected, fail);
3380+
notr(scratch1, mask);
3381+
bind(retry);
3382+
3383+
lr_w(result, aligned_addr, acquire);
3384+
andr(scratch0, result, mask);
3385+
bne(scratch0, expected, fail);
33803386

3381-
andr(tmp, old, not_mask);
3382-
orr(tmp, tmp, new_val);
3383-
sc_w(tmp, tmp, aligned_addr, release);
3384-
bnez(tmp, retry);
3387+
andr(scratch0, result, scratch1); // scratch1 is ~mask
3388+
orr(scratch0, scratch0, new_val);
3389+
sc_w(scratch0, scratch0, aligned_addr, release);
3390+
bnez(scratch0, retry);
33853391
}
33863392

33873393
if (result_as_bool) {
@@ -3393,10 +3399,10 @@ void MacroAssembler::cmpxchg_narrow_value(Register addr, Register expected,
33933399

33943400
bind(done);
33953401
} else {
3396-
andr(tmp, old, mask);
3397-
33983402
bind(fail);
3399-
srl(result, tmp, shift);
3403+
3404+
andr(scratch0, result, mask);
3405+
srl(result, scratch0, shift);
34003406

34013407
if (size == int8) {
34023408
sign_extend(result, result, 8);
@@ -3416,33 +3422,44 @@ void MacroAssembler::weak_cmpxchg_narrow_value(Register addr, Register expected,
34163422
Assembler::Aqrl acquire, Assembler::Aqrl release,
34173423
Register result,
34183424
Register tmp1, Register tmp2, Register tmp3) {
3419-
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0;
3420-
assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp);
3421-
cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3);
3425+
assert_different_registers(addr, expected, new_val, result, tmp1, tmp2, tmp3, t0, t1);
3426+
3427+
Register scratch0 = t0, aligned_addr = t1;
3428+
Register shift = tmp1, mask = tmp2, scratch1 = tmp3;
3429+
3430+
cmpxchg_narrow_value_helper(addr, expected, new_val, size, shift, mask, aligned_addr);
34223431

34233432
Label fail, done;
34243433

34253434
if (UseZacas) {
3426-
lw(old, aligned_addr);
3435+
lw(result, aligned_addr);
34273436

3428-
// if old & mask != expected
3429-
andr(tmp, old, mask);
3430-
bne(tmp, expected, fail);
3437+
notr(scratch1, mask);
34313438

3432-
andr(tmp, old, not_mask);
3433-
orr(tmp, tmp, new_val);
3439+
andr(scratch0, result, scratch1); // scratch0 = word - cas bits
3440+
orr(scratch1, expected, scratch0); // scratch1 = non-cas bits + cas bits
3441+
bne(result, scratch1, fail); // cas bits differ, cas failed
34343442

3435-
atomic_cas(tmp, new_val, addr, operand_size::int32, acquire, release);
3436-
bne(tmp, old, fail);
3443+
// result is the same as expected, use as expected value.
3444+
3445+
// scratch0 is still = word - cas bits
3446+
// Or in the new value to create complete new value.
3447+
orr(scratch0, scratch0, new_val);
3448+
3449+
mv(scratch1, result); // save our expected value
3450+
atomic_cas(result, scratch0, aligned_addr, operand_size::int32, acquire, release);
3451+
bne(scratch1, result, fail); // This weak, so just bail-out.
34373452
} else {
3438-
lr_w(old, aligned_addr, acquire);
3439-
andr(tmp, old, mask);
3440-
bne(tmp, expected, fail);
3441-
3442-
andr(tmp, old, not_mask);
3443-
orr(tmp, tmp, new_val);
3444-
sc_w(tmp, tmp, aligned_addr, release);
3445-
bnez(tmp, fail);
3453+
notr(scratch1, mask);
3454+
3455+
lr_w(result, aligned_addr, acquire);
3456+
andr(scratch0, result, mask);
3457+
bne(scratch0, expected, fail);
3458+
3459+
andr(scratch0, result, scratch1); // scratch1 is ~mask
3460+
orr(scratch0, scratch0, new_val);
3461+
sc_w(scratch0, scratch0, aligned_addr, release);
3462+
bnez(scratch0, fail);
34463463
}
34473464

34483465
// Success

‎src/hotspot/cpu/riscv/macroAssembler_riscv.hpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -1146,10 +1146,9 @@ class MacroAssembler: public Assembler {
11461146
enum operand_size size,
11471147
Assembler::Aqrl acquire, Assembler::Aqrl release,
11481148
Register result);
1149-
void cmpxchg_narrow_value_helper(Register addr, Register expected,
1150-
Register new_val,
1149+
void cmpxchg_narrow_value_helper(Register addr, Register expected, Register new_val,
11511150
enum operand_size size,
1152-
Register tmp1, Register tmp2, Register tmp3);
1151+
Register shift, Register mask, Register aligned_addr);
11531152
void cmpxchg_narrow_value(Register addr, Register expected,
11541153
Register new_val,
11551154
enum operand_size size,

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Nov 26, 2024

@openjdk-notifier[bot]
Please sign in to comment.