diff options
author | Nikita Popov <npopov@redhat.com> | 2022-07-07 12:27:43 +0200 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2022-07-15 10:18:17 +0200 |
commit | 2a721374aef326d4668f750d341c86d1aa1a0309 (patch) | |
tree | 234adf3c0ee20439eb8077b5a0702b4d88f35efa /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | cae5462a2caa4a14516d3935d2ca3a1f1d0522c9 (diff) | |
download | llvm-2a721374aef326d4668f750d341c86d1aa1a0309.zip llvm-2a721374aef326d4668f750d341c86d1aa1a0309.tar.gz llvm-2a721374aef326d4668f750d341c86d1aa1a0309.tar.bz2 |
[IR] Don't use blockaddresses as callbr arguments
Following some recent discussions, this changes the representation
of callbrs in IR. The current blockaddress arguments are replaced
with `!` label constraints that refer directly to callbr indirect
destinations:
; Before:
%res = callbr i8* asm "", "=r,r,i"(i8* %x, i8* blockaddress(@test8, %foo))
to label %asm.fallthrough [label %foo]
; After:
%res = callbr i8* asm "", "=r,r,!i"(i8* %x)
to label %asm.fallthrough [label %foo]
The benefit of this is that we can easily update the successors of
a callbr, without having to worry about also updating blockaddress
references. This should allow us to remove some limitations:
* Allow unrolling/peeling/rotation of callbr, or any other
clone-based optimizations
(https://github.com/llvm/llvm-project/issues/41834)
* Allow duplicate successors
(https://github.com/llvm/llvm-project/issues/45248)
This is just the IR representation change though, I will follow up
with patches to remove limtations in various transformation passes
that are no longer needed.
Differential Revision: https://reviews.llvm.org/D129288
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 8d5a255..1d6c21b 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5510,6 +5510,61 @@ Error BitcodeReader::parseFunctionBody(Function *F) { if (!OperandBundles.empty()) UpgradeOperandBundles(OperandBundles); + if (auto *IA = dyn_cast<InlineAsm>(Callee)) { + InlineAsm::ConstraintInfoVector ConstraintInfo = IA->ParseConstraints(); + auto IsLabelConstraint = [](const InlineAsm::ConstraintInfo &CI) { + return CI.Type == InlineAsm::isLabel; + }; + if (none_of(ConstraintInfo, IsLabelConstraint)) { + // Upgrade explicit blockaddress arguments to label constraints. + // Verify that the last arguments are blockaddress arguments that + // match the indirect destinations. Clang always generates callbr + // in this form. We could support reordering with more effort. + unsigned FirstBlockArg = Args.size() - IndirectDests.size(); + for (unsigned ArgNo = FirstBlockArg; ArgNo < Args.size(); ++ArgNo) { + unsigned LabelNo = ArgNo - FirstBlockArg; + auto *BA = dyn_cast<BlockAddress>(Args[ArgNo]); + if (!BA || BA->getFunction() != F || + LabelNo > IndirectDests.size() || + BA->getBasicBlock() != IndirectDests[LabelNo]) + return error("callbr argument does not match indirect dest"); + } + + // Remove blockaddress arguments. + Args.erase(Args.begin() + FirstBlockArg, Args.end()); + ArgTyIDs.erase(ArgTyIDs.begin() + FirstBlockArg, ArgTyIDs.end()); + + // Recreate the function type with less arguments. + SmallVector<Type *> ArgTys; + for (Value *Arg : Args) + ArgTys.push_back(Arg->getType()); + FTy = + FunctionType::get(FTy->getReturnType(), ArgTys, FTy->isVarArg()); + + // Update constraint string to use label constraints. + std::string Constraints = IA->getConstraintString(); + unsigned ArgNo = 0; + size_t Pos = 0; + for (const auto &CI : ConstraintInfo) { + if (CI.hasArg()) { + if (ArgNo >= FirstBlockArg) + Constraints.insert(Pos, "!"); + ++ArgNo; + } + + // Go to next constraint in string. + Pos = Constraints.find(',', Pos); + if (Pos == std::string::npos) + break; + ++Pos; + } + + Callee = InlineAsm::get(FTy, IA->getAsmString(), Constraints, + IA->hasSideEffects(), IA->isAlignStack(), + IA->getDialect(), IA->canThrow()); + } + } + I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args, OperandBundles); ResTypeID = getContainedTypeID(FTyID); |