1*d415bd75Srobert//===-- VOPDInstructions.td - Vector Instruction Definitions --------------===//
2*d415bd75Srobert//
3*d415bd75Srobert// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d415bd75Srobert// See https://llvm.org/LICENSE.txt for license information.
5*d415bd75Srobert// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d415bd75Srobert//
7*d415bd75Srobert//===----------------------------------------------------------------------===//
8*d415bd75Srobert
9*d415bd75Srobert//===----------------------------------------------------------------------===//
10*d415bd75Srobert// Encodings
11*d415bd75Srobert//===----------------------------------------------------------------------===//
12*d415bd75Srobert
13*d415bd75Srobertclass VOPDe<bits<4> opX, bits<5> opY> : Enc64 {
14*d415bd75Srobert  bits<9> src0X;
15*d415bd75Srobert  bits<8> vsrc1X;
16*d415bd75Srobert  bits<8> vdstX;
17*d415bd75Srobert  bits<9> src0Y;
18*d415bd75Srobert  bits<8> vsrc1Y;
19*d415bd75Srobert  bits<8> vdstY;
20*d415bd75Srobert
21*d415bd75Srobert  let Inst{8-0} = src0X;
22*d415bd75Srobert  let Inst{16-9} = vsrc1X;
23*d415bd75Srobert  let Inst{21-17} = opY;
24*d415bd75Srobert  let Inst{25-22} = opX;
25*d415bd75Srobert  let Inst{31-26} = 0x32; // encoding
26*d415bd75Srobert  let Inst{40-32} = src0Y;
27*d415bd75Srobert  let Inst{48-41} = vsrc1Y;
28*d415bd75Srobert  let Inst{55-49} = vdstY{7-1};
29*d415bd75Srobert  let Inst{63-56} = vdstX;
30*d415bd75Srobert}
31*d415bd75Srobert
32*d415bd75Srobertclass VOPD_MADKe<bits<4> opX, bits<5> opY> : Enc96 {
33*d415bd75Srobert  bits<9> src0X;
34*d415bd75Srobert  bits<8> vsrc1X;
35*d415bd75Srobert  bits<8> vdstX;
36*d415bd75Srobert  bits<9> src0Y;
37*d415bd75Srobert  bits<8> vsrc1Y;
38*d415bd75Srobert  bits<8> vdstY;
39*d415bd75Srobert  bits<32> imm;
40*d415bd75Srobert
41*d415bd75Srobert  let Inst{8-0} = src0X;
42*d415bd75Srobert  let Inst{16-9} = vsrc1X;
43*d415bd75Srobert  let Inst{21-17} = opY;
44*d415bd75Srobert  let Inst{25-22} = opX;
45*d415bd75Srobert  let Inst{31-26} = 0x32; // encoding
46*d415bd75Srobert  let Inst{40-32} = src0Y;
47*d415bd75Srobert  let Inst{48-41} = vsrc1Y;
48*d415bd75Srobert  let Inst{55-49} = vdstY{7-1};
49*d415bd75Srobert  let Inst{63-56} = vdstX;
50*d415bd75Srobert  let Inst{95-64} = imm;
51*d415bd75Srobert}
52*d415bd75Srobert
53*d415bd75Srobert//===----------------------------------------------------------------------===//
54*d415bd75Srobert// VOPD classes
55*d415bd75Srobert//===----------------------------------------------------------------------===//
56*d415bd75Srobert
57*d415bd75Srobertclass VOPD_Base<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
58*d415bd75Srobert                VOPD_Component XasVC, VOPD_Component YasVC>
59*d415bd75Srobert    : VOPAnyCommon<outs, ins, asm, []>,
60*d415bd75Srobert      VOP<NAME>,
61*d415bd75Srobert      SIMCInstr<NAME, SIEncodingFamily.GFX11> {
62*d415bd75Srobert  // Fields for table indexing
63*d415bd75Srobert  Instruction Opcode = !cast<Instruction>(NAME);
64*d415bd75Srobert  bits<5> OpX = XasVC.VOPDOp;
65*d415bd75Srobert  bits<5> OpY = YasVC.VOPDOp;
66*d415bd75Srobert
67*d415bd75Srobert  let VALU = 1;
68*d415bd75Srobert
69*d415bd75Srobert  let DecoderNamespace = "GFX11";
70*d415bd75Srobert  let AssemblerPredicate = isGFX11Plus;
71*d415bd75Srobert  let WaveSizePredicate = isWave32;
72*d415bd75Srobert  let isCodeGenOnly = 0;
73*d415bd75Srobert  let SubtargetPredicate = isGFX11Plus;
74*d415bd75Srobert  let AsmMatchConverter  = "cvtVOPD";
75*d415bd75Srobert  let Size = 8;
76*d415bd75Srobert  let ReadsModeReg = !or(VDX.ReadsModeReg, VDY.ReadsModeReg);
77*d415bd75Srobert  let mayRaiseFPException = ReadsModeReg;
78*d415bd75Srobert
79*d415bd75Srobert  // V_DUAL_FMAC and V_DUAL_DOT2ACC_F32_F16 need a dummy src2 tied to dst for
80*d415bd75Srobert  // passes to track its uses. Its presence does not affect VOPD formation rules
81*d415bd75Srobert  // because the rules for src2 and dst are the same. src2X and src2Y should not
82*d415bd75Srobert  // be encoded.
83*d415bd75Srobert  bit hasSrc2AccX = !or(!eq(VDX.Mnemonic, "v_fmac_f32"), !eq(VDX.Mnemonic, "v_dot2c_f32_f16"));
84*d415bd75Srobert  bit hasSrc2AccY = !or(!eq(VDY.Mnemonic, "v_fmac_f32"), !eq(VDY.Mnemonic, "v_dot2c_f32_f16"));
85*d415bd75Srobert  string ConstraintsX = !if(hasSrc2AccX, "$src2X = $vdstX", "");
86*d415bd75Srobert  string ConstraintsY = !if(hasSrc2AccY, "$src2Y = $vdstY", "");
87*d415bd75Srobert  let Constraints =
88*d415bd75Srobert      ConstraintsX # !if(!and(hasSrc2AccX, hasSrc2AccY), ", ", "") # ConstraintsY;
89*d415bd75Srobert  string DisableEncodingX = !if(hasSrc2AccX, "$src2X", "");
90*d415bd75Srobert  string DisableEncodingY = !if(hasSrc2AccY, "$src2Y", "");
91*d415bd75Srobert  let DisableEncoding =
92*d415bd75Srobert      DisableEncodingX # !if(!and(hasSrc2AccX, hasSrc2AccY), ", ", "") # DisableEncodingY;
93*d415bd75Srobert
94*d415bd75Srobert  let Uses = RegListUnion<VDX.Uses, VDY.Uses>.ret;
95*d415bd75Srobert  let Defs = RegListUnion<VDX.Defs, VDY.Defs>.ret;
96*d415bd75Srobert  let SchedRW = !listconcat(VDX.SchedRW, VDY.SchedRW);
97*d415bd75Srobert}
98*d415bd75Srobert
99*d415bd75Srobertclass VOPD<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
100*d415bd75Srobert           VOPD_Component XasVC, VOPD_Component YasVC>
101*d415bd75Srobert    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC>,
102*d415bd75Srobert      VOPDe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
103*d415bd75Srobert  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
104*d415bd75Srobert  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
105*d415bd75Srobert}
106*d415bd75Srobert
107*d415bd75Srobertclass VOPD_MADK<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
108*d415bd75Srobert                VOPD_Component XasVC, VOPD_Component YasVC>
109*d415bd75Srobert    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC>,
110*d415bd75Srobert      VOPD_MADKe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
111*d415bd75Srobert  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
112*d415bd75Srobert  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
113*d415bd75Srobert  let Size = 12;
114*d415bd75Srobert}
115*d415bd75Srobert
116*d415bd75Srobert// V_DUAL_DOT2ACC_F32_BF16 is a legal instruction, but V_DOT2ACC_F32_BF16 is
117*d415bd75Srobert// not. Since we generate the DUAL form by converting from the normal form we
118*d415bd75Srobert// will never generate it.
119*d415bd75Srobertdefvar VOPDYPseudos = [
120*d415bd75Srobert  "V_FMAC_F32_e32", "V_FMAAK_F32", "V_FMAMK_F32", "V_MUL_F32_e32",
121*d415bd75Srobert  "V_ADD_F32_e32", "V_SUB_F32_e32", "V_SUBREV_F32_e32", "V_MUL_LEGACY_F32_e32",
122*d415bd75Srobert  "V_MOV_B32_e32", "V_CNDMASK_B32_e32", "V_MAX_F32_e32", "V_MIN_F32_e32",
123*d415bd75Srobert  "V_DOT2C_F32_F16_e32", "V_ADD_U32_e32", "V_LSHLREV_B32_e32", "V_AND_B32_e32"
124*d415bd75Srobert];
125*d415bd75Srobertdefvar VOPDXPseudos = VOPDYPseudos[0...VOPDX_Max_Index];
126*d415bd75Srobert
127*d415bd75Srobertdef VOPDDstYOperand : RegisterOperand<VGPR_32, "printRegularOperand"> {
128*d415bd75Srobert  let DecoderMethod = "decodeOperandVOPDDstY";
129*d415bd75Srobert}
130*d415bd75Srobert
131*d415bd75Srobertforeach x = VOPDXPseudos in {
132*d415bd75Srobert  foreach y = VOPDYPseudos in {
133*d415bd75Srobert    defvar xInst = !cast<VOP_Pseudo>(x);
134*d415bd75Srobert    defvar yInst = !cast<VOP_Pseudo>(y);
135*d415bd75Srobert    defvar XasVC = !cast<VOPD_Component>(x);
136*d415bd75Srobert    defvar YasVC = !cast<VOPD_Component>(y);
137*d415bd75Srobert    defvar isMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"),
138*d415bd75Srobert                        !eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
139*d415bd75Srobert    // If X or Y is MADK (have a mandatory immediate), all src operands which
140*d415bd75Srobert    // may contain an optional literal must use the VSrc_*_Deferred operand
141*d415bd75Srobert    // type. Optional literal operands in MADK VOPD components always use this
142*d415bd75Srobert    // operand form. If Both X and Y are MADK, the mandatory literal of X
143*d415bd75Srobert    // additionally must use an alternate operand format which defers to the
144*d415bd75Srobert    // 'real' Y literal
145*d415bd75Srobert    defvar isOpXMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"));
146*d415bd75Srobert    defvar isOpYMADK = !or(!eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
147*d415bd75Srobert    defvar OpName = "V_DUAL_" # !substr(x,2) # "_X_" # !substr(y,2);
148*d415bd75Srobert    defvar outs = (outs VGPRSrc_32:$vdstX, VOPDDstYOperand:$vdstY);
149*d415bd75Srobert    if !or(isOpXMADK, isOpYMADK) then {
150*d415bd75Srobert      if !and(isOpXMADK, isOpYMADK) then {
151*d415bd75Srobert        defvar X_MADK_Pfl = !cast<VOP_MADK_Base>(xInst.Pfl);
152*d415bd75Srobert        defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
153*d415bd75Srobert        defvar asm = XasVC.VOPDName #" "# X_MADK_Pfl.AsmVOPDXDeferred #" :: "# YasVC.VOPDName #" "# yInst.Pfl.AsmVOPDY;
154*d415bd75Srobert        def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
155*d415bd75Srobert      } else {
156*d415bd75Srobert        defvar asm = XasVC.VOPDName #" "# xInst.Pfl.AsmVOPDX #" :: "# YasVC.VOPDName #" "# yInst.Pfl.AsmVOPDY;
157*d415bd75Srobert        if isOpXMADK then {
158*d415bd75Srobert          assert !not(isOpYMADK), "Expected only OpX as MADK";
159*d415bd75Srobert          defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDYDeferred);
160*d415bd75Srobert          def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
161*d415bd75Srobert        } else {
162*d415bd75Srobert          assert !not(isOpXMADK), "Expected only OpY as MADK";
163*d415bd75Srobert          defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
164*d415bd75Srobert          def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
165*d415bd75Srobert        }
166*d415bd75Srobert      }
167*d415bd75Srobert    } else {
168*d415bd75Srobert      defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDY);
169*d415bd75Srobert      defvar asm = XasVC.VOPDName #" "# xInst.Pfl.AsmVOPDX #" :: "# YasVC.VOPDName #" "# yInst.Pfl.AsmVOPDY;
170*d415bd75Srobert      def OpName : VOPD<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
171*d415bd75Srobert    }
172*d415bd75Srobert  }
173*d415bd75Srobert}
174*d415bd75Srobert
175