forked from OSchip/llvm-project
[ObjCARC] Drop nullary clang.arc.attachedcall bundles in autoupgrade.
In certain use-cases, these can be emitted by old compilers, but the operand is now always required. These are only used for optimizations, so it's safe to drop them if they happen to have the now-invalid format. The semantically-required call is already a separate instruction. Differential Revision: https://reviews.llvm.org/D123811
This commit is contained in:
parent
59726668f1
commit
362b4066f0
|
@ -14,6 +14,7 @@
|
|||
#define LLVM_IR_AUTOUPGRADE_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class AttrBuilder;
|
||||
|
@ -28,6 +29,9 @@ namespace llvm {
|
|||
class Type;
|
||||
class Value;
|
||||
|
||||
template <typename T> class OperandBundleDefT;
|
||||
using OperandBundleDef = OperandBundleDefT<Value *>;
|
||||
|
||||
/// 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 @@ namespace llvm {
|
|||
/// Upgrade attributes that changed format or kind.
|
||||
void UpgradeAttributes(AttrBuilder &B);
|
||||
|
||||
/// Upgrade operand bundles (without knowing about their user instruction).
|
||||
void UpgradeOperandBundles(std::vector<OperandBundleDef> &OperandBundles);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5138,6 +5138,10 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
|
|||
}
|
||||
}
|
||||
|
||||
// Upgrade the bundles if needed.
|
||||
if (!OperandBundles.empty())
|
||||
UpgradeOperandBundles(OperandBundles);
|
||||
|
||||
I = CallInst::Create(FTy, Callee, Args, OperandBundles);
|
||||
ResTypeID = getContainedTypeID(FTyID);
|
||||
OperandBundles.clear();
|
||||
|
|
|
@ -4675,3 +4675,15 @@ void llvm::UpgradeAttributes(AttrBuilder &B) {
|
|||
B.addAttribute(Attribute::NullPointerIsValid);
|
||||
}
|
||||
}
|
||||
|
||||
void llvm::UpgradeOperandBundles(std::vector<OperandBundleDef> &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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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*)
|
Binary file not shown.
Loading…
Reference in New Issue