【LLVM】nsw和nuw的一个例子

nsw和nuw是LLVMIR提供给二元运算的flag。分别表示not signed wrap和not unsigned wrap。在LLVM2.6的更新日志中表述如下:
The add, sub and mul instructions now support optional “nsw” and “nuw” bits which indicate that the operation is guaranteed to not overflow (in the signed or unsigned case, respectively). This gives the optimizer more information and can be used for things like C signed integer values, which are undefined on overflow.
给出了和官方文档中不同的角度,该flag的添加相当于向编译器提供了一个不溢出的保证,让编译器基于此进行优化。

一个例子

在查找相关资料时,发现了一篇帖子,是LLVM开发者讨论nsw和非nsw的相似性,当两者共同出现时,GVN的消除方式是否安全。

int func(int a, int b) {int c = a + b;return c;
}

上述例子使用clang14进行编译:

clang -emit-llvm -S -O example.cc

得到的IR为:

; ModuleID = 'nuw_and_nsw/nsw_example1.cc'
source_filename = "nuw_and_nsw/nsw_example1.cc"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn
define dso_local noundef i32 @_Z4funcii(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {%3 = add nsw i32 %1, %0ret i32 %3
}attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"uwtable", i32 1}
!2 = !{!"clang version 14.0.0"}

其中对add运算添加了一个nsw的flag,因为在此例子中源代码蕴含的意思不考虑溢出。

修改之后给出一个IR,和帖子中给出的例子一致。

; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn
define dso_local noundef i32 @_Z4funcii(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {%3 = add nsw i32 %1, %0%4 = add i32 %1, %0ret i32 %4
}

通过如下命令调用GVN优化:

opt -gvn source.ll -o target.ll

优化结果的核心部分如下:

; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn
define dso_local noundef i32 @_Z4funcii(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {%3 = add i32 %1, %0ret i32 %3
}

另一种尝试输入的源IR如下:

; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn
define dso_local noundef i32 @_Z4funcii(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {%3 = add i32 %1, %0%4 = add nsw i32 %1, %0ret i32 %4
}

最后得到的优化结果依旧是将带有nsw的结果优化掉。

如何生成一个不带nsw的加法?

int func(unsigned a, unsigned b) {unsigned c = a + b;return (int)c;
}

生成的IR核心部分为:

; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn
define dso_local noundef i32 @_Z4funcjj(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {%3 = add i32 %1, %0ret i32 %3
}

生成nsw flag的主要代码

首先关注clang/lib/CodeGen/CGExprScalar.cpp中的一个名为EmitAdd函数,该函数可以创建含有nsw flag的IR。现将部分函数片段摘录如下:

Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {if (op.LHS->getType()->isPointerTy() ||op.RHS->getType()->isPointerTy())return emitPointerArithmetic(CGF, op, CodeGenFunction::NotSubtraction);if (op.Ty->isSignedIntegerOrEnumerationType()) {switch (CGF.getLangOpts().getSignedOverflowBehavior()) {case LangOptions::SOB_Defined:return Builder.CreateAdd(op.LHS, op.RHS, "add");case LangOptions::SOB_Undefined:if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");[[fallthrough]];case LangOptions::SOB_Trapping:if (CanElideOverflowCheck(CGF.getContext(), op))return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");return EmitOverflowCheckedBinOp(op);}}

可以看到,首先判断两个操作数是否为指针,如果都不是,判断当前表达式是否是符号整数类型或枚举类型,然后根据CGF.getLangOpts().getSignedOverflowBehavior()判断不同的情况。
在clang/include/clang/Basic/LangOptions.h中可以找到SignedOverflowBehaviorTy的定义:

  enum SignedOverflowBehaviorTy {// Default C standard behavior.SOB_Undefined,// -fwrapvSOB_Defined,// -ftrapvSOB_Trapping};

可以看到,默认情况下SignedOverflowBehaviorTy的值为SOB_Undefined,而其余两行的flag分别是与溢出和陷阱相关的flag。可以参考笔者往期的文章。
如果将上述能够产生带有nsw的IR对应的编译过程添加-fwrapv flag,可以发现生成的IR中不再包含nsw flag。

一个包含nuw flag的例子

#include <stdio.h>
void func(unsigned a, unsigned b) {unsigned c = 0;if(a < 10000) {c = a + 10;}printf("%ud", c);
}

在该例子中,可以看到,a+10一定不会出现溢出的情况,因此智能的分析应该能够识别到此情况并将其设置为nuw和nsw。
上述程序生成的核心IR为:

; Function Attrs: mustprogress nofree nounwind uwtable
define dso_local void @_Z4funcjj(i32 noundef %a, i32 noundef %b) local_unnamed_addr #0 {
entry:%cmp = icmp ult i32 %a, 10000%add = add nuw nsw i32 %a, 10%spec.select = select i1 %cmp, i32 %add, i32 0%call = tail call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str, i32 noundef %spec.select)ret void
}

也就是说,包含nuw和nsw的表达式是比未包含上述情况的表达式更precise的,因此如果在优化中遇到了这两种同时出现的情况,应该注意不能直接将未包含nsw和nuw的那个表达式删除。这样会造成分析的精度下降。

通过调试发现,-O0生成的add表达式是不包含nuw和nsw flag的,因此是通过后续的优化将其设置上的。简化的调用栈如下:

llvm::Instruction::setHasNoUnsignedWrap llvm/lib/IR/Instruction.cpp:349
llvm::refineInstruction llvm/lib/Transforms/Utils/SCCPSolver.cpp:130

再次印证了nuw和nsw是和优化密切相关的两个flag。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/692045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

欲速则不达,慢就是快!

引言 随着生活水平的提高&#xff0c;不少人的目标从原先的解决温饱转变为追求内心充实&#xff0c;但由于现在的时间过得越来越快以及其他外部因素&#xff0c;我们对很多东西的获取越来越没耐心&#xff0c;例如书店经常会看到《7天精通Java》、《3天掌握XXX》等等之类的书籍…

金山下的wps,无法删除水印

RT&#xff0c;正常删除水印的流程是&#xff0c;插入-水印-删除水印。 如图的操作方法不生效时&#xff0c;可用下面的方法 点击页眉或页脚&#xff0c;进入页眉的编辑模式&#xff0c;可以看到水印变成可以选中的状态&#xff0c;选中&#xff0c;点击delete或者鼠标右键删…

数衍科技连接CRM和营销系统,无代码API集成

{无代码开发的优势} 在数字化转型的浪潮中&#xff0c;无代码开发为企业带来了巨大的便利。数衍科技&#xff0c;这家专注于生态数据服务的国家高新技术企业&#xff0c;提供了一种无需依赖传统API开发的解决方案。企业可以通过其无代码开发平台&#xff0c;迅速构建数据连接&…

[AIGC] 垃圾回收算法

垃圾回收算法 垃圾回收是一种自动化的内存管理方法。其核心目标是找出程序中不再使用的动态分配的内存块&#xff0c;并将其标记为可重用&#xff0c;以便能够进行新的内存分配。 下面我们将介绍三种主要的垃圾回收算法&#xff1a;标记清除算法、复制算法和标记压缩算法。 …

如何使用Docker搭建YesPlayMusic网易云音乐播放器并发布至公网访问

文章目录 1. 安装Docker2. 本地安装部署YesPlayMusic3. 安装cpolar内网穿透4. 固定YesPlayMusic公网地址 本篇文章讲解如何使用Docker搭建YesPlayMusic网易云音乐播放器&#xff0c;并且结合cpolar内网穿透实现公网访问音乐播放器。 YesPlayMusic是一款优秀的个人音乐播放器&am…

知识蒸馏实战代码教学一(原理部分)

一、知识蒸馏的来源 知识蒸馏&#xff08;Knowledge Distillation&#xff09;源自于一篇由Hinton等人于2015年提出的论文《Distilling the Knowledge in a Neural Network》。这个方法旨在将一个大型、复杂的模型的知识&#xff08;通常称为教师模型&#xff09;转移到一个小型…

不同编程网站应当注意的点

文章目录 引入&#xff1a;洛谷&#xff1a;POJ&#xff1a;C语言&#xff1a;C: CF&#xff1a;个人建议&#xff1a;补充&#xff1a; 引入&#xff1a; 小伙伴们有没有遇到过这种情况&#xff1a;到一个新的网站去编程&#xff0c;思路、算法完全正确&#xff0c;提交上去却…

初识动态规划

斐波那契数列大家一定很熟悉吧**【f(n)f(n-1)f(n-2)】**&#xff0c;如果要通过代码来表达斐波那契数列也是很简单的&#xff0c;只需要一个简易的递归即可。但是由于递归的一些缺陷&#xff0c;自然有人会写出迭代方式 int Fun(int n){if(n1 || n2)return 1;first1;second1th…

kube-ovn自定义vpc

配置自定义vpc 开启自定义vpc网关配置 对于自定义的vpc网关需要configmap配置文件进行开启 ovn-vpc-nat-config中指定了自定义vpc网关的pod使用的镜像&#xff0c;自定义vpc的网关就是一个pod&#xff0c;在pod中通过配置iptables来实现了eip、snat、dnat、fip 对于ovn-vpc-n…

Adobe Me下载安装免费(专业视频和音频编码应用软件Me安装包下载2024【Windows版】)

Adobe全家桶下载方式 Ae下载 Pr下载 Ai下载 Me下载 将持续更新~ 文章目录 Adobe全家桶下载方式Me下载方式【点我获取下载链接】我们的网站一、Me简介二、链接内容包含1.Me软件 声明 Me下载方式【点我获取下载链接】 百度网盘下载&#xff1a;百度网盘下载夸克网盘下载&#…

[Bug解决] Invalid bound statement (not found)出现原因和解决方法

1、问题描述 在写了一个很普通的查询语句之后&#xff0c;出现了下面的报错信息 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.oauth.mapper.WxVisitorQrBeanMapper.selectByComIdAndEmpId at org.apache.ibatis.binding.Mappe…

基于python+django+vue.js开发的健身房管理系统

功能介绍 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 功能包括&#xff1a;教练管理、会员管理、场地管理、设备管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeeeek/python_…

嵌入式C语言学习——基于Linux与GCC(二)

系列文章目录 一.C语言常用关键字及运算符操作 文章目录 系列文章目录内存四区指针指针概述指针 修饰符constvolatiletypedef 指针运算符多级指针 数组数组空间字符空间及地址 结构体、共用体定义、字节对齐位域 内存分布图段错误分析 内存四区 C/C语言的内存四区&#xff0…

Django模板(四)

一、include标签 加载一个模板,并在当前上下文中进行渲染。这是一种在模板中 “包含” 其他模板的方式 简单的理解:在当前模板中引入另外一个模板内容 1.1、使用方法 模板名称可以是变量,也可以是单引号或双引号的硬编码(带引号)的字符串 {% include "foo/bar.ht…

ALBEF算法解读

ALBEF论文全名Align before Fuse: Vision and Language Representation Learning with Momentum Distillation&#xff0c;来自于Align before Fuse&#xff0c;作者团队为Salesforce Research。 论文地址&#xff1a;https://arxiv.org/pdf/2107.07651.pdf 论文代码&#xff1…

美国首届生成式人工智能与法律研讨(上)

美国首届生成式人工智能与法律研讨(上) 文章目录 美国首届生成式人工智能与法律研讨(上)前言一、引言二、生成式AI对法律的影响三、生成式AI与法律的跨学科研究3.1 确定和定义跨学科术语3.2 构建有价值的隐喻3.3 理解不断发展的商业模式四、生成式AI的独特性4.1 从执行狭义…

GO框架基础 (三)、xorm库

xorm介绍 官网&#xff1a;https://xorm.io/ git文档&#xff1a;https://github.com/go-xorm/xorm xorm 是一个 Go 语言的 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它提供了一种简单、高效的方式来将 Go 语言中的结构体与数据库表进行映射&#xff0c;并提供了…

[OpenAI]继ChatGPT后发布的Sora模型解析与体验通道

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言OpenAI体验通道Spacetime Latent Patches 潜变量时空碎片, 建构视觉语言系统…

【RHCE】shell条件测试练习

目录 1、判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查次磁盘剩余空间。 2、判断web服务是否运行 3、使用curl命令访问第二题的web服务&#xff0c;看能否正常访问&#xff0c;如果能正常访问&#xff0c;…

计算机网络-H3C网络端口基础信息与配置

一、网络端口基础信息与配置 这个主要是记录一下关于华三的交换机、防火墙和路由器的物理接口的一些基础知识与配置。 1.1 命名规范 H3C的端口命名主要是根据端口的速率来进行区分的。基本都是千兆速率往上的&#xff0c;百兆的端口比较多用于二层傻瓜交换机或者不能CLI管理的。…