在 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
节点]参数。
我正在努力了解元数据在 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
节点]参数。