Llvm Tablegen Notes

Tablegen code

CodeGenDAGPatterns::CodeGenDAGPatterns

This is a very important function which decode the td file, and generate the intermediate representation for the final writing of inc file.

llvm::EmitMatcherTable
void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {

Instruction hierarchy

class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
string AsmStr, Domain d = GenericDomain>

class I<bits<8> o, Format f, dag outs, dag ins, string asm,
list pattern, Domain d = GenericDomain>
: X86Inst<o, f, NoImm, outs, ins, asm, d> {
let Pattern = pattern;
let CodeSize = 3;
}

class VPDI<bits<8> o, Format F, dag outs, dag ins, string asm,
list pattern>
: I<o, F, outs, ins, !strconcat(“v”, asm), pattern, SSEPackedDouble>,
PD, Requires<[HasAVX]>;

def VMOVDQArm : VPDI<0x6F, MRMSrcMem, (outs VR128: d s t ) , ( i n s i 128 m e m : dst), (ins i128mem: dst),(insi128mem:src),
"movdqa\t{$src, d s t ∣ dst| dstdst, KaTeX parse error: Expected 'EOF', got '}' at position 4: src}̲", …dst, (alignedloadv2i64 addr:$src))]>,
Sched<[SchedWriteVecMoveLS.XMM.RM]>, VEX, VEX_WIG;

Memory type hierarchy

class DAGOperand {
string OperandNamespace = “MCOI”;
string DecoderMethod = “”;
}
class Operand : DAGOperand {
ValueType Type = ty;
string PrintMethod = “printOperand”;
string EncoderMethod = “”;
bit hasCompleteDecoder = true;
string OperandType = “OPERAND_UNKNOWN”;
dag MIOperandInfo = (ops);

// MCOperandPredicate - Optionally, a code fragment operating on
// const MCOperand &MCOp, and returning a bool, to indicate if
// the value of MCOp is valid for the specific subclass of Operand
code MCOperandPredicate;

// ParserMatchClass - The “match class” that operands of this type fit
// in. Match classes are used to define the order in which instructions are
// match, to ensure that which instructions gets matched is deterministic.
//
// The target specific parser must be able to classify an parsed operand into
// a unique class, which does not partially overlap with any other classes. It
// can match a subset of some other class, in which case the AsmOperandClass
// should declare the other operand as one of its super classes.
AsmOperandClass ParserMatchClass = ImmAsmOperand;
}

class X86MemOperand<string printMethod,
AsmOperandClass parserMatchClass = X86MemAsmOperand,
int size = 0> : Operand {
let PrintMethod = printMethod;
let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG);
let ParserMatchClass = parserMatchClass;
let OperandType = “OPERAND_MEMORY”;
int Size = size;
}

def i128mem : X86MemOperand<“printxmmwordmem”, X86Mem128AsmOperand, 128>;

def iPTR : ValueType<0 , 254>;

    if (Val->getDef()->isSubClassOf("RegisterClass") ||
        Val->getDef()->isSubClassOf("ValueType") ||
        Val->getDef()->isSubClassOf("RegisterOperand") ||
        Val->getDef()->isSubClassOf("PointerLikeRegClass")) {

The members in RegisterClass, ValueType, …, and PointerLikeRegClass will be processed by tablegen.

/// PointerLikeRegClass - Values that are designed to have pointer width are
/// derived from this. TableGen treats the register class as having a symbolic
/// type that it doesn’t know, and resolves the actual regclass to use by using
/// the TargetRegisterInfo::getPointerRegClass() hook at codegen time.
class PointerLikeRegClass {
int RegClassKind = Kind;
}

def i8imm : Operand;

/// ptr_rc definition - Mark this operand as being a pointer value whose
/// register class is resolved dynamically via a callback to TargetInstrInfo.
/// FIXME: We should probably change this to a class which contain a list of
/// flags. But currently we have but one flag.
def ptr_rc : PointerLikeRegClass<0>;

def i32imm : Operand;
class ValueType<int size, int value> {
string Namespace = “MVT”;
int Size = size;
int Value = value;
}

def OtherVT : ValueType<0, 1>; // “Other” value
def i1 : ValueType<1, 2>; // One bit boolean value
def i2 : ValueType<2, 3>; // 2-bit integer value
def i4 : ValueType<4, 4>; // 4-bit integer value
def i8 : ValueType<8, 5>; // 8-bit integer value
def i16 : ValueType<16, 6>; // 16-bit integer value
def i32 : ValueType<32, 7>; // 32-bit integer value

let RenderMethod = “addMemOperands”, SuperClasses = [X86MemAsmOperand] in {

def X86Mem128AsmOperand : AsmOperandClass { let Name = “Mem128”; }

}

class RegisterClass<string namespace, list regTypes, int alignment,
dag regList, RegAltNameIndex idx = NoRegAltName>
: DAGOperand {
string Namespace = namespace;

def FR32 : RegisterClass<“X86”, [f32], 32, (sequence “XMM%u”, 0, 15)>;

def VR128 : RegisterClass<“X86”, [v4f32, v2f64, v8f16, v8bf16, v16i8, v8i16, v4i32, v2i64, f128],
128, (add FR32)>;

Important Definitions

alignedloadv2i64

def SDNPHasChain : SDNodeProperty;
def ld : SDNode<“ISD::LOAD” , SDTLoad,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
def unindexedload : PatFrag<(ops node: p t r ) , ( l d n o d e : ptr), (ld node: ptr),(ldnode:ptr)> {
let IsLoad = true;
let IsUnindexed = true;
}
def load : PatFrag<(ops node: p t r ) , ( u n i n d e x e d l o a d n o d e : ptr), (unindexedload node: ptr),(unindexedloadnode:ptr)> {
let IsLoad = true;
let IsNonExtLoad = true;
}
def alignedload : PatFrag<(ops node: p t r ) , ( l o a d n o d e : ptr), (load node: ptr),(loadnode:ptr), [{
auto *Ld = cast(N);
return Ld->getAlign() >= Ld->getMemoryVT().getStoreSize();
}]>;
def alignedloadv2i64 : PatFrag<(ops node: p t r ) , ( v 2 i 64 ( a l i g n e d l o a d n o d e : ptr), (v2i64 (alignedload node: ptr),(v2i64(alignedloadnode:ptr))>;

SDNode

class SDNode<string opcode, SDTypeProfile typeprof,
list props = [], string sdclass = “SDNode”>
: SDPatternOperator {
string Opcode = opcode;
string SDClass = sdclass;
let Properties = props;
SDTypeProfile TypeProfile = typeprof;
}

SDTypeConstraint

// SDTCisVT - The specified operand has exactly this VT.
class SDTCisVT<int OpNum, ValueType vt> : SDTypeConstraint {
ValueType VT = vt;
}

class SDTCisPtrTy : SDTypeConstraint;

// SDTCisInt - The specified operand has integer type.
class SDTCisInt : SDTypeConstraint;

// SDTCisFP - The specified operand has floating-point type.
class SDTCisFP : SDTypeConstraint;

// SDTCisVec - The specified operand has a vector type.
class SDTCisVec : SDTypeConstraint;

// SDTCisSameAs - The two specified operands have identical types.
class SDTCisSameAs<int OpNum, int OtherOp> : SDTypeConstraint {
int OtherOperandNum = OtherOp;
}

// SDTCisVTSmallerThanOp - The specified operand is a VT SDNode, and its type is
// smaller than the ‘Other’ operand.
class SDTCisVTSmallerThanOp<int OpNum, int OtherOp> : SDTypeConstraint {
int OtherOperandNum = OtherOp;
}

class SDTCisOpSmallerThanOp<int SmallOp, int BigOp> : SDTypeConstraint{
int BigOperandNum = BigOp;
}

/// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same
/// type as the element type of OtherOp, which is a vector type.
class SDTCisEltOfVec<int ThisOp, int OtherOp>
: SDTypeConstraint {
int OtherOpNum = OtherOp;
}

/// SDTCisSubVecOfVec - This indicates that ThisOp is a vector type
/// with length less that of OtherOp, which is a vector type.
class SDTCisSubVecOfVec<int ThisOp, int OtherOp>
: SDTypeConstraint {
int OtherOpNum = OtherOp;
}

// SDTCVecEltisVT - The specified operand is vector type with element type
// of VT.
class SDTCVecEltisVT<int OpNum, ValueType vt> : SDTypeConstraint {
ValueType VT = vt;
}

// SDTCisSameNumEltsAs - The two specified operands have identical number
// of elements.
class SDTCisSameNumEltsAs<int OpNum, int OtherOp> : SDTypeConstraint {
int OtherOperandNum = OtherOp;
}

// SDTCisSameSizeAs - The two specified operands have identical size.
class SDTCisSameSizeAs<int OpNum, int OtherOp> : SDTypeConstraint {
int OtherOperandNum = OtherOp;
}

SDNodeProperty

//=----------------------------------------------------------------------=//
// Selection DAG Node Properties.
//
// Note: These are hard coded into tblgen.
//
def SDNPCommutative : SDNodeProperty; // X op Y == Y op X
def SDNPAssociative : SDNodeProperty; // (X op Y) op Z == X op (Y op Z)
def SDNPHasChain : SDNodeProperty; // R/W chain operand and result
def SDNPOutGlue : SDNodeProperty; // Write a flag result
def SDNPInGlue : SDNodeProperty; // Read a flag operand
def SDNPOptInGlue : SDNodeProperty; // Optionally read a flag operand
def SDNPMayStore : SDNodeProperty; // May write to memory, sets ‘mayStore’.
def SDNPMayLoad : SDNodeProperty; // May read memory, sets ‘mayLoad’.
def SDNPSideEffect : SDNodeProperty; // Sets ‘HasUnmodelledSideEffects’.
def SDNPMemOperand : SDNodeProperty; // Touches memory, has assoc MemOperand
def SDNPVariadic : SDNodeProperty; // Node has variable arguments.
def SDNPWantRoot : SDNodeProperty; // ComplexPattern gets the root of match
def SDNPWantParent : SDNodeProperty; // ComplexPattern gets the parent

Pattern

//=----------------------------------------------------------------------=//
// Selection DAG Pattern Support.
//
// Patterns are what are actually matched against by the target-flavored
// instruction selection DAG. Instructions defined by the target implicitly
// define patterns in most cases, but patterns can also be explicitly added when
// an operation is defined by a sequence of instructions (e.g. loading a large
// immediate value on RISC targets that do not support immediates as large as
// their GPRs).
//

class Pattern<dag patternToMatch, list resultInstrs> {
dag PatternToMatch = patternToMatch;
list ResultInstrs = resultInstrs;
list Predicates = []; // See class Instruction in Target.td.
int AddedComplexity = 0; // See class Instruction in Target.td.
}

// Pat - A simple (but common) form of a pattern, which produces a simple result
// not needing a full list.
class Pat<dag pattern, dag result> : Pattern<pattern, [result]>;

Pattern Example

V_SET0
def V_SET0 : I<0, Pseudo, (outs VR128: d s t ) , ( i n s ) , " " , [ ( s e t V R 128 : dst), (ins), "", [(set VR128: dst),(ins),"",[(setVR128:dst, (v4f32 immAllZerosV))]>;
}

let Predicates = [NoAVX512] in {
def : Pat<(v16i8 immAllZerosV), (V_SET0)>;

VMOVNTDQZmr
class Encoding<bits<2> val> {
bits<2> Value = val;
}
def EncNormal : Encoding<0>;
def EncVEX : Encoding<1>;
def EncXOP : Encoding<2>;
def EncEVEX : Encoding<3>;

class EVEX { Encoding OpEnc = EncEVEX; }

multiclass avx512_movnt<bits<8> opc, string OpcodeStr, X86VectorVTInfo _,
X86SchedWriteMoveLS Sched,
PatFrag st_frag = alignednontemporalstore> {
let SchedRW = [Sched.MR], AddedComplexity = 400 in
def mr : AVX512PI<opc, MRMDestMem, (outs), (ins _.MemOp: d s t , . R C : dst, _.RC: dst,.RC:src),
!strconcat(OpcodeStr, "\t{$src, d s t ∣ dst| dstdst, KaTeX parse error: Expected 'EOF', got '}' at position 4: src}̲"), …src), addr:$dst)],
.ExeDomain>, EVEX, EVEX_CD8<.EltSize, CD8VF>;
}

multiclass avx512_movnt_vl<bits<8> opc, string OpcodeStr,
AVX512VLVectorVTInfo VTInfo,
X86SchedWriteMoveLSWidths Sched> {
let Predicates = [HasAVX512] in
defm Z : avx512_movnt<opc, OpcodeStr, VTInfo.info512, Sched.ZMM>, EVEX_V512;

defm VMOVNTDQ : avx512_movnt_vl<0xE7, “vmovntdq”, avx512vl_i64_info,
SchedWriteVecMoveLSNT>, PD;

let Predicates = [HasAVX512], AddedComplexity = 400 in {
def : Pat<(alignednontemporalstore (v16i32 VR512: s r c ) , a d d r : src), addr: src),addr:dst),
(VMOVNTDQZmr addr: d s t , V R 512 : dst, VR512: dst,VR512:src)>;

Code Analysis

void CodeGenDAGPatterns::ParseOnePattern(Record *TheDef,
       TreePattern &Pattern, TreePattern &Result,
       const std::vector<Record *> &InstImpResults) {

  // Inline pattern fragments and expand multiple alternatives.
  Pattern.InlinePatternFragments();
  Result.InlinePatternFragments();

For PatFrags, InlinePatternFragments will inline the PatFrags one level by one level. In the process the pred of one define will be add to the final pred list. The operand type will be propagates from the highest level to the lowest level. At the lowest level, such as SDNode, the tablegen may check the operand type propagated from the highest level to see if the operands’ type match the requirement of the SDNode.
Pattern is the source pattern, it aims to match the subtree in SelectionDag.
Result is the pattern which the result tree generated. Usually, it consists of the target op, outs and ins.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值