xref: /llvm-project/llvm/lib/Target/AMDGPU/VOPDInstructions.td (revision d1cf86fe53bd89e107f8348a117754b59b4ffca5)
107b7fadaSJoe Nash//===-- VOPDInstructions.td - Vector Instruction Definitions --------------===//
207b7fadaSJoe Nash//
307b7fadaSJoe Nash// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
407b7fadaSJoe Nash// See https://llvm.org/LICENSE.txt for license information.
507b7fadaSJoe Nash// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
607b7fadaSJoe Nash//
707b7fadaSJoe Nash//===----------------------------------------------------------------------===//
807b7fadaSJoe Nash
907b7fadaSJoe Nash//===----------------------------------------------------------------------===//
1007b7fadaSJoe Nash// Encodings
1107b7fadaSJoe Nash//===----------------------------------------------------------------------===//
1207b7fadaSJoe Nash
1307b7fadaSJoe Nashclass VOPDe<bits<4> opX, bits<5> opY> : Enc64 {
1407b7fadaSJoe Nash  bits<9> src0X;
1507b7fadaSJoe Nash  bits<8> vsrc1X;
1607b7fadaSJoe Nash  bits<8> vdstX;
1707b7fadaSJoe Nash  bits<9> src0Y;
1807b7fadaSJoe Nash  bits<8> vsrc1Y;
1907b7fadaSJoe Nash  bits<8> vdstY;
2007b7fadaSJoe Nash
2107b7fadaSJoe Nash  let Inst{8-0} = src0X;
2207b7fadaSJoe Nash  let Inst{16-9} = vsrc1X;
2307b7fadaSJoe Nash  let Inst{21-17} = opY;
2407b7fadaSJoe Nash  let Inst{25-22} = opX;
2507b7fadaSJoe Nash  let Inst{31-26} = 0x32; // encoding
2607b7fadaSJoe Nash  let Inst{40-32} = src0Y;
2707b7fadaSJoe Nash  let Inst{48-41} = vsrc1Y;
2807b7fadaSJoe Nash  let Inst{55-49} = vdstY{7-1};
2907b7fadaSJoe Nash  let Inst{63-56} = vdstX;
3007b7fadaSJoe Nash}
3107b7fadaSJoe Nash
3207b7fadaSJoe Nashclass VOPD_MADKe<bits<4> opX, bits<5> opY> : Enc96 {
3307b7fadaSJoe Nash  bits<9> src0X;
3407b7fadaSJoe Nash  bits<8> vsrc1X;
3507b7fadaSJoe Nash  bits<8> vdstX;
3607b7fadaSJoe Nash  bits<9> src0Y;
3707b7fadaSJoe Nash  bits<8> vsrc1Y;
3807b7fadaSJoe Nash  bits<8> vdstY;
3907b7fadaSJoe Nash  bits<32> imm;
4007b7fadaSJoe Nash
4107b7fadaSJoe Nash  let Inst{8-0} = src0X;
4207b7fadaSJoe Nash  let Inst{16-9} = vsrc1X;
4307b7fadaSJoe Nash  let Inst{21-17} = opY;
4407b7fadaSJoe Nash  let Inst{25-22} = opX;
4507b7fadaSJoe Nash  let Inst{31-26} = 0x32; // encoding
4607b7fadaSJoe Nash  let Inst{40-32} = src0Y;
4707b7fadaSJoe Nash  let Inst{48-41} = vsrc1Y;
4807b7fadaSJoe Nash  let Inst{55-49} = vdstY{7-1};
4907b7fadaSJoe Nash  let Inst{63-56} = vdstX;
5007b7fadaSJoe Nash  let Inst{95-64} = imm;
5107b7fadaSJoe Nash}
5207b7fadaSJoe Nash
5307b7fadaSJoe Nash//===----------------------------------------------------------------------===//
5407b7fadaSJoe Nash// VOPD classes
5507b7fadaSJoe Nash//===----------------------------------------------------------------------===//
5607b7fadaSJoe Nash
57a97028acSMariusz Sikora
58a97028acSMariusz Sikoraclass GFXGenD<GFXGen Gen, list<string> DXPseudos, list<string> DYPseudos,
59a97028acSMariusz Sikora              Predicate subtargetPred = Gen.AssemblerPredicate> :
60a97028acSMariusz Sikora    GFXGen<Gen.AssemblerPredicate, Gen.DecoderNamespace, Gen.Suffix,
61a97028acSMariusz Sikora           Gen.Subtarget> {
62a97028acSMariusz Sikora  list<string> VOPDXPseudos = DXPseudos;
63a97028acSMariusz Sikora  list<string> VOPDYPseudos = DYPseudos;
64a97028acSMariusz Sikora  Predicate SubtargetPredicate = subtargetPred;
65a97028acSMariusz Sikora}
66a97028acSMariusz Sikora
6707b7fadaSJoe Nashclass VOPD_Base<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
68a97028acSMariusz Sikora                VOPD_Component XasVC, VOPD_Component YasVC, GFXGenD Gen>
6907b7fadaSJoe Nash    : VOPAnyCommon<outs, ins, asm, []>,
7007b7fadaSJoe Nash      VOP<NAME>,
71a97028acSMariusz Sikora      SIMCInstr<NAME, Gen.Subtarget> {
7207b7fadaSJoe Nash  // Fields for table indexing
7307b7fadaSJoe Nash  Instruction Opcode = !cast<Instruction>(NAME);
7407b7fadaSJoe Nash  bits<5> OpX = XasVC.VOPDOp;
7507b7fadaSJoe Nash  bits<5> OpY = YasVC.VOPDOp;
76a97028acSMariusz Sikora  bits<4> SubTgt = Gen.Subtarget;
7707b7fadaSJoe Nash
7807b7fadaSJoe Nash  let VALU = 1;
7907b7fadaSJoe Nash
80a97028acSMariusz Sikora  let DecoderNamespace = Gen.DecoderNamespace;
81a97028acSMariusz Sikora  let AssemblerPredicate = Gen.AssemblerPredicate;
8207b7fadaSJoe Nash  let WaveSizePredicate = isWave32;
8307b7fadaSJoe Nash  let isCodeGenOnly = 0;
84a97028acSMariusz Sikora  let SubtargetPredicate = Gen.SubtargetPredicate;
8507b7fadaSJoe Nash  let AsmMatchConverter  = "cvtVOPD";
8607b7fadaSJoe Nash  let Size = 8;
8707b7fadaSJoe Nash  let ReadsModeReg = !or(VDX.ReadsModeReg, VDY.ReadsModeReg);
8807b7fadaSJoe Nash  let mayRaiseFPException = ReadsModeReg;
8907b7fadaSJoe Nash
90f9d6d46aSJay Foad  // V_DUAL_FMAC and V_DUAL_DOT2ACC_F32_F16 and V_DUAL_DOT2ACC_F32_BF16 need a
91f9d6d46aSJay Foad  // dummy src2 tied to dst for passes to track its uses. Its presence does not
92f9d6d46aSJay Foad  // affect VOPD formation rules because the rules for src2 and dst are the
93f9d6d46aSJay Foad  // same. src2X and src2Y should not be encoded.
94f9d6d46aSJay Foad  bit hasSrc2AccX = !or(!eq(VDX.Mnemonic, "v_fmac_f32"), !eq(VDX.Mnemonic, "v_dot2c_f32_f16"), !eq(VDX.Mnemonic, "v_dot2c_f32_bf16"));
95f9d6d46aSJay Foad  bit hasSrc2AccY = !or(!eq(VDY.Mnemonic, "v_fmac_f32"), !eq(VDY.Mnemonic, "v_dot2c_f32_f16"), !eq(VDY.Mnemonic, "v_dot2c_f32_bf16"));
9601b8140dSJoe Nash  string ConstraintsX = !if(hasSrc2AccX, "$src2X = $vdstX", "");
9701b8140dSJoe Nash  string ConstraintsY = !if(hasSrc2AccY, "$src2Y = $vdstY", "");
9801b8140dSJoe Nash  let Constraints =
9901b8140dSJoe Nash      ConstraintsX # !if(!and(hasSrc2AccX, hasSrc2AccY), ", ", "") # ConstraintsY;
10001b8140dSJoe Nash  string DisableEncodingX = !if(hasSrc2AccX, "$src2X", "");
10101b8140dSJoe Nash  string DisableEncodingY = !if(hasSrc2AccY, "$src2Y", "");
10201b8140dSJoe Nash  let DisableEncoding =
10301b8140dSJoe Nash      DisableEncodingX # !if(!and(hasSrc2AccX, hasSrc2AccY), ", ", "") # DisableEncodingY;
10401b8140dSJoe Nash
10507b7fadaSJoe Nash  let Uses = RegListUnion<VDX.Uses, VDY.Uses>.ret;
10607b7fadaSJoe Nash  let Defs = RegListUnion<VDX.Defs, VDY.Defs>.ret;
10707b7fadaSJoe Nash  let SchedRW = !listconcat(VDX.SchedRW, VDY.SchedRW);
10807b7fadaSJoe Nash}
10907b7fadaSJoe Nash
11007b7fadaSJoe Nashclass VOPD<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
111a97028acSMariusz Sikora           VOPD_Component XasVC, VOPD_Component YasVC, GFXGenD Gen>
112a97028acSMariusz Sikora    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC, Gen>,
11307b7fadaSJoe Nash      VOPDe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
11407b7fadaSJoe Nash  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
11507b7fadaSJoe Nash  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
11607b7fadaSJoe Nash}
11707b7fadaSJoe Nash
11807b7fadaSJoe Nashclass VOPD_MADK<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
119a97028acSMariusz Sikora                VOPD_Component XasVC, VOPD_Component YasVC, GFXGenD Gen>
120a97028acSMariusz Sikora    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC, Gen>,
12107b7fadaSJoe Nash      VOPD_MADKe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
12207b7fadaSJoe Nash  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
12307b7fadaSJoe Nash  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
12407b7fadaSJoe Nash  let Size = 12;
1256e86ab7eSMirko Brkusanin  let FixedSize = 1;
12607b7fadaSJoe Nash}
12707b7fadaSJoe Nash
128a97028acSMariusz Sikoradefvar VOPDPseudosCommon = [
12907b7fadaSJoe Nash  "V_FMAC_F32_e32", "V_FMAAK_F32", "V_FMAMK_F32", "V_MUL_F32_e32",
13007b7fadaSJoe Nash  "V_ADD_F32_e32", "V_SUB_F32_e32", "V_SUBREV_F32_e32", "V_MUL_LEGACY_F32_e32",
131*d1cf86feSJay Foad  "V_MOV_B32_e32", "V_CNDMASK_B32_e32", "V_MAX_F32_e32", "V_MIN_F32_e32",
132*d1cf86feSJay Foad  "V_DOT2C_F32_F16_e32", "V_DOT2C_F32_BF16_e32"
13307b7fadaSJoe Nash];
134a97028acSMariusz Sikoradefvar VOPDYOnlyPseudosCommon = ["V_ADD_U32_e32", "V_LSHLREV_B32_e32",
135a97028acSMariusz Sikora                                 "V_AND_B32_e32"];
136a97028acSMariusz Sikora
137*d1cf86feSJay Foaddefvar VOPDXPseudosGFX11 = VOPDPseudosCommon;
138a97028acSMariusz Sikoradefvar VOPDXPseudosGFX12 = VOPDPseudosCommon;
139a97028acSMariusz Sikoradefvar VOPDYPseudosGFX11 = !listconcat(VOPDXPseudosGFX11, VOPDYOnlyPseudosCommon);
140a97028acSMariusz Sikoradefvar VOPDYPseudosGFX12 = !listconcat(VOPDXPseudosGFX12, VOPDYOnlyPseudosCommon);
141a97028acSMariusz Sikora
142a97028acSMariusz Sikoradef GFX11GenD : GFXGenD<GFX11Gen, VOPDXPseudosGFX11, VOPDYPseudosGFX11>;
143a97028acSMariusz Sikoradef GFX12GenD : GFXGenD<GFX12Gen, VOPDXPseudosGFX12, VOPDYPseudosGFX12>;
144a97028acSMariusz Sikora
14507b7fadaSJoe Nash
14607b7fadaSJoe Nashdef VOPDDstYOperand : RegisterOperand<VGPR_32, "printRegularOperand"> {
14707b7fadaSJoe Nash  let DecoderMethod = "decodeOperandVOPDDstY";
14807b7fadaSJoe Nash}
14907b7fadaSJoe Nash
150a97028acSMariusz Sikoraclass getRenamed<string VOPDName, GFXGen Gen> {
151a97028acSMariusz Sikora  string ret = !if(!eq(Gen.Subtarget, GFX12Gen.Subtarget),
152a97028acSMariusz Sikora                   !if(!eq(VOPDName, "v_dual_max_f32"),
153a97028acSMariusz Sikora                       "v_dual_max_num_f32",
154a97028acSMariusz Sikora                       !if(!eq(VOPDName, "v_dual_min_f32"),
155a97028acSMariusz Sikora                           "v_dual_min_num_f32",
156a97028acSMariusz Sikora                           VOPDName)),
157a97028acSMariusz Sikora                   VOPDName);
158a97028acSMariusz Sikora}
159a97028acSMariusz Sikora
160a97028acSMariusz Sikoraforeach Gen = [GFX11GenD, GFX12GenD] in {
161a97028acSMariusz Sikora  foreach x = Gen.VOPDXPseudos in {
162a97028acSMariusz Sikora    foreach y = Gen.VOPDYPseudos in {
16307b7fadaSJoe Nash      defvar xInst = !cast<VOP_Pseudo>(x);
16407b7fadaSJoe Nash      defvar yInst = !cast<VOP_Pseudo>(y);
16507b7fadaSJoe Nash      defvar XasVC = !cast<VOPD_Component>(x);
16607b7fadaSJoe Nash      defvar YasVC = !cast<VOPD_Component>(y);
167a97028acSMariusz Sikora      defvar xAsmName = getRenamed<XasVC.VOPDName, Gen>.ret;
168a97028acSMariusz Sikora      defvar yAsmName = getRenamed<YasVC.VOPDName, Gen>.ret;
16907b7fadaSJoe Nash      defvar isMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"),
17007b7fadaSJoe Nash                          !eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
17107b7fadaSJoe Nash      // If X or Y is MADK (have a mandatory immediate), all src operands which
17207b7fadaSJoe Nash      // may contain an optional literal must use the VSrc_*_Deferred operand
17307b7fadaSJoe Nash      // type. Optional literal operands in MADK VOPD components always use this
17407b7fadaSJoe Nash      // operand form. If Both X and Y are MADK, the mandatory literal of X
17507b7fadaSJoe Nash      // additionally must use an alternate operand format which defers to the
17607b7fadaSJoe Nash      // 'real' Y literal
17707b7fadaSJoe Nash      defvar isOpXMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"));
17807b7fadaSJoe Nash      defvar isOpYMADK = !or(!eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
179a97028acSMariusz Sikora      defvar OpName = "V_DUAL_" # !substr(x,2) # "_X_" # !substr(y,2) # Gen.Suffix;
18007b7fadaSJoe Nash      defvar outs = (outs VGPRSrc_32:$vdstX, VOPDDstYOperand:$vdstY);
18107b7fadaSJoe Nash      if !or(isOpXMADK, isOpYMADK) then {
18207b7fadaSJoe Nash        if !and(isOpXMADK, isOpYMADK) then {
18307b7fadaSJoe Nash          defvar X_MADK_Pfl = !cast<VOP_MADK_Base>(xInst.Pfl);
18407b7fadaSJoe Nash          defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
185a97028acSMariusz Sikora          defvar asm = xAsmName #" "# X_MADK_Pfl.AsmVOPDXDeferred #" :: "# yAsmName #" "# yInst.Pfl.AsmVOPDY;
186a97028acSMariusz Sikora          def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
18707b7fadaSJoe Nash        } else {
188a97028acSMariusz Sikora          defvar asm = xAsmName #" "# xInst.Pfl.AsmVOPDX #" :: "# yAsmName #" "# yInst.Pfl.AsmVOPDY;
18907b7fadaSJoe Nash          if isOpXMADK then {
19007b7fadaSJoe Nash            assert !not(isOpYMADK), "Expected only OpX as MADK";
19107b7fadaSJoe Nash            defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDYDeferred);
192a97028acSMariusz Sikora            def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
19307b7fadaSJoe Nash          } else {
19407b7fadaSJoe Nash            assert !not(isOpXMADK), "Expected only OpY as MADK";
19507b7fadaSJoe Nash            defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
196a97028acSMariusz Sikora            def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
19707b7fadaSJoe Nash          }
19807b7fadaSJoe Nash        }
19907b7fadaSJoe Nash      } else {
20007b7fadaSJoe Nash        defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDY);
201a97028acSMariusz Sikora        defvar asm = xAsmName #" "# xInst.Pfl.AsmVOPDX #" :: "# yAsmName #" "# yInst.Pfl.AsmVOPDY;
202a97028acSMariusz Sikora        def OpName : VOPD<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
203a97028acSMariusz Sikora      }
20407b7fadaSJoe Nash    }
20507b7fadaSJoe Nash  }
20607b7fadaSJoe Nash}
20707b7fadaSJoe Nash
208