openGauss之LLVM代码走读 一. 前言openGauss的LLVM是指动态使用LLVM的库来构建动态代码和编译成字节码加速频繁调用的代码块的执行时间主要用在向量引擎中读取数据和join计算等场景下的计算加速被视为一个重要的性能优化方向。openGauss中通过将enable_codegen设置成true和codegen_cost_threshold设置为0强制开启此特性。本文主要简单的sqlselect col_bool is true from test1 了解openGauss是如何通过LLVM 动态生成col_bool is true的计算代码的。二. ExecInitCStoreScan 根据node生成动态代码ExecInitCStoreScan 的时候将expr的实现修改成动态代码的方式实现if (consider_codegen plan_stat-ps_ProjInfo-pi_targetlist) { jitted_vectarget dorado::VecExprCodeGen::TargetListCodeGen(plan_stat-ps_ProjInfo-pi_targetlist, (PlanState*)scan_stat); // 如下声明动态生成的函数为 bool JittedVecTargetList(ExprContext* econtext, VectorBatch* pBatch) GsCodeGen::FnPrototype fn_prototype(llvmCodeGen, JittedVecTargetList, boolType); fn_prototype.addArgument(GsCodeGen::NamedVariable(econtext, ExprContextPtrType)); fn_prototype.addArgument(GsCodeGen::NamedVariable(pBatch, VectorBatchPtrType)); jitted_vectarget fn_prototype.generatePrototype(builder, llvmargs[0]); // 生成ecxt_batch WrapGetVectorBatch(econtext) ecxt_batch WrapGetVectorBatchCodeGen(builder, econtext); // 生成 int m_rows pBatch-m_rows nsize builder.CreateLoad(int32Type, val, m_rows); // 生成for (int64 i 0; i nsize, i) builder.SetInsertPoint(for_body); Phi_idx builder.CreatePHI(int64Type, 2); idx_next builder.CreateAdd(Phi_idx, Datum_1); Phi_idx-addIncoming(Datum_0, entry); Phi_idx-addIncoming(idx_next, bb_end); // 依次生成每列的计算代码块,比如 // pBatch-m_arr[0]-m_vals[i] xx; // pBatch-m_arr[1]-m_vals[i] xx; // pBatch-m_arr[2]-m_vals[i] xx; foreach (cell, targetlist) { // 生成计算表达式的代码块比如对于is ture的判断生成一个JittedBooleanTest的动态代码实现原理和本代码段基本一样 res CodeGen(args); // 当前为第几列 AttrNumber resind tle-resno - 1; // 生成pBatch-m_arr[resind]-m_vals[i] res比如 // pBatch-m_arr[0]-m_vals[i] res Vals[0] colind; Vals[1] m_valsoffset; argVec builder.CreateInBoundsGEP(argArr, Vals); argVec builder.CreateLoad(int64PtrType, argVec, m_vals); argVal builder.CreateInBoundsGEP(argVec, loop_index); // 生成pBatch-m_arr[resind]-m_flag[i] tmpNull比如 // pBatch-m_arr[0]-m_flag[i] tmpNull Vals[1] m_flagoffset; argFlag builder.CreateInBoundsGEP(argArr, Vals); argFlag builder.CreateLoad(int8PtrType, argFlag, m_flag); llvm::Value* tmpFlag builder.CreateInBoundsGEP(argFlag, loop_index); llvm::Value* tmpNull isNull; tmpNull builder.CreateLoad(int8Type, tmpNull); builder.CreateStore(tmpNull, tmpFlag); } // pBatch-m_rows nsize foreach (cell, targetlist) { GenericExprState* gstate (GenericExprState*)lfirst(cell); TargetEntry* tle (TargetEntry*)gstate-xprstate.expr; AttrNumber resind tle-resno - 1; DEFINE_CGVAR_INT32(colind, resind); Vals[0] colind; Vals[1] int32_0; val1 builder.CreateInBoundsGEP(argArr, Vals); builder.CreateStore(nsize, val1); // argArr[resind].m_rows nsize; } // 存到hashMap中待后续生成机器码保存到plan_stat-ps_ProjInfo-jitted_vectarget中 if (jitted_vectarget ! NULL) llvm_code_gen-addFunctionToMCJit( jitted_vectarget, reinterpret_castvoid**((plan_stat-ps_ProjInfo-jitted_vectarget))); }综上所示上述的代码会生成一个类似如下的动态代码段bool JittedVecTargetList(ExprContext* econtext, VectorBatch* pBatch) { VectorBatch* ecxt_batch LLVMWrapGetVecBatch(econtext); int m_rows ecxt_batch-m_rows; for (int64 i 0; i m_rows; i) { // 同样用动态的方式生成列表达式的计算代码 res CodeGen(args); pBatch-m_arr[0]-m_vals[i] res; pBatch-m_arr[0]-m_flag[i] isNull; res CodeGen(args); pBatch-m_arr[1]-m_vals[i] res; pBatch-m_arr[1]-m_flag[i] isNull; res CodeGen(args); pBatch-m_arr[2]-m_vals[i] res; pBatch-m_arr[2]-m_flag[i] isNull; ..... } pBatch-m_arr[0].m_rows nsize; pBatch-m_arr[1].m_rows nsize; pBatch-m_arr[2].m_rows nsize; .... }三. standard_ExecutorRun中编译函数生成字节码步骤二生成的代码块仍然只是动态代码块需要编译成二进制字节码才可被执行。standard_ExecutorRun if (CodeGenThreadObjectReady()) { CodeGenThreadRuntimeCodeGenerate(); ((dorado::GsCodeGen*)t_thrd.codegen_cxt.thr_codegen_obj)-enableOptimizations(true); //对代码段使用o3优化 ((dorado::GsCodeGen*)t_thrd.codegen_cxt.thr_codegen_obj)-compileCurrentModule(false); GsCodeGen::compileCurrentModule llvm::Function* func map-key; // 步骤二生成的函数 void* jittedFunction exectorEngine-getPointerToFunction(func); // 编译成机器码 *map-value jittedFunction; // 编译后的字节码赋值给plan_stat-ps_ProjInfo-jitted_vectarget }四. 调用执行LLVM的动态代码在执行算子时判断如果plan_stat-ps_ProjInfo-jitted_vectarget有动态生成的机器码那么使用动态生成的机器码否则使用原来的流程。ExecVecProject if (projInfo-pi_targetlist) { if (projInfo-jitted_vectarget) { // 有动态生成的字节码 projInfo-jitted_vectarget(econtext, pProjBatch); JittedVecTargetList // 调用生成的函数 } }

相关新闻

最新新闻

GEO服务公司源易信息参与高校课程共建,推动AI时代信息资源管理教学

GEO服务公司源易信息参与高校课程共建,推动AI时代信息资源管理教学

当生成式AI正在改变用户获取信息的方式,企业也开始面对一个全新的问题:过去,企业关心自己在搜索引擎中能否被看见;今天,企业还必须关心自己在AI回答、智能推荐和大模型生成内容中如何被理解、被引用、被比较和被推荐。…

2026/7/5 5:22:42
Qwen3.5本地部署实战:sglang+LiteLLM打通Claude Code工具调用

Qwen3.5本地部署实战:sglang+LiteLLM打通Claude Code工具调用

1. 项目概述:为什么一个本地大模型部署教程值得花三小时读完?我最近把 Qwen3.5-9B 稳稳当当地跑在了自己那台双卡 4090 的工作站上,不是为了发论文,也不是为了搭 Demo 给老板看,而是为了每天写代码时少点“CtrlC / Ctr…

2026/7/5 5:22:42
喜马拉雅音频下载神器:跨平台GUI工具完全指南

喜马拉雅音频下载神器:跨平台GUI工具完全指南

喜马拉雅音频下载神器:跨平台GUI工具完全指南 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 喜马拉雅FM专辑下载器是一…

2026/7/5 5:22:42
终极指南:FanControl免费风扇控制软件,让PC散热与静音完美平衡

终极指南:FanControl免费风扇控制软件,让PC散热与静音完美平衡

终极指南:FanControl免费风扇控制软件,让PC散热与静音完美平衡 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com…

2026/7/5 5:22:42
英雄联盟自动化工具:5个关键功能提升你的游戏效率

英雄联盟自动化工具:5个关键功能提升你的游戏效率

英雄联盟自动化工具:5个关键功能提升你的游戏效率 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 英雄联盟Akari助手是一款基于LCU…

2026/7/5 5:22:42
英雄联盟效率工具League Akari:智能本地化助手的完整使用指南

英雄联盟效率工具League Akari:智能本地化助手的完整使用指南

英雄联盟效率工具League Akari:智能本地化助手的完整使用指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League Akari是一款基…

2026/7/5 5:17:41

月新闻