llvm-project/llvm/lib/Target/AMDGPU/VINTERPInstructions.td
Brox Chen 85142f5b35
[AMDGPU][True16][CodeGen] support for true16 for vinterp 16bit instructions (#116702)
vinterp 16bit instructions codeGen support in True16 format

Currently only enable two tests, will enable more when more true16
instructions are supported
2024-12-09 11:52:05 -05:00

278 lines
11 KiB
TableGen

//===-- VINTERPInstructions.td - VINTERP Instruction Definitions ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// VINTERP encoding
//===----------------------------------------------------------------------===//
class VINTERPe <VOPProfile P> : Enc64 {
bits<11> vdst;
bits<4> src0_modifiers;
bits<11> src0;
bits<3> src1_modifiers;
bits<11> src1;
bits<3> src2_modifiers;
bits<11> src2;
bits<1> clamp;
bits<3> waitexp;
let Inst{31-26} = 0x33; // VOP3P encoding
let Inst{25-24} = 0x1; // VINTERP sub-encoding
let Inst{7-0} = vdst{7-0};
let Inst{10-8} = waitexp;
// Fields for hi/lo 16-bits of register selection
let Inst{11} = !if(P.HasSrc0, src0_modifiers{2}, 0);
let Inst{12} = !if(P.HasSrc1, src1_modifiers{2}, 0);
let Inst{13} = !if(P.HasSrc2, src2_modifiers{2}, 0);
let Inst{14} = !if(P.HasDst, src0_modifiers{3}, 0);
let Inst{15} = clamp;
let Inst{40-32} = src0{8-0};
let Inst{49-41} = src1{8-0};
let Inst{58-50} = src2{8-0};
let Inst{61} = src0_modifiers{0}; // neg(0)
let Inst{62} = src1_modifiers{0}; // neg(1)
let Inst{63} = src2_modifiers{0}; // neg(2)
}
class VINTERPe_gfx11 <bits<7> op, VOPProfile P> : VINTERPe<P> {
let Inst{22-16} = op;
}
class VINTERPe_gfx12 <bits<7> op, VOPProfile P> : VINTERPe<P> {
let Inst{20-16} = op{4-0};
}
//===----------------------------------------------------------------------===//
// VOP3 VINTERP
//===----------------------------------------------------------------------===//
class VINTERP_Pseudo <string OpName, VOPProfile P, list<dag> pattern = []> :
VOP3_Pseudo<OpName, P, pattern, 0, 0> {
let AsmMatchConverter = "cvtVINTERP";
let mayRaiseFPException = 0;
let VOP3_OPSEL = 1;
let VINTERP = 1;
}
class VINTERP_Real <VOP_Pseudo ps, int EncodingFamily, string asmName> :
VOP3_Real <ps, EncodingFamily, asmName> {
let VINTERP = 1;
let IsSingle = 1;
}
def VOP3_VINTERP_F32 : VOPProfile<[f32, f32, f32, f32]> {
let HasOpSel = 0;
let HasModifiers = 1;
let Src0Mod = FPVRegInputMods;
let Src1Mod = FPVRegInputMods;
let Src2Mod = FPVRegInputMods;
let Outs64 = (outs VGPR_32:$vdst);
let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
Src1Mod:$src1_modifiers, VRegSrc_32:$src1,
Src2Mod:$src2_modifiers, VRegSrc_32:$src2,
Clamp:$clamp,
WaitEXP:$waitexp);
let Asm64 = " $vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers$clamp$waitexp";
}
class VOP3_VINTERP_F16_t16 <list<ValueType> ArgVT> : VOPProfile_True16<VOPProfile<ArgVT>> {
let Src0Mod = FPT16VRegInputMods</*Fake16*/0>;
let Src1Mod = FPVRegInputMods;
let Src2Mod = !if(!eq(ArgVT[3].Size, 16), FPT16VRegInputMods</*Fake16*/0>,
FPVRegInputMods);
let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_16:$src0,
Src1Mod:$src1_modifiers, VRegSrc_32:$src1,
Src2Mod:$src2_modifiers,
!if(!eq(ArgVT[3].Size, 16), VRegSrc_16, VRegSrc_32):$src2,
Clamp:$clamp, op_sel0:$op_sel,
WaitEXP:$waitexp);
let Asm64 = "$vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers$clamp$op_sel$waitexp";
}
class VOP3_VINTERP_F16_fake16 <list<ValueType> ArgVT> : VOPProfile_Fake16<VOPProfile<ArgVT>> {
let Src0Mod = FPT16VRegInputMods</*Fake16*/1>;
let Src1Mod = FPVRegInputMods;
let Src2Mod = !if(!eq(ArgVT[3].Size, 16), FPT16VRegInputMods</*Fake16*/1>,
FPVRegInputMods);
let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_fake16:$src0,
Src1Mod:$src1_modifiers, VRegSrc_32:$src1,
Src2Mod:$src2_modifiers,
!if(!eq(ArgVT[3].Size, 16), VRegSrc_fake16, VRegSrc_32):$src2,
Clamp:$clamp, op_sel0:$op_sel,
WaitEXP:$waitexp);
let Asm64 = "$vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers$clamp$op_sel$waitexp";
}
//===----------------------------------------------------------------------===//
// VINTERP Pseudo Instructions
//===----------------------------------------------------------------------===//
let SubtargetPredicate = HasVINTERPEncoding in {
multiclass VINTERP_t16<string OpName, list<ValueType> ArgVT> {
let True16Predicate = UseRealTrue16Insts in {
def _t16 : VINTERP_Pseudo<OpName#"_t16", VOP3_VINTERP_F16_t16<ArgVT>> ;
}
let True16Predicate = UseFakeTrue16Insts in {
def _fake16 : VINTERP_Pseudo<OpName#"_fake16", VOP3_VINTERP_F16_fake16<ArgVT>> ;
}
}
let Uses = [M0, EXEC, MODE] in {
def V_INTERP_P10_F32_inreg : VINTERP_Pseudo <"v_interp_p10_f32", VOP3_VINTERP_F32>;
def V_INTERP_P2_F32_inreg : VINTERP_Pseudo <"v_interp_p2_f32", VOP3_VINTERP_F32>;
defm V_INTERP_P10_F16_F32_inreg : VINTERP_t16<"v_interp_p10_f16_f32", [f32, f16, f32, f16]>;
defm V_INTERP_P2_F16_F32_inreg : VINTERP_t16<"v_interp_p2_f16_f32", [f16, f16, f32, f32]>;
} // Uses = [M0, EXEC, MODE]
let Uses = [M0, EXEC] in {
defm V_INTERP_P10_RTZ_F16_F32_inreg : VINTERP_t16<"v_interp_p10_rtz_f16_f32", [f32, f16, f32, f16]>;
defm V_INTERP_P2_RTZ_F16_F32_inreg : VINTERP_t16 <"v_interp_p2_rtz_f16_f32", [f16, f16, f32, f32]>;
} // Uses = [M0, EXEC]
} // SubtargetPredicate = HasVINTERPEncoding.
class VInterpF32Pat <SDPatternOperator op, Instruction inst> : GCNPat <
(f32 (op
(VINTERPMods f32:$src0, i32:$src0_modifiers),
(VINTERPMods f32:$src1, i32:$src1_modifiers),
(VINTERPMods f32:$src2, i32:$src2_modifiers))),
(inst $src0_modifiers, $src0,
$src1_modifiers, $src1,
$src2_modifiers, $src2,
0, /* clamp */
7) /* wait_exp */
>;
class VInterpF16Pat <SDPatternOperator op, Instruction inst,
ValueType dst_type, bit high,
list<ComplexPattern> pat> : GCNPat <
(dst_type (op
(pat[0] f32:$src0, i32:$src0_modifiers),
(pat[1] f32:$src1, i32:$src1_modifiers),
(pat[2] f32:$src2, i32:$src2_modifiers),
!if(high, (i1 -1), (i1 0)))),
(inst $src0_modifiers, $src0,
$src1_modifiers, $src1,
$src2_modifiers, $src2,
0, /* clamp */
/* op_sel = 0 */
7) /* wait_exp */
>;
multiclass VInterpF16Pat <SDPatternOperator op, Instruction inst,
ValueType dst_type, list<ComplexPattern> high_pat> {
def : VInterpF16Pat<op, inst, dst_type, 0,
[VINTERPMods, VINTERPMods, VINTERPMods]>;
def : VInterpF16Pat<op, inst, dst_type, 1, high_pat>;
}
class VInterpF16Pat_t16 <SDPatternOperator op, Instruction inst,
ValueType dstVT, bit high, bit isP2> : GCNPat <
(dstVT (op
(VINTERPMods f32:$src0, i32:$src0_modifiers),
(VINTERPMods f32:$src1, i32:$src1_modifiers),
(VINTERPMods f32:$src2, i32:$src2_modifiers),
!if(high, (i1 -1), (i1 0)))),
(inst $src0_modifiers,
(f16 (EXTRACT_SUBREG VGPR_32:$src0, !if(high, hi16, lo16))),
$src1_modifiers, VGPR_32:$src1,
$src2_modifiers,
!if(isP2, (f32 VGPR_32:$src2),
(f16 (EXTRACT_SUBREG VGPR_32:$src2, !if(high, hi16, lo16)))),
0, /* clamp */
7) /* wait_exp */
>;
multiclass VInterpF16Pat_t16 <SDPatternOperator op, Instruction inst,
ValueType dstVT, bit isP2> {
def : VInterpF16Pat_t16<op, inst, dstVT, 0, isP2>;
def : VInterpF16Pat_t16<op, inst, dstVT, 1, isP2>;
}
def : VInterpF32Pat<int_amdgcn_interp_inreg_p10, V_INTERP_P10_F32_inreg>;
def : VInterpF32Pat<int_amdgcn_interp_inreg_p2, V_INTERP_P2_F32_inreg>;
let True16Predicate = UseRealTrue16Insts in {
defm : VInterpF16Pat_t16<int_amdgcn_interp_inreg_p10_f16,
V_INTERP_P10_F16_F32_inreg_t16, f32, 0>;
defm : VInterpF16Pat_t16<int_amdgcn_interp_inreg_p2_f16,
V_INTERP_P2_F16_F32_inreg_t16, f16, 1>;
defm : VInterpF16Pat_t16<int_amdgcn_interp_p10_rtz_f16,
V_INTERP_P10_RTZ_F16_F32_inreg_t16, f32, 0>;
defm : VInterpF16Pat_t16<int_amdgcn_interp_p2_rtz_f16,
V_INTERP_P2_RTZ_F16_F32_inreg_t16, f16, 1>;
}
let True16Predicate = UseFakeTrue16Insts in {
defm : VInterpF16Pat<int_amdgcn_interp_inreg_p10_f16,
V_INTERP_P10_F16_F32_inreg_fake16, f32,
[VINTERPModsHi, VINTERPMods, VINTERPModsHi]>;
defm : VInterpF16Pat<int_amdgcn_interp_inreg_p2_f16,
V_INTERP_P2_F16_F32_inreg_fake16, f16,
[VINTERPModsHi, VINTERPMods, VINTERPMods]>;
defm : VInterpF16Pat<int_amdgcn_interp_p10_rtz_f16,
V_INTERP_P10_RTZ_F16_F32_inreg_fake16, f32,
[VINTERPModsHi, VINTERPMods, VINTERPModsHi]>;
defm : VInterpF16Pat<int_amdgcn_interp_p2_rtz_f16,
V_INTERP_P2_RTZ_F16_F32_inreg_fake16, f16,
[VINTERPModsHi, VINTERPMods, VINTERPMods]>;
}
//===----------------------------------------------------------------------===//
// VINTERP Real Instructions
//===----------------------------------------------------------------------===//
multiclass VINTERP_Real_gfx11 <bits<7> op, string asmName> {
defvar ps = !cast<VOP3_Pseudo>(NAME);
let AssemblerPredicate = isGFX11Only, DecoderNamespace = "GFX11" #
!if(ps.Pfl.IsRealTrue16, "", "_FAKE16") in {
def _gfx11 :
VINTERP_Real<ps, SIEncodingFamily.GFX11, asmName>,
VINTERPe_gfx11<op, ps.Pfl>;
}
}
multiclass VINTERP_Real_gfx12 <bits<7> op, string asmName> {
defvar ps = !cast<VOP3_Pseudo>(NAME);
let AssemblerPredicate = isGFX12Only, DecoderNamespace = "GFX12" #
!if(ps.Pfl.IsRealTrue16, "", "_FAKE16") in {
def _gfx12 :
VINTERP_Real<ps, SIEncodingFamily.GFX12, asmName>,
VINTERPe_gfx12<op, ps.Pfl>;
}
}
multiclass VINTERP_Real_gfx11_gfx12 <bits<7> op, string asmName = !cast<VOP3_Pseudo>(NAME).Mnemonic> :
VINTERP_Real_gfx11<op, asmName>, VINTERP_Real_gfx12<op, asmName>;
multiclass VINTERP_Real_t16_and_fake16_gfx11_gfx12 <bits<7> op, string asmName = !cast<VOP3_Pseudo>(NAME).Mnemonic> {
defm _t16: VINTERP_Real_gfx11_gfx12<op, asmName>;
defm _fake16: VINTERP_Real_gfx11_gfx12<op, asmName>;
}
defm V_INTERP_P10_F32_inreg : VINTERP_Real_gfx11_gfx12<0x000>;
defm V_INTERP_P2_F32_inreg : VINTERP_Real_gfx11_gfx12<0x001>;
defm V_INTERP_P10_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x002, "v_interp_p10_f16_f32">;
defm V_INTERP_P2_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x003, "v_interp_p2_f16_f32">;
defm V_INTERP_P10_RTZ_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x004, "v_interp_p10_rtz_f16_f32">;
defm V_INTERP_P2_RTZ_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x005, "v_interp_p2_rtz_f16_f32">;
let AssemblerPredicate = isGFX11Plus in
def : AMDGPUMnemonicAlias<"v_interp_p2_new_f32", "v_interp_p2_f32">;