在 LLVM IR 中设置分支权重元数据

Setting branch weight metadata in LLVM IR

我正在努力了解元数据在 LLVM 中的工作方式以及如何设置分析元数据以指定分支权重,具体针对 BranchInst 这些文档:https://llvm.org/docs/BranchWeightMetadata.html

使用 C API,我对元数据工作原理的理解使我相信这就是您实现此目标的方式:

LLVMMetadataRef branch_weights = LLVMMDStringInContext2(LLVMGetGlobalContext(), "branch_weights", 14);
LLVMMetadataRef weight1 = LLVMMDStringInContext2(LLVMGetGlobalContext(), "0", 1);
LLVMMetadataRef weight2 = LLVMMDStringInContext2(LLVMGetGlobalContext(), "100", 3);
LLVMMetadataRef mds[] = {branch_weights, weight1, weight2};
LLVMMetadataRef metadata = LLVMMDNodeInContext2(LLVMGetGlobalContext(), mds, 3);
LLVMValueRef metadata_value = LLVMMetadataAsValue(LLVMGetGlobalContext(), metadata);

但这在 IR 中给出了以下内容:

!0 = !{!"branch_weights", !"0", !"100"}

根据上面链接的文档,我想要这个:

!0 = metadata !{
  metadata !"branch_weights",
  i32 <TRUE_BRANCH_WEIGHT>,
  i32 <FALSE_BRANCH_WEIGHT>
}

如何在元数据中实现上述格式,最好使用 C API,确保它是文档中提到的 MD_prof 类型?

事实证明,主要区别在于必须使用 LLVMValueAsMetadata 来获取权重而不是字符串的整数,然后必须为 kindID 字段指定 prof,给出:

LLVMMetadataRef branch_weights = LLVMMDStringInContext2(LLVMGetGlobalContext(), branch, 14);
LLVMMetadataRef weight1 = LLVMValueAsMetadata(LLVMConstInt(LLVMIntType(32), 0, 0));
LLVMMetadataRef weight2 = LLVMValueAsMetadata(LLVMConstInt(LLVMIntType(32), 100, 0));
LLVMMetadataRef mds[] = {branch_weights, weight1, weight2};
LLVMMetadataRef metadata = LLVMMDNodeInContext2(LLVMGetGlobalContext(), mds, 3);
LLVMValueRef metadata_value = LLVMMetadataAsValue(LLVMGetGlobalContext(), metadata);

LLVMSetMetadata(<branch instruction here>, LLVMGetMDKindID("prof", 4), metadata_value);

这给出了 !0 = !{!"branch_weights", i32 0, i32 100},虽然格式与文档中的内容略有不同,但仍然通过了 opt -verify,并且由于 kindID 应该被解析为 MD_prof 节点]参数。