riscv64: Improve signed and zero extend codegen (#5844)
* riscv64: Remove unused code * riscv64: Group extend rules * riscv64: Remove more unused rules * riscv64: Cleanup existing extension rules * riscv64: Move the existing Extend rules to ISLE * riscv64: Use `sext.w` when extending * riscv64: Remove duplicate extend tests * riscv64: Use `zbb` instructions when extending values * riscv64: Use `zbkb` extensions when zero extending * riscv64: Enable additional tests for extend i128 * riscv64: Fix formatting for `Inst::Extend` * riscv64: Reverse register for pack * riscv64: Misc Cleanups * riscv64: Cleanup extend rules
This commit is contained in:
@@ -746,6 +746,9 @@ impl AluOPRRR {
|
||||
Self::Sh3add => "sh3add",
|
||||
Self::Sh3adduw => "sh3add.uw",
|
||||
Self::Xnor => "xnor",
|
||||
Self::Pack => "pack",
|
||||
Self::Packw => "packw",
|
||||
Self::Packh => "packh",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,6 +788,7 @@ impl AluOPRRR {
|
||||
AluOPRRR::Remw => 0b110,
|
||||
AluOPRRR::Remuw => 0b111,
|
||||
|
||||
// Zbb
|
||||
AluOPRRR::Adduw => 0b000,
|
||||
AluOPRRR::Andn => 0b111,
|
||||
AluOPRRR::Bclr => 0b001,
|
||||
@@ -810,6 +814,11 @@ impl AluOPRRR {
|
||||
AluOPRRR::Sh3add => 0b110,
|
||||
AluOPRRR::Sh3adduw => 0b110,
|
||||
AluOPRRR::Xnor => 0b100,
|
||||
|
||||
// Zbkb
|
||||
AluOPRRR::Pack => 0b100,
|
||||
AluOPRRR::Packw => 0b100,
|
||||
AluOPRRR::Packh => 0b111,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,11 +835,16 @@ impl AluOPRRR {
|
||||
| AluOPRRR::Srl
|
||||
| AluOPRRR::Sra
|
||||
| AluOPRRR::Or
|
||||
| AluOPRRR::And => 0b0110011,
|
||||
| AluOPRRR::And
|
||||
| AluOPRRR::Pack
|
||||
| AluOPRRR::Packh => 0b0110011,
|
||||
|
||||
AluOPRRR::Addw | AluOPRRR::Subw | AluOPRRR::Sllw | AluOPRRR::Srlw | AluOPRRR::Sraw => {
|
||||
0b0111011
|
||||
}
|
||||
AluOPRRR::Addw
|
||||
| AluOPRRR::Subw
|
||||
| AluOPRRR::Sllw
|
||||
| AluOPRRR::Srlw
|
||||
| AluOPRRR::Sraw
|
||||
| AluOPRRR::Packw => 0b0111011,
|
||||
|
||||
AluOPRRR::Mul
|
||||
| AluOPRRR::Mulh
|
||||
@@ -937,6 +951,11 @@ impl AluOPRRR {
|
||||
AluOPRRR::Sh3add => 0b0010000,
|
||||
AluOPRRR::Sh3adduw => 0b0010000,
|
||||
AluOPRRR::Xnor => 0b0100000,
|
||||
|
||||
// Zbkb
|
||||
AluOPRRR::Pack => 0b0000100,
|
||||
AluOPRRR::Packw => 0b0000100,
|
||||
AluOPRRR::Packh => 0b0000100,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -514,6 +514,38 @@ fn test_riscv64_binemit() {
|
||||
0x400545b3,
|
||||
));
|
||||
|
||||
// Zbkb
|
||||
insns.push(TestUnit::new(
|
||||
Inst::AluRRR {
|
||||
alu_op: AluOPRRR::Pack,
|
||||
rd: writable_a1(),
|
||||
rs1: a0(),
|
||||
rs2: zero_reg(),
|
||||
},
|
||||
"pack a1,a0,zero",
|
||||
0x080545b3,
|
||||
));
|
||||
insns.push(TestUnit::new(
|
||||
Inst::AluRRR {
|
||||
alu_op: AluOPRRR::Packw,
|
||||
rd: writable_a1(),
|
||||
rs1: a0(),
|
||||
rs2: zero_reg(),
|
||||
},
|
||||
"packw a1,a0,zero",
|
||||
0x080545bb,
|
||||
));
|
||||
insns.push(TestUnit::new(
|
||||
Inst::AluRRR {
|
||||
alu_op: AluOPRRR::Packh,
|
||||
rd: writable_a1(),
|
||||
rs1: a0(),
|
||||
rs2: zero_reg(),
|
||||
},
|
||||
"packh a1,a0,zero",
|
||||
0x080575b3,
|
||||
));
|
||||
|
||||
//
|
||||
insns.push(TestUnit::new(
|
||||
Inst::AluRRR {
|
||||
|
||||
@@ -845,16 +845,6 @@ impl Inst {
|
||||
x
|
||||
};
|
||||
|
||||
fn format_extend_op(signed: bool, from_bits: u8, _to_bits: u8) -> String {
|
||||
let type_name = match from_bits {
|
||||
1 => "b1",
|
||||
8 => "b",
|
||||
16 => "h",
|
||||
32 => "w",
|
||||
_ => unreachable!("from_bits:{:?}", from_bits),
|
||||
};
|
||||
format!("{}ext.{}", if signed { "s" } else { "u" }, type_name)
|
||||
}
|
||||
fn format_frm(rounding_mode: Option<FRM>) -> String {
|
||||
if let Some(r) = rounding_mode {
|
||||
format!(",{}", r.to_static_str(),)
|
||||
@@ -1341,15 +1331,23 @@ impl Inst {
|
||||
} => {
|
||||
let rs_s = format_reg(rs, allocs);
|
||||
let rd = format_reg(rd.to_reg(), allocs);
|
||||
// check if it is a load constant.
|
||||
if alu_op == AluOPRRI::Addi && rs == zero_reg() {
|
||||
format!("li {},{}", rd, imm12.as_i16())
|
||||
} else if alu_op == AluOPRRI::Xori && imm12.as_i16() == -1 {
|
||||
format!("not {},{}", rd, rs_s)
|
||||
} else {
|
||||
if alu_op.option_funct12().is_some() {
|
||||
|
||||
// Some of these special cases are better known as
|
||||
// their pseudo-instruction version, so prefer printing those.
|
||||
match (alu_op, rs, imm12) {
|
||||
(AluOPRRI::Addi, rs, _) if rs == zero_reg() => {
|
||||
return format!("li {},{}", rd, imm12.as_i16());
|
||||
}
|
||||
(AluOPRRI::Addiw, _, imm12) if imm12.as_i16() == 0 => {
|
||||
return format!("sext.w {},{}", rd, rs_s);
|
||||
}
|
||||
(AluOPRRI::Xori, _, imm12) if imm12.as_i16() == -1 => {
|
||||
return format!("not {},{}", rd, rs_s);
|
||||
}
|
||||
(alu_op, _, _) if alu_op.option_funct12().is_some() => {
|
||||
format!("{} {},{}", alu_op.op_name(), rd, rs_s)
|
||||
} else {
|
||||
}
|
||||
(alu_op, _, imm12) => {
|
||||
format!("{} {},{},{}", alu_op.op_name(), rd, rs_s, imm12.as_i16())
|
||||
}
|
||||
}
|
||||
@@ -1402,16 +1400,17 @@ impl Inst {
|
||||
rn,
|
||||
signed,
|
||||
from_bits,
|
||||
to_bits,
|
||||
..
|
||||
} => {
|
||||
let rn = format_reg(rn, allocs);
|
||||
let rm = format_reg(rd.to_reg(), allocs);
|
||||
format!(
|
||||
"{} {},{}",
|
||||
format_extend_op(signed, from_bits, to_bits),
|
||||
rm,
|
||||
rn
|
||||
)
|
||||
let rd = format_reg(rd.to_reg(), allocs);
|
||||
return if signed == false && from_bits == 8 {
|
||||
format!("andi {rd},{rn}")
|
||||
} else {
|
||||
let op = if signed { "srai" } else { "srli" };
|
||||
let shift_bits = (64 - from_bits) as i16;
|
||||
format!("slli {rd},{rn},{shift_bits}; {op} {rd},{rd},{shift_bits}")
|
||||
};
|
||||
}
|
||||
&MInst::AjustSp { amount } => {
|
||||
format!("{} sp,{:+}", "add", amount)
|
||||
|
||||
Reference in New Issue
Block a user