代码恒等式
- Algebraic identities: e.g, x + 0 = 0 + x = x
- Constant folding: e.g, 2 * 4 => 8
- Strength reductions: e.g, 2 * x => (x + x) or (x << 1)
基础代码
测试代码
1 | int compute () |
Makefile
1 | .PHONY : all clean run_ol build_ll make_so |
实现分析
为了实现代码恒等,首先。
我们需要知道 Instruction
里面保存着,
操作符,getOpcodeName()
得到操作符名字。
每个 IR 中间语言的 操作参数数量,getNumOperands()
每个参数是什么,getOperand(num)
num对应第几个参数(保存的是参数的地址)
对 IR 语句中 语句进行优化替换 replaceAllUsesWith(val)
替换所有 val 的地方
优化过后,会多出不需要的 IR 指令,IR 指令进行删除。
实现代码
实现第一个
Algebraic identities: e.g, x + 0 = 0 + x = x
实现功能代码。
1 | if(ConstVal1 == 0){ |
对 ssa 的修改
1 | // 未加载时 |
我们可以看到 我们已经优化了这个 ret的值 直接为 19。
但是有个问题就是,我们这里 %1 = add nsw i32 19, 0
这行代码就多余了,没有实际作用。
所以我们需要删除这段。
实现用到的代码 但是要注意 我们利用 eraseFromParent
函数后要 return 不然就会出现报错。 因为我们要 把Function 便利完 把找到需要删除的地方一起删除,这样才能实现程序的正常运行。所以放在 runOnFunction
最后。
1 | if(opted){ |
报错
这样我们的 优化过后就是最精炼的了。
1 | # 添加删除后。 |
- 注意 我们利用的是
dyn_cast<ConstantInt>(Opd1)->getSExtValue()
来得到值判断是不是0 - 但是想 %1 这种只能返回为 0。我们只是为了实现 目标中的 一次。所以代码有待改进。
实现第二个
Constant folding: e.g, 2 * 4 => 8
首先我们要注意 x * 0 = 0; 0*x = 0;
实现功能
1 | errs() << "Mul\n"; |
测试变化
1 | // 删除之前 |
实现第三个
Strength reductions: e.g, 2 * x => (x + x) or (x << 1)
这个要判断 相乘的数是否是 2的几次方等。要实现这个功能。
我们的 mul 要重写。
首先判断是否是 2的几次方。
1 | int getShift(int64_t x) { |
然后修改 mul为
1 | if (isa<ConstantInt>(Opd1) && getShift(ConstVal1) != -1) { |
参考 https://github.com/eternalsakura/sakura_llvm_opt/blob/master/assignment1/src/LocalOpts.cpp
逆向混淆可以看看实现办法