xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/VOPDInstructions.td (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
181ad6265SDimitry Andric//===-- VOPDInstructions.td - Vector Instruction Definitions --------------===//
281ad6265SDimitry Andric//
381ad6265SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric//
781ad6265SDimitry Andric//===----------------------------------------------------------------------===//
881ad6265SDimitry Andric
981ad6265SDimitry Andric//===----------------------------------------------------------------------===//
1081ad6265SDimitry Andric// Encodings
1181ad6265SDimitry Andric//===----------------------------------------------------------------------===//
1281ad6265SDimitry Andric
1381ad6265SDimitry Andricclass VOPDe<bits<4> opX, bits<5> opY> : Enc64 {
1481ad6265SDimitry Andric  bits<9> src0X;
1581ad6265SDimitry Andric  bits<8> vsrc1X;
1681ad6265SDimitry Andric  bits<8> vdstX;
1781ad6265SDimitry Andric  bits<9> src0Y;
1881ad6265SDimitry Andric  bits<8> vsrc1Y;
1981ad6265SDimitry Andric  bits<8> vdstY;
2081ad6265SDimitry Andric
2181ad6265SDimitry Andric  let Inst{8-0} = src0X;
2281ad6265SDimitry Andric  let Inst{16-9} = vsrc1X;
2381ad6265SDimitry Andric  let Inst{21-17} = opY;
2481ad6265SDimitry Andric  let Inst{25-22} = opX;
2581ad6265SDimitry Andric  let Inst{31-26} = 0x32; // encoding
2681ad6265SDimitry Andric  let Inst{40-32} = src0Y;
2781ad6265SDimitry Andric  let Inst{48-41} = vsrc1Y;
2881ad6265SDimitry Andric  let Inst{55-49} = vdstY{7-1};
2981ad6265SDimitry Andric  let Inst{63-56} = vdstX;
3081ad6265SDimitry Andric}
3181ad6265SDimitry Andric
3281ad6265SDimitry Andricclass VOPD_MADKe<bits<4> opX, bits<5> opY> : Enc96 {
3381ad6265SDimitry Andric  bits<9> src0X;
3481ad6265SDimitry Andric  bits<8> vsrc1X;
3581ad6265SDimitry Andric  bits<8> vdstX;
3681ad6265SDimitry Andric  bits<9> src0Y;
3781ad6265SDimitry Andric  bits<8> vsrc1Y;
3881ad6265SDimitry Andric  bits<8> vdstY;
3981ad6265SDimitry Andric  bits<32> imm;
4081ad6265SDimitry Andric
4181ad6265SDimitry Andric  let Inst{8-0} = src0X;
4281ad6265SDimitry Andric  let Inst{16-9} = vsrc1X;
4381ad6265SDimitry Andric  let Inst{21-17} = opY;
4481ad6265SDimitry Andric  let Inst{25-22} = opX;
4581ad6265SDimitry Andric  let Inst{31-26} = 0x32; // encoding
4681ad6265SDimitry Andric  let Inst{40-32} = src0Y;
4781ad6265SDimitry Andric  let Inst{48-41} = vsrc1Y;
4881ad6265SDimitry Andric  let Inst{55-49} = vdstY{7-1};
4981ad6265SDimitry Andric  let Inst{63-56} = vdstX;
5081ad6265SDimitry Andric  let Inst{95-64} = imm;
5181ad6265SDimitry Andric}
5281ad6265SDimitry Andric
5381ad6265SDimitry Andric//===----------------------------------------------------------------------===//
5481ad6265SDimitry Andric// VOPD classes
5581ad6265SDimitry Andric//===----------------------------------------------------------------------===//
5681ad6265SDimitry Andric
57*5f757f3fSDimitry Andric
58*5f757f3fSDimitry Andricclass GFXGenD<GFXGen Gen, list<string> DXPseudos, list<string> DYPseudos,
59*5f757f3fSDimitry Andric              Predicate subtargetPred = Gen.AssemblerPredicate> :
60*5f757f3fSDimitry Andric    GFXGen<Gen.AssemblerPredicate, Gen.DecoderNamespace, Gen.Suffix,
61*5f757f3fSDimitry Andric           Gen.Subtarget> {
62*5f757f3fSDimitry Andric  list<string> VOPDXPseudos = DXPseudos;
63*5f757f3fSDimitry Andric  list<string> VOPDYPseudos = DYPseudos;
64*5f757f3fSDimitry Andric  Predicate SubtargetPredicate = subtargetPred;
65*5f757f3fSDimitry Andric}
66*5f757f3fSDimitry Andric
6781ad6265SDimitry Andricclass VOPD_Base<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
68*5f757f3fSDimitry Andric                VOPD_Component XasVC, VOPD_Component YasVC, GFXGenD Gen>
6981ad6265SDimitry Andric    : VOPAnyCommon<outs, ins, asm, []>,
7081ad6265SDimitry Andric      VOP<NAME>,
71*5f757f3fSDimitry Andric      SIMCInstr<NAME, Gen.Subtarget> {
7281ad6265SDimitry Andric  // Fields for table indexing
7381ad6265SDimitry Andric  Instruction Opcode = !cast<Instruction>(NAME);
7481ad6265SDimitry Andric  bits<5> OpX = XasVC.VOPDOp;
7581ad6265SDimitry Andric  bits<5> OpY = YasVC.VOPDOp;
76*5f757f3fSDimitry Andric  bits<4> SubTgt = Gen.Subtarget;
7781ad6265SDimitry Andric
7881ad6265SDimitry Andric  let VALU = 1;
7981ad6265SDimitry Andric
80*5f757f3fSDimitry Andric  let DecoderNamespace = Gen.DecoderNamespace;
81*5f757f3fSDimitry Andric  let AssemblerPredicate = Gen.AssemblerPredicate;
8281ad6265SDimitry Andric  let WaveSizePredicate = isWave32;
8381ad6265SDimitry Andric  let isCodeGenOnly = 0;
84*5f757f3fSDimitry Andric  let SubtargetPredicate = Gen.SubtargetPredicate;
8581ad6265SDimitry Andric  let AsmMatchConverter  = "cvtVOPD";
8681ad6265SDimitry Andric  let Size = 8;
8781ad6265SDimitry Andric  let ReadsModeReg = !or(VDX.ReadsModeReg, VDY.ReadsModeReg);
8881ad6265SDimitry Andric  let mayRaiseFPException = ReadsModeReg;
8981ad6265SDimitry Andric
90bdd1243dSDimitry Andric  // V_DUAL_FMAC and V_DUAL_DOT2ACC_F32_F16 need a dummy src2 tied to dst for
91bdd1243dSDimitry Andric  // passes to track its uses. Its presence does not affect VOPD formation rules
92bdd1243dSDimitry Andric  // because the rules for src2 and dst are the same. src2X and src2Y should not
93bdd1243dSDimitry Andric  // be encoded.
94bdd1243dSDimitry Andric  bit hasSrc2AccX = !or(!eq(VDX.Mnemonic, "v_fmac_f32"), !eq(VDX.Mnemonic, "v_dot2c_f32_f16"));
95bdd1243dSDimitry Andric  bit hasSrc2AccY = !or(!eq(VDY.Mnemonic, "v_fmac_f32"), !eq(VDY.Mnemonic, "v_dot2c_f32_f16"));
96bdd1243dSDimitry Andric  string ConstraintsX = !if(hasSrc2AccX, "$src2X = $vdstX", "");
97bdd1243dSDimitry Andric  string ConstraintsY = !if(hasSrc2AccY, "$src2Y = $vdstY", "");
98bdd1243dSDimitry Andric  let Constraints =
99bdd1243dSDimitry Andric      ConstraintsX # !if(!and(hasSrc2AccX, hasSrc2AccY), ", ", "") # ConstraintsY;
100bdd1243dSDimitry Andric  string DisableEncodingX = !if(hasSrc2AccX, "$src2X", "");
101bdd1243dSDimitry Andric  string DisableEncodingY = !if(hasSrc2AccY, "$src2Y", "");
102bdd1243dSDimitry Andric  let DisableEncoding =
103bdd1243dSDimitry Andric      DisableEncodingX # !if(!and(hasSrc2AccX, hasSrc2AccY), ", ", "") # DisableEncodingY;
104bdd1243dSDimitry Andric
10581ad6265SDimitry Andric  let Uses = RegListUnion<VDX.Uses, VDY.Uses>.ret;
10681ad6265SDimitry Andric  let Defs = RegListUnion<VDX.Defs, VDY.Defs>.ret;
10781ad6265SDimitry Andric  let SchedRW = !listconcat(VDX.SchedRW, VDY.SchedRW);
10881ad6265SDimitry Andric}
10981ad6265SDimitry Andric
11081ad6265SDimitry Andricclass VOPD<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
111*5f757f3fSDimitry Andric           VOPD_Component XasVC, VOPD_Component YasVC, GFXGenD Gen>
112*5f757f3fSDimitry Andric    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC, Gen>,
11381ad6265SDimitry Andric      VOPDe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
11481ad6265SDimitry Andric  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
11581ad6265SDimitry Andric  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
11681ad6265SDimitry Andric}
11781ad6265SDimitry Andric
11881ad6265SDimitry Andricclass VOPD_MADK<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
119*5f757f3fSDimitry Andric                VOPD_Component XasVC, VOPD_Component YasVC, GFXGenD Gen>
120*5f757f3fSDimitry Andric    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC, Gen>,
12181ad6265SDimitry Andric      VOPD_MADKe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
12281ad6265SDimitry Andric  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
12381ad6265SDimitry Andric  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
12481ad6265SDimitry Andric  let Size = 12;
125*5f757f3fSDimitry Andric  let FixedSize = 1;
12681ad6265SDimitry Andric}
12781ad6265SDimitry Andric
12881ad6265SDimitry Andric// V_DUAL_DOT2ACC_F32_BF16 is a legal instruction, but V_DOT2ACC_F32_BF16 is
129*5f757f3fSDimitry Andric// not. V_DUAL_DOT2C_F32_BF16 is a legal instruction on GFX12, but
130*5f757f3fSDimitry Andric// V_DOT2C_F32_F16_e32 is not. Since we generate the DUAL form by converting
131*5f757f3fSDimitry Andric// from the normal form we will never generate them.
132*5f757f3fSDimitry Andricdefvar VOPDPseudosCommon = [
13381ad6265SDimitry Andric  "V_FMAC_F32_e32", "V_FMAAK_F32", "V_FMAMK_F32", "V_MUL_F32_e32",
13481ad6265SDimitry Andric  "V_ADD_F32_e32", "V_SUB_F32_e32", "V_SUBREV_F32_e32", "V_MUL_LEGACY_F32_e32",
135*5f757f3fSDimitry Andric  "V_MOV_B32_e32", "V_CNDMASK_B32_e32", "V_MAX_F32_e32", "V_MIN_F32_e32"
13681ad6265SDimitry Andric];
137*5f757f3fSDimitry Andricdefvar VOPDPseudosGFX11 = ["V_DOT2C_F32_F16_e32"];
138*5f757f3fSDimitry Andricdefvar VOPDYOnlyPseudosCommon = ["V_ADD_U32_e32", "V_LSHLREV_B32_e32",
139*5f757f3fSDimitry Andric                                 "V_AND_B32_e32"];
140*5f757f3fSDimitry Andric
141*5f757f3fSDimitry Andricdefvar VOPDXPseudosGFX11 = !listconcat(VOPDPseudosCommon, VOPDPseudosGFX11);
142*5f757f3fSDimitry Andricdefvar VOPDXPseudosGFX12 = VOPDPseudosCommon;
143*5f757f3fSDimitry Andricdefvar VOPDYPseudosGFX11 = !listconcat(VOPDXPseudosGFX11, VOPDYOnlyPseudosCommon);
144*5f757f3fSDimitry Andricdefvar VOPDYPseudosGFX12 = !listconcat(VOPDXPseudosGFX12, VOPDYOnlyPseudosCommon);
145*5f757f3fSDimitry Andric
146*5f757f3fSDimitry Andricdef GFX11GenD : GFXGenD<GFX11Gen, VOPDXPseudosGFX11, VOPDYPseudosGFX11>;
147*5f757f3fSDimitry Andricdef GFX12GenD : GFXGenD<GFX12Gen, VOPDXPseudosGFX12, VOPDYPseudosGFX12>;
148*5f757f3fSDimitry Andric
14981ad6265SDimitry Andric
15081ad6265SDimitry Andricdef VOPDDstYOperand : RegisterOperand<VGPR_32, "printRegularOperand"> {
15181ad6265SDimitry Andric  let DecoderMethod = "decodeOperandVOPDDstY";
15281ad6265SDimitry Andric}
15381ad6265SDimitry Andric
154*5f757f3fSDimitry Andricclass getRenamed<string VOPDName, GFXGen Gen> {
155*5f757f3fSDimitry Andric  string ret = !if(!eq(Gen.Subtarget, GFX12Gen.Subtarget),
156*5f757f3fSDimitry Andric                   !if(!eq(VOPDName, "v_dual_max_f32"),
157*5f757f3fSDimitry Andric                       "v_dual_max_num_f32",
158*5f757f3fSDimitry Andric                       !if(!eq(VOPDName, "v_dual_min_f32"),
159*5f757f3fSDimitry Andric                           "v_dual_min_num_f32",
160*5f757f3fSDimitry Andric                           VOPDName)),
161*5f757f3fSDimitry Andric                   VOPDName);
162*5f757f3fSDimitry Andric}
163*5f757f3fSDimitry Andric
164*5f757f3fSDimitry Andricforeach Gen = [GFX11GenD, GFX12GenD] in {
165*5f757f3fSDimitry Andric  foreach x = Gen.VOPDXPseudos in {
166*5f757f3fSDimitry Andric    foreach y = Gen.VOPDYPseudos in {
16781ad6265SDimitry Andric      defvar xInst = !cast<VOP_Pseudo>(x);
16881ad6265SDimitry Andric      defvar yInst = !cast<VOP_Pseudo>(y);
16981ad6265SDimitry Andric      defvar XasVC = !cast<VOPD_Component>(x);
17081ad6265SDimitry Andric      defvar YasVC = !cast<VOPD_Component>(y);
171*5f757f3fSDimitry Andric      defvar xAsmName = getRenamed<XasVC.VOPDName, Gen>.ret;
172*5f757f3fSDimitry Andric      defvar yAsmName = getRenamed<YasVC.VOPDName, Gen>.ret;
17381ad6265SDimitry Andric      defvar isMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"),
17481ad6265SDimitry Andric                          !eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
17581ad6265SDimitry Andric      // If X or Y is MADK (have a mandatory immediate), all src operands which
17681ad6265SDimitry Andric      // may contain an optional literal must use the VSrc_*_Deferred operand
17781ad6265SDimitry Andric      // type. Optional literal operands in MADK VOPD components always use this
17881ad6265SDimitry Andric      // operand form. If Both X and Y are MADK, the mandatory literal of X
17981ad6265SDimitry Andric      // additionally must use an alternate operand format which defers to the
18081ad6265SDimitry Andric      // 'real' Y literal
18181ad6265SDimitry Andric      defvar isOpXMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"));
18281ad6265SDimitry Andric      defvar isOpYMADK = !or(!eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
183*5f757f3fSDimitry Andric      defvar OpName = "V_DUAL_" # !substr(x,2) # "_X_" # !substr(y,2) # Gen.Suffix;
18481ad6265SDimitry Andric      defvar outs = (outs VGPRSrc_32:$vdstX, VOPDDstYOperand:$vdstY);
18581ad6265SDimitry Andric      if !or(isOpXMADK, isOpYMADK) then {
18681ad6265SDimitry Andric        if !and(isOpXMADK, isOpYMADK) then {
18781ad6265SDimitry Andric          defvar X_MADK_Pfl = !cast<VOP_MADK_Base>(xInst.Pfl);
18881ad6265SDimitry Andric          defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
189*5f757f3fSDimitry Andric          defvar asm = xAsmName #" "# X_MADK_Pfl.AsmVOPDXDeferred #" :: "# yAsmName #" "# yInst.Pfl.AsmVOPDY;
190*5f757f3fSDimitry Andric          def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
19181ad6265SDimitry Andric        } else {
192*5f757f3fSDimitry Andric          defvar asm = xAsmName #" "# xInst.Pfl.AsmVOPDX #" :: "# yAsmName #" "# yInst.Pfl.AsmVOPDY;
19381ad6265SDimitry Andric          if isOpXMADK then {
19481ad6265SDimitry Andric            assert !not(isOpYMADK), "Expected only OpX as MADK";
19581ad6265SDimitry Andric            defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDYDeferred);
196*5f757f3fSDimitry Andric            def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
19781ad6265SDimitry Andric          } else {
19881ad6265SDimitry Andric            assert !not(isOpXMADK), "Expected only OpY as MADK";
19981ad6265SDimitry Andric            defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
200*5f757f3fSDimitry Andric            def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
20181ad6265SDimitry Andric          }
20281ad6265SDimitry Andric        }
20381ad6265SDimitry Andric      } else {
20481ad6265SDimitry Andric        defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDY);
205*5f757f3fSDimitry Andric        defvar asm = xAsmName #" "# xInst.Pfl.AsmVOPDX #" :: "# yAsmName #" "# yInst.Pfl.AsmVOPDY;
206*5f757f3fSDimitry Andric        def OpName : VOPD<outs, ins, asm, xInst, yInst, XasVC, YasVC, Gen>;
207*5f757f3fSDimitry Andric      }
20881ad6265SDimitry Andric    }
20981ad6265SDimitry Andric  }
21081ad6265SDimitry Andric}
21181ad6265SDimitry Andric
212