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