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:
Afonso Bordado
2023-02-22 17:41:14 +00:00
committed by GitHub
parent 6e6a1034d7
commit f6c6bc2155
68 changed files with 1922 additions and 1585 deletions

View File

@@ -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,
}
}

View File

@@ -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 {

View File

@@ -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)