diff --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h --- a/llvm/include/llvm/IR/AutoUpgrade.h +++ b/llvm/include/llvm/IR/AutoUpgrade.h @@ -14,6 +14,7 @@ #define LLVM_IR_AUTOUPGRADE_H #include "llvm/ADT/StringRef.h" +#include namespace llvm { class AttrBuilder; @@ -28,6 +29,9 @@ class Type; class Value; + template class OperandBundleDefT; + using OperandBundleDef = OperandBundleDefT; + /// This is a more granular function that simply checks an intrinsic function /// for upgrading, and returns true if it requires upgrading. It may return /// null in NewFn if the all calls to the original intrinsic function @@ -99,6 +103,9 @@ /// Upgrade attributes that changed format or kind. void UpgradeAttributes(AttrBuilder &B); + /// Upgrade operand bundles (without knowing about their user instruction). + void UpgradeOperandBundles(std::vector &OperandBundles); + } // End llvm namespace #endif diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5138,6 +5138,10 @@ } } + // Upgrade the bundles if needed. + if (!OperandBundles.empty()) + UpgradeOperandBundles(OperandBundles); + I = InvokeInst::Create(FTy, Callee, NormalBB, UnwindBB, Ops, OperandBundles); ResTypeID = getContainedTypeID(FTyID); @@ -5235,6 +5239,10 @@ } } + // Upgrade the bundles if needed. + if (!OperandBundles.empty()) + UpgradeOperandBundles(OperandBundles); + I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args, OperandBundles); ResTypeID = getContainedTypeID(FTyID); @@ -5846,6 +5854,10 @@ } } + // Upgrade the bundles if needed. + if (!OperandBundles.empty()) + UpgradeOperandBundles(OperandBundles); + I = CallInst::Create(FTy, Callee, Args, OperandBundles); ResTypeID = getContainedTypeID(FTyID); OperandBundles.clear(); diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -4675,3 +4675,15 @@ B.addAttribute(Attribute::NullPointerIsValid); } } + +void llvm::UpgradeOperandBundles(std::vector &Bundles) { + + // clang.arc.attachedcall bundles are now required to have an operand. + // If they don't, it's okay to drop them entirely: when there is an operand, + // the "attachedcall" is meaningful and required, but without an operand, + // it's just a marker NOP. Dropping it merely prevents an optimization. + erase_if(Bundles, [&](OperandBundleDef &OBD) { + return OBD.getTag() == "clang.arc.attachedcall" && + OBD.inputs().empty(); + }); +} diff --git a/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll b/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll @@ -0,0 +1,23 @@ +; Test that nullary clang.arc.attachedcall operand bundles are "upgraded". + +; RUN: llvm-dis %s.bc -o - | FileCheck %s +; RUN: verify-uselistorder %s.bc + +define i8* @invalid() { +; CHECK-LABEL: define i8* @invalid() { +; CHECK-NEXT: %tmp0 = call i8* @foo(){{$}} +; CHECK-NEXT: ret i8* %tmp0 + %tmp0 = call i8* @foo() [ "clang.arc.attachedcall"() ] + ret i8* %tmp0 +} + +define i8* @valid() { +; CHECK-LABEL: define i8* @valid() { +; CHECK-NEXT: %tmp0 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] +; CHECK-NEXT: ret i8* %tmp0 + %tmp0 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] + ret i8* %tmp0 +} + +declare i8* @foo() +declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) diff --git a/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll.bc b/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@