use super::amdgpu_instr_info::{AmdgpuEncodingFormat, AmdgpuOpcode};
use crate::codegen::*;
use crate::opcode::Opcode;
use crate::value::Value;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum AmdgpuGfxVersion {
Gfx600,
Gfx601,
Gfx700,
Gfx701,
Gfx702,
Gfx703,
Gfx704,
Gfx801,
Gfx802,
Gfx803,
Gfx805,
Gfx810,
Gfx900,
Gfx902,
Gfx904,
Gfx906,
Gfx908,
Gfx909,
Gfx90a,
Gfx90c,
Gfx1010,
Gfx1011,
Gfx1012,
Gfx1030,
Gfx1031,
Gfx1032,
Gfx1033,
Gfx1100,
Gfx1101,
Gfx1102,
Gfx1103,
Gfx1150,
Gfx1151,
}
impl AmdgpuGfxVersion {
pub fn is_gcn(self) -> bool {
matches!(
self,
AmdgpuGfxVersion::Gfx600
| AmdgpuGfxVersion::Gfx601
| AmdgpuGfxVersion::Gfx700
| AmdgpuGfxVersion::Gfx701
| AmdgpuGfxVersion::Gfx702
| AmdgpuGfxVersion::Gfx703
| AmdgpuGfxVersion::Gfx704
| AmdgpuGfxVersion::Gfx801
| AmdgpuGfxVersion::Gfx802
| AmdgpuGfxVersion::Gfx803
| AmdgpuGfxVersion::Gfx805
| AmdgpuGfxVersion::Gfx810
| AmdgpuGfxVersion::Gfx900
| AmdgpuGfxVersion::Gfx902
| AmdgpuGfxVersion::Gfx904
| AmdgpuGfxVersion::Gfx906
| AmdgpuGfxVersion::Gfx908
| AmdgpuGfxVersion::Gfx909
| AmdgpuGfxVersion::Gfx90a
| AmdgpuGfxVersion::Gfx90c
)
}
pub fn is_rdna(self) -> bool {
matches!(
self,
AmdgpuGfxVersion::Gfx1010
| AmdgpuGfxVersion::Gfx1011
| AmdgpuGfxVersion::Gfx1012
| AmdgpuGfxVersion::Gfx1030
| AmdgpuGfxVersion::Gfx1031
| AmdgpuGfxVersion::Gfx1032
| AmdgpuGfxVersion::Gfx1033
)
}
pub fn is_rdna3(self) -> bool {
matches!(
self,
AmdgpuGfxVersion::Gfx1100
| AmdgpuGfxVersion::Gfx1101
| AmdgpuGfxVersion::Gfx1102
| AmdgpuGfxVersion::Gfx1103
| AmdgpuGfxVersion::Gfx1150
| AmdgpuGfxVersion::Gfx1151
)
}
pub fn supports_wave32(self) -> bool {
self >= AmdgpuGfxVersion::Gfx1010
}
pub fn supports_vopd(self) -> bool {
self.is_rdna3()
}
pub fn wavefront_size(self) -> u32 {
if self.supports_wave32() {
32
} else {
64
}
}
pub fn base_isa_name(self) -> &'static str {
match self {
AmdgpuGfxVersion::Gfx600 => "gfx600",
AmdgpuGfxVersion::Gfx700 => "gfx700",
AmdgpuGfxVersion::Gfx801 => "gfx801",
AmdgpuGfxVersion::Gfx802 => "gfx802",
AmdgpuGfxVersion::Gfx803 => "gfx803",
AmdgpuGfxVersion::Gfx900 => "gfx900",
AmdgpuGfxVersion::Gfx902 => "gfx902",
AmdgpuGfxVersion::Gfx906 => "gfx906",
AmdgpuGfxVersion::Gfx908 => "gfx908",
AmdgpuGfxVersion::Gfx90a => "gfx90a",
AmdgpuGfxVersion::Gfx1010 => "gfx1010",
AmdgpuGfxVersion::Gfx1030 => "gfx1030",
AmdgpuGfxVersion::Gfx1100 => "gfx1100",
AmdgpuGfxVersion::Gfx1150 => "gfx1150",
_ => "gfx900",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AmdgpuMemOp {
SLoadDword,
SStoreDword,
FlatLoad,
FlatStore,
BufferLoad,
BufferStore,
ScratchLoad,
ScratchStore,
GlobalLoad,
GlobalStore,
DsRead,
DsWrite,
}
impl AmdgpuMemOp {
pub fn is_load(self) -> bool {
matches!(
self,
AmdgpuMemOp::SLoadDword
| AmdgpuMemOp::FlatLoad
| AmdgpuMemOp::BufferLoad
| AmdgpuMemOp::ScratchLoad
| AmdgpuMemOp::GlobalLoad
| AmdgpuMemOp::DsRead
)
}
pub fn is_store(self) -> bool {
!self.is_load()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AmdgpuImageOp {
Load,
LoadMip,
LoadPck,
Store,
StoreMip,
StorePck,
Sample,
SampleB,
SampleD,
SampleL,
SampleC,
SampleCl,
SampleCd,
Gather4,
Gather4B,
Gather4C,
GetResinfo,
AtomicSwap,
AtomicAdd,
AtomicMin,
AtomicMax,
}
impl AmdgpuImageOp {
pub fn is_atomic(self) -> bool {
matches!(
self,
AmdgpuImageOp::AtomicSwap
| AmdgpuImageOp::AtomicAdd
| AmdgpuImageOp::AtomicMin
| AmdgpuImageOp::AtomicMax
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AmdgpuExportTarget {
Param0,
Param1,
Param2,
Param3,
Param4,
Param5,
Param6,
Param7,
Pos0,
Pos1,
Pos2,
Pos3,
Mrt0,
Mrt1,
Mrt2,
Mrt3,
Mrt4,
Mrt5,
Mrt6,
Mrt7,
MrtZ,
Null,
}
impl AmdgpuExportTarget {
pub fn from_index(idx: u32) -> Option<AmdgpuExportTarget> {
match idx {
0 => Some(AmdgpuExportTarget::Param0),
1 => Some(AmdgpuExportTarget::Param1),
2 => Some(AmdgpuExportTarget::Param2),
3 => Some(AmdgpuExportTarget::Param3),
4 => Some(AmdgpuExportTarget::Param4),
5 => Some(AmdgpuExportTarget::Param5),
6 => Some(AmdgpuExportTarget::Param6),
7 => Some(AmdgpuExportTarget::Param7),
12 => Some(AmdgpuExportTarget::Pos0),
13 => Some(AmdgpuExportTarget::Pos1),
14 => Some(AmdgpuExportTarget::Pos2),
15 => Some(AmdgpuExportTarget::Pos3),
16 => Some(AmdgpuExportTarget::Mrt0),
17 => Some(AmdgpuExportTarget::Mrt1),
18 => Some(AmdgpuExportTarget::Mrt2),
19 => Some(AmdgpuExportTarget::Mrt3),
20 => Some(AmdgpuExportTarget::Mrt4),
21 => Some(AmdgpuExportTarget::Mrt5),
22 => Some(AmdgpuExportTarget::Mrt6),
23 => Some(AmdgpuExportTarget::Mrt7),
32 => Some(AmdgpuExportTarget::MrtZ),
_ => None,
}
}
}
pub struct AmdgpuFullInstructionSelector {
pub gen: AmdgpuGfxVersion,
pub wave32: bool,
pub vreg_map: HashMap<usize, VirtReg>,
pub sreg_map: HashMap<usize, VirtReg>,
pub vcc_in_use: bool,
pub mbb: MachineBasicBlock,
pub func_name: String,
}
impl AmdgpuFullInstructionSelector {
pub fn new(gen: AmdgpuGfxVersion) -> Self {
let wave32 = gen.supports_wave32();
AmdgpuFullInstructionSelector {
gen,
wave32,
vreg_map: HashMap::new(),
sreg_map: HashMap::new(),
vcc_in_use: false,
mbb: MachineBasicBlock {
name: String::new(),
instructions: Vec::new(),
successors: Vec::new(),
},
func_name: String::new(),
}
}
pub fn lower_s_add_u32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SAddU32 as u32)
}
pub fn lower_s_sub_u32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SSubU32 as u32)
}
pub fn lower_s_and_b32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SAndB32 as u32)
}
pub fn lower_s_or_b32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SOrB32 as u32)
}
pub fn lower_s_xor_b32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SXorB32 as u32)
}
pub fn lower_s_lshl_b32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SLshlB32 as u32)
}
pub fn lower_s_lshr_b32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SLshrB32 as u32)
}
pub fn lower_s_ashr_i32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SAshrI32 as u32)
}
pub fn lower_s_mul_i32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SMulI32 as u32)
}
pub fn lower_s_mov_b32(&self, inst: &Value) -> MachineInstr {
self.lower_one_src(inst, AmdgpuOpcode::SMovB32 as u32)
}
pub fn lower_s_mov_b64(&self, inst: &Value) -> MachineInstr {
self.lower_one_src(inst, AmdgpuOpcode::SMovB64 as u32)
}
pub fn lower_s_not_b32(&self, inst: &Value) -> MachineInstr {
self.lower_one_src(inst, AmdgpuOpcode::SNotB32 as u32)
}
pub fn lower_s_brev_b32(&self, inst: &Value) -> MachineInstr {
self.lower_one_src(inst, AmdgpuOpcode::SBrevB32 as u32)
}
pub fn lower_s_abs_i32(&self, inst: &Value) -> MachineInstr {
self.lower_one_src(inst, AmdgpuOpcode::SAbsI32 as u32)
}
pub fn lower_cmp_eq_i32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SCmpEqI32 as u32)
}
pub fn lower_cmp_gt_i32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SCmpGtI32 as u32)
}
pub fn lower_cmp_lt_i32(&self, inst: &Value) -> MachineInstr {
self.lower_two_src(inst, AmdgpuOpcode::SCmpLtI32 as u32)
}
pub fn lower_s_movk_i32(&self, inst: &Value, imm: i16) -> MachineInstr {
let sdst: u32 = self.get_or_create_sreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::SMovkI32 as u32);
mi.push_reg(sdst);
mi.push_imm(imm as i64);
mi.def = Some(sdst);
mi
}
pub fn lower_s_nop(&self) -> MachineInstr {
MachineInstr::new(AmdgpuOpcode::SNop as u32)
}
pub fn lower_s_waitcnt(&self) -> MachineInstr {
MachineInstr::new(AmdgpuOpcode::SWaitcnt as u32)
}
pub fn lower_s_branch(&self, target: &str) -> MachineInstr {
let mut mi = MachineInstr::new(AmdgpuOpcode::SBranch as u32);
mi.push_label(target);
mi
}
pub fn lower_s_endpgm(&self) -> MachineInstr {
MachineInstr::new(AmdgpuOpcode::SEndpgm as u32)
}
pub fn lower_v_mov_b32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VMovB32 as u32)
}
pub fn lower_v_add_f32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VAddF32 as u32)
}
pub fn lower_v_sub_f32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VSubF32 as u32)
}
pub fn lower_v_mul_f32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VMulF32 as u32)
}
pub fn lower_v_mac_f32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VMacF32 as u32)
}
pub fn lower_v_min_f32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VMinF32 as u32)
}
pub fn lower_v_max_f32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VMaxF32 as u32)
}
pub fn lower_v_and_b32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VAndB32 as u32)
}
pub fn lower_v_or_b32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VOrB32 as u32)
}
pub fn lower_v_xor_b32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VXorB32 as u32)
}
pub fn lower_v_lshl_b32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VLshlB32 as u32)
}
pub fn lower_v_lshr_b32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VLshrB32 as u32)
}
pub fn lower_v_ashr_i32(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VAshrI32 as u32)
}
pub fn lower_v_rcp_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VRcpF32 as u32)
}
pub fn lower_v_rsq_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VRsqF32 as u32)
}
pub fn lower_v_sqrt_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VSqrtF32 as u32)
}
pub fn lower_v_log_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VLogF32 as u32)
}
pub fn lower_v_exp_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VExpF32 as u32)
}
pub fn lower_v_cos_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VCosF32 as u32)
}
pub fn lower_v_sin_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VSinF32 as u32)
}
pub fn lower_v_cvt_f32_i32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VCvtF32I32 as u32)
}
pub fn lower_v_cvt_i32_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VCvtI32F32 as u32)
}
pub fn lower_v_floor_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VFloorF32 as u32)
}
pub fn lower_v_ceil_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VCeilF32 as u32)
}
pub fn lower_v_trunc_f32(&self, inst: &Value) -> MachineInstr {
self.lower_one_vreg(inst, AmdgpuOpcode::VTruncF32 as u32)
}
pub fn lower_v_cmp_f32_eq(&self, inst: &Value) -> MachineInstr {
self.lower_vopc(inst, AmdgpuOpcode::VCmpF32Eq as u32)
}
pub fn lower_v_cmp_f32_gt(&self, inst: &Value) -> MachineInstr {
self.lower_vopc(inst, AmdgpuOpcode::VCmpF32Gt as u32)
}
pub fn lower_v_cmp_f32_lt(&self, inst: &Value) -> MachineInstr {
self.lower_vopc(inst, AmdgpuOpcode::VCmpF32Lt as u32)
}
pub fn lower_v_cmp_u32_eq(&self, inst: &Value) -> MachineInstr {
self.lower_vopc(inst, AmdgpuOpcode::VCmpU32Eq as u32)
}
pub fn lower_v_add_f64_vop3(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::VAddF64 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.def = Some(vdst);
mi
}
pub fn lower_v_mul_f64_vop3(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::VMulF64 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.def = Some(vdst);
mi
}
pub fn lower_v_fma_f32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let src2: u32 = self.get_vreg(inst, 2);
let mut mi = MachineInstr::new(AmdgpuOpcode::VFmaF32 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.push_reg(src2);
mi.def = Some(vdst);
mi
}
pub fn lower_v_fma_f64(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let src2: u32 = self.get_vreg(inst, 2);
let mut mi = MachineInstr::new(AmdgpuOpcode::VFmaF64 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.push_reg(src2);
mi.def = Some(vdst);
mi
}
pub fn lower_v_pk_add_f16(&self, inst: &Value) -> MachineInstr {
self.lower_vop3p(inst, AmdgpuOpcode::VPkAddF16 as u32)
}
pub fn lower_v_pk_mul_f16(&self, inst: &Value) -> MachineInstr {
self.lower_vop3p(inst, AmdgpuOpcode::VPkMulF16 as u32)
}
pub fn lower_v_pk_fma_f16(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let src2: u32 = self.get_vreg(inst, 2);
let mut mi = MachineInstr::new(AmdgpuOpcode::VPkFmaF16 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.push_reg(src2);
mi.def = Some(vdst);
mi
}
pub fn lower_v_pk_min_f16(&self, inst: &Value) -> MachineInstr {
self.lower_vop3p(inst, AmdgpuOpcode::VPkMinF16 as u32)
}
pub fn lower_v_pk_max_f16(&self, inst: &Value) -> MachineInstr {
self.lower_vop3p(inst, AmdgpuOpcode::VPkMaxF16 as u32)
}
pub fn lower_s_load_dword(&self, inst: &Value) -> MachineInstr {
let sdst: u32 = self.get_or_create_sreg(inst);
let sbase: u32 = self.get_sreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::SLoadDword as u32);
mi.push_reg(sdst);
mi.push_reg(sbase);
mi.push_imm(0);
mi.def = Some(sdst);
mi
}
pub fn lower_s_load_dwordx2(&self, inst: &Value) -> MachineInstr {
let sdst: u32 = self.get_or_create_sreg(inst);
let sbase: u32 = self.get_sreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::SLoadDwordX2 as u32);
mi.push_reg(sdst);
mi.push_reg(sbase);
mi.push_imm(0);
mi.def = Some(sdst);
mi
}
pub fn lower_s_store_dword(&self, inst: &Value) -> MachineInstr {
let sdata: u32 = self.get_sreg(inst, 0);
let sbase: u32 = self.get_sreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::SStoreDword as u32);
mi.push_reg(sdata);
mi.push_reg(sbase);
mi.push_imm(0);
mi
}
pub fn lower_flat_load_dword(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let addr: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::FlatLoadDword as u32);
mi.push_reg(vdst);
mi.push_reg(addr);
mi.def = Some(vdst);
mi
}
pub fn lower_flat_store_dword(&self, inst: &Value) -> MachineInstr {
let vdata: u32 = self.get_vreg(inst, 0);
let addr: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::FlatStoreDword as u32);
mi.push_reg(vdata);
mi.push_reg(addr);
mi
}
pub fn lower_global_load_dword(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let addr: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::GlobalLoadDword as u32);
mi.push_reg(vdst);
mi.push_reg(addr);
mi.push_imm(0);
mi.def = Some(vdst);
mi
}
pub fn lower_global_store_dword(&self, inst: &Value) -> MachineInstr {
let vdata: u32 = self.get_vreg(inst, 0);
let addr: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::GlobalStoreDword as u32);
mi.push_reg(vdata);
mi.push_reg(addr);
mi.push_imm(0);
mi
}
pub fn lower_ds_write_b32(&self, inst: &Value) -> MachineInstr {
let vdata: u32 = self.get_vreg(inst, 0);
let addr: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::DsWriteB32 as u32);
mi.push_reg(vdata);
mi.push_reg(addr);
mi
}
pub fn lower_ds_read_b32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let addr: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::DsReadB32 as u32);
mi.push_reg(vdst);
mi.push_reg(addr);
mi.def = Some(vdst);
mi
}
pub fn lower_ds_write_b64(&self, inst: &Value) -> MachineInstr {
let vdata: u32 = self.get_vreg(inst, 0);
let addr: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::DsWriteB64 as u32);
mi.push_reg(vdata);
mi.push_reg(addr);
mi
}
pub fn lower_ds_add_u32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let addr: u32 = self.get_vreg(inst, 0);
let vdata: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::DsAddU32 as u32);
mi.push_reg(vdst);
mi.push_reg(addr);
mi.push_reg(vdata);
mi.def = Some(vdst);
mi
}
pub fn lower_ds_swizzle_b32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::DsSwizzleB32 as u32);
mi.push_reg(vdst);
mi.push_reg(src);
mi.def = Some(vdst);
mi
}
pub fn lower_flat_atomic_add(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let addr: u32 = self.get_vreg(inst, 0);
let vdata: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::FlatAtomicAdd as u32);
mi.push_reg(vdst);
mi.push_reg(addr);
mi.push_reg(vdata);
mi.def = Some(vdst);
mi
}
pub fn lower_global_atomic_add(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let addr: u32 = self.get_vreg(inst, 0);
let vdata: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::GlobalAtomicAdd as u32);
mi.push_reg(vdst);
mi.push_reg(addr);
mi.push_reg(vdata);
mi.def = Some(vdst);
mi
}
pub fn lower_image_sample(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::ImageSample as u32);
mi.push_reg(vdst);
for i in 0..4.min(inst.operands.len()) {
let op: u32 = self.get_vreg(inst, i);
mi.push_reg(op);
}
mi.def = Some(vdst);
mi
}
pub fn lower_image_load(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::ImageLoad as u32);
mi.push_reg(vdst);
for i in 0..4.min(inst.operands.len()) {
mi.push_reg(self.get_vreg(inst, i));
}
mi.def = Some(vdst);
mi
}
pub fn lower_image_store(&self, inst: &Value) -> MachineInstr {
let mut mi = MachineInstr::new(AmdgpuOpcode::ImageStore as u32);
for i in 0..inst.operands.len().min(4) {
mi.push_reg(self.get_vreg(inst, i));
}
mi
}
pub fn lower_image_gather4(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::ImageGather4 as u32);
mi.push_reg(vdst);
for i in 0..4.min(inst.operands.len()) {
mi.push_reg(self.get_vreg(inst, i));
}
mi.def = Some(vdst);
mi
}
pub fn lower_image_get_resinfo(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::ImageGetResinfo as u32);
mi.push_reg(vdst);
mi.def = Some(vdst);
mi
}
pub fn lower_exp(&self, inst: &Value, target: AmdgpuExportTarget) -> MachineInstr {
let mut mi = MachineInstr::new(AmdgpuOpcode::Exp as u32);
for i in 0..4.min(inst.operands.len()) {
mi.push_reg(self.get_vreg(inst, i));
}
mi
}
pub fn lower_exp_null(&self) -> MachineInstr {
MachineInstr::new(AmdgpuOpcode::ExpNull as u32)
}
pub fn lower_v_interp_p1_f32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::VInterpP1F32 as u32);
mi.push_reg(vdst);
if inst.operands.len() >= 1 {
mi.push_reg(self.get_vreg(inst, 0));
}
mi.def = Some(vdst);
mi
}
pub fn lower_v_interp_p2_f32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::VInterpP2F32 as u32);
mi.push_reg(vdst);
if inst.operands.len() >= 2 {
mi.push_reg(self.get_vreg(inst, 0));
mi.push_reg(self.get_vreg(inst, 1));
}
mi.def = Some(vdst);
mi
}
pub fn lower_v_interp_mov_f32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::VInterpMovF32 as u32);
mi.push_reg(vdst);
if inst.operands.len() >= 1 {
mi.push_reg(self.get_vreg(inst, 0));
}
mi.def = Some(vdst);
mi
}
pub fn lower_v_mov_dpp(
&self,
inst: &Value,
row_mask: u32,
bank_mask: u32,
bound_ctrl: bool,
) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::VMovB32 as u32);
mi.push_reg(vdst);
mi.push_reg(src);
mi.push_imm(row_mask as i64);
mi.push_imm(bank_mask as i64);
if bound_ctrl {
mi.push_imm(1);
}
mi.def = Some(vdst);
mi
}
pub fn lower_v_mov_sdwa(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::VMovB32 as u32);
mi.push_reg(vdst);
mi.push_reg(src);
mi.def = Some(vdst);
mi
}
pub fn lower_v_dual_issue(&self, inst1: &Value, inst2: &Value) -> Vec<MachineInstr> {
let mi1 = self.lower_vop2(inst1, AmdgpuOpcode::VAddF32 as u32);
let mi2 = self.lower_vop2(inst2, AmdgpuOpcode::VMulF32 as u32);
vec![mi1, mi2]
}
pub fn lower_v_cndmask_b32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::VCndmaskB32 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.def = Some(vdst);
mi
}
pub fn lower_v_swap_b32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::VSwapB32 as u32);
mi.push_reg(vdst);
mi.push_reg(src);
mi.def = Some(vdst);
mi
}
pub fn lower_v_add_f16(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VAddF16 as u32)
}
pub fn lower_v_sub_f16(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VSubF16 as u32)
}
pub fn lower_v_mul_f16(&self, inst: &Value) -> MachineInstr {
self.lower_vop2(inst, AmdgpuOpcode::VMulF16 as u32)
}
pub fn lower_v_fma_f16(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let src2: u32 = self.get_vreg(inst, 2);
let mut mi = MachineInstr::new(AmdgpuOpcode::VFmaF16 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.push_reg(src2);
mi.def = Some(vdst);
mi
}
pub fn lower_v_mad_mix_f32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let src2: u32 = self.get_vreg(inst, 2);
let mut mi = MachineInstr::new(AmdgpuOpcode::VMadMixF32 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.push_reg(src2);
mi.def = Some(vdst);
mi
}
pub fn lower_buffer_load_dword(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let mut mi = MachineInstr::new(AmdgpuOpcode::SBufferLoadDword as u32);
mi.push_reg(vdst);
for i in 0..inst.operands.len().min(3) {
mi.push_reg(self.get_vreg(inst, i));
}
mi.push_imm(0);
mi.def = Some(vdst);
mi
}
pub fn lower_buffer_store_dword(&self, inst: &Value) -> MachineInstr {
let vdata: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::SBufferStoreDword as u32);
mi.push_reg(vdata);
for i in 1..inst.operands.len().min(3) {
mi.push_reg(self.get_vreg(inst, i));
}
mi.push_imm(0);
mi
}
pub fn lower_scratch_load_dword(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let addr: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::ScratchLoadDword as u32);
mi.push_reg(vdst);
mi.push_reg(addr);
mi.push_imm(0);
mi.def = Some(vdst);
mi
}
pub fn lower_scratch_store_dword(&self, inst: &Value) -> MachineInstr {
let vdata: u32 = self.get_vreg(inst, 0);
let addr: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(AmdgpuOpcode::ScratchStoreDword as u32);
mi.push_reg(vdata);
mi.push_reg(addr);
mi.push_imm(0);
mi
}
pub fn lower_v_readfirstlane_b32(&self, inst: &Value) -> MachineInstr {
let sdst: u32 = self.get_or_create_sreg(inst);
let src: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(AmdgpuOpcode::VReadfirstlaneB32 as u32);
mi.push_reg(sdst);
mi.push_reg(src);
mi.def = Some(sdst);
mi
}
pub fn lower_s_dcache_inv(&self) -> MachineInstr {
MachineInstr::new(AmdgpuOpcode::SDcacheInv as u32)
}
pub fn lower_v_perm_b32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let src2: u32 = self.get_vreg(inst, 2);
let mut mi = MachineInstr::new(AmdgpuOpcode::VPermB32 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.push_reg(src2);
mi.def = Some(vdst);
mi
}
pub fn lower_v_bfe_u32(&self, inst: &Value) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let src2: u32 = self.get_vreg(inst, 2);
let mut mi = MachineInstr::new(AmdgpuOpcode::VBfeU32 as u32);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.push_reg(src2);
mi.def = Some(vdst);
mi
}
fn lower_two_src(&self, inst: &Value, opcode: u32) -> MachineInstr {
let sdst: u32 = self.get_or_create_sreg(inst);
let src0: u32 = self.get_sreg(inst, 0);
let src1: u32 = self.get_sreg(inst, 1);
let mut mi = MachineInstr::new(opcode);
mi.push_reg(sdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.def = Some(sdst);
mi
}
fn lower_one_src(&self, inst: &Value, opcode: u32) -> MachineInstr {
let sdst: u32 = self.get_or_create_sreg(inst);
let src0: u32 = self.get_sreg(inst, 0);
let mut mi = MachineInstr::new(opcode);
mi.push_reg(sdst);
mi.push_reg(src0);
mi.def = Some(sdst);
mi
}
fn lower_one_vreg(&self, inst: &Value, opcode: u32) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let mut mi = MachineInstr::new(opcode);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.def = Some(vdst);
mi
}
fn lower_vop2(&self, inst: &Value, opcode: u32) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(opcode);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.def = Some(vdst);
mi
}
fn lower_vopc(&self, inst: &Value, opcode: u32) -> MachineInstr {
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(opcode);
mi.push_reg(src0);
mi.push_reg(src1);
mi
}
fn lower_vop3p(&self, inst: &Value, opcode: u32) -> MachineInstr {
let vdst: u32 = self.get_or_create_vreg(inst);
let src0: u32 = self.get_vreg(inst, 0);
let src1: u32 = self.get_vreg(inst, 1);
let mut mi = MachineInstr::new(opcode);
mi.push_reg(vdst);
mi.push_reg(src0);
mi.push_reg(src1);
mi.def = Some(vdst);
mi
}
fn get_or_create_vreg(&self, inst: &Value) -> VirtReg {
*self.vreg_map.get(&(inst.vid as usize)).unwrap_or(&0)
}
fn get_or_create_sreg(&self, inst: &Value) -> VirtReg {
*self.sreg_map.get(&(inst.vid as usize)).unwrap_or(&0)
}
fn get_vreg(&self, inst: &Value, idx: usize) -> VirtReg {
if idx >= inst.operands.len() {
return 0;
}
let op_ref = &inst.operands[idx];
let op = op_ref.borrow();
*self.vreg_map.get(&(op.vid as usize)).unwrap_or(&0)
}
fn get_sreg(&self, inst: &Value, idx: usize) -> VirtReg {
if idx >= inst.operands.len() {
return 0;
}
let op_ref = &inst.operands[idx];
let op = op_ref.borrow();
*self.sreg_map.get(&(op.vid as usize)).unwrap_or(&0)
}
}
pub struct AmdgpuFeatureQuery;
impl AmdgpuFeatureQuery {
pub fn supports_fp64(gen: AmdgpuGfxVersion) -> bool {
gen >= AmdgpuGfxVersion::Gfx700
}
pub fn supports_fp16(gen: AmdgpuGfxVersion) -> bool {
gen >= AmdgpuGfxVersion::Gfx803
}
pub fn supports_packed_math(gen: AmdgpuGfxVersion) -> bool {
gen >= AmdgpuGfxVersion::Gfx900
}
pub fn supports_sdwa(gen: AmdgpuGfxVersion) -> bool {
gen >= AmdgpuGfxVersion::Gfx801
}
pub fn supports_dpp(gen: AmdgpuGfxVersion) -> bool {
gen >= AmdgpuGfxVersion::Gfx801
}
pub fn supports_image_ops(gen: AmdgpuGfxVersion) -> bool {
true }
pub fn supports_flat_addressing(gen: AmdgpuGfxVersion) -> bool {
gen >= AmdgpuGfxVersion::Gfx700
}
pub fn supports_buffer_atomics(gen: AmdgpuGfxVersion) -> bool {
gen >= AmdgpuGfxVersion::Gfx803
}
pub fn max_num_sgprs(gen: AmdgpuGfxVersion) -> u32 {
match gen {
AmdgpuGfxVersion::Gfx600 | AmdgpuGfxVersion::Gfx601 => 104,
AmdgpuGfxVersion::Gfx700
| AmdgpuGfxVersion::Gfx701
| AmdgpuGfxVersion::Gfx702
| AmdgpuGfxVersion::Gfx703
| AmdgpuGfxVersion::Gfx704 => 104,
AmdgpuGfxVersion::Gfx801
| AmdgpuGfxVersion::Gfx802
| AmdgpuGfxVersion::Gfx803
| AmdgpuGfxVersion::Gfx805
| AmdgpuGfxVersion::Gfx810 => 104,
_ => 106,
}
}
pub fn max_num_vgprs(gen: AmdgpuGfxVersion) -> u32 {
256
}
pub fn lds_size_bytes(gen: AmdgpuGfxVersion) -> u32 {
65536
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generation_is_gcn() {
assert!(AmdgpuGfxVersion::Gfx900.is_gcn());
assert!(AmdgpuGfxVersion::Gfx803.is_gcn());
assert!(!AmdgpuGfxVersion::Gfx1010.is_gcn());
assert!(!AmdgpuGfxVersion::Gfx1100.is_gcn());
}
#[test]
fn test_generation_is_rdna() {
assert!(AmdgpuGfxVersion::Gfx1010.is_rdna());
assert!(!AmdgpuGfxVersion::Gfx900.is_rdna());
}
#[test]
fn test_wave32_support() {
assert!(AmdgpuGfxVersion::Gfx1010.supports_wave32());
assert!(!AmdgpuGfxVersion::Gfx900.supports_wave32());
}
#[test]
fn test_vopd_support() {
assert!(AmdgpuGfxVersion::Gfx1100.supports_vopd());
assert!(!AmdgpuGfxVersion::Gfx1010.supports_vopd());
}
#[test]
fn test_mem_op_is_load() {
assert!(AmdgpuMemOp::FlatLoad.is_load());
assert!(!AmdgpuMemOp::FlatStore.is_load());
}
#[test]
fn test_export_target_from_index() {
assert_eq!(
AmdgpuExportTarget::from_index(0),
Some(AmdgpuExportTarget::Param0)
);
assert_eq!(
AmdgpuExportTarget::from_index(32),
Some(AmdgpuExportTarget::MrtZ)
);
assert!(AmdgpuExportTarget::from_index(99).is_none());
}
#[test]
fn test_image_op_is_atomic() {
assert!(AmdgpuImageOp::AtomicAdd.is_atomic());
assert!(!AmdgpuImageOp::Sample.is_atomic());
}
#[test]
fn test_selector_creation() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
assert!(!sel.wave32);
assert_eq!(sel.gen, AmdgpuGfxVersion::Gfx900);
}
#[test]
fn test_feature_fp64() {
assert!(AmdgpuFeatureQuery::supports_fp64(AmdgpuGfxVersion::Gfx900));
assert!(!AmdgpuFeatureQuery::supports_fp64(AmdgpuGfxVersion::Gfx600));
}
#[test]
fn test_feature_flat_addressing() {
assert!(AmdgpuFeatureQuery::supports_flat_addressing(
AmdgpuGfxVersion::Gfx900
));
}
#[test]
fn test_max_sgprs() {
assert_eq!(
AmdgpuFeatureQuery::max_num_sgprs(AmdgpuGfxVersion::Gfx900),
106
);
assert_eq!(
AmdgpuFeatureQuery::max_num_sgprs(AmdgpuGfxVersion::Gfx700),
104
);
}
#[test]
fn test_base_isa_name() {
assert_eq!(AmdgpuGfxVersion::Gfx900.base_isa_name(), "gfx900");
assert_eq!(AmdgpuGfxVersion::Gfx1010.base_isa_name(), "gfx1010");
assert_eq!(AmdgpuGfxVersion::Gfx1100.base_isa_name(), "gfx1100");
}
#[test]
fn test_is_rdna3() {
assert!(AmdgpuGfxVersion::Gfx1100.is_rdna3());
assert!(AmdgpuGfxVersion::Gfx1150.is_rdna3());
assert!(!AmdgpuGfxVersion::Gfx1010.is_rdna3());
assert!(!AmdgpuGfxVersion::Gfx900.is_rdna3());
}
#[test]
fn test_wavefront_size_gcn() {
assert_eq!(AmdgpuGfxVersion::Gfx900.wavefront_size(), 64);
}
#[test]
fn test_wavefront_size_rdna() {
assert_eq!(AmdgpuGfxVersion::Gfx1010.wavefront_size(), 32);
}
#[test]
fn test_all_generations_isa_names() {
let gens = &[
(AmdgpuGfxVersion::Gfx600, "gfx600"),
(AmdgpuGfxVersion::Gfx700, "gfx700"),
(AmdgpuGfxVersion::Gfx801, "gfx801"),
(AmdgpuGfxVersion::Gfx900, "gfx900"),
(AmdgpuGfxVersion::Gfx1010, "gfx1010"),
(AmdgpuGfxVersion::Gfx1030, "gfx1030"),
(AmdgpuGfxVersion::Gfx1100, "gfx1100"),
];
for (gen, name) in gens {
assert_eq!(gen.base_isa_name(), *name);
}
}
#[test]
fn test_scalar_add() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_add_u32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SAddU32 as u32);
}
#[test]
fn test_scalar_mov_b32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_mov_b32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SMovB32 as u32);
}
#[test]
fn test_scalar_cmp_eq() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_cmp_eq_i32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SCmpEqI32 as u32);
}
#[test]
fn test_vector_add_f32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_add_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VAddF32 as u32);
}
#[test]
fn test_vector_mul_f32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_mul_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VMulF32 as u32);
}
#[test]
fn test_vector_cmp_f32_eq() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_cmp_f32_eq(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VCmpF32Eq as u32);
}
#[test]
fn test_vector_sqrt_f32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_sqrt_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VSqrtF32 as u32);
}
#[test]
fn test_vector_rcp_f32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_rcp_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VRcpF32 as u32);
}
#[test]
fn test_vop3_fma_f32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_fma_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VFmaF32 as u32);
}
#[test]
fn test_vop3p_pk_add_f16() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_pk_add_f16(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VPkAddF16 as u32);
}
#[test]
fn test_vop3p_pk_fma_f16() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_pk_fma_f16(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VPkFmaF16 as u32);
}
#[test]
fn test_smem_load_dword() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_load_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SLoadDword as u32);
}
#[test]
fn test_smem_store_dword() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_store_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SStoreDword as u32);
}
#[test]
fn test_flat_load_dword() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_flat_load_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::FlatLoadDword as u32);
}
#[test]
fn test_flat_store_dword() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_flat_store_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::FlatStoreDword as u32);
}
#[test]
fn test_global_load_dword() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_global_load_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::GlobalLoadDword as u32);
}
#[test]
fn test_ds_read_write() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_ds_read_b32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::DsReadB32 as u32);
let mi2 = sel.lower_ds_write_b32(&crate::value::Value::placeholder());
assert_eq!(mi2.opcode, AmdgpuOpcode::DsWriteB32 as u32);
}
#[test]
fn test_flat_atomic_add() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_flat_atomic_add(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::FlatAtomicAdd as u32);
}
#[test]
fn test_image_load_sample() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_image_load(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::ImageLoad as u32);
let mi2 = sel.lower_image_sample(&crate::value::Value::placeholder());
assert_eq!(mi2.opcode, AmdgpuOpcode::ImageSample as u32);
}
#[test]
fn test_exp_null() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_exp_null();
assert_eq!(mi.opcode, AmdgpuOpcode::ExpNull as u32);
}
#[test]
fn test_interpolators() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_interp_p1_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VInterpP1F32 as u32);
let mi2 = sel.lower_v_interp_p2_f32(&crate::value::Value::placeholder());
assert_eq!(mi2.opcode, AmdgpuOpcode::VInterpP2F32 as u32);
}
#[test]
fn test_scratch_ops() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_scratch_load_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::ScratchLoadDword as u32);
let mi2 = sel.lower_scratch_store_dword(&crate::value::Value::placeholder());
assert_eq!(mi2.opcode, AmdgpuOpcode::ScratchStoreDword as u32);
}
#[test]
fn test_buffer_load_dword() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_buffer_load_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SBufferLoadDword as u32);
}
#[test]
fn test_v_readfirstlane() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_readfirstlane_b32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VReadfirstlaneB32 as u32);
}
#[test]
fn test_v_cndmask() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_cndmask_b32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VCndmaskB32 as u32);
}
#[test]
fn test_v_perm_bfe() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_perm_b32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VPermB32 as u32);
let mi2 = sel.lower_v_bfe_u32(&crate::value::Value::placeholder());
assert_eq!(mi2.opcode, AmdgpuOpcode::VBfeU32 as u32);
}
#[test]
fn test_f16_ops() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_add_f16(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VAddF16 as u32);
let mi2 = sel.lower_v_mul_f16(&crate::value::Value::placeholder());
assert_eq!(mi2.opcode, AmdgpuOpcode::VMulF16 as u32);
}
#[test]
fn test_mad_mix() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_mad_mix_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VMadMixF32 as u32);
}
#[test]
fn test_feature_sdwa_dpp() {
assert!(AmdgpuFeatureQuery::supports_sdwa(AmdgpuGfxVersion::Gfx900));
assert!(AmdgpuFeatureQuery::supports_dpp(AmdgpuGfxVersion::Gfx900));
}
#[test]
fn test_feature_buffer_atomics() {
assert!(AmdgpuFeatureQuery::supports_buffer_atomics(
AmdgpuGfxVersion::Gfx900
));
}
#[test]
fn test_feature_packed_math() {
assert!(AmdgpuFeatureQuery::supports_packed_math(
AmdgpuGfxVersion::Gfx900
));
}
#[test]
fn test_export_target_from_index_all_params() {
for i in 0..=7 {
assert!(AmdgpuExportTarget::from_index(i).is_some());
}
assert!(AmdgpuExportTarget::from_index(12).is_some());
assert!(AmdgpuExportTarget::from_index(32).is_some());
assert!(AmdgpuExportTarget::from_index(5).unwrap() == AmdgpuExportTarget::Param5);
}
#[test]
fn test_global_atomic_add() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_global_atomic_add(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::GlobalAtomicAdd as u32);
}
#[test]
fn test_ds_add_u32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_ds_add_u32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::DsAddU32 as u32);
}
#[test]
fn test_s_dcache_inv() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_dcache_inv();
assert_eq!(mi.opcode, AmdgpuOpcode::SDcacheInv as u32);
}
#[test]
fn test_v_mov_dpp() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_mov_dpp(&crate::value::Value::placeholder(), 0xF, 0xF, true);
assert_eq!(mi.opcode, AmdgpuOpcode::VMovB32 as u32);
}
#[test]
fn test_v_mov_sdwa() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_mov_sdwa(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VMovB32 as u32);
}
#[test]
fn test_all_generations_covered() {
for gen in &[
AmdgpuGfxVersion::Gfx700,
AmdgpuGfxVersion::Gfx803,
AmdgpuGfxVersion::Gfx900,
AmdgpuGfxVersion::Gfx1010,
AmdgpuGfxVersion::Gfx1100,
] {
let sel = AmdgpuFullInstructionSelector::new(*gen);
assert_eq!(sel.gen, *gen);
}
}
#[test]
fn test_all_generations_is_gcn() {
assert!(AmdgpuGfxVersion::Gfx600.is_gcn());
assert!(AmdgpuGfxVersion::Gfx700.is_gcn());
assert!(AmdgpuGfxVersion::Gfx801.is_gcn());
assert!(AmdgpuGfxVersion::Gfx900.is_gcn());
}
#[test]
fn test_all_generations_is_rdna() {
assert!(AmdgpuGfxVersion::Gfx1010.is_rdna());
assert!(AmdgpuGfxVersion::Gfx1011.is_rdna());
assert!(AmdgpuGfxVersion::Gfx1030.is_rdna());
assert!(!AmdgpuGfxVersion::Gfx900.is_rdna());
}
#[test]
fn test_selector_wave32_default() {
let sel_rdna = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx1010);
assert!(sel_rdna.wave32);
let sel_gcn = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
assert!(!sel_gcn.wave32);
}
#[test]
fn test_image_gather4() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_image_gather4(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::ImageGather4 as u32);
}
#[test]
fn test_image_get_resinfo() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_image_get_resinfo(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::ImageGetResinfo as u32);
}
#[test]
fn test_flat_atomic_operations() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_flat_atomic_add(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::FlatAtomicAdd as u32);
}
#[test]
fn test_ds_swizzle_b32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_ds_swizzle_b32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::DsSwizzleB32 as u32);
}
#[test]
fn test_all_mem_ops_load_store() {
assert!(AmdgpuMemOp::SLoadDword.is_load());
assert!(AmdgpuMemOp::FlatLoad.is_load());
assert!(AmdgpuMemOp::GlobalLoad.is_load());
assert!(AmdgpuMemOp::DsRead.is_load());
assert!(!AmdgpuMemOp::SStoreDword.is_load());
assert!(!AmdgpuMemOp::FlatStore.is_load());
assert!(!AmdgpuMemOp::DsWrite.is_load());
}
#[test]
fn test_image_op_atomic() {
assert!(AmdgpuImageOp::AtomicSwap.is_atomic());
assert!(AmdgpuImageOp::AtomicAdd.is_atomic());
assert!(AmdgpuImageOp::AtomicMin.is_atomic());
assert!(AmdgpuImageOp::AtomicMax.is_atomic());
assert!(!AmdgpuImageOp::Load.is_atomic());
assert!(!AmdgpuImageOp::Sample.is_atomic());
}
#[test]
fn test_export_target_all_positions() {
assert_eq!(
AmdgpuExportTarget::from_index(12),
Some(AmdgpuExportTarget::Pos0)
);
assert_eq!(
AmdgpuExportTarget::from_index(13),
Some(AmdgpuExportTarget::Pos1)
);
assert_eq!(
AmdgpuExportTarget::from_index(14),
Some(AmdgpuExportTarget::Pos2)
);
assert_eq!(
AmdgpuExportTarget::from_index(15),
Some(AmdgpuExportTarget::Pos3)
);
}
#[test]
fn test_export_target_all_mrt() {
assert_eq!(
AmdgpuExportTarget::from_index(16),
Some(AmdgpuExportTarget::Mrt0)
);
assert_eq!(
AmdgpuExportTarget::from_index(20),
Some(AmdgpuExportTarget::Mrt4)
);
assert_eq!(
AmdgpuExportTarget::from_index(23),
Some(AmdgpuExportTarget::Mrt7)
);
}
#[test]
fn test_vop3p_pk_min_max_f16() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_pk_min_f16(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VPkMinF16 as u32);
let mi2 = sel.lower_v_pk_max_f16(&crate::value::Value::placeholder());
assert_eq!(mi2.opcode, AmdgpuOpcode::VPkMaxF16 as u32);
}
#[test]
fn test_s_nop_and_waitcnt() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_nop();
assert_eq!(mi.opcode, AmdgpuOpcode::SNop as u32);
let mi2 = sel.lower_s_waitcnt();
assert_eq!(mi2.opcode, AmdgpuOpcode::SWaitcnt as u32);
}
#[test]
fn test_s_endpgm() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_endpgm();
assert_eq!(mi.opcode, AmdgpuOpcode::SEndpgm as u32);
}
#[test]
fn test_s_abs_brev_not() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi_abs = sel.lower_s_abs_i32(&crate::value::Value::placeholder());
assert_eq!(mi_abs.opcode, AmdgpuOpcode::SAbsI32 as u32);
let mi_brev = sel.lower_s_brev_b32(&crate::value::Value::placeholder());
assert_eq!(mi_brev.opcode, AmdgpuOpcode::SBrevB32 as u32);
let mi_not = sel.lower_s_not_b32(&crate::value::Value::placeholder());
assert_eq!(mi_not.opcode, AmdgpuOpcode::SNotB32 as u32);
}
#[test]
fn test_s_mov_b64() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_mov_b64(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SMovB64 as u32);
}
#[test]
fn test_v_cvt_and_transcendental() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi_ftoi = sel.lower_v_cvt_f32_i32(&crate::value::Value::placeholder());
assert_eq!(mi_ftoi.opcode, AmdgpuOpcode::VCvtF32I32 as u32);
let mi_itof = sel.lower_v_cvt_i32_f32(&crate::value::Value::placeholder());
assert_eq!(mi_itof.opcode, AmdgpuOpcode::VCvtI32F32 as u32);
let mi_cos = sel.lower_v_cos_f32(&crate::value::Value::placeholder());
assert_eq!(mi_cos.opcode, AmdgpuOpcode::VCosF32 as u32);
let mi_sin = sel.lower_v_sin_f32(&crate::value::Value::placeholder());
assert_eq!(mi_sin.opcode, AmdgpuOpcode::VSinF32 as u32);
}
#[test]
fn test_v_floor_ceil_trunc() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi_floor = sel.lower_v_floor_f32(&crate::value::Value::placeholder());
assert_eq!(mi_floor.opcode, AmdgpuOpcode::VFloorF32 as u32);
let mi_ceil = sel.lower_v_ceil_f32(&crate::value::Value::placeholder());
assert_eq!(mi_ceil.opcode, AmdgpuOpcode::VCeilF32 as u32);
let mi_trunc = sel.lower_v_trunc_f32(&crate::value::Value::placeholder());
assert_eq!(mi_trunc.opcode, AmdgpuOpcode::VTruncF32 as u32);
}
#[test]
fn test_v_log_exp() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi_log = sel.lower_v_log_f32(&crate::value::Value::placeholder());
assert_eq!(mi_log.opcode, AmdgpuOpcode::VLogF32 as u32);
let mi_exp = sel.lower_v_exp_f32(&crate::value::Value::placeholder());
assert_eq!(mi_exp.opcode, AmdgpuOpcode::VExpF32 as u32);
}
#[test]
fn test_v_rsq_f32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_rsq_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VRsqF32 as u32);
}
#[test]
fn test_v_addc_subbrev() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_vop2(
&crate::value::Value::placeholder(),
AmdgpuOpcode::VAddcU32 as u32,
);
assert_eq!(mi.opcode, AmdgpuOpcode::VAddcU32 as u32);
}
#[test]
fn test_v_cmp_u32_eq() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_cmp_u32_eq(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VCmpU32Eq as u32);
}
#[test]
fn test_s_load_dwordx2() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_load_dwordx2(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SLoadDwordX2 as u32);
}
#[test]
fn test_ds_write_b64() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_ds_write_b64(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::DsWriteB64 as u32);
}
#[test]
fn test_v_fma_f64() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_fma_f64(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VFmaF64 as u32);
}
#[test]
fn test_v_add_sub_f64_vop3() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_add_f64_vop3(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VAddF64 as u32);
}
#[test]
fn test_s_mul_i32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_s_mul_i32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SMulI32 as u32);
}
#[test]
fn test_image_store() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_image_store(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::ImageStore as u32);
}
#[test]
fn test_v_interp_mov_f32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_interp_mov_f32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VInterpMovF32 as u32);
}
#[test]
fn test_buffer_store_dword() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_buffer_store_dword(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::SBufferStoreDword as u32);
}
#[test]
fn test_v_swap_b32() {
let sel = AmdgpuFullInstructionSelector::new(AmdgpuGfxVersion::Gfx900);
let mi = sel.lower_v_swap_b32(&crate::value::Value::placeholder());
assert_eq!(mi.opcode, AmdgpuOpcode::VSwapB32 as u32);
}
#[test]
fn test_mem_op_is_store() {
assert!(AmdgpuMemOp::SStoreDword.is_store());
assert!(AmdgpuMemOp::FlatStore.is_store());
assert!(AmdgpuMemOp::GlobalStore.is_store());
assert!(AmdgpuMemOp::DsWrite.is_store());
}
#[test]
fn test_feature_fp16() {
assert!(AmdgpuFeatureQuery::supports_fp16(AmdgpuGfxVersion::Gfx900));
assert!(AmdgpuFeatureQuery::supports_fp16(AmdgpuGfxVersion::Gfx1010));
}
#[test]
fn test_max_vgprs() {
assert_eq!(
AmdgpuFeatureQuery::max_num_vgprs(AmdgpuGfxVersion::Gfx900),
256
);
}
#[test]
fn test_lds_size() {
assert_eq!(
AmdgpuFeatureQuery::lds_size_bytes(AmdgpuGfxVersion::Gfx900),
65536
);
}
#[test]
fn test_supported_vopd_dual() {
assert!(AmdgpuGfxVersion::Gfx1100.supports_vopd());
assert!(AmdgpuGfxVersion::Gfx1150.supports_vopd());
assert!(!AmdgpuGfxVersion::Gfx1010.supports_vopd());
assert!(!AmdgpuGfxVersion::Gfx900.supports_vopd());
}
#[test]
fn test_features() {
assert!(AmdgpuFeatureQuery::supports_image_ops(
AmdgpuGfxVersion::Gfx900
));
assert!(AmdgpuFeatureQuery::supports_flat_addressing(
AmdgpuGfxVersion::Gfx900
));
assert!(AmdgpuFeatureQuery::supports_packed_math(
AmdgpuGfxVersion::Gfx900
));
}
}