//===-- AMDGPUInstructions.td - Common instruction defs ---*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains instruction defs that are common to all hw codegen // targets. // //===----------------------------------------------------------------------===// class AddressSpacesImpl { int Flat = 0; int Global = 1; int Region = 2; int Local = 3; int Constant = 4; int Private = 5; int Constant32Bit = 6; } def AddrSpaces : AddressSpacesImpl; class AMDGPUInst pattern = []> : Instruction { field bit isRegisterLoad = 0; field bit isRegisterStore = 0; let Namespace = "AMDGPU"; let OutOperandList = outs; let InOperandList = ins; let AsmString = asm; let Pattern = pattern; let Itinerary = NullALU; // SoftFail is a field the disassembler can use to provide a way for // instructions to not match without killing the whole decode process. It is // mainly used for ARM, but Tablegen expects this field to exist or it fails // to build the decode table. field bits<96> SoftFail = 0; let DecoderNamespace = Namespace; let TSFlags{63} = isRegisterLoad; let TSFlags{62} = isRegisterStore; } class AMDGPUShaderInst pattern = []> : AMDGPUInst { field bits<32> Inst = 0xffffffff; } //===---------------------------------------------------------------------===// // Return instruction //===---------------------------------------------------------------------===// class ILFormat pattern> : Instruction { let Namespace = "AMDGPU"; dag OutOperandList = outs; dag InOperandList = ins; let Pattern = pattern; let AsmString = !strconcat(asmstr, "\n"); let isPseudo = 1; let Itinerary = NullALU; bit hasIEEEFlag = 0; bit hasZeroOpFlag = 0; let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; let isCodeGenOnly = 1; } def TruePredicate : Predicate<"">; // FIXME: Tablegen should specially supports this def FalsePredicate : Predicate<"false">; // Add a predicate to the list if does not already exist to deduplicate it. class PredConcat lst, Predicate pred> { list ret = !listconcat(lst, !listremove([pred], lst)); } // Get the union of two Register lists class RegListUnion lstA, list lstB> { list ret = !listconcat(lstA, !listremove(lstB, lstA)); } class PredicateControl { Predicate SubtargetPredicate = TruePredicate; Predicate AssemblerPredicate = TruePredicate; Predicate WaveSizePredicate = TruePredicate; list OtherPredicates = []; list Predicates = PredConcat< PredConcat.ret, AssemblerPredicate>.ret, WaveSizePredicate>.ret; } class AMDGPUPat : Pat, PredicateControl; let RecomputePerFunction = 1 in { def FP16Denormals : Predicate<"MF->getInfo()->getMode().allFP64FP16Denormals()">; def FP32Denormals : Predicate<"MF->getInfo()->getMode().allFP32Denormals()">; def FP64Denormals : Predicate<"MF->getInfo()->getMode().allFP64FP16Denormals()">; def NoFP16Denormals : Predicate<"!MF->getInfo()->getMode().allFP64FP16Denormals()">; def NoFP32Denormals : Predicate<"!MF->getInfo()->getMode().allFP32Denormals()">; def NoFP64Denormals : Predicate<"!MF->getInfo()->getMode().allFP64FP16Denormals()">; def UnsafeFPMath : Predicate<"TM.Options.UnsafeFPMath">; } def FMA : Predicate<"Subtarget->hasFMA()">; def InstFlag : OperandWithDefaultOps ; def u16ImmTarget : AsmOperandClass { let Name = "U16Imm"; let RenderMethod = "addImmOperands"; } def s16ImmTarget : AsmOperandClass { let Name = "S16Imm"; let RenderMethod = "addImmOperands"; } let OperandType = "OPERAND_IMMEDIATE" in { def u32imm : Operand { let PrintMethod = "printU32ImmOperand"; } def u16imm : Operand { let PrintMethod = "printU16ImmOperand"; let ParserMatchClass = u16ImmTarget; } def s16imm : Operand { let PrintMethod = "printU16ImmOperand"; let ParserMatchClass = s16ImmTarget; } def u8imm : Operand { let PrintMethod = "printU8ImmOperand"; } } // End OperandType = "OPERAND_IMMEDIATE" //===--------------------------------------------------------------------===// // Custom Operands //===--------------------------------------------------------------------===// def brtarget : Operand; //===----------------------------------------------------------------------===// // Misc. PatFrags //===----------------------------------------------------------------------===// class HasOneUseUnaryOp : PatFrag< (ops node:$src0), (op $src0), [{ return N->hasOneUse(); }]> { let GISelPredicateCode = [{ return MRI.hasOneNonDBGUse(MI.getOperand(0).getReg()); }]; } class HasOneUseBinOp : PatFrag< (ops node:$src0, node:$src1), (op $src0, $src1), [{ return N->hasOneUse(); }]> { let GISelPredicateCode = [{ return MRI.hasOneNonDBGUse(MI.getOperand(0).getReg()); }]; } class HasOneUseTernaryOp : PatFrag< (ops node:$src0, node:$src1, node:$src2), (op $src0, $src1, $src2), [{ return N->hasOneUse(); }]> { let GISelPredicateCode = [{ return MRI.hasOneNonDBGUse(MI.getOperand(0).getReg()); }]; } class is_canonicalized : PatFrag< (ops node:$src0, node:$src1), (op $src0, $src1), [{ const SITargetLowering &Lowering = *static_cast(getTargetLowering()); return Lowering.isCanonicalized(*CurDAG, N->getOperand(0)) && Lowering.isCanonicalized(*CurDAG, N->getOperand(1)); }]> { // TODO: Improve the Legalizer for g_build_vector in Global Isel to match this class let GISelPredicateCode = [{ const SITargetLowering *TLI = static_cast( MF.getSubtarget().getTargetLowering()); return TLI->isCanonicalized(MI.getOperand(1).getReg(), const_cast(MF)) && TLI->isCanonicalized(MI.getOperand(2).getReg(), const_cast(MF)); }]; } let Properties = [SDNPCommutative, SDNPAssociative] in { def smax_oneuse : HasOneUseBinOp; def smin_oneuse : HasOneUseBinOp; def umax_oneuse : HasOneUseBinOp; def umin_oneuse : HasOneUseBinOp; def fminnum_oneuse : HasOneUseBinOp; def fmaxnum_oneuse : HasOneUseBinOp; def fminnum_ieee_oneuse : HasOneUseBinOp; def fmaxnum_ieee_oneuse : HasOneUseBinOp; def and_oneuse : HasOneUseBinOp; def or_oneuse : HasOneUseBinOp; def xor_oneuse : HasOneUseBinOp; } // Properties = [SDNPCommutative, SDNPAssociative] def not_oneuse : HasOneUseUnaryOp; def add_oneuse : HasOneUseBinOp; def sub_oneuse : HasOneUseBinOp; def srl_oneuse : HasOneUseBinOp; def shl_oneuse : HasOneUseBinOp; def select_oneuse : HasOneUseTernaryOp