[llvm] 2a72137 - [IR] Don't use blockaddresses as callbr arguments

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 15 01:18:27 PDT 2022


Author: Nikita Popov
Date: 2022-07-15T10:18:17+02:00
New Revision: 2a721374aef326d4668f750d341c86d1aa1a0309

URL: https://github.com/llvm/llvm-project/commit/2a721374aef326d4668f750d341c86d1aa1a0309
DIFF: https://github.com/llvm/llvm-project/commit/2a721374aef326d4668f750d341c86d1aa1a0309.diff

LOG: [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

Added: 
    

Modified: 
    clang/lib/CodeGen/CGStmt.cpp
    clang/test/CodeGen/asm-goto.c
    clang/test/CodeGen/asm.c
    clang/test/Modules/asm-goto.c
    llvm/docs/LangRef.rst
    llvm/docs/ReleaseNotes.rst
    llvm/include/llvm/IR/InlineAsm.h
    llvm/include/llvm/IR/Instructions.h
    llvm/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
    llvm/lib/IR/InlineAsm.cpp
    llvm/lib/IR/Instructions.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/test/Analysis/BasicAA/pr52735.ll
    llvm/test/Assembler/call-arg-is-callee.ll
    llvm/test/Assembler/inline-asm-constraint-error.ll
    llvm/test/Bitcode/callbr.ll
    llvm/test/CodeGen/AArch64/callbr-asm-label.ll
    llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll
    llvm/test/CodeGen/AArch64/speculation-hardening-sls.ll
    llvm/test/CodeGen/ARM/speculation-hardening-sls.ll
    llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll
    llvm/test/CodeGen/SystemZ/asm-20.ll
    llvm/test/CodeGen/X86/callbr-asm-bb-exports.ll
    llvm/test/CodeGen/X86/callbr-asm-blockplacement.ll
    llvm/test/CodeGen/X86/callbr-asm-branch-folding.ll
    llvm/test/CodeGen/X86/callbr-asm-destinations.ll
    llvm/test/CodeGen/X86/callbr-asm-instr-scheduling.ll
    llvm/test/CodeGen/X86/callbr-asm-kill.mir
    llvm/test/CodeGen/X86/callbr-asm-label-addr.ll
    llvm/test/CodeGen/X86/callbr-asm-obj-file.ll
    llvm/test/CodeGen/X86/callbr-asm-outputs-pred-succ.ll
    llvm/test/CodeGen/X86/callbr-asm-outputs.ll
    llvm/test/CodeGen/X86/callbr-asm-phi-placement.ll
    llvm/test/CodeGen/X86/callbr-asm-sink.ll
    llvm/test/CodeGen/X86/callbr-asm.ll
    llvm/test/CodeGen/X86/callbr-codegenprepare.ll
    llvm/test/CodeGen/X86/inline-asm-pic.ll
    llvm/test/CodeGen/X86/shrinkwrap-callbr.ll
    llvm/test/CodeGen/X86/speculation-hardening-sls.ll
    llvm/test/CodeGen/X86/tail-dup-asm-goto.ll
    llvm/test/Instrumentation/MemorySanitizer/msan_asm_conservative.ll
    llvm/test/Transforms/CallSiteSplitting/callsite-split-callbr.ll
    llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll
    llvm/test/Transforms/Coroutines/coro-debug.ll
    llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll
    llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll
    llvm/test/Transforms/GVN/critical-edge-split-failure.ll
    llvm/test/Transforms/IROutliner/illegal-callbr.ll
    llvm/test/Transforms/Inline/blockaddress.ll
    llvm/test/Transforms/Inline/callbr.ll
    llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
    llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
    llvm/test/Transforms/LICM/callbr-crash.ll
    llvm/test/Transforms/LoopDeletion/two-predecessors.ll
    llvm/test/Transforms/LoopRotate/callbr.ll
    llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll
    llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting2.ll
    llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll
    llvm/test/Transforms/LoopUnroll/callbr.ll
    llvm/test/Transforms/PGOProfile/callbr.ll
    llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll
    llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll
    llvm/test/Transforms/SimplifyCFG/jump-threading.ll
    llvm/test/Verifier/callbr.ll
    llvm/test/Verifier/dominates.ll
    llvm/test/tools/llvm-diff/callbr.ll
    llvm/test/tools/llvm-diff/phinode.ll
    llvm/test/tools/llvm-reduce/remove-function-arguments-of-funcs-used-in-blockaddress.ll
    llvm/unittests/IR/InstructionsTest.cpp
    polly/test/ScopDetect/callbr.ll

Removed: 
    llvm/test/CodeGen/X86/callbr-asm-errors.ll


################################################################################
diff  --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index df7e5608f8f05..05ab16668743b 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2603,14 +2603,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
       for (const auto *E : GS->labels()) {
         JumpDest Dest = getJumpDestForLabel(E->getLabel());
         Transfer.push_back(Dest.getBlock());
-        llvm::BlockAddress *BA =
-            llvm::BlockAddress::get(CurFn, Dest.getBlock());
-        Args.push_back(BA);
-        ArgTypes.push_back(BA->getType());
-        ArgElemTypes.push_back(nullptr);
         if (!Constraints.empty())
           Constraints += ',';
-        Constraints += 'i';
+        Constraints += "!i";
       }
       Fallthrough = createBasicBlock("asm.fallthrough");
     }

diff  --git a/clang/test/CodeGen/asm-goto.c b/clang/test/CodeGen/asm-goto.c
index 5949cda82434e..663aec3ebfad5 100644
--- a/clang/test/CodeGen/asm-goto.c
+++ b/clang/test/CodeGen/asm-goto.c
@@ -55,14 +55,14 @@ int test3(int out1, int out2) {
 
 int test4(int out1, int out2) {
   // CHECK-LABEL: define{{.*}} i32 @test4(
-  // CHECK: callbr { i32, i32 } asm sideeffect "jne ${5:l}", "={si},={di},r,0,1,i,i
+  // CHECK: callbr { i32, i32 } asm sideeffect "jne ${5:l}", "={si},={di},r,0,1,!i,!i
   // CHECK: to label %asm.fallthrough [label %label_true, label %loop]
   // CHECK-LABEL: asm.fallthrough:
   if (out1 < out2)
     asm volatile goto("jne %l5" : "+S"(out1), "+D"(out2) : "r"(out1) :: label_true, loop);
   else
     asm volatile goto("jne %l7" : "+S"(out1), "+D"(out2) : "r"(out1), "r"(out2) :: label_true, loop);
-  // CHECK: callbr { i32, i32 } asm sideeffect "jne ${7:l}", "={si},={di},r,r,0,1,i,i
+  // CHECK: callbr { i32, i32 } asm sideeffect "jne ${7:l}", "={si},={di},r,r,0,1,!i,!i
   // CHECK: to label %asm.fallthrough2 [label %label_true, label %loop]
   // CHECK-LABEL: asm.fallthrough2:
   return out1 + out2;
@@ -74,7 +74,7 @@ int test4(int out1, int out2) {
 
 int test5(int addr, int size, int limit) {
   // CHECK-LABEL: define{{.*}} i32 @test5(
-  // CHECK: callbr i32 asm "add $1,$0 ; jc ${4:l} ; cmp $2,$0 ; ja ${4:l} ; ", "=r,imr,imr,0,i
+  // CHECK: callbr i32 asm "add $1,$0 ; jc ${4:l} ; cmp $2,$0 ; ja ${4:l} ; ", "=r,imr,imr,0,!i
   // CHECK: to label %asm.fallthrough [label %t_err]
   // CHECK-LABEL: asm.fallthrough:
   asm goto(
@@ -92,7 +92,7 @@ int test5(int addr, int size, int limit) {
 
 int test6(int out1) {
   // CHECK-LABEL: define{{.*}} i32 @test6(
-  // CHECK: callbr i32 asm sideeffect "testl $0, $0; testl $1, $1; jne ${3:l}", "={si},r,0,i,i,{{.*}} i8* blockaddress(@test6, %label_true), i8* blockaddress(@test6, %landing)
+  // CHECK: callbr i32 asm sideeffect "testl $0, $0; testl $1, $1; jne ${3:l}", "={si},r,0,!i,!i,{{.*}}
   // CHECK: to label %asm.fallthrough [label %label_true, label %landing]
   // CHECK-LABEL: asm.fallthrough:
   // CHECK-LABEL: landing:
@@ -110,7 +110,7 @@ int test6(int out1) {
 // string, not $1.
 void *test7(void) {
   // CHECK-LABEL: define{{.*}} i8* @test7(
-  // CHECK: %1 = callbr i8* asm "# $0\0A\09# ${2:l}", "=r,0,i,~{dirflag},~{fpsr},~{flags}"(i8* %0, i8* blockaddress(@test7, %foo))
+  // CHECK: %1 = callbr i8* asm "# $0\0A\09# ${2:l}", "=r,0,!i,~{dirflag},~{fpsr},~{flags}"(i8* %0)
   // CHECK-NEXT: to label %asm.fallthrough [label %foo]
   void *p = &&foo;
   asm goto ("# %0\n\t# %l2":"+r"(p):::foo);
@@ -122,7 +122,7 @@ void *test7(void) {
 // numbered outputs.
 void *test8(void) {
   // CHECK-LABEL: define{{.*}} i8* @test8(
-  // CHECK: %1 = callbr i8* asm "# $0\0A\09# ${2:l}", "=r,0,i,~{dirflag},~{fpsr},~{flags}"(i8* %0, i8* blockaddress(@test8, %foo))
+  // CHECK: %1 = callbr i8* asm "# $0\0A\09# ${2:l}", "=r,0,!i,~{dirflag},~{fpsr},~{flags}"(i8* %0)
   // CHECK-NEXT: to label %asm.fallthrough [label %foo]
   void *p = &&foo;
   asm goto ("# %0\n\t# %l[foo]":"+r"(p):::foo);

diff  --git a/clang/test/CodeGen/asm.c b/clang/test/CodeGen/asm.c
index ec7e6d1556cb6..1901640afa97f 100644
--- a/clang/test/CodeGen/asm.c
+++ b/clang/test/CodeGen/asm.c
@@ -267,7 +267,8 @@ void t31(int len) {
 int t32(int cond)
 {
   asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop);
-  // CHECK: callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@t32, %label_true), i8* blockaddress(@t32, %loop)) #1
+  // CHECK: callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) #1
+  // CHECK-NEXT: to label %asm.fallthrough [label %label_true, label %loop]
   return 0;
 loop:
   return 0;

diff  --git a/clang/test/Modules/asm-goto.c b/clang/test/Modules/asm-goto.c
index 340795ee57458..278a710ae91c0 100644
--- a/clang/test/Modules/asm-goto.c
+++ b/clang/test/Modules/asm-goto.c
@@ -4,7 +4,7 @@
 #include "a.h"
 
 // CHECK-LABEL: define {{.*}} @foo(
-// CHECK: callbr {{.*}} "=r,i{{.*}} blockaddress(@foo, %indirect))
+// CHECK: callbr {{.*}} "=r,!i{{.*}}()
 // CHECK-NEXT: to label %asm.fallthrough [label %indirect]
 
 int bar(void) {

diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 24b3b5183da8e..d4dbff6f10f81 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4695,6 +4695,17 @@ output.
 Note that clobbering named registers that are also present in output
 constraints is not legal.
 
+Label constraints
+"""""""""""""""""
+
+A label constraint is indicated by a "``!``" prefix and typically used in the
+form ``"!i"``. Instead of consuming call arguments, label constraints consume
+indirect destination labels of ``callbr`` instructions.
+
+Label constraints can only be used in conjunction with ``callbr`` and the
+number of label constraints must match the number of indirect destination
+labels in the ``callbr`` instruction.
+
 
 Constraint Codes
 """"""""""""""""
@@ -8416,8 +8427,8 @@ This instruction requires several arguments:
 #. '``fallthrough label``': the label reached when the inline assembly's
    execution exits the bottom.
 #. '``indirect labels``': the labels reached when a callee transfers control
-   to a location other than the '``fallthrough label``'. The blockaddress
-   constant for these should also be in the list of '``function args``'.
+   to a location other than the '``fallthrough label``'. Label constraints
+   refer to these destinations.
 #. The optional :ref:`function attributes <fnattrs>` list.
 #. The optional :ref:`operand bundles <opbundles>` list.
 
@@ -8442,11 +8453,11 @@ Example:
 .. code-block:: llvm
 
       ; "asm goto" without output constraints.
-      callbr void asm "", "r,X"(i32 %x, i8 *blockaddress(@foo, %indirect))
+      callbr void asm "", "r,!i"(i32 %x)
                   to label %fallthrough [label %indirect]
 
       ; "asm goto" with output constraints.
-      <result> = callbr i32 asm "", "=r,r,X"(i32 %x, i8 *blockaddress(@foo, %indirect))
+      <result> = callbr i32 asm "", "=r,r,!i"(i32 %x)
                   to label %fallthrough [label %indirect]
 
 .. _i_resume:

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index f29a7aaba587c..5f7dca3c8e64a 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -84,6 +84,18 @@ Changes to the LLVM IR
 * Added the support for ``fmax`` and ``fmin`` in ``atomicrmw`` instruction. The
   comparison is expected to match the behavior of ``llvm.maxnum.*`` and
   ``llvm.minnum.*`` respectively.
+* ``callbr`` instructions no longer use ``blockaddress`` arguments for labels.
+  Instead, label constraints starting with ``!`` refer directly to entries in
+  the ``callbr`` indirect destination list.
+
+.. code-block:: llvm
+
+    ; Old representation
+    %res = callbr i32 asm "", "=r,r,i"(i32 %x, i8 *blockaddress(@foo, %indirect))
+          to label %fallthrough [label %indirect]
+    ; New representation
+    %res = callbr i32 asm "", "=r,r,!i"(i32 %x)
+          to label %fallthrough [label %indirect]
 
 Changes to building LLVM
 ------------------------

diff  --git a/llvm/include/llvm/IR/InlineAsm.h b/llvm/include/llvm/IR/InlineAsm.h
index 032a70efdceb0..0a8d27aad58a2 100644
--- a/llvm/include/llvm/IR/InlineAsm.h
+++ b/llvm/include/llvm/IR/InlineAsm.h
@@ -92,7 +92,8 @@ class InlineAsm final : public Value {
   enum ConstraintPrefix {
     isInput,            // 'x'
     isOutput,           // '=x'
-    isClobber           // '~x'
+    isClobber,          // '~x'
+    isLabel,            // '!x'
   };
 
   using ConstraintCodeVector = std::vector<std::string>;
@@ -117,7 +118,7 @@ class InlineAsm final : public Value {
   using ConstraintInfoVector = std::vector<ConstraintInfo>;
 
   struct ConstraintInfo {
-    /// Type - The basic type of the constraint: input/output/clobber
+    /// Type - The basic type of the constraint: input/output/clobber/label
     ///
     ConstraintPrefix Type = isInput;
 

diff  --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index a14bc39cea65b..083fed5de4a39 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -44,6 +44,7 @@ namespace llvm {
 class APFloat;
 class APInt;
 class BasicBlock;
+class BlockAddress;
 class ConstantInt;
 class DataLayout;
 class StringRef;
@@ -4004,9 +4005,6 @@ class CallBrInst : public CallBase {
             ArrayRef<BasicBlock *> IndirectDests, ArrayRef<Value *> Args,
             ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr);
 
-  /// Should the Indirect Destinations change, scan + update the Arg list.
-  void updateArgBlockAddresses(unsigned i, BasicBlock *B);
-
   /// Compute the number of operands to allocate.
   static int ComputeNumOperands(int NumArgs, int NumIndirectDests,
                                 int NumBundleInputs = 0) {
@@ -4154,7 +4152,6 @@ class CallBrInst : public CallBase {
     *(&Op<-1>() - getNumIndirectDests() - 1) = reinterpret_cast<Value *>(B);
   }
   void setIndirectDest(unsigned i, BasicBlock *B) {
-    updateArgBlockAddresses(i, B);
     *(&Op<-1>() - getNumIndirectDests() + i) = reinterpret_cast<Value *>(B);
   }
 
@@ -4172,6 +4169,8 @@ class CallBrInst : public CallBase {
 
   unsigned getNumSuccessors() const { return getNumIndirectDests() + 1; }
 
+  BlockAddress *getBlockAddressForIndirectDest(unsigned DestNo) const;
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const Instruction *I) {
     return (I->getOpcode() == Instruction::CallBr);

diff  --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 8d5a2555f9afb..1d6c21bd66d1b 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);

diff  --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
index 95ae8383b6faa..e0357c50e555a 100644
--- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
@@ -332,6 +332,8 @@ bool InlineAsmLowering::lowerInlineAsm(
       }
       ++ResNo;
     } else {
+      assert(OpInfo.Type != InlineAsm::isLabel &&
+             "GlobalISel currently doesn't support callbr");
       OpInfo.ConstraintVT = MVT::Other;
     }
 
@@ -427,7 +429,8 @@ bool InlineAsmLowering::lowerInlineAsm(
       }
 
       break;
-    case InlineAsm::isInput: {
+    case InlineAsm::isInput:
+    case InlineAsm::isLabel: {
       if (OpInfo.isMatchingInputConstraint()) {
         unsigned DefIdx = OpInfo.getMatchedOperand();
         // Find operand with register def that corresponds to DefIdx.

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index fe3c38ec590d0..d879fec7b11b3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2990,14 +2990,20 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
   CopyToExportRegsIfNeeded(&I);
 
   // Retrieve successors.
+  SmallPtrSet<BasicBlock *, 8> Dests;
+  Dests.insert(I.getDefaultDest());
   MachineBasicBlock *Return = FuncInfo.MBBMap[I.getDefaultDest()];
 
   // Update successor info.
   addSuccessorWithProb(CallBrMBB, Return, BranchProbability::getOne());
   for (unsigned i = 0, e = I.getNumIndirectDests(); i < e; ++i) {
-    MachineBasicBlock *Target = FuncInfo.MBBMap[I.getIndirectDest(i)];
-    addSuccessorWithProb(CallBrMBB, Target, BranchProbability::getZero());
+    BasicBlock *Dest = I.getIndirectDest(i);
+    MachineBasicBlock *Target = FuncInfo.MBBMap[Dest];
     Target->setIsInlineAsmBrIndirectTarget();
+    Target->setHasAddressTaken();
+    // Don't add duplicate machine successors.
+    if (Dests.insert(Dest).second)
+      addSuccessorWithProb(CallBrMBB, Target, BranchProbability::getZero());
   }
   CallBrMBB->normalizeSuccProbs();
 
@@ -8855,7 +8861,8 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
       }
       break;
 
-    case InlineAsm::isInput: {
+    case InlineAsm::isInput:
+    case InlineAsm::isLabel: {
       SDValue InOperandVal = OpInfo.CallOperand;
 
       if (OpInfo.isMatchingInputConstraint()) {

diff  --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index f61b5256d46b3..a31a5fa679967 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -5224,6 +5224,7 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
   // ConstraintOperands list.
   unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
   unsigned ResNo = 0; // ResNo - The result number of the next output.
+  unsigned LabelNo = 0; // LabelNo - CallBr indirect dest number.
 
   for (InlineAsm::ConstraintInfo &CI : IA->ParseConstraints()) {
     ConstraintOperands.emplace_back(std::move(CI));
@@ -5260,6 +5261,14 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
     case InlineAsm::isInput:
       OpInfo.CallOperandVal = Call.getArgOperand(ArgNo);
       break;
+    case InlineAsm::isLabel:
+      OpInfo.CallOperandVal =
+          cast<CallBrInst>(&Call)->getBlockAddressForIndirectDest(LabelNo);
+      OpInfo.ConstraintVT =
+          getAsmOperandValueType(DL, OpInfo.CallOperandVal->getType())
+              .getSimpleVT();
+      ++LabelNo;
+      continue;
     case InlineAsm::isClobber:
       // Nothing to do.
       break;

diff  --git a/llvm/lib/IR/InlineAsm.cpp b/llvm/lib/IR/InlineAsm.cpp
index c75b1aa7c1d65..088fcfdec742a 100644
--- a/llvm/lib/IR/InlineAsm.cpp
+++ b/llvm/lib/IR/InlineAsm.cpp
@@ -93,6 +93,9 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
   } else if (*I == '=') {
     ++I;
     Type = isOutput;
+  } else if (*I == '!') {
+    ++I;
+    Type = isLabel;
   }
 
   if (*I == '*') {
@@ -265,14 +268,14 @@ Error InlineAsm::verify(FunctionType *Ty, StringRef ConstStr) {
     return makeStringError("failed to parse constraints");
 
   unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
-  unsigned NumIndirect = 0;
+  unsigned NumIndirect = 0, NumLabels = 0;
 
   for (const ConstraintInfo &Constraint : Constraints) {
     switch (Constraint.Type) {
     case InlineAsm::isOutput:
-      if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
-        return makeStringError("output constraint occurs after input "
-                               "or clobber constraint");
+      if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0 || NumLabels != 0)
+        return makeStringError("output constraint occurs after input, "
+                               "clobber or label constraint");
 
       if (!Constraint.isIndirect) {
         ++NumOutputs;
@@ -289,6 +292,13 @@ Error InlineAsm::verify(FunctionType *Ty, StringRef ConstStr) {
     case InlineAsm::isClobber:
       ++NumClobbers;
       break;
+    case InlineAsm::isLabel:
+      if (NumClobbers)
+        return makeStringError("label constraint occurs after clobber "
+                               "constraint");
+
+      ++NumLabels;
+      break;
     }
   }
 
@@ -312,5 +322,7 @@ Error InlineAsm::verify(FunctionType *Ty, StringRef ConstStr) {
   if (Ty->getNumParams() != NumInputs)
     return makeStringError("number of input constraints does not match number "
                            "of parameters");
+
+  // We don't have access to labels here, NumLabels will be checked separately.
   return Error::success();
 }

diff  --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index b333f40f3ce95..26171f537244c 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -960,15 +960,10 @@ void CallBrInst::init(FunctionType *FTy, Value *Fn, BasicBlock *Fallthrough,
   setName(NameStr);
 }
 
-void CallBrInst::updateArgBlockAddresses(unsigned i, BasicBlock *B) {
-  assert(getNumIndirectDests() > i && "IndirectDest # out of range for callbr");
-  if (BasicBlock *OldBB = getIndirectDest(i)) {
-    BlockAddress *Old = BlockAddress::get(OldBB);
-    BlockAddress *New = BlockAddress::get(B);
-    for (unsigned ArgNo = 0, e = arg_size(); ArgNo != e; ++ArgNo)
-      if (dyn_cast<BlockAddress>(getArgOperand(ArgNo)) == Old)
-        setArgOperand(ArgNo, New);
-  }
+BlockAddress *
+CallBrInst::getBlockAddressForIndirectDest(unsigned DestNo) const {
+  return BlockAddress::get(const_cast<Function *>(getFunction()),
+                           getIndirectDest(DestNo));
 }
 
 CallBrInst::CallBrInst(const CallBrInst &CBI)

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 75d02f4c8c828..c540b01392fcd 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2200,7 +2200,13 @@ bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) {
 void Verifier::verifyInlineAsmCall(const CallBase &Call) {
   const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
   unsigned ArgNo = 0;
+  unsigned LabelNo = 0;
   for (const InlineAsm::ConstraintInfo &CI : IA->ParseConstraints()) {
+    if (CI.Type == InlineAsm::isLabel) {
+      ++LabelNo;
+      continue;
+    }
+
     // Only deal with constraints that correspond to call arguments.
     if (!CI.hasArg())
       continue;
@@ -2222,6 +2228,15 @@ void Verifier::verifyInlineAsmCall(const CallBase &Call) {
 
     ArgNo++;
   }
+
+  if (auto *CallBr = dyn_cast<CallBrInst>(&Call)) {
+    Check(LabelNo == CallBr->getNumIndirectDests(),
+          "Number of label constraints does not match number of callbr dests",
+          &Call);
+  } else {
+    Check(LabelNo == 0, "Label constraints can only be used with callbr",
+          &Call);
+  }
 }
 
 /// Verify that statepoint intrinsic is well formed.
@@ -2839,25 +2854,6 @@ void Verifier::visitCallBrInst(CallBrInst &CBI) {
   Check(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!", &CBI);
   const InlineAsm *IA = cast<InlineAsm>(CBI.getCalledOperand());
   Check(!IA->canThrow(), "Unwinding from Callbr is not allowed");
-  for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i)
-    Check(CBI.getSuccessor(i)->getType()->isLabelTy(),
-          "Callbr successors must all have pointer type!", &CBI);
-  for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) {
-    Check(i >= CBI.arg_size() || !isa<BasicBlock>(CBI.getOperand(i)),
-          "Using an unescaped label as a callbr argument!", &CBI);
-    if (isa<BasicBlock>(CBI.getOperand(i)))
-      for (unsigned j = i + 1; j != e; ++j)
-        Check(CBI.getOperand(i) != CBI.getOperand(j),
-              "Duplicate callbr destination!", &CBI);
-  }
-  {
-    SmallPtrSet<BasicBlock *, 4> ArgBBs;
-    for (Value *V : CBI.args())
-      if (auto *BA = dyn_cast<BlockAddress>(V))
-        ArgBBs.insert(BA->getBasicBlock());
-    for (BasicBlock *BB : CBI.getIndirectDests())
-      Check(ArgBBs.count(BB), "Indirect label missing from arglist.", &CBI);
-  }
 
   verifyInlineAsmCall(CBI);
   visitTerminator(CBI);

diff  --git a/llvm/test/Analysis/BasicAA/pr52735.ll b/llvm/test/Analysis/BasicAA/pr52735.ll
index ed62a3e4ecd6a..70ad87434e8fa 100644
--- a/llvm/test/Analysis/BasicAA/pr52735.ll
+++ b/llvm/test/Analysis/BasicAA/pr52735.ll
@@ -11,14 +11,14 @@
 
 target triple = "x86_64-unknown-linux-gnu"
 
-; CHECK: Both ModRef:  Ptr: i32* %v	<->  callbr void asm "movl $$1, $0", "=*m,X,~{dirflag},~{fpsr},~{flags}"(i32* nonnull elementtype(i32) %v, i8* blockaddress(@foo, %out))
+; CHECK: Both ModRef:  Ptr: i32* %v	<->  callbr void asm "movl $$1, $0", "=*m,!i,~{dirflag},~{fpsr},~{flags}"(i32* nonnull elementtype(i32) %v)
 
 
 define dso_local i32 @foo() {
 entry:
   %v = alloca i32, align 4
   %0 = bitcast i32* %v to i8*
-  callbr void asm "movl $$1, $0", "=*m,X,~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) nonnull %v, i8* blockaddress(@foo, %out))
+  callbr void asm "movl $$1, $0", "=*m,!i,~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) nonnull %v)
           to label %asm.fallthrough [label %out]
 
 asm.fallthrough:

diff  --git a/llvm/test/Assembler/call-arg-is-callee.ll b/llvm/test/Assembler/call-arg-is-callee.ll
index f2dd6ed1eeb07..e7cafaaf553fe 100644
--- a/llvm/test/Assembler/call-arg-is-callee.ll
+++ b/llvm/test/Assembler/call-arg-is-callee.ll
@@ -26,9 +26,7 @@ exception:
 ; verifier prevents duplicating callbr destinations.
 define void @callbr() {
 entry:
-  callbr i32 asm "", "=r,r,i,i"(i32 0,
-                                i8 *blockaddress(@callbr, %two),
-                                i8 *blockaddress(@callbr, %three))
+  callbr i32 asm "", "=r,r,!i,!i"(i32 0)
               to label %one [label %two, label %three]
 one:
   ret void

diff  --git a/llvm/test/Assembler/inline-asm-constraint-error.ll b/llvm/test/Assembler/inline-asm-constraint-error.ll
index 5ecf67ab34ade..f9d030c0434eb 100644
--- a/llvm/test/Assembler/inline-asm-constraint-error.ll
+++ b/llvm/test/Assembler/inline-asm-constraint-error.ll
@@ -6,6 +6,8 @@
 ; RUN: not llvm-as < %t/cannot-be-struct.ll 2>&1 | FileCheck %s --check-prefix=CHECK-CANNOT-BE-STRUCT
 ; RUN: not llvm-as < %t/incorrect-struct-elements.ll 2>&1 | FileCheck %s --check-prefix=CHECK-INCORRECT-STRUCT-ELEMENTS
 ; RUN: not llvm-as < %t/incorrect-arg-num.ll 2>&1 | FileCheck %s --check-prefix=CHECK-INCORRECT-ARG-NUM
+; RUN: not llvm-as < %t/label-after-clobber.ll 2>&1 | FileCheck %s --check-prefix=CHECK-LABEL-AFTER-CLOBBER
+; RUN: not llvm-as < %t/output-after-label.ll 2>&1 | FileCheck %s --check-prefix=CHECK-OUTPUT-AFTER-LABEL
 
 ;--- parse-fail.ll
 ; CHECK-PARSE-FAIL: failed to parse constraints
@@ -16,7 +18,7 @@ define void @foo() {
 }
 
 ;--- input-before-output.ll
-; CHECK-INPUT-BEFORE-OUTPUT: output constraint occurs after input or clobber constraint
+; CHECK-INPUT-BEFORE-OUTPUT: output constraint occurs after input, clobber or label constraint
 define void @foo() {
   call void asm sideeffect "mov x0, #42", "r,=r"()
   ret void
@@ -56,3 +58,25 @@ define void @foo() {
   call void asm sideeffect "mov x0, #42", "r"()
   ret void
 }
+
+;--- label-after-clobber.ll
+; CHECK-LABEL-AFTER-CLOBBER: label constraint occurs after clobber constraint
+define void @foo() {
+  callbr void asm sideeffect "", "~{flags},!i"()
+  to label %1 [label %2]
+1:
+  ret void
+2:
+  ret void
+}
+
+;--- output-after-label.ll
+; CHECK-OUTPUT-AFTER-LABEL: output constraint occurs after input, clobber or label constraint
+define void @foo() {
+  %res = callbr i32 asm sideeffect "", "!i,=r,~{flags}"()
+  to label %1 [label %2]
+1:
+  ret void
+2:
+  ret void
+}

diff  --git a/llvm/test/Bitcode/callbr.ll b/llvm/test/Bitcode/callbr.ll
index d7f413e268672..de9c8650d7df0 100644
--- a/llvm/test/Bitcode/callbr.ll
+++ b/llvm/test/Bitcode/callbr.ll
@@ -6,10 +6,9 @@
 
 define i32 @test_asm_goto(i32 %x){
 entry:
-; CHECK-TYPED:      callbr void asm "", "r,i"(i32 %x, i8* blockaddress(@test_asm_goto, %fail))
-; CHECK-OPAQUE:     callbr void asm "", "r,i"(i32 %x, ptr blockaddress(@test_asm_goto, %fail))
+; CHECK: callbr void asm "", "r,!i"(i32 %x)
 ; CHECK-NEXT: to label %normal [label %fail]
-  callbr void asm "", "r,i"(i32 %x, i8* blockaddress(@test_asm_goto, %fail)) to label %normal [label %fail]
+  callbr void asm "", "r,!i"(i32 %x) to label %normal [label %fail]
 normal:
   ret i32 1
 fail:
@@ -18,10 +17,9 @@ fail:
 
 define i32 @test_asm_goto2(i32 %x){
 entry:
-; CHECK-TYPED:      callbr void asm "", "r,i,i"(i32 %x, i8* blockaddress(@test_asm_goto2, %fail), i8* blockaddress(@test_asm_goto2, %fail2))
-; CHECK-OPAQUE:     callbr void asm "", "r,i,i"(i32 %x, ptr blockaddress(@test_asm_goto2, %fail), ptr blockaddress(@test_asm_goto2, %fail2))
+; CHECK: callbr void asm "", "r,!i,!i"(i32 %x)
 ; CHECK-NEXT: to label %normal [label %fail, label %fail2]
-  callbr void asm "", "r,i,i"(i32 %x, i8* blockaddress(@test_asm_goto2, %fail), i8* blockaddress(@test_asm_goto2, %fail2)) to label %normal [label %fail, label %fail2]
+  callbr void asm "", "r,!i,!i"(i32 %x) to label %normal [label %fail, label %fail2]
 normal:
   ret i32 1
 fail:
@@ -32,10 +30,10 @@ fail2:
 
 define i32 @test_asm_goto3(i32 %x){
 entry:
-; CHECK-TYPED:      callbr void asm "", "r,i,i"(i32 %x, i8* blockaddress(@test_asm_goto3, %unrelated), i8* blockaddress(@test_asm_goto3, %fail))
-; CHECK-OPAQUE:     callbr void asm "", "r,i,i"(i32 %x, ptr blockaddress(@test_asm_goto3, %unrelated), ptr blockaddress(@test_asm_goto3, %fail))
+; CHECK-TYPED:      callbr void asm "", "r,i,!i"(i32 %x, i8* blockaddress(@test_asm_goto3, %unrelated))
+; CHECK-OPAQUE:     callbr void asm "", "r,i,!i"(i32 %x, ptr blockaddress(@test_asm_goto3, %unrelated))
 ; CHECK-NEXT: to label %normal [label %fail]
-  callbr void asm "", "r,i,i"(i32 %x, i8* blockaddress(@test_asm_goto3, %unrelated), i8* blockaddress(@test_asm_goto3, %fail)) to label %normal [label %fail]
+  callbr void asm "", "r,i,!i"(i32 %x, i8* blockaddress(@test_asm_goto3, %unrelated)) to label %normal [label %fail]
 normal:
   ret i32 1
 fail:

diff  --git a/llvm/test/CodeGen/AArch64/callbr-asm-label.ll b/llvm/test/CodeGen/AArch64/callbr-asm-label.ll
index 60f3846cae1ea..3e16d746214d4 100644
--- a/llvm/test/CodeGen/AArch64/callbr-asm-label.ll
+++ b/llvm/test/CodeGen/AArch64/callbr-asm-label.ll
@@ -10,7 +10,7 @@ define i32 @test1() {
 ; CHECK: .Ltmp0:
 ; CHECK: .LBB0_2: // %indirect
 entry:
-  callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "i"(i8* blockaddress(@test1, %indirect))
+  callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "!i"()
           to label %cleanup [label %indirect]
 
 indirect:
@@ -34,7 +34,7 @@ if.then:
 ; CHECK-NEXT:  .word .Ltmp2
 ; CHECK:       .Ltmp2:
 ; CHECK-NEXT:  .LBB1_3: // %if.end6
-  callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "i"(i8* blockaddress(@test2, %if.end6))
+  callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "!i"()
           to label %if.then4 [label %if.end6]
 
 if.then4:
@@ -50,7 +50,7 @@ if.end6:
 if.then9:
 ; CHECK: .Ltmp4:
 ; CHECK-NEXT:  .LBB1_5: // %l_yes
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@test2, %l_yes))
+  callbr void asm sideeffect "", "!i"()
           to label %if.end10 [label %l_yes]
 
 if.end10:

diff  --git a/llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll b/llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll
index f6660000390a8..5105c34513a9b 100644
--- a/llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll
+++ b/llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll
@@ -20,7 +20,7 @@ define hidden i32 @test1() {
   br i1 %2, label %3, label %5
 
 3:                                                ; preds = %0
-  callbr void asm sideeffect "1: nop\0A\09.quad a\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,i"(i32* null, i8* blockaddress(@test1, %7))
+  callbr void asm sideeffect "1: nop\0A\09.quad a\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,!i"(i32* null)
           to label %4 [label %7]
 
 4:                                                ; preds = %3
@@ -55,7 +55,7 @@ define hidden i32 @test2() local_unnamed_addr {
   br i1 %5, label %6, label %7
 
 6:                                                ; preds = %3
-  callbr void asm sideeffect "1: nop\0A\09.quad b\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,i"(i32* null, i8* blockaddress(@test2, %7))
+  callbr void asm sideeffect "1: nop\0A\09.quad b\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,!i"(i32* null)
           to label %10 [label %7]
 
 7:                                                ; preds = %3
@@ -83,7 +83,7 @@ define internal i1 @test3() {
   br i1 %2, label %3, label %5
 
 3:                                                ; preds = %0
-  callbr void asm sideeffect "1: nop\0A\09.quad c\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,i"(i32* null, i8* blockaddress(@test3, %8))
+  callbr void asm sideeffect "1: nop\0A\09.quad c\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,!i"(i32* null)
           to label %4 [label %8]
 
 4:                                                ; preds = %3

diff  --git a/llvm/test/CodeGen/AArch64/speculation-hardening-sls.ll b/llvm/test/CodeGen/AArch64/speculation-hardening-sls.ll
index c88f9b21a8f12..d1c7c78c3eb5c 100644
--- a/llvm/test/CodeGen/AArch64/speculation-hardening-sls.ll
+++ b/llvm/test/CodeGen/AArch64/speculation-hardening-sls.ll
@@ -89,7 +89,7 @@ entry:
 define i32 @asmgoto() {
 entry:
 ; CHECK-LABEL: asmgoto:
-  callbr void asm sideeffect "B $0", "i"(i8* blockaddress(@asmgoto, %d))
+  callbr void asm sideeffect "B $0", "!i"()
             to label %asm.fallthrough [label %d]
      ; The asm goto above produces a direct branch:
 ; CHECK:           //APP

diff  --git a/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll b/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll
index 835583085c318..dfae40effe96c 100644
--- a/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll
+++ b/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll
@@ -89,7 +89,7 @@ return:                                           ; preds = %entry, %l2
 define i32 @asmgoto() {
 entry:
 ; CHECK-LABEL: asmgoto:
-  callbr void asm sideeffect "B $0", "i"(i8* blockaddress(@asmgoto, %d))
+  callbr void asm sideeffect "B $0", "!i"()
             to label %asm.fallthrough [label %d]
      ; The asm goto above produces a direct branch:
 ; CHECK:           @APP

diff  --git a/llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll b/llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll
index e2fb1f87773e1..fe0fae0dd51db 100644
--- a/llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll
+++ b/llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll
@@ -111,7 +111,7 @@ define dso_local signext i32 @ClobberLR_BR(i32 signext %in) #0 {
 ; PPC64BE-NEXT:    li r3, 0
 ; PPC64BE-NEXT:    b .LBB3_1
 entry:
-  callbr void asm sideeffect "nop", "i,~{lr}"(i8* blockaddress(@ClobberLR_BR, %return_early))
+  callbr void asm sideeffect "nop", "!i,~{lr}"()
           to label %return [label %return_early]
 
 return_early:
@@ -151,7 +151,7 @@ define dso_local signext i32 @ClobberR5_BR(i32 signext %in) #0 {
 ; PPC64BE-NEXT:    extsw r3, r3
 ; PPC64BE-NEXT:    blr
 entry:
-  callbr void asm sideeffect "nop", "i,~{r5}"(i8* blockaddress(@ClobberR5_BR, %return_early))
+  callbr void asm sideeffect "nop", "!i,~{r5}"()
           to label %return [label %return_early]
 
 return_early:

diff  --git a/llvm/test/CodeGen/SystemZ/asm-20.ll b/llvm/test/CodeGen/SystemZ/asm-20.ll
index da336cf45d0be..7f6c0d1c27d47 100644
--- a/llvm/test/CodeGen/SystemZ/asm-20.ll
+++ b/llvm/test/CodeGen/SystemZ/asm-20.ll
@@ -4,7 +4,7 @@
 
 define i32 @c() {
 entry:
-  callbr void asm sideeffect "j d", "i"(i8* blockaddress(@c, %d))
+  callbr void asm sideeffect "j d", "!i"()
           to label %asm.fallthrough [label %d]
 
 asm.fallthrough:               ; preds = %entry

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-bb-exports.ll b/llvm/test/CodeGen/X86/callbr-asm-bb-exports.ll
index 9b7a69f19affa..61e712f2024a3 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-bb-exports.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-bb-exports.ll
@@ -17,14 +17,14 @@
 ; CHECK-NEXT: t2: i32,ch = CopyFromReg t0, Register:i32 %2
 ; CHECK-NEXT: t8: i32 = add t2, Constant:i32<4>
 ; CHECK-NEXT: t22: ch,glue = CopyToReg t17, Register:i32 %5, t8
-; CHECK-NEXT: t30: ch,glue = inlineasm_br t22, TargetExternalSymbol:i64'xorl $0, $0; jmp ${1:l}', MDNode:ch<null>, TargetConstant:i64<8>, TargetConstant:i32<2359305>, Register:i32 %5, TargetConstant:i64<13>, TargetBlockAddress:i64<@test, %fail> 0, TargetConstant:i32<12>, Register:i32 $df, TargetConstant:i32<12>, Register:i16 $fpsw, TargetConstant:i32<12>, Register:i32 $eflags, t22:1
+; CHECK-NEXT: t30: ch,glue = inlineasm_br t22, TargetExternalSymbol:i64'xorl $0, $0; jmp ${1:l}', MDNode:ch<null>, TargetConstant:i64<0>, TargetConstant:i32<2359305>, Register:i32 %5, TargetConstant:i64<13>, TargetBlockAddress:i64<@test, %fail> 0, TargetConstant:i32<12>, Register:i32 $df, TargetConstant:i32<12>, Register:i16 $fpsw, TargetConstant:i32<12>, Register:i32 $eflags, t22:1
 
 define i32 @test(i32 %a, i32 %b, i32 %c) {
 entry:
   %0 = add i32 %a, 4
   %1 = add i32 %b, 1
   %2 = add i32 %c, 1
-  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, ptr blockaddress(@test, %fail)) to label %normal [label %fail]
+  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]
 
 normal:
   ret i32 %1

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-blockplacement.ll b/llvm/test/CodeGen/X86/callbr-asm-blockplacement.ll
index b54db0256d4fd..41fb8b57ae61c 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-blockplacement.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-blockplacement.ll
@@ -85,7 +85,7 @@ bb8:                                              ; preds = %bb8, %bb5
 bb15:                                             ; preds = %bb8
   %tmp16 = getelementptr [0 x %struct.wibble], ptr @global, i64 0, i64 %tmp4, i32 2
   store ptr %tmp9, ptr %tmp16
-  callbr void asm sideeffect "", "i"(ptr blockaddress(@foo, %bb18))
+  callbr void asm sideeffect "", "!i"()
           to label %bb17 [label %bb18]
 
 bb17:                                             ; preds = %bb15

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-branch-folding.ll b/llvm/test/CodeGen/X86/callbr-asm-branch-folding.ll
index dad0564398f8e..d1b17e4238086 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-branch-folding.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-branch-folding.ll
@@ -116,7 +116,7 @@ if.end12:                                         ; preds = %if.end8
   br i1 %tobool13, label %if.else, label %if.then14
 
 if.then14:                                        ; preds = %if.end12
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@n, %if.then20.critedge))
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %cleanup [label %if.then20.critedge]
 
 if.then20.critedge:                               ; preds = %if.then14

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-destinations.ll b/llvm/test/CodeGen/X86/callbr-asm-destinations.ll
index e4ebcbd279020..c84847a0cddea 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-destinations.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-destinations.ll
@@ -1,14 +1,49 @@
-; RUN: not llc -mtriple=i686-- < %s 2> %t
-; RUN: FileCheck %s < %t
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=i686-- -verify-machineinstrs < %s | FileCheck %s
 
-; CHECK: Duplicate callbr destination
+define i32 @duplicate_normal_and_indirect_dest(i32 %a) {
+; CHECK-LABEL: duplicate_normal_and_indirect_dest:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; CHECK-NEXT:    addl $4, %eax
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    jmp .Ltmp0
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:  .Ltmp0: # Block address taken
+; CHECK-NEXT:  # %bb.1: # %fail
+; CHECK-NEXT:    movl $1, %eax
+; CHECK-NEXT:    retl
+entry:
+  %0 = add i32 %a, 4
+  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %fail [label %fail]
 
-; A test for asm-goto duplicate labels limitation
+fail:
+  ret i32 1
+}
 
-define i32 @test(i32 %a) {
+define i32 @duplicate_indirect_dest(i32 %a) {
+; CHECK-LABEL: duplicate_indirect_dest:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; CHECK-NEXT:    addl $4, %eax
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    jmp .Ltmp1
+; CHECK-NEXT:    jmp .Ltmp1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:  # %bb.1: # %normal
+; CHECK-NEXT:    retl
+; CHECK-NEXT:  .Ltmp1: # Block address taken
+; CHECK-NEXT:  .LBB1_2: # %fail
+; CHECK-NEXT:    movl $1, %eax
+; CHECK-NEXT:    retl
 entry:
   %0 = add i32 %a, 4
-  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, ptr blockaddress(@test, %fail)) to label %fail [label %fail]
+  callbr void asm "xorl $0, $0; jmp ${1:l}; jmp ${2:l}", "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail, label %fail]
+
+normal:
+  ret i32 %0
 
 fail:
   ret i32 1

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-errors.ll b/llvm/test/CodeGen/X86/callbr-asm-errors.ll
deleted file mode 100644
index e10283edc8c5c..0000000000000
--- a/llvm/test/CodeGen/X86/callbr-asm-errors.ll
+++ /dev/null
@@ -1,18 +0,0 @@
-; RUN: not llc -mtriple=i686-- < %s 2> %t
-; RUN: FileCheck %s < %t
-
-; CHECK: Duplicate callbr destination
-
-; A test for asm-goto duplicate labels limitation
-
-define i32 @test(i32 %a) {
-entry:
-  %0 = add i32 %a, 4
-  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, ptr blockaddress(@test, %fail), ptr blockaddress(@test, %fail)) to label %normal [label %fail, label %fail]
-
-normal:
-  ret i32 %0
-
-fail:
-  ret i32 1
-}

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-instr-scheduling.ll b/llvm/test/CodeGen/X86/callbr-asm-instr-scheduling.ll
index abe56d48b3159..17c95cf0cf6fd 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-instr-scheduling.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-instr-scheduling.ll
@@ -49,7 +49,7 @@ entry:
   %shr = lshr i64 %addr, %sh_prom
   %and = and i64 %shr, 511
   %arrayidx = getelementptr %struct.pgd_t, ptr %2, i64 %and
-  callbr void asm sideeffect "1: jmp 6f\0A2:\0A.skip -(((5f-4f) - (2b-1b)) > 0) * ((5f-4f) - (2b-1b)),0x90\0A3:\0A.section .altinstructions,\22a\22\0A .long 1b - .\0A .long 4f - .\0A .word ${1:P}\0A .byte 3b - 1b\0A .byte 5f - 4f\0A .byte 3b - 2b\0A.previous\0A.section .altinstr_replacement,\22ax\22\0A4: jmp ${5:l}\0A5:\0A.previous\0A.section .altinstructions,\22a\22\0A .long 1b - .\0A .long 0\0A .word ${0:P}\0A .byte 3b - 1b\0A .byte 0\0A .byte 0\0A.previous\0A.section .altinstr_aux,\22ax\22\0A6:\0A testb $2,$3\0A jnz ${4:l}\0A jmp ${5:l}\0A.previous\0A", "i,i,i,*m,i,i,~{dirflag},~{fpsr},~{flags}"(i16 528, i32 117, i32 1, ptr elementtype(i8) getelementptr inbounds (%struct.cpuinfo_x86, ptr @boot_cpu_data, i64 0, i32 12, i32 1, i64 58), ptr blockaddress(@early_ioremap_pmd, %if.end.i), ptr blockaddress(@early_ioremap_pmd, %if.then.i))
+  callbr void asm sideeffect "1: jmp 6f\0A2:\0A.skip -(((5f-4f) - (2b-1b)) > 0) * ((5f-4f) - (2b-1b)),0x90\0A3:\0A.section .altinstructions,\22a\22\0A .long 1b - .\0A .long 4f - .\0A .word ${1:P}\0A .byte 3b - 1b\0A .byte 5f - 4f\0A .byte 3b - 2b\0A.previous\0A.section .altinstr_replacement,\22ax\22\0A4: jmp ${5:l}\0A5:\0A.previous\0A.section .altinstructions,\22a\22\0A .long 1b - .\0A .long 0\0A .word ${0:P}\0A .byte 3b - 1b\0A .byte 0\0A .byte 0\0A.previous\0A.section .altinstr_aux,\22ax\22\0A6:\0A testb $2,$3\0A jnz ${4:l}\0A jmp ${5:l}\0A.previous\0A", "i,i,i,*m,!i,!i,~{dirflag},~{fpsr},~{flags}"(i16 528, i32 117, i32 1, ptr elementtype(i8) getelementptr inbounds (%struct.cpuinfo_x86, ptr @boot_cpu_data, i64 0, i32 12, i32 1, i64 58))
           to label %_static_cpu_has.exit.thread.i [label %if.end.i, label %if.then.i]
 
 _static_cpu_has.exit.thread.i:                    ; preds = %entry

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-kill.mir b/llvm/test/CodeGen/X86/callbr-asm-kill.mir
index 9bb03aeb3fdcc..6a38d620984e9 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-kill.mir
+++ b/llvm/test/CodeGen/X86/callbr-asm-kill.mir
@@ -21,7 +21,7 @@
     %a = phi i8* [ %arg, %entry ], [ %b, %loop ]
     %b = load i8*, i8** %mem, align 8
     call void @foo(i8* %a)
-    callbr void asm sideeffect "", "*m,i"(i8* elementtype(i8) %b, i8* blockaddress(@test1, %loop))
+    callbr void asm sideeffect "", "*m,!i"(i8* elementtype(i8) %b)
             to label %end [label %loop]
 
   end:                                              ; preds = %loop

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll b/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll
index 451f4b7f49b43..73d8d7fa446fc 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll
@@ -10,7 +10,7 @@ define i32 @test1(i32 %x) {
 ; CHECK-NEXT: .Ltmp0:
 ; CHECK-NEXT:  # %bb.2: # %baz
 entry:
-  callbr void asm sideeffect ".quad ${0:l}\0A\09.quad ${1:l}", "i,i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test1, %baz), ptr blockaddress(@test1, %bar))
+  callbr void asm sideeffect ".quad ${0:l}\0A\09.quad ${1:l}", "i,!i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test1, %baz))
           to label %asm.fallthrough [label %bar]
 
 asm.fallthrough:

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-obj-file.ll b/llvm/test/CodeGen/X86/callbr-asm-obj-file.ll
index 307b8f427c6cd..4f633cd8ac33e 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-obj-file.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-obj-file.ll
@@ -8,7 +8,7 @@
 
 define void @test1() {
 entry:
-  callbr void asm sideeffect "je ${0:l}", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test1, %a.b.normal.jump))
+  callbr void asm sideeffect "je ${0:l}", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough [label %a.b.normal.jump]
 
 asm.fallthrough:

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-outputs-pred-succ.ll b/llvm/test/CodeGen/X86/callbr-asm-outputs-pred-succ.ll
index 6f59c99436658..f1b6d288fcb19 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-outputs-pred-succ.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-outputs-pred-succ.ll
@@ -32,12 +32,12 @@
 
 ; Function Attrs: nounwind uwtable
 define dso_local i32 @main(i32 %0, ptr nocapture readnone %1) #0 {
-  %3 = callbr i32 asm "jmp ${1:l}", "=r,i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@main, %11)) #3
+  %3 = callbr i32 asm "jmp ${1:l}", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #3
           to label %4 [label %11]
 
 4:                                                ; preds = %2
   %5 = tail call i32 (ptr, ...) @printf(ptr nonnull dereferenceable(1) @.str, i32 %3)
-  %6 = callbr i32 asm "jmp ${1:l}", "=r,i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@main, %7)) #3
+  %6 = callbr i32 asm "jmp ${1:l}", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #3
           to label %9 [label %7]
 
 7:                                                ; preds = %4

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-outputs.ll b/llvm/test/CodeGen/X86/callbr-asm-outputs.ll
index f2c73348e919c..2b45f3267a8d8 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-outputs.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-outputs.ll
@@ -20,7 +20,7 @@ define i32 @test1(i32 %x) {
 ; CHECK-NEXT:    retl
 entry:
   %add = add nsw i32 %x, 4
-  %ret = callbr i32 asm "xorl $1, $0; jmp ${2:l}", "=r,r,i,~{dirflag},~{fpsr},~{flags}"(i32 %add, ptr blockaddress(@test1, %abnormal))
+  %ret = callbr i32 asm "xorl $1, $0; jmp ${2:l}", "=r,r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %add)
           to label %normal [label %abnormal]
 
 normal:
@@ -77,11 +77,11 @@ entry:
   br i1 %cmp, label %if.then, label %if.else
 
 if.then:                                          ; preds = %entry
-  %0 = callbr { i32, i32 } asm sideeffect "testl $0, $0; testl $1, $2; jne ${3:l}", "={si},={di},r,i,i,0,1,~{dirflag},~{fpsr},~{flags}"(i32 %out1, ptr blockaddress(@test2, %label_true), ptr blockaddress(@test2, %return), i32 %out1, i32 %out2)
+  %0 = callbr { i32, i32 } asm sideeffect "testl $0, $0; testl $1, $2; jne ${3:l}", "={si},={di},r,!i,!i,0,1,~{dirflag},~{fpsr},~{flags}"(i32 %out1, i32 %out1, i32 %out2)
           to label %if.end [label %label_true, label %return]
 
 if.else:                                          ; preds = %entry
-  %1 = callbr { i32, i32 } asm sideeffect "testl $0, $1; testl $2, $3; jne ${5:l}", "={si},={di},r,r,i,i,0,1,~{dirflag},~{fpsr},~{flags}"(i32 %out1, i32 %out2, ptr blockaddress(@test2, %label_true), ptr blockaddress(@test2, %return), i32 %out1, i32 %out2)
+  %1 = callbr { i32, i32 } asm sideeffect "testl $0, $1; testl $2, $3; jne ${5:l}", "={si},={di},r,r,!i,!i,0,1,~{dirflag},~{fpsr},~{flags}"(i32 %out1, i32 %out2, i32 %out1, i32 %out2)
           to label %if.end [label %label_true, label %return]
 
 if.end:                                           ; preds = %if.else, %if.then
@@ -140,10 +140,10 @@ entry:
   br i1 %cmp, label %true, label %false
 
 true:
-  %0 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={si},={di},i" (ptr blockaddress(@test3, %indirect)) to label %asm.fallthrough [label %indirect]
+  %0 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={si},={di},!i" () to label %asm.fallthrough [label %indirect]
 
 false:
-  %1 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={ax},={dx},i" (ptr blockaddress(@test3, %indirect)) to label %asm.fallthrough [label %indirect]
+  %1 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={ax},={dx},!i" () to label %asm.fallthrough [label %indirect]
 
 asm.fallthrough:
   %vals = phi { i32, i32 } [ %0, %true ], [ %1, %false ]
@@ -182,13 +182,13 @@ define i32 @test4(i32 %out1, i32 %out2) {
 ; CHECK-NEXT:  .LBB3_4: # %return
 ; CHECK-NEXT:    retl
 entry:
-  %0 = callbr { i32, i32 } asm sideeffect "testl $0, $0; testl $1, $2; jne ${3:l}", "=r,=r,r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %out1, ptr blockaddress(@test4, %label_true), ptr blockaddress(@test4, %return))
+  %0 = callbr { i32, i32 } asm sideeffect "testl $0, $0; testl $1, $2; jne ${3:l}", "=r,=r,r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %out1)
           to label %asm.fallthrough [label %label_true, label %return]
 
 asm.fallthrough:                                  ; preds = %entry
   %asmresult = extractvalue { i32, i32 } %0, 0
   %asmresult1 = extractvalue { i32, i32 } %0, 1
-  %1 = callbr { i32, i32 } asm sideeffect "testl $0, $1; testl $2, $3; jne ${5:l}", "=r,=r,r,r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %asmresult, i32 %asmresult1, ptr blockaddress(@test4, %label_true), ptr blockaddress(@test4, %return))
+  %1 = callbr { i32, i32 } asm sideeffect "testl $0, $1; testl $2, $3; jne ${5:l}", "=r,=r,r,r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %asmresult, i32 %asmresult1)
           to label %asm.fallthrough2 [label %label_true, label %return]
 
 asm.fallthrough2:                                 ; preds = %asm.fallthrough
@@ -218,7 +218,7 @@ define dso_local void @test5() {
 ; CHECK-NEXT:  # %bb.1:
 ; CHECK-NEXT:    retl
   %1 = call i32 @llvm.read_register.i32(metadata !3)
-  %2 = callbr i32 asm "", "={esp},X,{esp},~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test5, %4), i32 %1)
+  %2 = callbr i32 asm "", "={esp},!i,{esp},~{dirflag},~{fpsr},~{flags}"(i32 %1)
           to label %3 [label %4]
 
 3:

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-phi-placement.ll b/llvm/test/CodeGen/X86/callbr-asm-phi-placement.ll
index 4be162f72383d..4375ffb63cecc 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-phi-placement.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-phi-placement.ll
@@ -36,7 +36,7 @@ loop:
   %a = phi ptr [ %arg, %entry ], [ %b, %loop ]
   %b = load ptr, ptr %mem, align 8
   call void @foo(ptr %a)
-  callbr void asm sideeffect "", "*m,i"(ptr elementtype(i8) %b, ptr blockaddress(@test1, %loop))
+  callbr void asm sideeffect "", "*m,!i"(ptr elementtype(i8) %b)
           to label %end [label %loop]
 
 end:

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-sink.ll b/llvm/test/CodeGen/X86/callbr-asm-sink.ll
index 21381de231546..51d01cb078a0f 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-sink.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-sink.ll
@@ -21,7 +21,7 @@ define void @klist_dec_and_del(%struct1*) {
 ; CHECK-NEXT:    movq $0, -8(%rax)
 ; CHECK-NEXT:    retq
   %2 = getelementptr inbounds %struct1, %struct1* %0, i64 0, i32 1
-  callbr void asm sideeffect "# $0 $1", "*m,i,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %2, i8* blockaddress(@klist_dec_and_del, %3))
+  callbr void asm sideeffect "# $0 $1", "*m,!i,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %2)
           to label %6 [label %3]
 
 3:

diff  --git a/llvm/test/CodeGen/X86/callbr-asm.ll b/llvm/test/CodeGen/X86/callbr-asm.ll
index 2edbfae839f93..5bc9643ab37bd 100644
--- a/llvm/test/CodeGen/X86/callbr-asm.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm.ll
@@ -23,7 +23,7 @@ define i32 @test1(i32 %a) {
 ; CHECK-NEXT:    retl
 entry:
   %0 = add i32 %a, 4
-  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, ptr blockaddress(@test1, %fail)) to label %normal [label %fail]
+  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]
 
 normal:
   ret i32 0
@@ -53,7 +53,7 @@ define i32 @test1b(i32 %a) {
 ; CHECK-NEXT:    retl
 entry:
   %0 = add i32 %a, 4
-  callbr void asm inteldialect "xor $0, $0; jmp ${1:l}", "r,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, ptr blockaddress(@test1b, %fail)) to label %normal [label %fail]
+  callbr void asm inteldialect "xor $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]
 
 normal:
   ret i32 0
@@ -74,7 +74,7 @@ entry:
 
 unreachableasm:
   %0 = add i32 %a, 4
-  callbr void asm sideeffect "xorl $0, $0; jmp ${1:l}", "r,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, ptr blockaddress(@test2, %fail)) to label %normal [label %fail]
+  callbr void asm sideeffect "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]
 
 normal:
   ret i32 0
@@ -148,11 +148,11 @@ label03:                                          ; preds = %normal0, %label04,
   br label %label04
 
 label04:                                          ; preds = %normal0, %label03
-  callbr void asm sideeffect "jmp ${0:l}; jmp ${1:l}; jmp ${2:l}", "i,i,i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test3, %label01), ptr blockaddress(@test3, %label02), ptr blockaddress(@test3, %label03))
+  callbr void asm sideeffect "jmp ${0:l}; jmp ${1:l}; jmp ${2:l}", "!i,!i,!i,~{dirflag},~{fpsr},~{flags}"()
           to label %normal0 [label %label01, label %label02, label %label03]
 
 normal0:                                          ; preds = %label04
-  callbr void asm sideeffect "jmp ${0:l}; jmp ${1:l}; jmp ${2:l}; jmp ${3:l}", "i,i,i,i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test3, %label01), ptr blockaddress(@test3, %label02), ptr blockaddress(@test3, %label03), ptr blockaddress(@test3, %label04))
+  callbr void asm sideeffect "jmp ${0:l}; jmp ${1:l}; jmp ${2:l}; jmp ${3:l}", "!i,!i,!i,!i,~{dirflag},~{fpsr},~{flags}"()
           to label %normal1 [label %label01, label %label02, label %label03, label %label04]
 
 normal1:                                          ; preds = %normal0
@@ -175,11 +175,11 @@ define void @test4() {
 ; CHECK-NEXT:  .LBB4_3: # %quux
 ; CHECK-NEXT:    retl
 entry:
-  callbr void asm sideeffect "ja $0", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test4, %quux))
+  callbr void asm sideeffect "ja $0", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough [label %quux]
 
 asm.fallthrough:                                  ; preds = %entry
-  callbr void asm sideeffect "ja ${0:l}", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test4, %quux))
+  callbr void asm sideeffect "ja ${0:l}", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %cleanup [label %quux]
 
 quux:                                             ; preds = %asm.fallthrough, %entry

diff  --git a/llvm/test/CodeGen/X86/callbr-codegenprepare.ll b/llvm/test/CodeGen/X86/callbr-codegenprepare.ll
index c2ea5145f2de8..854cc4bf7a9cc 100644
--- a/llvm/test/CodeGen/X86/callbr-codegenprepare.ll
+++ b/llvm/test/CodeGen/X86/callbr-codegenprepare.ll
@@ -12,7 +12,7 @@ declare void @foo(i32)
 
 define dso_local i32 @futex_lock_pi_atomic() local_unnamed_addr {
 entry:
-  %0 = callbr i32 asm "", "=r,i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@futex_lock_pi_atomic, %b.exit))
+  %0 = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough.i [label %b.exit]
 
 asm.fallthrough.i:

diff  --git a/llvm/test/CodeGen/X86/inline-asm-pic.ll b/llvm/test/CodeGen/X86/inline-asm-pic.ll
index 0d14b4b11693d..95c8d51273701 100644
--- a/llvm/test/CodeGen/X86/inline-asm-pic.ll
+++ b/llvm/test/CodeGen/X86/inline-asm-pic.ll
@@ -34,7 +34,7 @@ define void @x() {
 ; CHECK-NEXT:  Ltmp0: ## Block address taken
 ; CHECK-NEXT:  LBB1_1: ## %overflow
 ; CHECK-NEXT:    retl
-  callbr void asm "#  ${0:l}\0A", "i"(ptr blockaddress(@x, %overflow))
+  callbr void asm "#  ${0:l}\0A", "!i"()
           to label %return [label %overflow]
 
 overflow:

diff  --git a/llvm/test/CodeGen/X86/shrinkwrap-callbr.ll b/llvm/test/CodeGen/X86/shrinkwrap-callbr.ll
index 367239f56e9fd..72e78c69f8fbe 100644
--- a/llvm/test/CodeGen/X86/shrinkwrap-callbr.ll
+++ b/llvm/test/CodeGen/X86/shrinkwrap-callbr.ll
@@ -48,7 +48,7 @@ ret0:
 
 if.end:
   %call = tail call i32 @fn()
-  callbr void asm sideeffect "# jump to $0", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test1, %two))
+  callbr void asm sideeffect "# jump to $0", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %return [label %two]
 
 two:

diff  --git a/llvm/test/CodeGen/X86/speculation-hardening-sls.ll b/llvm/test/CodeGen/X86/speculation-hardening-sls.ll
index ad415f15315b1..a68d6f039939e 100644
--- a/llvm/test/CodeGen/X86/speculation-hardening-sls.ll
+++ b/llvm/test/CodeGen/X86/speculation-hardening-sls.ll
@@ -64,7 +64,7 @@ define i32 @asmgoto() {
 ; RET-NEXT:      int3
 ; IJMP-NOT:      int3
 entry:
-  callbr void asm sideeffect "jmp $0", "X"(ptr blockaddress(@asmgoto, %d))
+  callbr void asm sideeffect "jmp $0", "!i"()
             to label %asm.fallthrough [label %d]
      ; The asm goto above produces a direct branch:
 

diff  --git a/llvm/test/CodeGen/X86/tail-dup-asm-goto.ll b/llvm/test/CodeGen/X86/tail-dup-asm-goto.ll
index 2bc826c3be9be..b3f9e3e8dc9ff 100644
--- a/llvm/test/CodeGen/X86/tail-dup-asm-goto.ll
+++ b/llvm/test/CodeGen/X86/tail-dup-asm-goto.ll
@@ -50,7 +50,7 @@ bb106:                                            ; preds = %bb
 
 bb110:                                            ; preds = %bb106, %bb100
   %i10.1 = phi ptr [ %arg2, %bb106 ], [ %i28.i, %bb100 ]
-  callbr void asm sideeffect "#$0 $1 $2", "i,i,i,~{dirflag},~{fpsr},~{flags}"(i32 42, i1 false, ptr blockaddress(@test1, %bb17.i.i.i))
+  callbr void asm sideeffect "#$0 $1 $2", "i,i,!i,~{dirflag},~{fpsr},~{flags}"(i32 42, i1 false)
           to label %kmem_cache_has_cpu_partial.exit [label %bb17.i.i.i]
 
 bb17.i.i.i:                                       ; preds = %bb110

diff  --git a/llvm/test/Instrumentation/MemorySanitizer/msan_asm_conservative.ll b/llvm/test/Instrumentation/MemorySanitizer/msan_asm_conservative.ll
index c39ae7a69ecae..e9915e80eb590 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/msan_asm_conservative.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/msan_asm_conservative.ll
@@ -276,7 +276,7 @@ entry:
 ; and the compiler doesn't crash.
 define dso_local i32 @asm_goto(i32 %n) sanitize_memory {
 entry:
-  callbr void asm sideeffect "cmp $0, $1; jnz ${2:l}", "r,r,i,~{dirflag},~{fpsr},~{flags}"(i32 %n, i32 1, i8* blockaddress(@asm_goto, %skip_label))
+  callbr void asm sideeffect "cmp $0, $1; jnz ${2:l}", "r,r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %n, i32 1)
           to label %cleanup [label %skip_label]
 
 skip_label:                                       ; preds = %entry

diff  --git a/llvm/test/Transforms/CallSiteSplitting/callsite-split-callbr.ll b/llvm/test/Transforms/CallSiteSplitting/callsite-split-callbr.ll
index 5d3df529fa1ac..b0ccc5b198e72 100644
--- a/llvm/test/Transforms/CallSiteSplitting/callsite-split-callbr.ll
+++ b/llvm/test/Transforms/CallSiteSplitting/callsite-split-callbr.ll
@@ -7,7 +7,7 @@
 define void @caller() {
 ; CHECK-LABEL: define {{[^@]+}}@caller() {
 ; CHECK-NEXT:  Top:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@caller, [[TOP_SPLIT:%.*]]))
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
 ; CHECK-NEXT:    to label [[NEXTCOND:%.*]] [label %Top.split]
 ; CHECK:       Top.split:
 ; CHECK-NEXT:    call void @callee(i1 false)
@@ -18,8 +18,8 @@ define void @caller() {
 ; CHECK-NEXT:    call void @callee(i1 true)
 ; CHECK-NEXT:    br label [[CALLSITEBB]]
 ; CHECK:       CallSiteBB:
-; CHECK-NEXT:    [[PHI:%.*]] = phi i1 [ false, [[TOP_SPLIT]] ], [ true, [[NEXTCOND_SPLIT]] ]
-; CHECK-NEXT:    callbr void asm sideeffect "", "r,i,~{dirflag},~{fpsr},~{flags}"(i1 [[PHI]], i8* blockaddress(@caller, [[END2:%.*]]))
+; CHECK-NEXT:    [[PHI:%.*]] = phi i1 [ false, [[TOP_SPLIT:%.*]] ], [ true, [[NEXTCOND_SPLIT]] ]
+; CHECK-NEXT:    callbr void asm sideeffect "", "r,!i,~{dirflag},~{fpsr},~{flags}"(i1 [[PHI]])
 ; CHECK-NEXT:    to label [[END:%.*]] [label %End2]
 ; CHECK:       End:
 ; CHECK-NEXT:    ret void
@@ -27,7 +27,7 @@ define void @caller() {
 ; CHECK-NEXT:    ret void
 ;
 Top:
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@caller, %CallSiteBB))
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
   to label %NextCond [label %CallSiteBB]
 
 NextCond:
@@ -36,7 +36,7 @@ NextCond:
 CallSiteBB:
   %phi = phi i1 [0, %Top],[1, %NextCond]
   call void @callee(i1 %phi)
-  callbr void asm sideeffect "", "r,i,~{dirflag},~{fpsr},~{flags}"(i1 %phi, i8* blockaddress(@caller, %End2))
+  callbr void asm sideeffect "", "r,!i,~{dirflag},~{fpsr},~{flags}"(i1 %phi)
   to label %End [label %End2]
 
 End:

diff  --git a/llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll b/llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll
index 8b6137fe1aa22..560d2ff42b8a7 100644
--- a/llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll
@@ -101,7 +101,7 @@ for.inc2:                                          ; preds = %if.end2
   br label %for.cond2
 
 for.end:                                          ; preds = %for.cond2
-  callbr void asm sideeffect "1: nop\0A\09.quad b, ${0:l}, $$5\0A\09", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@bar, %l_yes))
+  callbr void asm sideeffect "1: nop\0A\09.quad b, ${0:l}, $$5\0A\09", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough [label %l_yes]
 asm.fallthrough:                                  ; preds = %for.end
   br label %l_yes

diff  --git a/llvm/test/Transforms/Coroutines/coro-debug.ll b/llvm/test/Transforms/Coroutines/coro-debug.ll
index 057fc83d5c7a3..396cf5472d64e 100644
--- a/llvm/test/Transforms/Coroutines/coro-debug.ll
+++ b/llvm/test/Transforms/Coroutines/coro-debug.ll
@@ -56,7 +56,7 @@ sw.epilog:                                        ; preds = %sw.bb
   %4 = load i32, i32* %x.addr, align 4, !dbg !20
   %add = add nsw i32 %4, 1, !dbg !21
   store i32 %add, i32* %x.addr, align 4, !dbg !22
-  %asm_res = callbr i32 asm "", "=r,r,i"(i32 %x, i8* blockaddress(@f, %indirect.dest))
+  %asm_res = callbr i32 asm "", "=r,r,!i"(i32 %x)
           to label %coro_Cleanup [label %indirect.dest]
 
 indirect.dest:

diff  --git a/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll b/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll
index 87fb7fdfd116b..ce995da50e232 100644
--- a/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll
+++ b/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll
@@ -9,8 +9,8 @@
 define void @widget(%struct.pluto** %tmp1) {
 ; CHECK-LABEL: @widget(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i,i"(i8* blockaddress(@widget, [[BB5:%.*]]), i8* blockaddress(@widget, [[BB_BB8_CRIT_EDGE:%.*]]))
-; CHECK-NEXT:    to label [[BB4:%.*]] [label [[BB5]], label %bb.bb8_crit_edge]
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i,!i"()
+; CHECK-NEXT:    to label [[BB4:%.*]] [label [[BB5:%.*]], label %bb.bb8_crit_edge]
 ; CHECK:       bb.bb8_crit_edge:
 ; CHECK-NEXT:    [[TMP10_PRE:%.*]] = load %struct.pluto*, %struct.pluto** [[TMP1:%.*]], align 8
 ; CHECK-NEXT:    br label [[BB8:%.*]]
@@ -21,7 +21,7 @@ define void @widget(%struct.pluto** %tmp1) {
 ; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_PLUTO:%.*]], %struct.pluto* [[TMP6]], i64 0, i32 1
 ; CHECK-NEXT:    br label [[BB8]]
 ; CHECK:       bb8:
-; CHECK-NEXT:    [[TMP10:%.*]] = phi %struct.pluto* [ [[TMP6]], [[BB5]] ], [ [[TMP10_PRE]], [[BB_BB8_CRIT_EDGE]] ]
+; CHECK-NEXT:    [[TMP10:%.*]] = phi %struct.pluto* [ [[TMP6]], [[BB5]] ], [ [[TMP10_PRE]], [[BB_BB8_CRIT_EDGE:%.*]] ]
 ; CHECK-NEXT:    [[TMP9:%.*]] = phi i8* [ [[TMP7]], [[BB5]] ], [ null, [[BB_BB8_CRIT_EDGE]] ]
 ; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_PLUTO]], %struct.pluto* [[TMP10]], i64 0, i32 0
 ; CHECK-NEXT:    [[TMP12:%.*]] = load i8, i8* [[TMP11]], align 1
@@ -29,7 +29,7 @@ define void @widget(%struct.pluto** %tmp1) {
 ; CHECK-NEXT:    ret void
 ;
 bb:
-  callbr void asm sideeffect "", "i,i"(i8* blockaddress(@widget, %bb5), i8* blockaddress(@widget, %bb8))
+  callbr void asm sideeffect "", "!i,!i"()
   to label %bb4 [label %bb5, label %bb8]
 
 bb4:                                              ; preds = %bb

diff  --git a/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll b/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll
index 414614b370903..3d87703c087c4 100644
--- a/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll
+++ b/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll
@@ -8,8 +8,8 @@ define void @wombat(i64 %arg, i64* %arg1, i64 %arg2, i32* %arg3) {
 ; CHECK-LABEL: @wombat(
 ; CHECK-NEXT:  bb:
 ; CHECK-NEXT:    [[TMP5:%.*]] = or i64 [[ARG2:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    callbr void asm sideeffect "", "i,i"(i8* blockaddress(@wombat, [[BB7:%.*]]), i8* blockaddress(@wombat, [[BB_BB9_CRIT_EDGE:%.*]]))
-; CHECK-NEXT:    to label [[BB6:%.*]] [label [[BB7]], label %bb.bb9_crit_edge]
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i,!i"()
+; CHECK-NEXT:    to label [[BB6:%.*]] [label [[BB7:%.*]], label %bb.bb9_crit_edge]
 ; CHECK:       bb.bb9_crit_edge:
 ; CHECK-NEXT:    [[DOTPRE:%.*]] = trunc i64 [[TMP5]] to i32
 ; CHECK-NEXT:    br label [[BB9:%.*]]
@@ -20,13 +20,13 @@ define void @wombat(i64 %arg, i64* %arg1, i64 %arg2, i32* %arg3) {
 ; CHECK-NEXT:    tail call void @barney(i32 [[TMP8]])
 ; CHECK-NEXT:    br label [[BB9]]
 ; CHECK:       bb9:
-; CHECK-NEXT:    [[TMP10_PRE_PHI:%.*]] = phi i32 [ [[DOTPRE]], [[BB_BB9_CRIT_EDGE]] ], [ [[TMP8]], [[BB7]] ]
+; CHECK-NEXT:    [[TMP10_PRE_PHI:%.*]] = phi i32 [ [[DOTPRE]], [[BB_BB9_CRIT_EDGE:%.*]] ], [ [[TMP8]], [[BB7]] ]
 ; CHECK-NEXT:    store i32 [[TMP10_PRE_PHI]], i32* [[ARG3:%.*]], align 4
 ; CHECK-NEXT:    ret void
 ;
 bb:
   %tmp5 = or i64 %arg2, %arg
-  callbr void asm sideeffect "", "i,i"(i8* blockaddress(@wombat, %bb7), i8* blockaddress(@wombat, %bb9))
+  callbr void asm sideeffect "", "!i,!i"()
   to label %bb6 [label %bb7, label %bb9]
 
 bb6:                                              ; preds = %bb

diff  --git a/llvm/test/Transforms/GVN/critical-edge-split-failure.ll b/llvm/test/Transforms/GVN/critical-edge-split-failure.ll
index b41eba7dd9c01..2a064b6e0c4b9 100644
--- a/llvm/test/Transforms/GVN/critical-edge-split-failure.ll
+++ b/llvm/test/Transforms/GVN/critical-edge-split-failure.ll
@@ -31,9 +31,9 @@ if.then:                                          ; preds = %for.cond
 ; Splitting the critical edge from if.then to if.end will fail, but should not
 ; cause an infinite loop in GVN. If we can one day split edges of callbr
 ; indirect targets, great!
-; CHECK: callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@l2tp_recv_dequeue, %if.end))
+; CHECK: callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
 ; CHECK-NEXT: to label %asm.fallthrough.i [label %if.end]
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@l2tp_recv_dequeue, %if.end))
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough.i [label %if.end]
 
 asm.fallthrough.i:                                ; preds = %if.then

diff  --git a/llvm/test/Transforms/IROutliner/illegal-callbr.ll b/llvm/test/Transforms/IROutliner/illegal-callbr.ll
index 1614de5cfab74..24b2e4f7c2521 100644
--- a/llvm/test/Transforms/IROutliner/illegal-callbr.ll
+++ b/llvm/test/Transforms/IROutliner/illegal-callbr.ll
@@ -16,15 +16,14 @@ define i32 @function1(i32 %a, i32 %b) {
 ; CHECK-NEXT:    call void @outlined_ir_func_0(i32 [[B]])
 ; CHECK-NEXT:    ret i32 0
 ; CHECK:       fail1:
-; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[B]], 1
-; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[B]], 1
+; CHECK-NEXT:    call void @outlined_ir_func_0(i32 [[B]])
 ; CHECK-NEXT:    ret i32 0
 ;
 bb0:
   %0 = add i32 %a, 4
   %1 = add i32 %b, 1
   %2 = add i32 %b, 1
-  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@function1, %fail1)) to label %normal [label %fail1]
+  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail1]
 normal:
   %3 = add i32 %b, 1
   %4 = add i32 %b, 1
@@ -46,15 +45,14 @@ define i32 @function2(i32 %a, i32 %b) {
 ; CHECK-NEXT:    call void @outlined_ir_func_0(i32 [[B]])
 ; CHECK-NEXT:    ret i32 0
 ; CHECK:       fail1:
-; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[B]], 1
-; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[B]], 1
+; CHECK-NEXT:    call void @outlined_ir_func_0(i32 [[B]])
 ; CHECK-NEXT:    ret i32 0
 ;
 bb0:
   %0 = add i32 %a, 4
   %1 = add i32 %b, 1
   %2 = add i32 %b, 1
-  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,i,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@function2, %fail1)) to label %normal [label %fail1]
+  callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail1]
 normal:
   %3 = add i32 %b, 1
   %4 = add i32 %b, 1

diff  --git a/llvm/test/Transforms/Inline/blockaddress.ll b/llvm/test/Transforms/Inline/blockaddress.ll
index 1f4c852f0bdef..9760667865814 100644
--- a/llvm/test/Transforms/Inline/blockaddress.ll
+++ b/llvm/test/Transforms/Inline/blockaddress.ll
@@ -59,7 +59,7 @@ define internal i32 @foo(i32) {
   %3 = alloca i32, align 4
   store i32 %0, i32* %3, align 4
   %4 = load i32, i32* %3, align 4
-  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %4, i8* blockaddress(@foo, %7), i8* blockaddress(@foo, %6)) #1
+  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %4) #1
           to label %5 [label %7, label %6]
 
 ; <label>:5:                                      ; preds = %1
@@ -100,7 +100,7 @@ define internal i32 @baz(i32) {
   %3 = alloca i32, align 4
   store i32 %0, i32* %3, align 4
   %4 = load i32, i32* %3, align 4
-  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %4, i8* blockaddress(@baz, %7), i8* blockaddress(@baz, %6)) #1
+  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %4) #1
           to label %5 [label %7, label %6]
 
 ; <label>:5:                                      ; preds = %1

diff  --git a/llvm/test/Transforms/Inline/callbr.ll b/llvm/test/Transforms/Inline/callbr.ll
index 4b3be5cb217ee..383f1f0471117 100644
--- a/llvm/test/Transforms/Inline/callbr.ll
+++ b/llvm/test/Transforms/Inline/callbr.ll
@@ -14,7 +14,7 @@ define internal i32 @t32(i32) #0 {
   %3 = alloca i32, align 4
   store i32 %0, i32* %3, align 4
   %4 = load i32, i32* %3, align 4
-  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %4, i8* blockaddress(@t32, %7), i8* blockaddress(@t32, %6)) #1
+  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %4) #1
           to label %5 [label %7, label %6]
 
 ; <label>:5:                                      ; preds = %1
@@ -39,7 +39,7 @@ define internal i32 @t32(i32) #0 {
 
 ; CHECK-NOT: @t32
 ; CHECK: define dso_local i32 @main
-; CHECK: callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,i,i,~{dirflag},~{fpsr},~{flags}"(i32 %6, i8* blockaddress(@main, %9), i8* blockaddress(@main, %8))
+; CHECK: callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %6)
 ; CHECK: to label %7 [label %9, label %8]
 ; CHECK: 7:
 ; CHECK-NEXT: store i32 0, i32* %1, align 4

diff  --git a/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll b/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
index 44befe9751ed7..7d1cb4ca05feb 100644
--- a/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
+++ b/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
@@ -12,10 +12,10 @@ define i32 @c() {
 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.else:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i"(i8* blockaddress(@c, [[IF_THEN2:%.*]]))
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i"()
 ; CHECK-NEXT:    to label [[NORMAL:%.*]] [label %if.then2]
 ; CHECK:       normal:
-; CHECK-NEXT:    br label [[IF_THEN2]]
+; CHECK-NEXT:    br label [[IF_THEN2:%.*]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @b()
 ; CHECK-NEXT:    [[PHITMP:%.*]] = icmp ne i32 [[CALL]], 0
@@ -37,7 +37,7 @@ if.then:                                          ; preds = %entry
   br label %if.end
 
 if.else:                                          ; preds = %entry
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@c, %if.end)) #2
+  callbr void asm sideeffect "", "!i"() #2
   to label %normal [label %if.end]
 
 normal:                                           ; preds = %if.else

diff  --git a/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll b/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
index 882a6ea705636..a5ccde0d540bc 100644
--- a/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
+++ b/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
@@ -8,10 +8,10 @@ define i1 @func(i1 %arg, i32 %arg1, i1 %arg2) {
 ; CHECK-NEXT:  bb:
 ; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB7:%.*]], label [[BB4:%.*]]
 ; CHECK:       bb4:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i"(i8* blockaddress(@func, [[BB7_THR_COMM:%.*]]))
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i"()
 ; CHECK-NEXT:    to label [[BB5:%.*]] [label %bb7.thr_comm]
 ; CHECK:       bb5:
-; CHECK-NEXT:    br label [[BB7_THR_COMM]]
+; CHECK-NEXT:    br label [[BB7_THR_COMM:%.*]]
 ; CHECK:       bb7.thr_comm:
 ; CHECK-NEXT:    [[I91:%.*]] = xor i1 [[ARG2:%.*]], [[ARG]]
 ; CHECK-NEXT:    br i1 [[I91]], label [[BB11:%.*]], label [[BB11]]
@@ -31,7 +31,7 @@ bb3:
   br label %bb7
 
 bb4:
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@func, %bb6))
+  callbr void asm sideeffect "", "!i"()
   to label %bb5 [label %bb6]
 
 bb5:

diff  --git a/llvm/test/Transforms/LICM/callbr-crash.ll b/llvm/test/Transforms/LICM/callbr-crash.ll
index b69ffc76b79fa..5c14594276b6e 100644
--- a/llvm/test/Transforms/LICM/callbr-crash.ll
+++ b/llvm/test/Transforms/LICM/callbr-crash.ll
@@ -6,7 +6,7 @@ define i32 @j() {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
 ; CHECK:       for.cond:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@j, [[FOR_END_SPLIT_LOOP_EXIT1:%.*]]))
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
 ; CHECK-NEXT:    to label [[COND_TRUE_I:%.*]] [label %for.end.split.loop.exit1]
 ; CHECK:       cond.true.i:
 ; CHECK-NEXT:    br i1 true, label [[FOR_END_SPLIT_LOOP_EXIT:%.*]], label [[FOR_COND]]
@@ -17,14 +17,14 @@ define i32 @j() {
 ; CHECK-NEXT:    [[PHI_PH2:%.*]] = phi i32 [ undef, [[FOR_COND]] ]
 ; CHECK-NEXT:    br label [[FOR_END]]
 ; CHECK:       for.end:
-; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[ASMRESULT1_I_I_LE]], [[FOR_END_SPLIT_LOOP_EXIT]] ], [ [[PHI_PH2]], [[FOR_END_SPLIT_LOOP_EXIT1]] ]
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[ASMRESULT1_I_I_LE]], [[FOR_END_SPLIT_LOOP_EXIT]] ], [ [[PHI_PH2]], [[FOR_END_SPLIT_LOOP_EXIT1:%.*]] ]
 ; CHECK-NEXT:    ret i32 [[PHI]]
 ;
 entry:
   br label %for.cond
 
 for.cond:                                         ; preds = %cond.true.i, %entry
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@j, %for.end))
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
   to label %cond.true.i [label %for.end]
 
 cond.true.i:                                      ; preds = %for.cond

diff  --git a/llvm/test/Transforms/LoopDeletion/two-predecessors.ll b/llvm/test/Transforms/LoopDeletion/two-predecessors.ll
index 4f959f513f1fb..b6476b3532cbb 100644
--- a/llvm/test/Transforms/LoopDeletion/two-predecessors.ll
+++ b/llvm/test/Transforms/LoopDeletion/two-predecessors.ll
@@ -7,17 +7,17 @@ target triple = "aarch64-unknown-linux-gnu"
 define dso_local i32 @hoge() local_unnamed_addr #0 {
 ; CHECK-LABEL: @hoge(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i"(i8* blockaddress(@hoge, [[BB2:%.*]]))
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i"()
 ; CHECK-NEXT:    to label [[BB1:%.*]] [label %bb2]
 ; CHECK:       bb1:
-; CHECK-NEXT:    br label [[BB2]]
+; CHECK-NEXT:    br label [[BB2:%.*]]
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ undef, [[BB1]] ], [ [[TMP3:%.*]], [[BB2]] ], [ undef, [[BB:%.*]] ]
 ; CHECK-NEXT:    [[TMP3]] = tail call i32 bitcast (i32 (...)* @widget to i32 (i32)*)(i32 [[TMP]])
 ; CHECK-NEXT:    br label [[BB2]]
 ;
 bb:
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@hoge, %bb2)) #1
+  callbr void asm sideeffect "", "!i"() #1
   to label %bb1 [label %bb2]
 
 bb1:                                              ; preds = %bb

diff  --git a/llvm/test/Transforms/LoopRotate/callbr.ll b/llvm/test/Transforms/LoopRotate/callbr.ll
index 3dfda22f0bc3a..c24a9105b6859 100644
--- a/llvm/test/Transforms/LoopRotate/callbr.ll
+++ b/llvm/test/Transforms/LoopRotate/callbr.ll
@@ -31,7 +31,7 @@ define i32 @o() #0 {
 ; CHECK:       .lr.ph:
 ; CHECK-NEXT:    br label [[TMP13:%.*]]
 ; CHECK:         [[DOT11:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP14:%.*]], [[J_EXIT_I:%.*]] ]
-; CHECK-NEXT:    callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@o, [[M_EXIT]])) #1
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() #1
 ; CHECK-NEXT:    to label [[J_EXIT_I]] [label %m.exit]
 ; CHECK:       j.exit.i:
 ; CHECK-NEXT:    [[TMP14]] = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #2
@@ -79,7 +79,7 @@ thread-pre-split:                                 ; preds = %6
   br i1 %13, label %m.exit, label %14
 
 ; <label>:14:                                     ; preds = %12
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@o, %m.exit)) #1
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() #1
   to label %j.exit.i [label %m.exit]
 
 j.exit.i:                                         ; preds = %14

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll b/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll
index 18b4564cc5390..a7bd527e52abc 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll
@@ -9,8 +9,8 @@ define dso_local i32 @test1() local_unnamed_addr {
 ; LEGACYPM-NEXT:  entry:
 ; LEGACYPM-NEXT:    br label [[FOR_COND:%.*]]
 ; LEGACYPM:       for.cond:
-; LEGACYPM-NEXT:    callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, [[COND_TRUE_I:%.*]]), i8* blockaddress(@test1, [[FOR_ENDSPLIT:%.*]]))
-; LEGACYPM-NEXT:    to label [[ASM_FALLTHROUGH_I_I:%.*]] [label [[COND_TRUE_I]], label %for.endsplit]
+; LEGACYPM-NEXT:    callbr void asm sideeffect "", "!i,!i,~{dirflag},~{fpsr},~{flags}"()
+; LEGACYPM-NEXT:    to label [[ASM_FALLTHROUGH_I_I:%.*]] [label [[COND_TRUE_I:%.*]], label %for.endsplit]
 ; LEGACYPM:       asm.fallthrough.i.i:
 ; LEGACYPM-NEXT:    unreachable
 ; LEGACYPM:       cond.true.i:
@@ -28,15 +28,15 @@ define dso_local i32 @test1() local_unnamed_addr {
 ; LEGACYPM:       for.endsplit:
 ; LEGACYPM-NEXT:    br label [[FOR_END]]
 ; LEGACYPM:       for.end:
-; LEGACYPM-NEXT:    [[PGOCOUNT_PROMOTED24:%.*]] = phi i64 [ [[LSR_IV_NEXT]], [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE_FOR_END_CRIT_EDGE]] ], [ undef, [[FOR_ENDSPLIT]] ]
+; LEGACYPM-NEXT:    [[PGOCOUNT_PROMOTED24:%.*]] = phi i64 [ [[LSR_IV_NEXT]], [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE_FOR_END_CRIT_EDGE]] ], [ undef, [[FOR_ENDSPLIT:%.*]] ]
 ; LEGACYPM-NEXT:    ret i32 undef
 ;
 ; NEWPM-LABEL: @test1(
 ; NEWPM-NEXT:  entry:
 ; NEWPM-NEXT:    br label [[FOR_COND:%.*]]
 ; NEWPM:       for.cond:
-; NEWPM-NEXT:    callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, [[COND_TRUE_I:%.*]]), i8* blockaddress(@test1, [[FOR_END:%.*]]))
-; NEWPM-NEXT:    to label [[ASM_FALLTHROUGH_I_I:%.*]] [label [[COND_TRUE_I]], label %for.end]
+; NEWPM-NEXT:    callbr void asm sideeffect "", "!i,!i,~{dirflag},~{fpsr},~{flags}"()
+; NEWPM-NEXT:    to label [[ASM_FALLTHROUGH_I_I:%.*]] [label [[COND_TRUE_I:%.*]], label %for.end]
 ; NEWPM:       asm.fallthrough.i.i:
 ; NEWPM-NEXT:    unreachable
 ; NEWPM:       cond.true.i:
@@ -45,7 +45,7 @@ define dso_local i32 @test1() local_unnamed_addr {
 ; NEWPM-NEXT:    br i1 true, label [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE:%.*]], label [[DO_BODY_I_I_DO_BODY_I_I_CRIT_EDGE]]
 ; NEWPM:       do.body.i.i.rdrand_int.exit.i_crit_edge:
 ; NEWPM-NEXT:    [[TMP0:%.*]] = add i64 1, undef
-; NEWPM-NEXT:    br i1 true, label [[FOR_END]], label [[FOR_INC:%.*]]
+; NEWPM-NEXT:    br i1 true, label [[FOR_END:%.*]], label [[FOR_INC:%.*]]
 ; NEWPM:       for.inc:
 ; NEWPM-NEXT:    br label [[FOR_COND]]
 ; NEWPM:       for.end:
@@ -58,7 +58,7 @@ entry:
 for.cond:                                         ; preds = %for.inc, %entry
 ; It's ok to modify this test in the future should we be able to split critical
 ; edges here, just noting that this is the critical edge that we care about.
-  callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %cond.true.i), i8* blockaddress(@test1, %for.end))
+  callbr void asm sideeffect "", "!i,!i,~{dirflag},~{fpsr},~{flags}"()
   to label %asm.fallthrough.i.i [label %cond.true.i, label %for.end]
 
 asm.fallthrough.i.i:                              ; preds = %for.cond

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting2.ll b/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting2.ll
index 28edceb3fec3e..5852df8a9a532 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting2.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting2.ll
@@ -17,9 +17,9 @@ entry:
 if.then:                                          ; preds = %entry
 ; It's ok to modify this test in the future should be able to split critical
 ; edges here, just noting that this is the critical edge that we care about.
-; CHECK: callbr void asm sideeffect "", "i"(i8* blockaddress(@b, %cleanup.cont.critedge))
+; CHECK: callbr void asm sideeffect "", "!i"()
 ; CHECK-NEXT: to label %return [label %cleanup.cont.critedge]
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@b, %cleanup.cont.critedge))
+  callbr void asm sideeffect "", "!i"()
           to label %return [label %cleanup.cont.critedge]
 
 cleanup.cont.critedge:                            ; preds = %entry, %if.then
@@ -46,7 +46,7 @@ if.then:                                          ; preds = %for.cond
   br i1 %tobool.not.i, label %if.then2, label %if.then.i
 
 if.then.i:                                        ; preds = %if.then
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@do_pages_move_nr_pages, %if.then2))
+  callbr void asm sideeffect "", "!i"()
           to label %if.end3 [label %if.then2]
 
 if.then2:                                         ; preds = %if.then, %if.then.i

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll b/llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll
index f702732661f66..1eac53f7d83ee 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll
@@ -96,7 +96,7 @@ dead:                                             ; No predecessors!
 ; Check that this doesn't crash
 define void @kernfs_path_from_node() {
 entry:
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@kernfs_path_from_node, %while.body))
+  callbr void asm sideeffect "", "!i"()
           to label %asm.fallthrough [label %while.body]
 
 asm.fallthrough:                                  ; preds = %entry

diff  --git a/llvm/test/Transforms/LoopUnroll/callbr.ll b/llvm/test/Transforms/LoopUnroll/callbr.ll
index a2f6f22bf4ac5..4f512f30aaecd 100644
--- a/llvm/test/Transforms/LoopUnroll/callbr.ll
+++ b/llvm/test/Transforms/LoopUnroll/callbr.ll
@@ -32,7 +32,7 @@ for.body:                                         ; preds = %for.inc, %entry
   br i1 %tobool, label %for.inc, label %if.then
 
 if.then:                                          ; preds = %for.body
-  callbr void asm sideeffect "1: nop\0A\09.quad b, ${0:l}, $$5\0A\09", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@d, %l_yes))
+  callbr void asm sideeffect "1: nop\0A\09.quad b, ${0:l}, $$5\0A\09", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough [label %l_yes]
 
 asm.fallthrough:                                  ; preds = %if.then

diff  --git a/llvm/test/Transforms/PGOProfile/callbr.ll b/llvm/test/Transforms/PGOProfile/callbr.ll
index a3020a6b04d8e..b5f5f41fe6ae4 100644
--- a/llvm/test/Transforms/PGOProfile/callbr.ll
+++ b/llvm/test/Transforms/PGOProfile/callbr.ll
@@ -5,7 +5,7 @@ entry:
 ; CHECK-NOT: ptrtoint void (i8*)* asm sideeffect
 ; CHECK: callbr void asm sideeffect
   %retval = alloca i32, align 4
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@a, %b)) #1
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() #1
           to label %asm.fallthrough [label %b]
 
 asm.fallthrough:

diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll b/llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll
index 23a0e6b478ef5..e22d467b7deee 100644
--- a/llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll
@@ -11,7 +11,7 @@ for.cond:                                         ; preds = %if.end8, %entry
   br i1 %tree, label %if.end8, label %if.else
 
 if.else:                                          ; preds = %for.cond
-  callbr void asm sideeffect ".pushsection __jump_table,  \22aw\22 \0A\09.popsection \0A\09", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@mem_cgroup_node_nr_lru_pages, %for.cond5))
+  callbr void asm sideeffect ".pushsection __jump_table,  \22aw\22 \0A\09.popsection \0A\09", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %if.end8 [label %for.cond5]
 
 for.cond5:                                        ; preds = %if.else, %for.cond5

diff  --git a/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll b/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll
index 3771f160f598a..aa1b37a249ba3 100644
--- a/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll
+++ b/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll
@@ -5,7 +5,7 @@
 
 define void @fun0() {
 entry:
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@fun0, %bb1))
+  callbr void asm sideeffect "", "!i"()
           to label %bb2 [label %bb1]
 
 bb1:                                              ; preds = %bb
@@ -17,7 +17,7 @@ bb2:                                             ; preds = %bb
 
 define void @fun1() {
 entry:
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@fun1, %bb1))
+  callbr void asm sideeffect "", "!i"()
           to label %bb2 [label %bb1]
 
 bb2:                                             ; preds = %bb

diff  --git a/llvm/test/Transforms/SimplifyCFG/jump-threading.ll b/llvm/test/Transforms/SimplifyCFG/jump-threading.ll
index c340fa0880b85..e7d7662fd3ccc 100644
--- a/llvm/test/Transforms/SimplifyCFG/jump-threading.ll
+++ b/llvm/test/Transforms/SimplifyCFG/jump-threading.ll
@@ -424,7 +424,7 @@ exit:
 define void @callbr() {
 ; CHECK-LABEL: @callbr(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@callbr, [[TARGET:%.*]]))
+; CHECK-NEXT:    callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
 ; CHECK-NEXT:    to label [[IF_END:%.*]] [label %target]
 ; CHECK:       target:
 ; CHECK-NEXT:    br label [[IF_END]]
@@ -432,7 +432,7 @@ define void @callbr() {
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@callbr, %target))
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
   to label %join [label %target]
 
 target:

diff  --git a/llvm/test/Verifier/callbr.ll b/llvm/test/Verifier/callbr.ll
index 4442e864298f3..45e3e1a58096e 100644
--- a/llvm/test/Verifier/callbr.ll
+++ b/llvm/test/Verifier/callbr.ll
@@ -1,52 +1,58 @@
 ; RUN: not opt -S %s -verify 2>&1 | FileCheck %s
 
-; CHECK: Indirect label missing from arglist.
-; CHECK-NEXT: #test1
-define void @test1() {
-  ; The %4 in the indirect label list is not found in the blockaddresses in the
-  ; arg list (bad).
-  callbr void asm sideeffect "#test1", "i,i"(i8* blockaddress(@test1, %3), i8* blockaddress(@test1, %2))
-  to label %1 [label %4, label %2]
+; CHECK: Number of label constraints does not match number of callbr dests
+; CHECK-NEXT: #too_few_label_constraints
+define void @too_few_label_constraints() {
+  callbr void asm sideeffect "#too_few_label_constraints", "!i"()
+  to label %1 [label %2, label %3]
 1:
   ret void
 2:
   ret void
 3:
   ret void
-4:
-  ret void
 }
 
-; CHECK-NOT: Indirect label missing from arglist.
-define void @test2() {
-  ; %4 and %2 are both in the indirect label list and the arg list (good).
-  callbr void asm sideeffect "${0:l} ${1:l}", "i,i"(i8* blockaddress(@test2, %4), i8* blockaddress(@test2, %2))
-  to label %1 [label %4, label %2]
+; CHECK-NOT: Number of label constraints does not match number of callbr dests
+define void @correct_label_constraints() {
+  callbr void asm sideeffect "${0:l} ${1:l}", "!i,!i"()
+  to label %1 [label %2, label %3]
 1:
   ret void
 2:
   ret void
 3:
   ret void
-4:
-  ret void
 }
 
-; CHECK-NOT: Indirect label missing from arglist.
-define void @test3() {
-  ; note %2 blockaddress. Such a case is possible when passing the address of
-  ; a label as an input to the inline asm (both address of label and asm goto
-  ; use blockaddress constants; we're testing that the indirect label list from
-  ; the asm goto is in the arg list to the asm).
-  callbr void asm sideeffect "${0:l} ${1:l} ${2:l}", "i,X,i"(i8* blockaddress(@test3, %4), i8* blockaddress(@test3, %2), i8* blockaddress(@test3, %3))
-  to label %1 [label %3, label %4]
+; CHECK: Number of label constraints does not match number of callbr dests
+; CHECK-NEXT: #too_many_label_constraints
+define void @too_many_label_constraints() {
+  callbr void asm sideeffect "#too_many_label_constraints", "!i,!i,!i"()
+  to label %1 [label %2, label %3]
 1:
   ret void
 2:
   ret void
 3:
   ret void
-4:
+}
+
+; CHECK: Label constraints can only be used with callbr
+; CHECK-NEXT: #label_constraint_without_callbr
+define void @label_constraint_without_callbr() {
+  call void asm sideeffect "#label_constraint_without_callbr", "!i"()
+  ret void
+}
+
+; CHECK: Number of label constraints does not match number of callbr dests
+; CHECK-NEXT: #callbr_without_label_constraint
+define void @callbr_without_label_constraint() {
+  callbr void asm sideeffect "#callbr_without_label_constraint", ""()
+  to label %1 [label %2]
+1:
+  ret void
+2:
   ret void
 }
 
@@ -55,7 +61,7 @@ define void @test3() {
 ; CHECK-NEXT: #test4
 define i32 @test4(i1 %var) {
 entry:
-  %ret = callbr i32 asm sideeffect "#test4", "=r,i"(i8* blockaddress(@test4, %abnormal)) to label %normal [label %abnormal]
+  %ret = callbr i32 asm sideeffect "#test4", "=r,!i"() to label %normal [label %abnormal]
 
 normal:
   ret i32 0
@@ -63,14 +69,3 @@ normal:
 abnormal:
   ret i32 %ret
 }
-
-;; Ensure you cannot specify the same label as both normal and indirect targets.
-; CHECK: Duplicate callbr destination!
-; CHECK-NEXT: #test5
-define i32 @test5() {
-entry:
-  %ret = callbr i32 asm sideeffect "#test5", "=r,i"(i8* blockaddress(@test5, %both)) to label %both [label %both]
-
-both:
-  ret i32 0
-}

diff  --git a/llvm/test/Verifier/dominates.ll b/llvm/test/Verifier/dominates.ll
index 3f2f698b4b280..17d7826543b9c 100644
--- a/llvm/test/Verifier/dominates.ll
+++ b/llvm/test/Verifier/dominates.ll
@@ -71,13 +71,13 @@ next:
 
 define i32 @f6(i32 %x) {
 bb0:
-  %y1 = callbr i32 asm "", "=r"() to label %bb1 [label %bb2]
+  %y1 = callbr i32 asm "", "=r,!i"() to label %bb1 [label %bb2]
 bb1:
   ret i32 0
 bb2:
   ret i32 %y1
 ; CHECK: Instruction does not dominate all uses!
-; CHECK-NEXT:  %y1 = callbr i32 asm "", "=r"()
+; CHECK-NEXT:  %y1 = callbr i32 asm "", "=r,!i"()
 ; CHECK-NEXT:        to label %bb1 [label %bb2]
 ; CHECK-NEXT:  ret i32 %y1
 }

diff  --git a/llvm/test/tools/llvm-
diff /callbr.ll b/llvm/test/tools/llvm-
diff /callbr.ll
index f925606c11cf7..10de611ab00fd 100644
--- a/llvm/test/tools/llvm-
diff /callbr.ll
+++ b/llvm/test/tools/llvm-
diff /callbr.ll
@@ -1,8 +1,8 @@
-; RUN: not llvm-
diff  %s %s 2>&1 | FileCheck %s
+; RUN: llvm-
diff  %s %s
 
 define void @foo() {
 entry:
-  callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %return), i8* blockaddress(@foo, %t_no))
+  callbr void asm sideeffect "", "!i,!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough [label %return, label %t_no]
 
 asm.fallthrough:
@@ -15,17 +15,9 @@ return:
   ret void
 }
 
-; CHECK:      in function bar:
-; CHECK-NOT:  in function foo:
-; CHECK-NEXT:  in block %entry:
-; CHECK-NEXT:    >   callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %t_no), i8* blockaddress(@foo, %return))
-; CHECK-NEXT:          to label %asm.fallthrough [label %return, label %t_no]
-; CHECK-NEXT:    <   callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %t_no), i8* blockaddress(@foo, %return))
-; CHECK-NEXT:          to label %asm.fallthrough [label %return, label %t_no]
-
 define void @bar() {
 entry:
-  callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %t_no), i8* blockaddress(@foo, %return))
+  callbr void asm sideeffect "", "!i,!i,~{dirflag},~{fpsr},~{flags}"()
           to label %asm.fallthrough [label %return, label %t_no]
 
 asm.fallthrough:

diff  --git a/llvm/test/tools/llvm-
diff /phinode.ll b/llvm/test/tools/llvm-
diff /phinode.ll
index 72927a071d6ff..b6163ee2ac634 100644
--- a/llvm/test/tools/llvm-
diff /phinode.ll
+++ b/llvm/test/tools/llvm-
diff /phinode.ll
@@ -9,7 +9,7 @@
 ; CHECK-NEXT:    <   %7 = phi i32 [ 0, %2 ], [ -1, %1 ]
 ; CHECK-NEXT:    <   ret i32 %7
 define i32 @foo(i32 %0) #0 {
-  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %6))
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
           to label %2 [label %6]
 
 2:

diff  --git a/llvm/test/tools/llvm-reduce/remove-function-arguments-of-funcs-used-in-blockaddress.ll b/llvm/test/tools/llvm-reduce/remove-function-arguments-of-funcs-used-in-blockaddress.ll
index b1d4f0197246f..f2fec66e227b2 100644
--- a/llvm/test/tools/llvm-reduce/remove-function-arguments-of-funcs-used-in-blockaddress.ll
+++ b/llvm/test/tools/llvm-reduce/remove-function-arguments-of-funcs-used-in-blockaddress.ll
@@ -4,27 +4,17 @@
 ; CHECK-INTERESTINGNESS: define void @func(
 ; CHECK-FINAL: define void @func()
 define void @func(i1 %arg) {
-; CHECK-ALL: bb:
-; CHECK-ALL: br label %bb4
-bb:
-  br label %bb4
-
-; CHECK-ALL: bb4
-bb4:
-; CHECK-INTERESTINGNESS: callbr void asm
-; CHECK-INTERESTINGNESS-SAME: blockaddress
-; CHECK-FINAL: callbr void asm sideeffect "", "i"(i8* blockaddress(@func, %bb11))
-; CHECK-ALL: to label %bb5 [label %bb11]
-  callbr void asm sideeffect "", "i"(i8* blockaddress(@func, %bb11))
-          to label %bb5 [label %bb11]
+; CHECK-ALL: entry:
+; CHECK-INTERESTINGNESS: call void @foo({{.*}}blockaddress
+; CHECK-FINAL: call void @foo(i8* blockaddress(@func, %bb5))
+entry:
+  call void @foo(i8* blockaddress(@func, %bb5))
+  ret void
 
 ; CHECK-ALL: bb5:
-; CHECK-ALL: br label %bb11
-bb5:
-  br label %bb11
-
-; CHECK-ALL: bb11:
 ; CHECK-ALL: ret void
-bb11:
+bb5:
   ret void
 }
+
+declare void @foo(i8*)

diff  --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index 6324adfea4c4d..c80bfa9762663 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -1498,7 +1498,7 @@ TEST(InstructionsTest, CallBrInstruction) {
   std::unique_ptr<Module> M = parseIR(Context, R"(
 define void @foo() {
 entry:
-  callbr void asm sideeffect "// XXX: ${0:l}", "X"(i8* blockaddress(@foo, %branch_test.exit))
+  callbr void asm sideeffect "// XXX: ${0:l}", "!i"()
           to label %land.rhs.i [label %branch_test.exit]
 
 land.rhs.i:
@@ -1528,20 +1528,6 @@ if.end:
   EXPECT_EQ(&BranchTestExit, CBI.getIndirectDest(0));
   CBI.setIndirectDest(0, &IfThen);
   EXPECT_EQ(&IfThen, CBI.getIndirectDest(0));
-
-  // Further, test that changing the indirect destination updates the arg
-  // operand to use the block address of the new indirect destination basic
-  // block. This is a critical invariant of CallBrInst.
-  BlockAddress *IndirectBA = BlockAddress::get(CBI.getIndirectDest(0));
-  BlockAddress *ArgBA = cast<BlockAddress>(CBI.getArgOperand(0));
-  EXPECT_EQ(IndirectBA, ArgBA)
-      << "After setting the indirect destination, callbr had an indirect "
-         "destination of '"
-      << CBI.getIndirectDest(0)->getName() << "', but a argument of '"
-      << ArgBA->getBasicBlock()->getName() << "'. These should always match:\n"
-      << CBI;
-  EXPECT_EQ(IndirectBA->getBasicBlock(), &IfThen);
-  EXPECT_EQ(ArgBA->getBasicBlock(), &IfThen);
 }
 
 TEST(InstructionsTest, UnaryOperator) {

diff  --git a/polly/test/ScopDetect/callbr.ll b/polly/test/ScopDetect/callbr.ll
index 1981f0127e873..f226818a4ca13 100644
--- a/polly/test/ScopDetect/callbr.ll
+++ b/polly/test/ScopDetect/callbr.ll
@@ -12,7 +12,7 @@ target triple = "x86_64-unknown-linux-gnu"
 
 define void @func(i32 %n, double* noalias nonnull %A) {
 entry:
-  callbr void asm sideeffect "", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@func, %for)) #1
+  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() #1
           to label %fallthrough [label %for]
 
 fallthrough:


        


More information about the llvm-commits mailing list