目标指令选择

目标指令选择阶段会把后端td文件里面的DAG模式和selection DAG的节点相匹配
如果找到一个匹配,则匹配的节点会被有具体机器指令(或者伪指令)的节点代替。
因此你的td模式的指令对于生成好的代码很重要,因此你需要话费很多时间来调试
这些模式。

理解pat用法

模式的record记录从llvm的pat类继承,这个pat类有两个参数,第一个参数是要匹配模式
的dag,第二个参数是机器指令的dag,当模式匹配了dag中的一些节点时,匹配的节点会被第二个参数中的dag替换。

接下来要使用一些类来帮助精简基于pat构建的td模式,这里有这样两个类。

class PatGprGpr<SDPatternOperator OpNode, RWInst Inst>: Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
class PatGprSimm12<SDPatternOperator OpNode, RWInstI Inst>: Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>;

patgprgpr会把在dag中两通用寄存器为输入指令的节点替换掉,比如下面是对ADD指令的
pattern的定义:

def : PatGprGpr<add, ADD>;

PatGprSimm12会把dag中输入为一个通用寄存器和一个12bit立即数的指令替换掉。为了
达到这个目标,第一个和第二个参数的第二个操作数应该是simm12而不是GPR。注意这里simm12是一个记录,它也是从类Operand继承的,因为可以用于做指令定义。
simm12还继承了ImmLeaf类,因此它也可以在模式中使用。

下面的例子中展示了对ADDI指令的模式定义。

def : PatGprSimm12<add, ADDI>;

NOTE: ImmLeaf类是一个用来匹配立即数的模式,他的参数是立即数的类型,这里的类型
可以是i32, i16等等,和一个predicate,也就是一段c++代码,
这段代码用来表达如何检查模式要匹配一个节点必须满足的条件。
举个例子,simm12的predicate是

return isInt<12>(Imm)

用来检查是否一个整数能够放进12比特中。

def simm12 : Operand<i32>, ImmLeaf<i32, [{return isInt<12>(Imm);}]> {let ParserMatchClass = SImmAsmOperand<12>;let EncoderMethod = "getImmOpValue";let DecoderMethod = "decodeSImmOperand<12>";let MCOperandPredicate = [{int64_t Imm;if (MCOp.evaluateAsConstantImm(Imm))return isInt<12>(Imm);return MCOp.isBareSymbolRef();}];let OperandType = "OPERAND_SIMM12";let OperandNamespace = "RISCWOp";
}

NOTE:有的时候同一个指令可能会在selectiondag中被匹配到一个或者多个模式,在这种情况下,LLVM的PatFrag和Pat配合来避免代码重复,这个可以参见RISCW架构的bit shift模式。

class shiftop<SDPatternOperator operator>: PatFrags<(ops node:$val, node:$count),[(operator node:$val, node:$count),(operator node:$val, (and node:$count, immbottomwsizeset))]>;
def : PatGprGpr<shiftop<shl>, SLL>;

理解SDNodeXForm

RISCW和RISCV后端都先定义指令然后会单独提供模式记录。然而其他后端比如ARM和XCore会
有所不同,他们把模式参数作为输入,这种方法降低了代码总行数,但是导致代码很难读懂。

Pat的第二个参数,如果找到了dag中的一个匹配,还会对操作数(通常是立即数)做变换。

为了这样做,我们首先需要定义一个继承自SDNodeXForm的操作节点。SDNodeXForm的参数
为一段实现变换的C++代码,我们使用我们新生命的模式中的代码作为例子,在这个例子中,
HI20节点会抽取一个立即数的高20位。

def HI20 : SDNodeXForm<imm, [{return CurDAG->getTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff,SDLoc(N), N->getValueType(0));
}]>;
def : Pat<(simm32hi20:$imm), (LUI (HI20 imm:$imm))>;

NOTE: SDNodeXForm节点不会插入任何实际的节点,通常他们是被用来对立即数做变换。
这样操作就能够在代码释放之前完全解析。

随着目标指令选择的进行,LLVM会对每个它处理selection DAG节点来调用来自后端SelectionDAGIsel的select方法。这样后端就能够提供代码,在RISCVW的Select方法
中,包含了把常量0替换为x0寄存器的访问的方法。

switch(Opcode) {case ISD::Constant: {auto ConstNode = cast<ConstantSDNode>(Node);if (ConstNode->isNullValue()) {SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(Node),RISCW::X0, MVT::i32);ReplaceNode(Node, New.getNode());return;}break;}default: break;}

LLVM指令选择中的模式定义方法相关推荐

  1. 单片机c语言字符,单片机C语言中变量的定义方法解析

    描述 1.C语言中变量的定义方法 -C语言中变量定义语法为: #pragma rambank0 :即以关键词#pragma开始,rambank0指明资料区块为第0块. unsigned char m_ ...

  2. 单片机c语言怎么定义字符串,单片机C语言中变量的定义方法解析

    1.C语言中变量的定义方法 -C语言中变量定义语法为: #pragma rambank0 :即以关键词#pragma开始,rambank0指明资料区块为第0块. unsigned char m_acc ...

  3. 编程中最佳常量定义方法

    一.常量定义最佳方法 采用左移和或运算,具体参考谷歌常量定义方法. 例子: 现在有一个手机视屏app,有以下标记属性: 1.视屏是否免费 2.是否是视频播放期 3.视频是否为VIP视频 4.视频是否为 ...

  4. android自定义常量,Android中最佳常量定义方法

    一.常量定义最佳方法 采用左移和与运算,具体参考谷歌常量定义方法. 例子: 现在有一个手机视屏app,有一下标记属性: 1.视屏是否免费 2.是否是视频播放期 3.视频是否为VIP视频 4.视频是否为 ...

  5. Spring中策略模式实现方法

    一.定义 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而 ...

  6. 非本地类型不能定义方法 cannot define new methods on non-local type time.Duration

    能够随意地为各种类型起名字,是否意味着可以在自己包里为这些类型任意添加方法 ? 参见下面的代码演示 : package mainimport "time"type MyDurati ...

  7. ACL 2019开源论文 | 句对匹配任务中的样本选择偏差与去偏方法

    作者丨张冠华 单位丨腾讯实习生 & 哈工大本科生 研究方向丨自然语言处理 导读 句对匹配 (Natural Language Sentence Matching,NLSM) 任务是指给定两个句 ...

  8. 11,外观模式(Facade Pattern)是为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。...

    Facade模式也叫外观模式,是由GoF提出的23种设计模式中的一种.Facade模式为一组具有类似功能的类群,比如类库,子系统等等,提供一个一致的简单的界面.这个一致的简单的界面被称作facade. ...

  9. cdr里怎么看html颜色代码大全,CDR中怎么查看一个设计文件是RGB还是CMYK颜色-CDR颜色模式查看方法_好特教程...

    使用CorelDRAW作出的文件在印刷的时候,要做印前检查,区别颜色模式,以保证能正常印刷效果.那么如何查看一个设计文件是RGB还是CMYK颜色,文本将介绍三种方法以做详细说明. 方法一:查找和替换 ...

最新文章

  1. Node.js Buffer静态方法
  2. linux基础分支,Linux基础--/etc/shadow中字段的分支和操作
  3. 深入V8引擎-Time模块介绍
  4. 科研必备学士搜索引擎推荐
  5. 用simple from暂不用formtastic
  6. mysql数据库安全吗_mysql数据库的安全
  7. python中not是什么意思_python中的not具体使用及意思
  8. 自适应屏幕空间环境光遮蔽
  9. mac上的微信小助手WeChatPlugin
  10. 计算机设计项目符号和编号,项目符号和编号
  11. 电瓶车行驶过程中突然无动力,加速没反应,怎么办?
  12. java实现找一条转乘次数最少的公交线路?,基于最优换乘次数的城市公交查询算法...
  13. 只要7步,就能将任何魔方6面还原(留着以后教孩子玩)
  14. python如何定义函数k_Python 函数
  15. LTE-TDD随机接入过程(4)-RIV的解析和Preamble资源的选择
  16. Common Vector Operators(常见的向量操作)
  17. 中国式智慧:古人为何乐意露破绽给皇帝?
  18. 晚上有空做什么副业?业余时间怎么赚钱?
  19. shiro for example: not eligible for auto-proxying
  20. Matlab中运算符优先级

热门文章

  1. Python中的四种队列(queue)、堆(heap)
  2. oracle数据库some,【案例】Oracle报错Some indexes or index [sub]partitions of table VAS.TAB_PUB_CALLLOG...
  3. 札记-20190707
  4. 【七七八八】coursera python-basis certification
  5. 央视3·15晚会起底直播乱象 直播平台佣金高达50%
  6. rsync实现文件服务器间文件同步
  7. OS实战笔记(4)-- 虚拟地址和物理地址的转换
  8. AST实战|AST入门与实战星球高频问题汇总(二)
  9. 【来日复制粘贴】关于排名
  10. TIL —静态工厂方法