[ObjCARC] Drop nullary clang.arc.attachedcall bundles in autoupgrade.
authorAhmed Bougacha <ahmed@bougacha.org>
Fri, 20 May 2022 22:26:31 +0000 (15:26 -0700)
committerAhmed Bougacha <ahmed@bougacha.org>
Fri, 20 May 2022 22:27:29 +0000 (15:27 -0700)
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

llvm/include/llvm/IR/AutoUpgrade.h
llvm/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/lib/IR/AutoUpgrade.cpp
llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll [new file with mode: 0644]
llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll.bc [new file with mode: 0644]

index bcece46..96d20a7 100644 (file)
@@ -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
index 9d49a96..cc58929 100644 (file)
@@ -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();
index fbd0877..8028371 100644 (file)
@@ -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();
+  });
+}
diff --git a/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll b/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll
new file mode 100644 (file)
index 0000000..7b012ab
--- /dev/null
@@ -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 (file)
index 0000000..bd47cfc
Binary files /dev/null and b/llvm/test/Bitcode/upgrade-arc-attachedcall-bundle.ll.bc differ