use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HexagonFullOpcode {
Add,
Sub,
And,
Or,
Xor,
Not,
Neg,
AddImm,
SubImm,
AndImm,
OrImm,
Combinew,
Combineh,
Padd,
Psub,
Pand,
Por,
SatAdd,
SatSub,
Mpyi,
Mpyu,
Mpy,
MpyAcc,
MpyNac,
MpyRnd,
Mpyll,
Mpyhh,
Mpylh,
Mpyhl,
MpyiImm,
MpyImm,
Asl,
Asr,
Lsr,
AslReg,
AsrReg,
LsrReg,
AslImm,
AsrImm,
LsrImm,
Loadw,
Loadrd,
Loadri,
Loadrub,
Loadruh,
Loadrb,
Loadrh,
LoadAlignw,
Storew,
Storeri,
Storerb,
Storerh,
Storerd,
StoreAlignw,
Jump,
Jumpr,
Call,
Callr,
Jumpt,
Jumpf,
Jumptnew,
Jumpfnew,
JumptPt,
JumpfPt,
Loop0,
Loop1,
Endloop0,
Endloop1,
Cmpeq,
Cmpgt,
Cmpgtu,
Cmplt,
Cmpltu,
Cmpeqi,
Cmpgti,
Cmpgtui,
Cmplti,
Cmpltui,
CmpeqAnd,
CmpeqOr,
CmpbEq,
CmpbGt,
VAddB,
VAddH,
VAddW,
VSubB,
VSubH,
VSubW,
VMpy,
VMpyi,
VMpyu,
VMaxB,
VMaxH,
VMaxW,
VMinB,
VMinH,
VMinW,
VAnd,
VOr,
VXor,
VNot,
VShuf,
VSplat,
VAlign,
VLAlign,
VAbsB,
VAbsH,
VAbsW,
VAvgB,
VAvgH,
VAvgW,
VNavgB,
VNavgH,
VNavgW,
VLd32b,
VS32b,
VGather,
VScatter,
VLut16,
VLut32,
VHist,
VMemU,
VMemT,
Copy,
MoveImm,
Nop,
Trap,
ConvertDf2Sf,
ConvertSf2Df,
Memw,
Memb,
Memh,
Membh,
Memub,
Memuh,
Brev,
Cl0,
Cl1,
Ct0,
Ct1,
}
#[derive(Debug, Clone)]
pub struct HexagonFullNode {
pub opcode: HexagonFullOpcode,
pub operands: Vec<HexagonFullOperand>,
pub result_reg: Option<u32>,
pub predicate: Option<u32>,
pub predicate_sense: bool,
pub is_new_predicate: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HexagonFullOperand {
Reg(u32),
PReg(u32),
VReg(u32),
Imm(i32),
ImmU(u32),
Label(String),
Addr { base: u32, offset: i32 },
Slot(u32),
}
pub struct HexagonFullInstructionSelector {
pub reg_map: HashMap<u32, u32>,
pub next_reg: u32,
pub pred_reg_map: HashMap<u32, u32>,
pub vec_reg_map: HashMap<u32, u32>,
pub is_v60: bool,
pub is_v65: bool,
pub is_v66: bool,
}
impl HexagonFullInstructionSelector {
pub fn new(v6: bool) -> Self {
HexagonFullInstructionSelector {
reg_map: HashMap::new(),
next_reg: 0,
pred_reg_map: HashMap::new(),
vec_reg_map: HashMap::new(),
is_v60: v6,
is_v65: v6,
is_v66: v6,
}
}
fn alloc_reg(&mut self) -> u32 {
let r = self.next_reg;
self.next_reg += 1;
r
}
pub fn select_alu(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or_else(|| self.alloc_reg());
let rs = Self::extract_reg(&node.operands, 0);
let rt = Self::extract_reg(&node.operands, 1);
if let (Some(rs), Some(rt)) = (rs, rt) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::Reg(rt),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_alu_imm(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or_else(|| self.alloc_reg());
let rs = Self::extract_reg(&node.operands, 0);
let imm = Self::extract_imm(&node.operands, 1);
if let (Some(rs), Some(imm)) = (rs, imm) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::Imm(imm),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_mpy(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or_else(|| self.alloc_reg());
let rs = Self::extract_reg(&node.operands, 0);
let rt = Self::extract_reg(&node.operands, 1);
if let (Some(rs), Some(rt)) = (rs, rt) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::Reg(rt),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_mpy_acc(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or(0);
let rs = Self::extract_reg(&node.operands, 0);
let rt = Self::extract_reg(&node.operands, 1);
if let (Some(rs), Some(rt)) = (rs, rt) {
vec![HexagonFullNode {
opcode: HexagonFullOpcode::MpyAcc,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::Reg(rt),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_mpy_nac(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or(0);
let rs = Self::extract_reg(&node.operands, 0);
let rt = Self::extract_reg(&node.operands, 1);
if let (Some(rs), Some(rt)) = (rs, rt) {
vec![HexagonFullNode {
opcode: HexagonFullOpcode::MpyNac,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::Reg(rt),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_mpy_rnd(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
self.select_mpy(node)
}
pub fn select_shift(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or_else(|| self.alloc_reg());
let rs = Self::extract_reg(&node.operands, 0);
let amount = Self::extract_reg(&node.operands, 1);
if let (Some(rs), Some(rt)) = (rs, amount) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::Reg(rt),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_shift_imm(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or_else(|| self.alloc_reg());
let rs = Self::extract_reg(&node.operands, 0);
let imm = Self::extract_imm(&node.operands, 1);
if let (Some(rs), Some(imm)) = (rs, imm) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::ImmU(imm as u32),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_load(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or_else(|| self.alloc_reg());
let addr = Self::extract_addr(&node.operands, 0);
if let Some((base, offset)) = addr {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Addr { base, offset },
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_store(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let src = Self::extract_reg(&node.operands, 0);
let addr = Self::extract_addr(&node.operands, 1);
if let (Some(rt), Some((base, offset))) = (src, addr) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rt),
HexagonFullOperand::Addr { base, offset },
],
result_reg: None,
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_branch(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
match node.opcode {
HexagonFullOpcode::Jump | HexagonFullOpcode::Call => {
let target = node.operands.iter().find_map(|o| {
if let HexagonFullOperand::Label(s) = o {
Some(s.clone())
} else {
None
}
});
target
.map(|t| HexagonFullNode {
opcode: node.opcode,
operands: vec![HexagonFullOperand::Label(t)],
result_reg: None,
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
})
.into_iter()
.collect()
}
HexagonFullOpcode::Jumpr | HexagonFullOpcode::Callr => {
let rs = Self::extract_reg(&node.operands, 0);
rs.map(|r| HexagonFullNode {
opcode: node.opcode,
operands: vec![HexagonFullOperand::Reg(r)],
result_reg: None,
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
})
.into_iter()
.collect()
}
HexagonFullOpcode::Jumpt | HexagonFullOpcode::Jumpf => {
let pred = node.operands.iter().find_map(|o| {
if let HexagonFullOperand::PReg(p) = o {
Some(*p)
} else {
None
}
});
let target = node.operands.iter().find_map(|o| {
if let HexagonFullOperand::Label(s) = o {
Some(s.clone())
} else {
None
}
});
if let (Some(p), Some(t)) = (pred, target) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![HexagonFullOperand::PReg(p), HexagonFullOperand::Label(t)],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
}]
} else {
Vec::new()
}
}
_ => Vec::new(),
}
}
pub fn select_compare(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let pd = node.result_reg.unwrap_or(0);
let rs = Self::extract_reg(&node.operands, 0);
let rt_or_imm = node.operands.get(1).cloned();
if let Some(rs) = rs {
let mut ops = vec![HexagonFullOperand::PReg(pd), HexagonFullOperand::Reg(rs)];
if let Some(o) = rt_or_imm {
ops.push(o);
}
vec![HexagonFullNode {
opcode: node.opcode,
operands: ops,
result_reg: Some(pd),
predicate: None,
predicate_sense: true,
is_new_predicate: true, }]
} else {
Vec::new()
}
}
pub fn select_hvx_arith(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let vd = node.result_reg.unwrap_or(0);
let vs = Self::extract_vreg(&node.operands, 0);
let vt = Self::extract_vreg(&node.operands, 1);
if let (Some(vs), Some(vt)) = (vs, vt) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::VReg(vd),
HexagonFullOperand::VReg(vs),
HexagonFullOperand::VReg(vt),
],
result_reg: Some(vd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_hvx_vmpyi(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let vd = node.result_reg.unwrap_or(0);
let vs = Self::extract_vreg(&node.operands, 0);
let imm = Self::extract_imm(&node.operands, 1);
if let (Some(vs), Some(imm)) = (vs, imm) {
vec![HexagonFullNode {
opcode: HexagonFullOpcode::VMpyi,
operands: vec![
HexagonFullOperand::VReg(vd),
HexagonFullOperand::VReg(vs),
HexagonFullOperand::Imm(imm),
],
result_reg: Some(vd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_hvx_bitwise(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
self.select_hvx_arith(node)
}
pub fn select_hvx_shuffle(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
self.select_hvx_arith(node)
}
pub fn select_hvx_align(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
self.select_hvx_arith(node)
}
pub fn select_hvx_load(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let vd = node.result_reg.unwrap_or(0);
let addr = Self::extract_addr(&node.operands, 0);
if let Some((base, offset)) = addr {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::VReg(vd),
HexagonFullOperand::Addr { base, offset },
],
result_reg: Some(vd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_hvx_store(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let vs = Self::extract_vreg(&node.operands, 0);
let addr = Self::extract_addr(&node.operands, 1);
if let (Some(vs), Some((base, offset))) = (vs, addr) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::VReg(vs),
HexagonFullOperand::Addr { base, offset },
],
result_reg: None,
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_combine(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let rd = node.result_reg.unwrap_or_else(|| self.alloc_reg());
let rs = Self::extract_reg(&node.operands, 0);
let rt = Self::extract_reg(&node.operands, 1);
if let (Some(rs), Some(rt)) = (rs, rt) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![
HexagonFullOperand::Reg(rd),
HexagonFullOperand::Reg(rs),
HexagonFullOperand::Reg(rt),
],
result_reg: Some(rd),
predicate: node.predicate,
predicate_sense: node.predicate_sense,
is_new_predicate: node.is_new_predicate,
}]
} else {
Vec::new()
}
}
pub fn select_loop(&mut self, node: &HexagonFullNode) -> Vec<HexagonFullNode> {
let reg = Self::extract_reg(&node.operands, 0);
let target = node.operands.iter().find_map(|o| {
if let HexagonFullOperand::Label(s) = o {
Some(s.clone())
} else {
None
}
});
if let (Some(r), Some(t)) = (reg, target) {
vec![HexagonFullNode {
opcode: node.opcode,
operands: vec![HexagonFullOperand::Reg(r), HexagonFullOperand::Label(t)],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
}]
} else {
Vec::new()
}
}
fn extract_reg(ops: &[HexagonFullOperand], idx: usize) -> Option<u32> {
ops.get(idx).and_then(|o| {
if let HexagonFullOperand::Reg(r) = o {
Some(*r)
} else {
None
}
})
}
fn extract_vreg(ops: &[HexagonFullOperand], idx: usize) -> Option<u32> {
ops.get(idx).and_then(|o| {
if let HexagonFullOperand::VReg(r) = o {
Some(*r)
} else {
None
}
})
}
fn extract_imm(ops: &[HexagonFullOperand], idx: usize) -> Option<i32> {
ops.get(idx).and_then(|o| {
if let HexagonFullOperand::Imm(i) = o {
Some(*i)
} else {
None
}
})
}
fn extract_addr(ops: &[HexagonFullOperand], idx: usize) -> Option<(u32, i32)> {
ops.get(idx).and_then(|o| {
if let HexagonFullOperand::Addr { base, offset } = o {
Some((*base, *offset))
} else {
None
}
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_select_alu_add() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Add,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_alu(&node);
assert!(!result.is_empty());
assert_eq!(result[0].operands.len(), 3);
}
#[test]
fn test_select_alu_imm() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::AddImm,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Imm(42)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_alu_imm(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_mpy() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Mpy,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_mpy(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_mpy_acc() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::MpyAcc,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_mpy_acc(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_mpy_nac() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::MpyNac,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_mpy_nac(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_shift() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::AslReg,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_shift(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_shift_imm() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::AslImm,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Imm(5)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_shift_imm(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_load() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Loadw,
operands: vec![HexagonFullOperand::Addr { base: 5, offset: 0 }],
result_reg: Some(4),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_load(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_store() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Storew,
operands: vec![
HexagonFullOperand::Reg(3),
HexagonFullOperand::Addr { base: 5, offset: 8 },
],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_store(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_branch_jump() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Jump,
operands: vec![HexagonFullOperand::Label("loop".to_string())],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_branch_call() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Call,
operands: vec![HexagonFullOperand::Label("func".to_string())],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_branch_jumpr() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Jumpr,
operands: vec![HexagonFullOperand::Reg(31)],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_branch_conditional() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Jumpt,
operands: vec![
HexagonFullOperand::PReg(0),
HexagonFullOperand::Label("if_true".to_string()),
],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_compare() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Cmpeq,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(0),
predicate: None,
predicate_sense: true,
is_new_predicate: true,
};
let result = sel.select_compare(&node);
assert!(!result.is_empty());
assert!(result[0].is_new_predicate);
}
#[test]
fn test_select_compare_imm() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Cmpeqi,
operands: vec![HexagonFullOperand::Reg(2), HexagonFullOperand::Imm(0)],
result_reg: Some(1),
predicate: None,
predicate_sense: true,
is_new_predicate: true,
};
let result = sel.select_compare(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_hvx_add() {
let mut sel = HexagonFullInstructionSelector::new(true);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::VAddB,
operands: vec![HexagonFullOperand::VReg(1), HexagonFullOperand::VReg(2)],
result_reg: Some(0),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_hvx_arith(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_hvx_mpyi() {
let mut sel = HexagonFullInstructionSelector::new(true);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::VMpyi,
operands: vec![HexagonFullOperand::VReg(1), HexagonFullOperand::Imm(3)],
result_reg: Some(2),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_hvx_vmpyi(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_hvx_bitwise() {
let mut sel = HexagonFullInstructionSelector::new(true);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::VAnd,
operands: vec![HexagonFullOperand::VReg(1), HexagonFullOperand::VReg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_hvx_bitwise(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_hvx_load() {
let mut sel = HexagonFullInstructionSelector::new(true);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::VLd32b,
operands: vec![HexagonFullOperand::Addr { base: 5, offset: 0 }],
result_reg: Some(2),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_hvx_load(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_hvx_store() {
let mut sel = HexagonFullInstructionSelector::new(true);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::VS32b,
operands: vec![
HexagonFullOperand::VReg(1),
HexagonFullOperand::Addr {
base: 5,
offset: 32,
},
],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_hvx_store(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_combine() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Combineh,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_combine(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_loop() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Loop0,
operands: vec![
HexagonFullOperand::Reg(8),
HexagonFullOperand::Label("loop_body".to_string()),
],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let result = sel.select_loop(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_all_alu_ops() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![
HexagonFullOpcode::Add,
HexagonFullOpcode::Sub,
HexagonFullOpcode::And,
HexagonFullOpcode::Or,
HexagonFullOpcode::Xor,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_alu(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_mpy_ops() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Mpyi,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_mpy(&node).is_empty());
assert!(!sel.select_mpy_rnd(&node).is_empty());
}
#[test]
fn test_select_all_hvx_ops() {
let mut sel = HexagonFullInstructionSelector::new(true);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::VAddW,
operands: vec![HexagonFullOperand::VReg(1), HexagonFullOperand::VReg(2)],
result_reg: Some(0),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_hvx_arith(&node).is_empty());
assert!(!sel.select_hvx_shuffle(&node).is_empty());
assert!(!sel.select_hvx_align(&node).is_empty());
}
#[test]
fn test_select_all_branch_ops() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Jump,
operands: vec![HexagonFullOperand::Label("t".to_string())],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_branch(&node).is_empty());
}
#[test]
fn test_combined_alu_mul_pattern() {
let mut sel = HexagonFullInstructionSelector::new(false);
let add_node = HexagonFullNode {
opcode: HexagonFullOpcode::Add,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(5),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let add_result = sel.select_alu(&add_node);
assert!(!add_result.is_empty());
let mul_node = HexagonFullNode {
opcode: HexagonFullOpcode::Mpy,
operands: vec![HexagonFullOperand::Reg(5), HexagonFullOperand::Reg(3)],
result_reg: Some(5),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
let mul_result = sel.select_mpy(&mul_node);
assert!(!mul_result.is_empty());
}
#[test]
fn test_predicated_instruction() {
let mut sel = HexagonFullInstructionSelector::new(false);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::Add,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: Some(1),
predicate_sense: false,
is_new_predicate: false,
};
let result = sel.select_alu(&node);
assert!(!result.is_empty());
assert_eq!(result[0].predicate, Some(1));
assert!(!result[0].predicate_sense);
}
#[test]
fn test_select_all_load_types() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![
HexagonFullOpcode::Loadw,
HexagonFullOpcode::Loadrd,
HexagonFullOpcode::Loadri,
HexagonFullOpcode::Loadrub,
HexagonFullOpcode::Loadruh,
HexagonFullOpcode::Loadrb,
HexagonFullOpcode::Loadrh,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::Addr { base: 5, offset: 0 }],
result_reg: Some(4),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_load(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_store_types() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![
HexagonFullOpcode::Storew,
HexagonFullOpcode::Storeri,
HexagonFullOpcode::Storerb,
HexagonFullOpcode::Storerh,
HexagonFullOpcode::Storerd,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![
HexagonFullOperand::Reg(3),
HexagonFullOperand::Addr { base: 5, offset: 8 },
],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_store(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_hvx_arith() {
let mut sel = HexagonFullInstructionSelector::new(true);
let ops = vec![
HexagonFullOpcode::VAddB,
HexagonFullOpcode::VAddH,
HexagonFullOpcode::VAddW,
HexagonFullOpcode::VSubB,
HexagonFullOpcode::VSubH,
HexagonFullOpcode::VSubW,
HexagonFullOpcode::VMaxB,
HexagonFullOpcode::VMinW,
HexagonFullOpcode::VAbsB,
HexagonFullOpcode::VAvgW,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::VReg(1), HexagonFullOperand::VReg(2)],
result_reg: Some(0),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_hvx_arith(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_hvx_bitwise() {
let mut sel = HexagonFullInstructionSelector::new(true);
let ops = vec![
HexagonFullOpcode::VAnd,
HexagonFullOpcode::VOr,
HexagonFullOpcode::VXor,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::VReg(1), HexagonFullOperand::VReg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_hvx_bitwise(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_shifts() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![
HexagonFullOpcode::AslReg,
HexagonFullOpcode::AsrReg,
HexagonFullOpcode::LsrReg,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_shift(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_shift_imm() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![
HexagonFullOpcode::AslImm,
HexagonFullOpcode::AsrImm,
HexagonFullOpcode::LsrImm,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Imm(5)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_shift_imm(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_compare_ops() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![
HexagonFullOpcode::Cmpeq,
HexagonFullOpcode::Cmpgt,
HexagonFullOpcode::Cmpgtu,
HexagonFullOpcode::Cmplt,
HexagonFullOpcode::Cmpltu,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::Reg(1), HexagonFullOperand::Reg(2)],
result_reg: Some(0),
predicate: None,
predicate_sense: true,
is_new_predicate: true,
};
assert!(!sel.select_compare(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_compare_imm_ops() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![
HexagonFullOpcode::Cmpeqi,
HexagonFullOpcode::Cmpgti,
HexagonFullOpcode::Cmpgtui,
];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![HexagonFullOperand::Reg(2), HexagonFullOperand::Imm(0)],
result_reg: Some(1),
predicate: None,
predicate_sense: true,
is_new_predicate: true,
};
assert!(!sel.select_compare(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_loop_types() {
let mut sel = HexagonFullInstructionSelector::new(false);
let ops = vec![HexagonFullOpcode::Loop0, HexagonFullOpcode::Loop1];
for op in &ops {
let node = HexagonFullNode {
opcode: *op,
operands: vec![
HexagonFullOperand::Reg(8),
HexagonFullOperand::Label("body".to_string()),
],
result_reg: None,
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_loop(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_hvx_special_ops() {
let mut sel = HexagonFullInstructionSelector::new(true);
let node = HexagonFullNode {
opcode: HexagonFullOpcode::VShuf,
operands: vec![HexagonFullOperand::VReg(1), HexagonFullOperand::VReg(2)],
result_reg: Some(3),
predicate: None,
predicate_sense: true,
is_new_predicate: false,
};
assert!(!sel.select_hvx_shuffle(&node).is_empty());
assert!(!sel.select_hvx_align(&node).is_empty());
}
}