// 只支持 X86
static cl::opt<bool> SimplifyRODataLoads(
"simplify-rodata-loads",
cl::desc("通过用相应节中找到的常数替换内存操作数,简化来自只读节的加载"),
cl::cat(BoltOptCategory));
测试用例:
./build4/bin/llvm-lit bolt/test/X86/rodata-simpl-loads.test -a
# bolt/test/X86/Inputs/rodata_simpl_loads.s
效果(立即数代替了地址(少了寻址过程)
):
bool SimplifyRODataLoads::simplifyRODataLoads(BinaryFunction &BF) {
// 对所以可能加载内存的操作
Desc.mayLoad()
// 如果是 PC 相关的指令
if (MIB->hasPCRelOperand(Inst)) {
// 获取内存操作数的偏移
MCOperand *DispOpI = MIB->getMemOperandDisp(Inst);
// 通过内存操作数获取目标符号与偏移
std::tie(DisplSymbol, DisplOffset) = MIB->getTargetSymbolInfo(DispOpI->getExpr());
// 通过偏移符号获取 BinaryData
BinaryData *BD = BC.getBinaryDataByName(DisplSymbol->getName());
// 起始地址加偏移获取目的地址
TargetAddress = BD->getAddress() + DisplOffset;
}
// 不然直接通过接口获取
else if (!MIB->evaluateMemOperandTarget(Inst, TargetAddress))
// 根据目标地址获取Sec, 只处理只读节
BC.getSectionForAddress(TargetAddress);
// 如果目标地址需要重定位或需要动态重定位(链接时数据可能会更改) -- 无法处理
// 计算节省的动态加载的次数
NumDynamicLocalLoadsFound += BB->getExecutionCount();
// 最后的替换动作 -- 只支持x86
MIB->replaceMemOperandWithImm(Inst, ConstantData, Offset)
}
遗留问题:
- arm 能否实现相同场景的优化
- 是否可以放到链接时做