8344382: RISC-V: CASandCAEwithNegExpected fails with Zacas
Reviewed-by: fyang, mli
This commit is contained in:
parent
0105203575
commit
57d35f98f6
@ -3313,14 +3313,11 @@ void MacroAssembler::store_conditional(Register dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expected,
|
void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expected, Register new_val,
|
||||||
Register new_val,
|
|
||||||
enum operand_size size,
|
enum operand_size size,
|
||||||
Register tmp1, Register tmp2, Register tmp3) {
|
Register shift, Register mask, Register aligned_addr) {
|
||||||
assert(size == int8 || size == int16, "unsupported operand size");
|
assert(size == int8 || size == int16, "unsupported operand size");
|
||||||
|
|
||||||
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3;
|
|
||||||
|
|
||||||
andi(shift, addr, 3);
|
andi(shift, addr, 3);
|
||||||
slli(shift, shift, 3);
|
slli(shift, shift, 3);
|
||||||
|
|
||||||
@ -3335,8 +3332,6 @@ void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expecte
|
|||||||
}
|
}
|
||||||
sll(mask, mask, shift);
|
sll(mask, mask, shift);
|
||||||
|
|
||||||
notr(not_mask, mask);
|
|
||||||
|
|
||||||
sll(expected, expected, shift);
|
sll(expected, expected, shift);
|
||||||
andr(expected, expected, mask);
|
andr(expected, expected, mask);
|
||||||
|
|
||||||
@ -3353,35 +3348,46 @@ void MacroAssembler::cmpxchg_narrow_value(Register addr, Register expected,
|
|||||||
Assembler::Aqrl acquire, Assembler::Aqrl release,
|
Assembler::Aqrl acquire, Assembler::Aqrl release,
|
||||||
Register result, bool result_as_bool,
|
Register result, bool result_as_bool,
|
||||||
Register tmp1, Register tmp2, Register tmp3) {
|
Register tmp1, Register tmp2, Register tmp3) {
|
||||||
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0;
|
assert_different_registers(addr, expected, new_val, result, tmp1, tmp2, tmp3, t0, t1);
|
||||||
assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp);
|
|
||||||
cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3);
|
Register scratch0 = t0, aligned_addr = t1;
|
||||||
|
Register shift = tmp1, mask = tmp2, scratch1 = tmp3;
|
||||||
|
|
||||||
|
cmpxchg_narrow_value_helper(addr, expected, new_val, size, shift, mask, aligned_addr);
|
||||||
|
|
||||||
Label retry, fail, done;
|
Label retry, fail, done;
|
||||||
|
|
||||||
bind(retry);
|
|
||||||
|
|
||||||
if (UseZacas) {
|
if (UseZacas) {
|
||||||
lw(old, aligned_addr);
|
lw(result, aligned_addr);
|
||||||
|
|
||||||
// if old & mask != expected
|
bind(retry); // amocas loads the current value into result
|
||||||
andr(tmp, old, mask);
|
notr(scratch1, mask);
|
||||||
bne(tmp, expected, fail);
|
|
||||||
|
|
||||||
andr(tmp, old, not_mask);
|
andr(scratch0, result, scratch1); // scratch0 = word - cas bits
|
||||||
orr(tmp, tmp, new_val);
|
orr(scratch1, expected, scratch0); // scratch1 = non-cas bits + cas bits
|
||||||
|
bne(result, scratch1, fail); // cas bits differ, cas failed
|
||||||
|
|
||||||
atomic_cas(old, tmp, aligned_addr, operand_size::int32, acquire, release);
|
// result is the same as expected, use as expected value.
|
||||||
bne(tmp, old, retry);
|
|
||||||
|
// scratch0 is still = word - cas bits
|
||||||
|
// Or in the new value to create complete new value.
|
||||||
|
orr(scratch0, scratch0, new_val);
|
||||||
|
|
||||||
|
mv(scratch1, result); // save our expected value
|
||||||
|
atomic_cas(result, scratch0, aligned_addr, operand_size::int32, acquire, release);
|
||||||
|
bne(scratch1, result, retry);
|
||||||
} else {
|
} else {
|
||||||
lr_w(old, aligned_addr, acquire);
|
notr(scratch1, mask);
|
||||||
andr(tmp, old, mask);
|
bind(retry);
|
||||||
bne(tmp, expected, fail);
|
|
||||||
|
|
||||||
andr(tmp, old, not_mask);
|
lr_w(result, aligned_addr, acquire);
|
||||||
orr(tmp, tmp, new_val);
|
andr(scratch0, result, mask);
|
||||||
sc_w(tmp, tmp, aligned_addr, release);
|
bne(scratch0, expected, fail);
|
||||||
bnez(tmp, retry);
|
|
||||||
|
andr(scratch0, result, scratch1); // scratch1 is ~mask
|
||||||
|
orr(scratch0, scratch0, new_val);
|
||||||
|
sc_w(scratch0, scratch0, aligned_addr, release);
|
||||||
|
bnez(scratch0, retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result_as_bool) {
|
if (result_as_bool) {
|
||||||
@ -3393,10 +3399,10 @@ void MacroAssembler::cmpxchg_narrow_value(Register addr, Register expected,
|
|||||||
|
|
||||||
bind(done);
|
bind(done);
|
||||||
} else {
|
} else {
|
||||||
andr(tmp, old, mask);
|
|
||||||
|
|
||||||
bind(fail);
|
bind(fail);
|
||||||
srl(result, tmp, shift);
|
|
||||||
|
andr(scratch0, result, mask);
|
||||||
|
srl(result, scratch0, shift);
|
||||||
|
|
||||||
if (size == int8) {
|
if (size == int8) {
|
||||||
sign_extend(result, result, 8);
|
sign_extend(result, result, 8);
|
||||||
@ -3416,33 +3422,44 @@ void MacroAssembler::weak_cmpxchg_narrow_value(Register addr, Register expected,
|
|||||||
Assembler::Aqrl acquire, Assembler::Aqrl release,
|
Assembler::Aqrl acquire, Assembler::Aqrl release,
|
||||||
Register result,
|
Register result,
|
||||||
Register tmp1, Register tmp2, Register tmp3) {
|
Register tmp1, Register tmp2, Register tmp3) {
|
||||||
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0;
|
assert_different_registers(addr, expected, new_val, result, tmp1, tmp2, tmp3, t0, t1);
|
||||||
assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp);
|
|
||||||
cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3);
|
Register scratch0 = t0, aligned_addr = t1;
|
||||||
|
Register shift = tmp1, mask = tmp2, scratch1 = tmp3;
|
||||||
|
|
||||||
|
cmpxchg_narrow_value_helper(addr, expected, new_val, size, shift, mask, aligned_addr);
|
||||||
|
|
||||||
Label fail, done;
|
Label fail, done;
|
||||||
|
|
||||||
if (UseZacas) {
|
if (UseZacas) {
|
||||||
lw(old, aligned_addr);
|
lw(result, aligned_addr);
|
||||||
|
|
||||||
// if old & mask != expected
|
notr(scratch1, mask);
|
||||||
andr(tmp, old, mask);
|
|
||||||
bne(tmp, expected, fail);
|
|
||||||
|
|
||||||
andr(tmp, old, not_mask);
|
andr(scratch0, result, scratch1); // scratch0 = word - cas bits
|
||||||
orr(tmp, tmp, new_val);
|
orr(scratch1, expected, scratch0); // scratch1 = non-cas bits + cas bits
|
||||||
|
bne(result, scratch1, fail); // cas bits differ, cas failed
|
||||||
|
|
||||||
atomic_cas(tmp, new_val, addr, operand_size::int32, acquire, release);
|
// result is the same as expected, use as expected value.
|
||||||
bne(tmp, old, fail);
|
|
||||||
|
// scratch0 is still = word - cas bits
|
||||||
|
// Or in the new value to create complete new value.
|
||||||
|
orr(scratch0, scratch0, new_val);
|
||||||
|
|
||||||
|
mv(scratch1, result); // save our expected value
|
||||||
|
atomic_cas(result, scratch0, aligned_addr, operand_size::int32, acquire, release);
|
||||||
|
bne(scratch1, result, fail); // This weak, so just bail-out.
|
||||||
} else {
|
} else {
|
||||||
lr_w(old, aligned_addr, acquire);
|
notr(scratch1, mask);
|
||||||
andr(tmp, old, mask);
|
|
||||||
bne(tmp, expected, fail);
|
|
||||||
|
|
||||||
andr(tmp, old, not_mask);
|
lr_w(result, aligned_addr, acquire);
|
||||||
orr(tmp, tmp, new_val);
|
andr(scratch0, result, mask);
|
||||||
sc_w(tmp, tmp, aligned_addr, release);
|
bne(scratch0, expected, fail);
|
||||||
bnez(tmp, fail);
|
|
||||||
|
andr(scratch0, result, scratch1); // scratch1 is ~mask
|
||||||
|
orr(scratch0, scratch0, new_val);
|
||||||
|
sc_w(scratch0, scratch0, aligned_addr, release);
|
||||||
|
bnez(scratch0, fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
|
@ -1146,10 +1146,9 @@ public:
|
|||||||
enum operand_size size,
|
enum operand_size size,
|
||||||
Assembler::Aqrl acquire, Assembler::Aqrl release,
|
Assembler::Aqrl acquire, Assembler::Aqrl release,
|
||||||
Register result);
|
Register result);
|
||||||
void cmpxchg_narrow_value_helper(Register addr, Register expected,
|
void cmpxchg_narrow_value_helper(Register addr, Register expected, Register new_val,
|
||||||
Register new_val,
|
|
||||||
enum operand_size size,
|
enum operand_size size,
|
||||||
Register tmp1, Register tmp2, Register tmp3);
|
Register shift, Register mask, Register aligned_addr);
|
||||||
void cmpxchg_narrow_value(Register addr, Register expected,
|
void cmpxchg_narrow_value(Register addr, Register expected,
|
||||||
Register new_val,
|
Register new_val,
|
||||||
enum operand_size size,
|
enum operand_size size,
|
||||||
|
Loading…
Reference in New Issue
Block a user