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