summaryrefslogtreecommitdiff
path: root/lib/Target/AMDGPU/VOP3Instructions.td
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AMDGPU/VOP3Instructions.td')
-rw-r--r--lib/Target/AMDGPU/VOP3Instructions.td430
1 files changed, 372 insertions, 58 deletions
diff --git a/lib/Target/AMDGPU/VOP3Instructions.td b/lib/Target/AMDGPU/VOP3Instructions.td
index 92ed0706dc01..aedbfa015bf6 100644
--- a/lib/Target/AMDGPU/VOP3Instructions.td
+++ b/lib/Target/AMDGPU/VOP3Instructions.td
@@ -53,6 +53,46 @@ class getVOP3PModPat<VOPProfile P, SDPatternOperator node> {
ret1));
}
+class getVOP3OpSelPat<VOPProfile P, SDPatternOperator node> {
+ list<dag> ret3 = [(set P.DstVT:$vdst,
+ (node (P.Src0VT !if(P.HasClamp, (VOP3OpSel0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp),
+ (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers))),
+ (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers)),
+ (P.Src2VT (VOP3OpSel P.Src2VT:$src2, i32:$src2_modifiers))))];
+
+ list<dag> ret2 = [(set P.DstVT:$vdst,
+ (node !if(P.HasClamp, (P.Src0VT (VOP3OpSel0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp)),
+ (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers))),
+ (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers))))];
+
+ list<dag> ret1 = [(set P.DstVT:$vdst,
+ (node (P.Src0VT (VOP3OpSel0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp))))];
+
+ list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
+ !if(!eq(P.NumSrcArgs, 2), ret2,
+ ret1));
+}
+
+class getVOP3OpSelModPat<VOPProfile P, SDPatternOperator node> {
+ list<dag> ret3 = [(set P.DstVT:$vdst,
+ (node (P.Src0VT !if(P.HasClamp, (VOP3OpSelMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp),
+ (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))),
+ (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers)),
+ (P.Src2VT (VOP3OpSelMods P.Src2VT:$src2, i32:$src2_modifiers))))];
+
+ list<dag> ret2 = [(set P.DstVT:$vdst,
+ (node !if(P.HasClamp, (P.Src0VT (VOP3OpSelMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp)),
+ (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))),
+ (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers))))];
+
+ list<dag> ret1 = [(set P.DstVT:$vdst,
+ (node (P.Src0VT (VOP3OpSelMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp))))];
+
+ list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
+ !if(!eq(P.NumSrcArgs, 2), ret2,
+ ret1));
+}
+
class getVOP3Pat<VOPProfile P, SDPatternOperator node> {
list<dag> ret3 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2))];
list<dag> ret2 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1))];
@@ -62,10 +102,36 @@ class getVOP3Pat<VOPProfile P, SDPatternOperator node> {
ret1));
}
+class getVOP3ClampPat<VOPProfile P, SDPatternOperator node> {
+ list<dag> ret3 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, i1:$clamp))];
+ list<dag> ret2 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, i1:$clamp))];
+ list<dag> ret1 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, i1:$clamp))];
+ list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
+ !if(!eq(P.NumSrcArgs, 2), ret2,
+ ret1));
+}
+
class VOP3Inst<string OpName, VOPProfile P, SDPatternOperator node = null_frag, bit VOP3Only = 0> :
VOP3_Pseudo<OpName, P,
- !if(P.HasModifiers, getVOP3ModPat<P, node>.ret, getVOP3Pat<P, node>.ret),
- VOP3Only>;
+ !if(P.HasOpSel,
+ !if(P.HasModifiers,
+ getVOP3OpSelModPat<P, node>.ret,
+ getVOP3OpSelPat<P, node>.ret),
+ !if(P.HasModifiers,
+ getVOP3ModPat<P, node>.ret,
+ !if(P.HasIntClamp,
+ getVOP3ClampPat<P, node>.ret,
+ getVOP3Pat<P, node>.ret))),
+ VOP3Only, 0, P.HasOpSel> {
+
+ let IntClamp = P.HasIntClamp;
+ let AsmMatchConverter =
+ !if(P.HasOpSel,
+ "cvtVOP3OpSel",
+ !if(!or(P.HasModifiers, !or(P.HasOMod, P.HasIntClamp)),
+ "cvtVOP3",
+ ""));
+}
// Special case for v_div_fmas_{f32|f64}, since it seems to be the
// only VOP instruction that implicitly reads VCC.
@@ -87,10 +153,33 @@ class getVOP3VCC<VOPProfile P, SDPatternOperator node> {
(i1 VCC)))];
}
-class VOP3_Profile<VOPProfile P> : VOPProfile<P.ArgVT> {
+class VOP3Features<bit Clamp, bit OpSel> {
+ bit HasClamp = Clamp;
+ bit HasOpSel = OpSel;
+}
+
+def VOP3_REGULAR : VOP3Features<0, 0>;
+def VOP3_CLAMP : VOP3Features<1, 0>;
+def VOP3_OPSEL : VOP3Features<1, 1>;
+
+class VOP3_Profile<VOPProfile P, VOP3Features Features = VOP3_REGULAR> : VOPProfile<P.ArgVT> {
+
+ let HasClamp = !if(Features.HasClamp, 1, P.HasClamp);
+ let HasOpSel = !if(Features.HasOpSel, 1, P.HasOpSel);
+
// FIXME: Hack to stop printing _e64
let Outs64 = (outs DstRC.RegClass:$vdst);
- let Asm64 = " " # P.Asm64;
+ let Asm64 =
+ " " # !if(Features.HasOpSel,
+ getAsmVOP3OpSel<NumSrcArgs,
+ HasIntClamp,
+ HasSrc0FloatMods,
+ HasSrc1FloatMods,
+ HasSrc2FloatMods>.ret,
+ !if(Features.HasClamp,
+ getAsm64<HasDst, NumSrcArgs, HasIntClamp,
+ HasModifiers, HasOMod, DstVT>.ret,
+ P.Asm64));
}
class VOP3b_Profile<ValueType vt> : VOPProfile<[vt, vt, vt, vt]> {
@@ -112,11 +201,75 @@ def VOP3b_F64_I1_F64_F64_F64 : VOP3b_Profile<f64> {
}
def VOP3b_I64_I1_I32_I32_I64 : VOPProfile<[i64, i32, i32, i64]> {
+ let HasClamp = 1;
+
// FIXME: Hack to stop printing _e64
let DstRC = RegisterOperand<VReg_64>;
let Outs64 = (outs DstRC:$vdst, SReg_64:$sdst);
- let Asm64 = " $vdst, $sdst, $src0, $src1, $src2";
+ let Asm64 = " $vdst, $sdst, $src0, $src1, $src2$clamp";
+}
+
+//===----------------------------------------------------------------------===//
+// VOP3 INTERP
+//===----------------------------------------------------------------------===//
+
+class VOP3Interp<string OpName, VOPProfile P> : VOP3_Pseudo<OpName, P> {
+ let AsmMatchConverter = "cvtVOP3Interp";
+}
+
+def VOP3_INTERP : VOPProfile<[f32, f32, i32, untyped]> {
+ let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
+ Attr:$attr, AttrChan:$attrchan,
+ clampmod:$clamp, omod:$omod);
+
+ let Asm64 = "$vdst, $src0_modifiers, $attr$attrchan$clamp$omod";
+}
+
+def VOP3_INTERP_MOV : VOPProfile<[f32, i32, i32, untyped]> {
+ let Ins64 = (ins InterpSlot:$src0,
+ Attr:$attr, AttrChan:$attrchan,
+ clampmod:$clamp, omod:$omod);
+
+ let Asm64 = "$vdst, $src0, $attr$attrchan$clamp$omod";
+
+ let HasClamp = 1;
+}
+
+class getInterp16Asm <bit HasSrc2, bit HasOMod> {
+ string src2 = !if(HasSrc2, ", $src2_modifiers", "");
+ string omod = !if(HasOMod, "$omod", "");
+ string ret =
+ " $vdst, $src0_modifiers, $attr$attrchan"#src2#"$high$clamp"#omod;
+}
+
+class getInterp16Ins <bit HasSrc2, bit HasOMod,
+ Operand Src0Mod, Operand Src2Mod> {
+ dag ret = !if(HasSrc2,
+ !if(HasOMod,
+ (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
+ Attr:$attr, AttrChan:$attrchan,
+ Src2Mod:$src2_modifiers, VRegSrc_32:$src2,
+ highmod:$high, clampmod:$clamp, omod:$omod),
+ (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
+ Attr:$attr, AttrChan:$attrchan,
+ Src2Mod:$src2_modifiers, VRegSrc_32:$src2,
+ highmod:$high, clampmod:$clamp)
+ ),
+ (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
+ Attr:$attr, AttrChan:$attrchan,
+ highmod:$high, clampmod:$clamp, omod:$omod)
+ );
+}
+
+class VOP3_INTERP16 <list<ValueType> ArgVT> : VOPProfile<ArgVT> {
+
+ let HasOMod = !if(!eq(DstVT.Value, f16.Value), 0, 1);
+ let HasHigh = 1;
+
+ let Outs64 = (outs VGPR_32:$vdst);
+ let Ins64 = getInterp16Ins<HasSrc2, HasOMod, Src0Mod, Src2Mod>.ret;
+ let Asm64 = getInterp16Asm<HasSrc2, HasOMod>.ret;
}
//===----------------------------------------------------------------------===//
@@ -127,8 +280,8 @@ let isCommutable = 1 in {
def V_MAD_LEGACY_F32 : VOP3Inst <"v_mad_legacy_f32", VOP3_Profile<VOP_F32_F32_F32_F32>>;
def V_MAD_F32 : VOP3Inst <"v_mad_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, fmad>;
-def V_MAD_I32_I24 : VOP3Inst <"v_mad_i32_i24", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUmad_i24>;
-def V_MAD_U32_U24 : VOP3Inst <"v_mad_u32_u24", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUmad_u24>;
+def V_MAD_I32_I24 : VOP3Inst <"v_mad_i32_i24", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
+def V_MAD_U32_U24 : VOP3Inst <"v_mad_u32_u24", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
def V_FMA_F32 : VOP3Inst <"v_fma_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, fma>;
def V_FMA_F64 : VOP3Inst <"v_fma_f64", VOP3_Profile<VOP_F64_F64_F64_F64>, fma>;
def V_LERP_U8 : VOP3Inst <"v_lerp_u8", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_lerp>;
@@ -188,10 +341,10 @@ def V_MAX3_U32 : VOP3Inst <"v_max3_u32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDG
def V_MED3_F32 : VOP3Inst <"v_med3_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, AMDGPUfmed3>;
def V_MED3_I32 : VOP3Inst <"v_med3_i32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUsmed3>;
def V_MED3_U32 : VOP3Inst <"v_med3_u32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUumed3>;
-def V_SAD_U8 : VOP3Inst <"v_sad_u8", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_sad_u8>;
-def V_SAD_HI_U8 : VOP3Inst <"v_sad_hi_u8", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_sad_hi_u8>;
-def V_SAD_U16 : VOP3Inst <"v_sad_u16", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_sad_u16>;
-def V_SAD_U32 : VOP3Inst <"v_sad_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
+def V_SAD_U8 : VOP3Inst <"v_sad_u8", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
+def V_SAD_HI_U8 : VOP3Inst <"v_sad_hi_u8", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
+def V_SAD_U16 : VOP3Inst <"v_sad_u16", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
+def V_SAD_U32 : VOP3Inst <"v_sad_u32", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
def V_CVT_PK_U8_F32 : VOP3Inst<"v_cvt_pk_u8_f32", VOP3_Profile<VOP_I32_F32_I32_I32>, int_amdgcn_cvt_pk_u8_f32>;
def V_DIV_FIXUP_F32 : VOP3Inst <"v_div_fixup_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, AMDGPUdiv_fixup>;
@@ -213,10 +366,10 @@ def V_DIV_SCALE_F64 : VOP3_Pseudo <"v_div_scale_f64", VOP3b_F64_I1_F64_F64_F64,
let AsmMatchConverter = "";
}
-def V_MSAD_U8 : VOP3Inst <"v_msad_u8", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_msad_u8>;
+def V_MSAD_U8 : VOP3Inst <"v_msad_u8", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
let Constraints = "@earlyclobber $vdst" in {
-def V_MQSAD_PK_U16_U8 : VOP3Inst <"v_mqsad_pk_u16_u8", VOP3_Profile<VOP_I64_I64_I32_I64>, int_amdgcn_mqsad_pk_u16_u8>;
+def V_MQSAD_PK_U16_U8 : VOP3Inst <"v_mqsad_pk_u16_u8", VOP3_Profile<VOP_I64_I64_I32_I64, VOP3_CLAMP>>;
} // End Constraints = "@earlyclobber $vdst"
def V_TRIG_PREOP_F64 : VOP3Inst <"v_trig_preop_f64", VOP3_Profile<VOP_F64_F64_I32>, AMDGPUtrig_preop> {
@@ -241,13 +394,15 @@ def V_ASHRREV_I64 : VOP3Inst <"v_ashrrev_i64", VOP3_Profile<VOP_I64_I32_I64>>;
let SubtargetPredicate = isCIVI in {
let Constraints = "@earlyclobber $vdst" in {
-def V_QSAD_PK_U16_U8 : VOP3Inst <"v_qsad_pk_u16_u8", VOP3_Profile<VOP_I64_I64_I32_I64>, int_amdgcn_qsad_pk_u16_u8>;
-def V_MQSAD_U32_U8 : VOP3Inst <"v_mqsad_u32_u8", VOP3_Profile<VOP_V4I32_I64_I32_V4I32>, int_amdgcn_mqsad_u32_u8>;
+def V_QSAD_PK_U16_U8 : VOP3Inst <"v_qsad_pk_u16_u8", VOP3_Profile<VOP_I64_I64_I32_I64, VOP3_CLAMP>>;
+def V_MQSAD_U32_U8 : VOP3Inst <"v_mqsad_u32_u8", VOP3_Profile<VOP_V4I32_I64_I32_V4I32, VOP3_CLAMP>>;
} // End Constraints = "@earlyclobber $vdst"
let isCommutable = 1 in {
+let SchedRW = [WriteDouble, WriteSALU] in {
def V_MAD_U64_U32 : VOP3Inst <"v_mad_u64_u32", VOP3b_I64_I1_I32_I32_I64>;
def V_MAD_I64_I32 : VOP3Inst <"v_mad_i64_i32", VOP3b_I64_I1_I32_I32_I64>;
+} // End SchedRW = [WriteDouble, WriteSALU]
} // End isCommutable = 1
} // End SubtargetPredicate = isCIVI
@@ -255,23 +410,42 @@ def V_MAD_I64_I32 : VOP3Inst <"v_mad_i64_i32", VOP3b_I64_I1_I32_I32_I64>;
let SubtargetPredicate = Has16BitInsts in {
-def V_DIV_FIXUP_F16 : VOP3Inst <"v_div_fixup_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUdiv_fixup>;
+let renamedInGFX9 = 1 in {
+def V_DIV_FIXUP_F16 : VOP3Inst <"v_div_fixup_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUdiv_fixup>;
+}
+let SubtargetPredicate = isGFX9 in {
+def V_DIV_FIXUP_F16_gfx9 : VOP3Inst <"v_div_fixup_f16_gfx9", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>>;
+}
let isCommutable = 1 in {
-def V_FMA_F16 : VOP3Inst <"v_fma_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, fma>;
-def V_INTERP_P1LL_F16 : VOP3Inst <"v_interp_p1ll_f16", VOP3_Profile<VOP_F32_F32_F16>>;
-def V_INTERP_P1LV_F16 : VOP3Inst <"v_interp_p1lv_f16", VOP3_Profile<VOP_F32_F32_F16_F16>>;
-def V_INTERP_P2_F16 : VOP3Inst <"v_interp_p2_f16", VOP3_Profile<VOP_F16_F32_F16_F32>>;
-def V_MAD_F16 : VOP3Inst <"v_mad_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, fmad>;
+let renamedInGFX9 = 1 in {
+def V_MAD_F16 : VOP3Inst <"v_mad_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, fmad>;
+def V_MAD_U16 : VOP3Inst <"v_mad_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_CLAMP>>;
+def V_MAD_I16 : VOP3Inst <"v_mad_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_CLAMP>>;
+def V_FMA_F16 : VOP3Inst <"v_fma_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, fma>;
+def V_INTERP_P2_F16 : VOP3Interp <"v_interp_p2_f16", VOP3_INTERP16<[f16, f32, i32, f32]>>;
+}
-def V_MAD_U16 : VOP3Inst <"v_mad_u16", VOP3_Profile<VOP_I16_I16_I16_I16>>;
-def V_MAD_I16 : VOP3Inst <"v_mad_i16", VOP3_Profile<VOP_I16_I16_I16_I16>>;
+let SubtargetPredicate = isGFX9 in {
+def V_MAD_F16_gfx9 : VOP3Inst <"v_mad_f16_gfx9", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>>;
+def V_MAD_U16_gfx9 : VOP3Inst <"v_mad_u16_gfx9", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>>;
+def V_MAD_I16_gfx9 : VOP3Inst <"v_mad_i16_gfx9", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>>;
+def V_FMA_F16_gfx9 : VOP3Inst <"v_fma_f16_gfx9", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>>;
+def V_INTERP_P2_F16_gfx9 : VOP3Interp <"v_interp_p2_f16_gfx9", VOP3_INTERP16<[f16, f32, i32, f32]>>;
+} // End SubtargetPredicate = isGFX9
+
+def V_INTERP_P1LL_F16 : VOP3Interp <"v_interp_p1ll_f16", VOP3_INTERP16<[f32, f32, i32, untyped]>>;
+def V_INTERP_P1LV_F16 : VOP3Interp <"v_interp_p1lv_f16", VOP3_INTERP16<[f32, f32, i32, f16]>>;
} // End isCommutable = 1
} // End SubtargetPredicate = Has16BitInsts
let SubtargetPredicate = isVI in {
+def V_INTERP_P1_F32_e64 : VOP3Interp <"v_interp_p1_f32", VOP3_INTERP>;
+def V_INTERP_P2_F32_e64 : VOP3Interp <"v_interp_p2_f32", VOP3_INTERP>;
+def V_INTERP_MOV_F32_e64 : VOP3Interp <"v_interp_mov_f32", VOP3_INTERP_MOV>;
+
def V_PERM_B32 : VOP3Inst <"v_perm_b32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
} // End SubtargetPredicate = isVI
@@ -279,20 +453,20 @@ let Predicates = [Has16BitInsts] in {
multiclass Ternary_i16_Pats <SDPatternOperator op1, SDPatternOperator op2,
Instruction inst, SDPatternOperator op3> {
-def : Pat<
+def : GCNPat <
(op2 (op1 i16:$src0, i16:$src1), i16:$src2),
- (inst i16:$src0, i16:$src1, i16:$src2)
+ (inst i16:$src0, i16:$src1, i16:$src2, (i1 0))
>;
-def : Pat<
+def : GCNPat<
(i32 (op3 (op2 (op1 i16:$src0, i16:$src1), i16:$src2))),
- (inst i16:$src0, i16:$src1, i16:$src2)
+ (inst i16:$src0, i16:$src1, i16:$src2, (i1 0))
>;
-def : Pat<
+def : GCNPat<
(i64 (op3 (op2 (op1 i16:$src0, i16:$src1), i16:$src2))),
(REG_SEQUENCE VReg_64,
- (inst i16:$src0, i16:$src1, i16:$src2), sub0,
+ (inst i16:$src0, i16:$src1, i16:$src2, (i1 0)), sub0,
(V_MOV_B32_e32 (i32 0)), sub1)
>;
}
@@ -303,7 +477,7 @@ defm: Ternary_i16_Pats<mul, add, V_MAD_I16, sext>;
} // End Predicates = [Has16BitInsts]
let SubtargetPredicate = isGFX9 in {
-def V_PACK_B32_F16 : VOP3Inst <"v_pack_b32_f16", VOP3_Profile<VOP_B32_F16_F16>>;
+def V_PACK_B32_F16 : VOP3Inst <"v_pack_b32_f16", VOP3_Profile<VOP_B32_F16_F16, VOP3_OPSEL>>;
def V_LSHL_ADD_U32 : VOP3Inst <"v_lshl_add_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
def V_ADD_LSHL_U32 : VOP3Inst <"v_add_lshl_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
def V_ADD3_U32 : VOP3Inst <"v_add3_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
@@ -313,19 +487,70 @@ def V_OR3_B32 : VOP3Inst <"v_or3_b32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
def V_XAD_U32 : VOP3Inst <"v_xad_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
-def V_MED3_F16 : VOP3Inst <"v_med3_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUfmed3>;
-def V_MED3_I16 : VOP3Inst <"v_med3_i16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUsmed3>;
-def V_MED3_U16 : VOP3Inst <"v_med3_u16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUumed3>;
+def V_MED3_F16 : VOP3Inst <"v_med3_f16", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, AMDGPUfmed3>;
+def V_MED3_I16 : VOP3Inst <"v_med3_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUsmed3>;
+def V_MED3_U16 : VOP3Inst <"v_med3_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUumed3>;
-def V_MIN3_F16 : VOP3Inst <"v_min3_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUfmin3>;
-def V_MIN3_I16 : VOP3Inst <"v_min3_i16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUsmin3>;
-def V_MIN3_U16 : VOP3Inst <"v_min3_u16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUumin3>;
+def V_MIN3_F16 : VOP3Inst <"v_min3_f16", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, AMDGPUfmin3>;
+def V_MIN3_I16 : VOP3Inst <"v_min3_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUsmin3>;
+def V_MIN3_U16 : VOP3Inst <"v_min3_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUumin3>;
-def V_MAX3_F16 : VOP3Inst <"v_max3_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUfmax3>;
-def V_MAX3_I16 : VOP3Inst <"v_max3_i16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUsmax3>;
-def V_MAX3_U16 : VOP3Inst <"v_max3_u16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUumax3>;
+def V_MAX3_F16 : VOP3Inst <"v_max3_f16", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, AMDGPUfmax3>;
+def V_MAX3_I16 : VOP3Inst <"v_max3_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUsmax3>;
+def V_MAX3_U16 : VOP3Inst <"v_max3_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUumax3>;
+
+def V_ADD_I16 : VOP3Inst <"v_add_i16", VOP3_Profile<VOP_I16_I16_I16, VOP3_OPSEL>>;
+def V_SUB_I16 : VOP3Inst <"v_sub_i16", VOP3_Profile<VOP_I16_I16_I16, VOP3_OPSEL>>;
+
+def V_MAD_U32_U16 : VOP3Inst <"v_mad_u32_u16", VOP3_Profile<VOP_I32_I16_I16_I32, VOP3_OPSEL>>;
+def V_MAD_I32_I16 : VOP3Inst <"v_mad_i32_i16", VOP3_Profile<VOP_I32_I16_I16_I32, VOP3_OPSEL>>;
+
+def V_CVT_PKNORM_I16_F16 : VOP3Inst <"v_cvt_pknorm_i16_f16", VOP3_Profile<VOP_B32_F16_F16, VOP3_OPSEL>>;
+def V_CVT_PKNORM_U16_F16 : VOP3Inst <"v_cvt_pknorm_u16_f16", VOP3_Profile<VOP_B32_F16_F16, VOP3_OPSEL>>;
+
+def V_ADD_I32_gfx9 : VOP3Inst <"v_add_i32_gfx9", VOP3_Profile<VOP_I32_I32_I32>>;
+def V_SUB_I32_gfx9 : VOP3Inst <"v_sub_i32_gfx9", VOP3_Profile<VOP_I32_I32_I32>>;
} // End SubtargetPredicate = isGFX9
+//===----------------------------------------------------------------------===//
+// Integer Clamp Patterns
+//===----------------------------------------------------------------------===//
+
+class getClampPat<VOPProfile P, SDPatternOperator node> {
+ dag ret3 = (P.DstVT (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2));
+ dag ret2 = (P.DstVT (node P.Src0VT:$src0, P.Src1VT:$src1));
+ dag ret1 = (P.DstVT (node P.Src0VT:$src0));
+ dag ret = !if(!eq(P.NumSrcArgs, 3), ret3,
+ !if(!eq(P.NumSrcArgs, 2), ret2,
+ ret1));
+}
+
+class getClampRes<VOPProfile P, Instruction inst> {
+ dag ret3 = (inst P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, (i1 0));
+ dag ret2 = (inst P.Src0VT:$src0, P.Src1VT:$src1, (i1 0));
+ dag ret1 = (inst P.Src0VT:$src0, (i1 0));
+ dag ret = !if(!eq(P.NumSrcArgs, 3), ret3,
+ !if(!eq(P.NumSrcArgs, 2), ret2,
+ ret1));
+}
+
+class IntClampPat<VOP3Inst inst, SDPatternOperator node> : GCNPat<
+ getClampPat<inst.Pfl, node>.ret,
+ getClampRes<inst.Pfl, inst>.ret
+>;
+
+def : IntClampPat<V_MAD_I32_I24, AMDGPUmad_i24>;
+def : IntClampPat<V_MAD_U32_U24, AMDGPUmad_u24>;
+
+def : IntClampPat<V_SAD_U8, int_amdgcn_sad_u8>;
+def : IntClampPat<V_SAD_HI_U8, int_amdgcn_sad_hi_u8>;
+def : IntClampPat<V_SAD_U16, int_amdgcn_sad_u16>;
+
+def : IntClampPat<V_MSAD_U8, int_amdgcn_msad_u8>;
+def : IntClampPat<V_MQSAD_PK_U16_U8, int_amdgcn_mqsad_pk_u16_u8>;
+
+def : IntClampPat<V_QSAD_PK_U16_U8, int_amdgcn_qsad_pk_u16_u8>;
+def : IntClampPat<V_MQSAD_U32_U8, int_amdgcn_mqsad_u32_u8>;
//===----------------------------------------------------------------------===//
// Target
@@ -443,8 +668,68 @@ multiclass VOP3be_Real_vi<bits<10> op> {
VOP3be_vi <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
}
+multiclass VOP3OpSel_Real_gfx9<bits<10> op> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.VI>,
+ VOP3OpSel_gfx9 <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
+}
+
+multiclass VOP3Interp_Real_vi<bits<10> op> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.VI>,
+ VOP3Interp_vi <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
+}
+
} // End AssemblerPredicates = [isVI], DecoderNamespace = "VI"
+let AssemblerPredicates = [isVIOnly], DecoderNamespace = "VI" in {
+
+multiclass VOP3_F16_Real_vi<bits<10> op> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.VI>,
+ VOP3e_vi <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
+}
+
+multiclass VOP3Interp_F16_Real_vi<bits<10> op> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.VI>,
+ VOP3Interp_vi <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
+}
+
+} // End AssemblerPredicates = [isVIOnly], DecoderNamespace = "VI"
+
+let AssemblerPredicates = [isGFX9], DecoderNamespace = "GFX9" in {
+
+multiclass VOP3_F16_Real_gfx9<bits<10> op, string OpName, string AsmName> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(OpName), SIEncodingFamily.GFX9>,
+ VOP3e_vi <op, !cast<VOP3_Pseudo>(OpName).Pfl> {
+ VOP3_Pseudo ps = !cast<VOP3_Pseudo>(OpName);
+ let AsmString = AsmName # ps.AsmOperands;
+ }
+}
+
+multiclass VOP3OpSel_F16_Real_gfx9<bits<10> op, string AsmName> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.GFX9>,
+ VOP3OpSel_gfx9 <op, !cast<VOP3_Pseudo>(NAME).Pfl> {
+ VOP3_Pseudo ps = !cast<VOP3_Pseudo>(NAME);
+ let AsmString = AsmName # ps.AsmOperands;
+ }
+}
+
+multiclass VOP3Interp_F16_Real_gfx9<bits<10> op, string OpName, string AsmName> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(OpName), SIEncodingFamily.GFX9>,
+ VOP3Interp_vi <op, !cast<VOP3_Pseudo>(OpName).Pfl> {
+ VOP3_Pseudo ps = !cast<VOP3_Pseudo>(OpName);
+ let AsmString = AsmName # ps.AsmOperands;
+ }
+}
+
+multiclass VOP3_Real_gfx9<bits<10> op, string AsmName> {
+ def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.GFX9>,
+ VOP3e_vi <op, !cast<VOP3_Pseudo>(NAME).Pfl> {
+ VOP3_Pseudo ps = !cast<VOP3_Pseudo>(NAME);
+ let AsmString = AsmName # ps.AsmOperands;
+ }
+}
+
+} // End AssemblerPredicates = [isGFX9], DecoderNamespace = "GFX9"
+
defm V_MAD_U64_U32 : VOP3be_Real_vi <0x1E8>;
defm V_MAD_I64_I32 : VOP3be_Real_vi <0x1E9>;
@@ -489,18 +774,38 @@ defm V_QSAD_PK_U16_U8 : VOP3_Real_vi <0x1e5>;
defm V_MQSAD_PK_U16_U8 : VOP3_Real_vi <0x1e6>;
defm V_MQSAD_U32_U8 : VOP3_Real_vi <0x1e7>;
-defm V_MAD_F16 : VOP3_Real_vi <0x1ea>;
-defm V_MAD_U16 : VOP3_Real_vi <0x1eb>;
-defm V_MAD_I16 : VOP3_Real_vi <0x1ec>;
-
defm V_PERM_B32 : VOP3_Real_vi <0x1ed>;
-defm V_FMA_F16 : VOP3_Real_vi <0x1ee>;
-defm V_DIV_FIXUP_F16 : VOP3_Real_vi <0x1ef>;
+defm V_MAD_F16 : VOP3_F16_Real_vi <0x1ea>;
+defm V_MAD_U16 : VOP3_F16_Real_vi <0x1eb>;
+defm V_MAD_I16 : VOP3_F16_Real_vi <0x1ec>;
+defm V_FMA_F16 : VOP3_F16_Real_vi <0x1ee>;
+defm V_DIV_FIXUP_F16 : VOP3_F16_Real_vi <0x1ef>;
+defm V_INTERP_P2_F16 : VOP3Interp_F16_Real_vi <0x276>;
-defm V_INTERP_P1LL_F16 : VOP3_Real_vi <0x274>;
-defm V_INTERP_P1LV_F16 : VOP3_Real_vi <0x275>;
-defm V_INTERP_P2_F16 : VOP3_Real_vi <0x276>;
+defm V_MAD_LEGACY_F16 : VOP3_F16_Real_gfx9 <0x1ea, "V_MAD_F16", "v_mad_legacy_f16">;
+defm V_MAD_LEGACY_U16 : VOP3_F16_Real_gfx9 <0x1eb, "V_MAD_U16", "v_mad_legacy_u16">;
+defm V_MAD_LEGACY_I16 : VOP3_F16_Real_gfx9 <0x1ec, "V_MAD_I16", "v_mad_legacy_i16">;
+defm V_FMA_LEGACY_F16 : VOP3_F16_Real_gfx9 <0x1ee, "V_FMA_F16", "v_fma_legacy_f16">;
+defm V_DIV_FIXUP_LEGACY_F16 : VOP3_F16_Real_gfx9 <0x1ef, "V_DIV_FIXUP_F16", "v_div_fixup_legacy_f16">;
+defm V_INTERP_P2_LEGACY_F16 : VOP3Interp_F16_Real_gfx9 <0x276, "V_INTERP_P2_F16", "v_interp_p2_legacy_f16">;
+
+defm V_MAD_F16_gfx9 : VOP3OpSel_F16_Real_gfx9 <0x203, "v_mad_f16">;
+defm V_MAD_U16_gfx9 : VOP3OpSel_F16_Real_gfx9 <0x204, "v_mad_u16">;
+defm V_MAD_I16_gfx9 : VOP3OpSel_F16_Real_gfx9 <0x205, "v_mad_i16">;
+defm V_FMA_F16_gfx9 : VOP3OpSel_F16_Real_gfx9 <0x206, "v_fma_f16">;
+defm V_DIV_FIXUP_F16_gfx9 : VOP3OpSel_F16_Real_gfx9 <0x207, "v_div_fixup_f16">;
+defm V_INTERP_P2_F16_gfx9 : VOP3Interp_F16_Real_gfx9 <0x277, "V_INTERP_P2_F16_gfx9", "v_interp_p2_f16">;
+
+defm V_ADD_I32_gfx9 : VOP3_Real_gfx9 <0x29c, "v_add_i32">;
+defm V_SUB_I32_gfx9 : VOP3_Real_gfx9 <0x29d, "v_sub_i32">;
+
+defm V_INTERP_P1_F32_e64 : VOP3Interp_Real_vi <0x270>;
+defm V_INTERP_P2_F32_e64 : VOP3Interp_Real_vi <0x271>;
+defm V_INTERP_MOV_F32_e64 : VOP3Interp_Real_vi <0x272>;
+
+defm V_INTERP_P1LL_F16 : VOP3Interp_Real_vi <0x274>;
+defm V_INTERP_P1LV_F16 : VOP3Interp_Real_vi <0x275>;
defm V_ADD_F64 : VOP3_Real_vi <0x280>;
defm V_MUL_F64 : VOP3_Real_vi <0x281>;
defm V_MIN_F64 : VOP3_Real_vi <0x282>;
@@ -527,18 +832,27 @@ defm V_ADD3_U32 : VOP3_Real_vi <0x1ff>;
defm V_LSHL_OR_B32 : VOP3_Real_vi <0x200>;
defm V_AND_OR_B32 : VOP3_Real_vi <0x201>;
defm V_OR3_B32 : VOP3_Real_vi <0x202>;
-defm V_PACK_B32_F16 : VOP3_Real_vi <0x2a0>;
+defm V_PACK_B32_F16 : VOP3OpSel_Real_gfx9 <0x2a0>;
defm V_XAD_U32 : VOP3_Real_vi <0x1f3>;
-defm V_MIN3_F16 : VOP3_Real_vi <0x1f4>;
-defm V_MIN3_I16 : VOP3_Real_vi <0x1f5>;
-defm V_MIN3_U16 : VOP3_Real_vi <0x1f6>;
+defm V_MIN3_F16 : VOP3OpSel_Real_gfx9 <0x1f4>;
+defm V_MIN3_I16 : VOP3OpSel_Real_gfx9 <0x1f5>;
+defm V_MIN3_U16 : VOP3OpSel_Real_gfx9 <0x1f6>;
+
+defm V_MAX3_F16 : VOP3OpSel_Real_gfx9 <0x1f7>;
+defm V_MAX3_I16 : VOP3OpSel_Real_gfx9 <0x1f8>;
+defm V_MAX3_U16 : VOP3OpSel_Real_gfx9 <0x1f9>;
+
+defm V_MED3_F16 : VOP3OpSel_Real_gfx9 <0x1fa>;
+defm V_MED3_I16 : VOP3OpSel_Real_gfx9 <0x1fb>;
+defm V_MED3_U16 : VOP3OpSel_Real_gfx9 <0x1fc>;
+
+defm V_ADD_I16 : VOP3OpSel_Real_gfx9 <0x29e>;
+defm V_SUB_I16 : VOP3OpSel_Real_gfx9 <0x29f>;
-defm V_MAX3_F16 : VOP3_Real_vi <0x1f7>;
-defm V_MAX3_I16 : VOP3_Real_vi <0x1f8>;
-defm V_MAX3_U16 : VOP3_Real_vi <0x1f9>;
+defm V_MAD_U32_U16 : VOP3OpSel_Real_gfx9 <0x1f1>;
+defm V_MAD_I32_I16 : VOP3OpSel_Real_gfx9 <0x1f2>;
-defm V_MED3_F16 : VOP3_Real_vi <0x1fa>;
-defm V_MED3_I16 : VOP3_Real_vi <0x1fb>;
-defm V_MED3_U16 : VOP3_Real_vi <0x1fc>;
+defm V_CVT_PKNORM_I16_F16 : VOP3OpSel_Real_gfx9 <0x299>;
+defm V_CVT_PKNORM_U16_F16 : VOP3OpSel_Real_gfx9 <0x29a>;