Codegen fix atomic_rmw_loop missing move result to dst register On riscv64. (#5898)
* fix issue5884. * fix issue5884 * fix test failure * fix atomic rmw missing move result to dst register. * specify little endian some s390x can pass test.
This commit is contained in:
@@ -1375,7 +1375,7 @@ impl MachInstEmit for Inst {
|
|||||||
| crate::ir::AtomicRmwOp::And
|
| crate::ir::AtomicRmwOp::And
|
||||||
| crate::ir::AtomicRmwOp::Or
|
| crate::ir::AtomicRmwOp::Or
|
||||||
| crate::ir::AtomicRmwOp::Xor => {
|
| crate::ir::AtomicRmwOp::Xor => {
|
||||||
AtomicOP::extract(t0, offset, dst.to_reg(), ty)
|
AtomicOP::extract(dst, offset, dst.to_reg(), ty)
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
||||||
Inst::AluRRR {
|
Inst::AluRRR {
|
||||||
@@ -1388,7 +1388,7 @@ impl MachInstEmit for Inst {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
rd: t0,
|
rd: t0,
|
||||||
rs1: t0.to_reg(),
|
rs1: dst.to_reg(),
|
||||||
rs2: x,
|
rs2: x,
|
||||||
}
|
}
|
||||||
.emit(&[], sink, emit_info, state);
|
.emit(&[], sink, emit_info, state);
|
||||||
@@ -1412,19 +1412,16 @@ impl MachInstEmit for Inst {
|
|||||||
spilltmp_reg2()
|
spilltmp_reg2()
|
||||||
}
|
}
|
||||||
crate::ir::AtomicRmwOp::Nand => {
|
crate::ir::AtomicRmwOp::Nand => {
|
||||||
let x2 = if ty.bits() < 32 {
|
if ty.bits() < 32 {
|
||||||
AtomicOP::extract(t0, offset, dst.to_reg(), ty)
|
AtomicOP::extract(dst, offset, dst.to_reg(), ty)
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
||||||
t0.to_reg()
|
}
|
||||||
} else {
|
|
||||||
dst.to_reg()
|
|
||||||
};
|
|
||||||
Inst::AluRRR {
|
Inst::AluRRR {
|
||||||
alu_op: AluOPRRR::And,
|
alu_op: AluOPRRR::And,
|
||||||
rd: t0,
|
rd: t0,
|
||||||
rs1: x,
|
rs1: x,
|
||||||
rs2: x2,
|
rs2: dst.to_reg(),
|
||||||
}
|
}
|
||||||
.emit(&[], sink, emit_info, state);
|
.emit(&[], sink, emit_info, state);
|
||||||
Inst::construct_bit_not(t0, t0.to_reg()).emit(&[], sink, emit_info, state);
|
Inst::construct_bit_not(t0, t0.to_reg()).emit(&[], sink, emit_info, state);
|
||||||
@@ -1456,12 +1453,13 @@ impl MachInstEmit for Inst {
|
|||||||
| crate::ir::AtomicRmwOp::Umax
|
| crate::ir::AtomicRmwOp::Umax
|
||||||
| crate::ir::AtomicRmwOp::Smin
|
| crate::ir::AtomicRmwOp::Smin
|
||||||
| crate::ir::AtomicRmwOp::Smax => {
|
| crate::ir::AtomicRmwOp::Smax => {
|
||||||
|
let label_select_dst = sink.get_label();
|
||||||
let label_select_done = sink.get_label();
|
let label_select_done = sink.get_label();
|
||||||
if op == crate::ir::AtomicRmwOp::Umin || op == crate::ir::AtomicRmwOp::Umax
|
if op == crate::ir::AtomicRmwOp::Umin || op == crate::ir::AtomicRmwOp::Umax
|
||||||
{
|
{
|
||||||
AtomicOP::extract(t0, offset, dst.to_reg(), ty)
|
AtomicOP::extract(dst, offset, dst.to_reg(), ty)
|
||||||
} else {
|
} else {
|
||||||
AtomicOP::extract_sext(t0, offset, dst.to_reg(), ty)
|
AtomicOP::extract_sext(dst, offset, dst.to_reg(), ty)
|
||||||
}
|
}
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
||||||
@@ -1473,9 +1471,9 @@ impl MachInstEmit for Inst {
|
|||||||
crate::ir::AtomicRmwOp::Smax => IntCC::SignedGreaterThan,
|
crate::ir::AtomicRmwOp::Smax => IntCC::SignedGreaterThan,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
ValueRegs::one(t0.to_reg()),
|
ValueRegs::one(dst.to_reg()),
|
||||||
ValueRegs::one(x),
|
ValueRegs::one(x),
|
||||||
BranchTarget::Label(label_select_done),
|
BranchTarget::Label(label_select_dst),
|
||||||
BranchTarget::zero(),
|
BranchTarget::zero(),
|
||||||
ty,
|
ty,
|
||||||
)
|
)
|
||||||
@@ -1483,6 +1481,12 @@ impl MachInstEmit for Inst {
|
|||||||
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
||||||
// here we select x.
|
// here we select x.
|
||||||
Inst::gen_move(t0, x, I64).emit(&[], sink, emit_info, state);
|
Inst::gen_move(t0, x, I64).emit(&[], sink, emit_info, state);
|
||||||
|
Inst::Jal {
|
||||||
|
dest: BranchTarget::Label(label_select_done),
|
||||||
|
}
|
||||||
|
.emit(&[], sink, emit_info, state);
|
||||||
|
sink.bind_label(label_select_dst);
|
||||||
|
Inst::gen_move(t0, dst.to_reg(), I64).emit(&[], sink, emit_info, state);
|
||||||
sink.bind_label(label_select_done);
|
sink.bind_label(label_select_done);
|
||||||
Inst::Atomic {
|
Inst::Atomic {
|
||||||
op: AtomicOP::load_op(ty),
|
op: AtomicOP::load_op(ty),
|
||||||
@@ -1504,6 +1508,9 @@ impl MachInstEmit for Inst {
|
|||||||
spilltmp_reg2()
|
spilltmp_reg2()
|
||||||
}
|
}
|
||||||
crate::ir::AtomicRmwOp::Xchg => {
|
crate::ir::AtomicRmwOp::Xchg => {
|
||||||
|
AtomicOP::extract(dst, offset, dst.to_reg(), ty)
|
||||||
|
.iter()
|
||||||
|
.for_each(|i| i.emit(&[], sink, emit_info, state));
|
||||||
Inst::Atomic {
|
Inst::Atomic {
|
||||||
op: AtomicOP::load_op(ty),
|
op: AtomicOP::load_op(ty),
|
||||||
rd: writable_spilltmp_reg2(),
|
rd: writable_spilltmp_reg2(),
|
||||||
|
|||||||
20
cranelift/filetests/filetests/runtests/issue5884.clif
Normal file
20
cranelift/filetests/filetests/runtests/issue5884.clif
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
target x86_64
|
||||||
|
target riscv64
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
|
||||||
|
function %a(i64, i16) -> i16 {
|
||||||
|
ss0 = explicit_slot 8
|
||||||
|
|
||||||
|
block0(v0: i64, v1: i16):
|
||||||
|
v2 = stack_addr.i64 ss0+0
|
||||||
|
store little v0, v2
|
||||||
|
|
||||||
|
v3 = stack_addr.i64 ss0+6
|
||||||
|
v4 = atomic_rmw.i16 little or v3, v1
|
||||||
|
return v4
|
||||||
|
}
|
||||||
|
|
||||||
|
; run: %a(8608481011852310776, 0) == 30583
|
||||||
Reference in New Issue
Block a user