[llvm] e886e76 - Revert "Allow output constraints on "asm goto""

Bill Wendling via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 7 13:44:16 PST 2020


Author: Bill Wendling
Date: 2020-01-07T13:44:08-08:00
New Revision: e886e762dd7972064b948119f9af2f6be312b995

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

LOG: Revert "Allow output constraints on "asm goto""

This reverts commit 52366088a8e42c2f1e96e8430b84b8b65ec3f7bc.

I accidentally pushed this before supporting changes.

Added: 
    

Modified: 
    llvm/docs/LangRef.rst
    llvm/include/llvm/CodeGen/MachineBasicBlock.h
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/CodeGen/MachineBasicBlock.cpp
    llvm/lib/CodeGen/MachineVerifier.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/test/CodeGen/X86/callbr-asm-outputs.ll
    llvm/test/CodeGen/X86/callbr-asm.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index fc2526aafcee..97e454e5e538 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -7099,14 +7099,14 @@ Syntax:
 ::
 
       <result> = callbr [cconv] [ret attrs] [addrspace(<num>)] <ty>|<fnty> <fnptrval>(<function args>) [fn attrs]
-                    [operand bundles] to label <fallthrough label> [indirect labels]
+                    [operand bundles] to label <normal label> [other labels]
 
 Overview:
 """""""""
 
 The '``callbr``' instruction causes control to transfer to a specified
 function, with the possibility of control flow transfer to either the
-'``fallthrough``' label or one of the '``indirect``' labels.
+'``normal``' label or one of the '``other``' labels.
 
 This instruction should only be used to implement the "goto" feature of gcc
 style inline assembly. Any other usage is an error in the IR verifier.
@@ -7133,17 +7133,17 @@ This instruction requires several arguments:
    type can be omitted if the function is not varargs.
 #. '``fnptrval``': An LLVM value containing a pointer to a function to
    be called. In most cases, this is a direct function call, but
-   other ``callbr``'s are just as possible, calling an arbitrary pointer
+   indirect ``callbr``'s are just as possible, calling an arbitrary pointer
    to function value.
 #. '``function args``': argument list whose types match the function
    signature argument types and parameter attributes. All arguments must
    be of :ref:`first class <t_firstclass>` type. If the function signature
    indicates the function accepts a variable number of arguments, the
    extra arguments can be specified.
-#. '``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
+#. '``normal label``': the label reached when the called function
+   executes a '``ret``' instruction.
+#. '``other labels``': the labels reached when a callee transfers control
+   to a location other than the normal '``normal label``'. The blockaddress
    constant for these should also be in the list of '``function args``'.
 #. The optional :ref:`function attributes <fnattrs>` list.
 #. The optional :ref:`operand bundles <opbundles>` list.
@@ -7156,13 +7156,6 @@ instruction in most regards. The primary 
diff erence is that it
 establishes an association with additional labels to define where control
 flow goes after the call.
 
-Outputs of a '``callbr``' instruction are valid only on the '``fallthrough``'
-path.  Use of outputs on the '``indirect``' path(s) results in :ref:`poison
-values <poisonvalues>`. Care should be taken if the '``fallthrough``' block is
-also listed in the '``indirect``' blocks. The outputs may or may not result in
-:ref:`poison values <poisonvalues>` depending on the behavior of the inline
-assembly.
-
 The only use of this today is to implement the "goto" feature of gcc inline
 assembly where additional labels can be provided as locations for the inline
 assembly to jump to.
@@ -7170,15 +7163,10 @@ assembly to jump to.
 Example:
 """"""""
 
-.. code-block:: llvm
-
-      ; "asm goto" without output constraints.
-      callbr void asm "", "r,X"(i32 %x, i8 *blockaddress(@foo, %indirect))
-                  to label %fallthrough [label %indirect]
+.. code-block:: text
 
-      ; "asm goto" with output constraints.
-      <result> = callbr i32 asm "", "=r,r,X"(i32 %x, i8 *blockaddress(@foo, %indirect))
-                  to label %fallthrough [label %indirect]
+      callbr void asm "", "r,x"(i32 %x, i8 *blockaddress(@foo, %fail))
+                  to label %normal [label %fail]
 
 .. _i_resume:
 

diff  --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index cbcd0b61ecb6..ccdde78a0b22 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -129,9 +129,6 @@ class MachineBasicBlock
   /// Indicate that this basic block is the entry block of a cleanup funclet.
   bool IsCleanupFuncletEntry = false;
 
-  /// Indicate that this basic block is the indirect dest of an INLINEASM_BR.
-  bool IsInlineAsmBrIndirectPad = false;
-
   /// since getSymbol is a relatively heavy-weight operation, the symbol
   /// is only computed once and is cached.
   mutable MCSymbol *CachedMCSymbol = nullptr;
@@ -411,12 +408,6 @@ class MachineBasicBlock
   /// Indicates if this is the entry block of a cleanup funclet.
   void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; }
 
-  /// Returns true if this is the indirect dest of an INLINEASM_BR.
-  bool isInlineAsmBrIndirectPad() const { return IsInlineAsmBrIndirectPad; }
-
-  /// Indicates if this is the indirect dest of an INLINEASM_BR.
-  void setIsInlineAsmBrIndirectPad(bool V = true) { IsInlineAsmBrIndirectPad = V; }
-
   /// Returns true if it is legal to hoist instructions into this block.
   bool isLegalToHoistInto() const;
 

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 731c1cea0dc3..1a17f633ae16 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6419,6 +6419,9 @@ bool LLParser::ParseCallBr(Instruction *&Inst, PerFunctionState &PFS) {
                           /*IsCall=*/true))
     return true;
 
+  if (isa<InlineAsm>(Callee) && !Ty->getReturnType()->isVoidTy())
+    return Error(RetTypeLoc, "asm-goto outputs not supported");
+
   // Set up the Attribute for the function.
   SmallVector<Value *, 8> Args;
   SmallVector<AttributeSet, 8> ArgAttrs;

diff  --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 8928dc858d5d..f433c4b6c90b 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -1109,17 +1109,6 @@ bool MachineBasicBlock::canSplitCriticalEdge(
   if (Succ->isEHPad())
     return false;
 
-  // Splitting the critical edge to a callbr's indirect block isn't advised.
-  // Don't do it in this generic function.
-  if (Succ->hasAddressTaken())
-    if (auto *cbr = dyn_cast<CallBrInst>(getBasicBlock()->getTerminator()))
-      if (auto *bb = Succ->getBasicBlock())
-        if (cbr->getDefaultDest() != bb)
-          if (llvm::any_of(cbr->getIndirectDests(), [&](const BasicBlock *succ){
-                  return succ == bb;
-              }))
-            return false;
-
   const MachineFunction *MF = getParent();
 
   // Performance might be harmed on HW that implements branching using exec mask

diff  --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index cbafd387a62c..ca57e51268e8 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -633,30 +633,17 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
   }
 
   // Count the number of landing pad successors.
-  SmallPtrSet<const MachineBasicBlock*, 4> LandingPadSuccs;
-  for (const auto *succ : MBB->successors()) {
-    if (succ->isEHPad())
-      LandingPadSuccs.insert(succ);
-    if (!FunctionBlocks.count(succ))
-      report("MBB has successor that isn't part of the function.", MBB);
-    if (!MBBInfoMap[succ].Preds.count(MBB)) {
-      report("Inconsistent CFG", MBB);
-      errs() << "MBB is not in the predecessor list of the successor "
-             << printMBBReference(*succ) << ".\n";
-    }
-  }
-
-  // Count the number of INLINEASM_BR indirect pad successors.
-  SmallPtrSet<const MachineBasicBlock*, 4> IndirectPadSuccs;
-  for (const auto *succ : MBB->successors()) {
-    if (succ->isInlineAsmBrIndirectPad())
-      IndirectPadSuccs.insert(succ);
-    if (!FunctionBlocks.count(succ))
+  SmallPtrSet<MachineBasicBlock*, 4> LandingPadSuccs;
+  for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(),
+       E = MBB->succ_end(); I != E; ++I) {
+    if ((*I)->isEHPad())
+      LandingPadSuccs.insert(*I);
+    if (!FunctionBlocks.count(*I))
       report("MBB has successor that isn't part of the function.", MBB);
-    if (!MBBInfoMap[succ].Preds.count(MBB)) {
+    if (!MBBInfoMap[*I].Preds.count(MBB)) {
       report("Inconsistent CFG", MBB);
       errs() << "MBB is not in the predecessor list of the successor "
-             << printMBBReference(*succ) << ".\n";
+             << printMBBReference(*(*I)) << ".\n";
     }
   }
 
@@ -697,13 +684,11 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
         // It's possible that the block legitimately ends with a noreturn
         // call or an unreachable, in which case it won't actually fall
         // out the bottom of the function.
-      } else if (MBB->succ_size() == LandingPadSuccs.size() ||
-                 MBB->succ_size() == IndirectPadSuccs.size()) {
+      } else if (MBB->succ_size() == LandingPadSuccs.size()) {
         // It's possible that the block legitimately ends with a noreturn
         // call or an unreachable, in which case it won't actually fall
         // out of the block.
-      } else if (MBB->succ_size() != 1 + LandingPadSuccs.size() &&
-                 MBB->succ_size() != 1 + IndirectPadSuccs.size()) {
+      } else if (MBB->succ_size() != 1+LandingPadSuccs.size()) {
         report("MBB exits via unconditional fall-through but doesn't have "
                "exactly one CFG successor!", MBB);
       } else if (!MBB->isSuccessor(&*MBBI)) {
@@ -725,10 +710,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
       // landingpad, accept it as valid control flow.
       if (MBB->succ_size() != 1+LandingPadSuccs.size() &&
           (MBB->succ_size() != 1 || LandingPadSuccs.size() != 1 ||
-           *MBB->succ_begin() != *LandingPadSuccs.begin()) &&
-          MBB->succ_size() != 1 + IndirectPadSuccs.size() &&
-          (MBB->succ_size() != 1 || IndirectPadSuccs.size() != 1 ||
-           *MBB->succ_begin() != *IndirectPadSuccs.begin())) {
+           *MBB->succ_begin() != *LandingPadSuccs.begin())) {
         report("MBB exits via unconditional branch but doesn't have "
                "exactly one CFG successor!", MBB);
       } else if (!MBB->isSuccessor(TBB)) {
@@ -858,14 +840,8 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) {
     if (!FirstTerminator)
       FirstTerminator = MI;
   } else if (FirstTerminator && !MI->isDebugEntryValue()) {
-    // An "INLINEASM_BR" will fallthrough to the successor block executing any
-    // "COPY" instructions that exist so that they can be assigned in the
-    // fallthrough block..
-    if (FirstTerminator->getOpcode() != TargetOpcode::INLINEASM_BR ||
-        MI->getOpcode() != TargetOpcode::COPY) {
-      report("Non-terminator instruction after the first terminator", MI);
-      errs() << "First terminator was:\t" << *FirstTerminator;
-    }
+    report("Non-terminator instruction after the first terminator", MI);
+    errs() << "First terminator was:\t" << *FirstTerminator;
   }
 }
 

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1505506dbf03..00b05c5db2f8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2847,7 +2847,6 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
   assert(isa<InlineAsm>(I.getCalledValue()) &&
          "Only know how to handle inlineasm callbr");
   visitInlineAsm(&I);
-  CopyToExportRegsIfNeeded(&I);
 
   // Retrieve successors.
   MachineBasicBlock *Return = FuncInfo.MBBMap[I.getDefaultDest()];
@@ -2857,7 +2856,6 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
   for (unsigned i = 0, e = I.getNumIndirectDests(); i < e; ++i) {
     MachineBasicBlock *Target = FuncInfo.MBBMap[I.getIndirectDest(i)];
     addSuccessorWithProb(CallBrMBB, Target);
-    Target->setIsInlineAsmBrIndirectPad();
   }
   CallBrMBB->normalizeSuccProbs();
 

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 184a9a0569b6..e3a3d91b455b 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2501,6 +2501,8 @@ void Verifier::visitIndirectBrInst(IndirectBrInst &BI) {
 void Verifier::visitCallBrInst(CallBrInst &CBI) {
   Assert(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!",
          &CBI);
+  Assert(CBI.getType()->isVoidTy(), "Callbr return value is not supported!",
+         &CBI);
   for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i)
     Assert(CBI.getSuccessor(i)->getType()->isLabelTy(),
            "Callbr successors must all have pointer type!", &CBI);

diff  --git a/llvm/test/CodeGen/X86/callbr-asm-outputs.ll b/llvm/test/CodeGen/X86/callbr-asm-outputs.ll
index 7aebf180c794..7595deba3364 100644
--- a/llvm/test/CodeGen/X86/callbr-asm-outputs.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm-outputs.ll
@@ -1,118 +1,18 @@
-; RUN: llc -mtriple=i686-- -verify-machineinstrs < %s | FileCheck %s
+; RUN: not llc -mtriple=i686-- < %s 2> %t
+; RUN: FileCheck %s < %t
 
-; A test for asm-goto output
+; CHECK: error: asm-goto outputs not supported
 
-; CHECK-LABEL: test1:
-; CHECK:       movl 4(%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:  .LBB0_1:
-; CHECK-NEXT:  retl
-; CHECK-NEXT:  .Ltmp0:
-define i32 @test1(i32 %x) {
+; A test for asm-goto output prohibition
+
+define i32 @test(i32 %a) {
 entry:
-  %add = add nsw i32 %x, 4
-  %ret = callbr i32 asm "xorl $1, $0; jmp ${2:l}", "=r,r,X,~{dirflag},~{fpsr},~{flags}"(i32 %add, i8* blockaddress(@test1, %abnormal))
-          to label %normal [label %abnormal]
+  %0 = add i32 %a, 4
+  %1 = callbr i32 asm "xorl $1, $1; jmp ${1:l}", "=&r,r,X,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@test, %fail)) to label %normal [label %fail]
 
 normal:
-  ret i32 %ret
+  ret i32 %1
 
-abnormal:
+fail:
   ret i32 1
 }
-
-; CHECK-LABEL: test2:
-; CHECK:       # %bb.1: # %if.then
-; CHECK-NEXT:      #APP
-; CHECK-NEXT:      testl %esi, %esi
-; CHECK-NEXT:      testl %edi, %esi
-; CHECK-NEXT:      jne .Ltmp1
-; CHECK-NEXT:      #NO_APP
-; CHECK-NEXT:  .LBB1_2:
-; CHECK-NEXT:      jmp .LBB1_4
-; CHECK-NEXT:  .LBB1_3: # %if.else
-; CHECK-NEXT:      #APP
-; CHECK-NEXT:      testl %esi, %edi
-; CHECK-NEXT:      testl %esi, %edi
-; CHECK-NEXT:      jne .Ltmp2
-; CHECK-NEXT:      #NO_APP
-; CHECK-NEXT:  .LBB1_4:
-; CHECK-NEXT:      movl %esi, %eax
-; CHECK-NEXT:      addl %edi, %eax
-; CHECK-NEXT:      jmp .LBB1_6
-; CHECK-NEXT:  .Ltmp1:
-; CHECK-NEXT:  .LBB1_5: # %label_true
-; CHECK-NEXT:      movl $-2, %eax
-; CHECK-NEXT:  .Ltmp2:
-; CHECK-NEXT:  .LBB1_6: # %return
-define i32 @test2(i32 %out1, i32 %out2) {
-entry:
-  %cmp = icmp slt i32 %out1, %out2
-  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 ${5:l}", "={si},={di},r,0,1,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %out1, i32 %out1, i32 %out2, i8* blockaddress(@test2, %label_true), i8* blockaddress(@test2, %return))
-          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 ${7:l}", "={si},={di},r,r,0,1,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %out1, i32 %out2, i32 %out1, i32 %out2, i8* blockaddress(@test2, %label_true), i8* blockaddress(@test2, %return))
-          to label %if.end [label %label_true, label %return]
-
-if.end:                                           ; preds = %if.else, %if.then
-  %.sink11 = phi { i32, i32 } [ %0, %if.then ], [ %1, %if.else ]
-  %asmresult3 = extractvalue { i32, i32 } %.sink11, 0
-  %asmresult4 = extractvalue { i32, i32 } %.sink11, 1
-  %add = add nsw i32 %asmresult4, %asmresult3
-  br label %return
-
-label_true:                                       ; preds = %if.else, %if.then
-  br label %return
-
-return:                                           ; preds = %if.then, %if.else, %label_true, %if.end
-  %retval.0 = phi i32 [ %add, %if.end ], [ -2, %label_true ], [ -1, %if.else ], [ -1, %if.then ]
-  ret i32 %retval.0
-}
-
-; CHECK-LABEL: test3:
-; CHECK:       # %bb.1:                                # %true
-; CHECK-NEXT:      #APP
-; CHECK-NEXT:      .short %esi
-; CHECK-NEXT:      .short %edi
-; CHECK-NEXT:      #NO_APP
-; CHECK-NEXT:  .LBB2_2:
-; CHECK-NEXT:      movl %edi, %eax
-; CHECK-NEXT:      jmp .LBB2_5
-; CHECK-NEXT:  .LBB2_3:                                # %false
-; CHECK-NEXT:      #APP
-; CHECK-NEXT:      .short %eax
-; CHECK-NEXT:      .short %edx
-; CHECK-NEXT:      #NO_APP
-; CHECK-NEXT:  .LBB2_4:
-; CHECK-NEXT:      movl %edx, %eax
-; CHECK-NEXT:      jmp .LBB2_5
-; CHECK-NEXT:  .Ltmp3:                                 # Block address taken
-; CHECK-NEXT:  .LBB2_6:                                # %indirect
-; CHECK-NEXT:      movl $42, %eax
-; CHECK-NEXT:  .LBB2_5:                                # %asm.fallthrough
-define i32 @test3(i1 %cmp) {
-entry:
-  br i1 %cmp, label %true, label %false
-
-true:
-  %0 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={si},={di},X" (i8* blockaddress(@test3, %indirect)) to label %asm.fallthrough [label %indirect]
-
-false:
-  %1 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={ax},={dx},X" (i8* blockaddress(@test3, %indirect)) to label %asm.fallthrough [label %indirect]
-
-asm.fallthrough:
-  %vals = phi { i32, i32 } [ %0, %true ], [ %1, %false ]
-  %v = extractvalue { i32, i32 } %vals, 1
-  ret i32 %v
-
-indirect:
-  ret i32 42
-}

diff  --git a/llvm/test/CodeGen/X86/callbr-asm.ll b/llvm/test/CodeGen/X86/callbr-asm.ll
index ecfcd5149654..8938aefca087 100644
--- a/llvm/test/CodeGen/X86/callbr-asm.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=i686-- -O3 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=i686-- -O3 | FileCheck %s
 
 ; Tests for using callbr as an asm-goto wrapper
 
@@ -159,54 +159,3 @@ quux:                                             ; preds = %asm.fallthrough, %e
 cleanup:                                          ; preds = %asm.fallthrough, %quux
   ret void
 }
-
-define i32 @test5(i32 %out1, i32 %out2) {
-; Test 5 - asm-goto with output constraints.
-; CHECK-LABEL: test5:
-; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:      movl $-1, %eax
-; CHECK-NEXT:      movl 4(%esp), %ecx
-; CHECK-NEXT:      #APP
-; CHECK-NEXT:      testl %ecx, %ecx
-; CHECK-NEXT:      testl %edx, %ecx
-; CHECK-NEXT:      jne .Ltmp6
-; CHECK-NEXT:      #NO_APP
-; CHECK-NEXT:  .LBB4_1:
-; CHECK-NEXT:      #APP
-; CHECK-NEXT:      testl %ecx, %edx
-; CHECK-NEXT:      testl %ecx, %edx
-; CHECK-NEXT:      jne .Ltmp7
-; CHECK-NEXT:      #NO_APP
-; CHECK-NEXT:  .LBB4_2:
-; CHECK-NEXT:      addl %edx, %ecx
-; CHECK-NEXT:      movl %ecx, %eax
-; CHECK-NEXT:      retl
-; CHECK-NEXT:  .Ltmp6:
-; CHECK-NEXT:  .LBB4_3:
-; CHECK-NEXT:      movl $-2, %eax
-; CHECK-NEXT:  .Ltmp7:
-; CHECK-NEXT:  .LBB4_4:
-; CHECK-NEXT:      retl
-entry:
-  %0 = callbr { i32, i32 } asm sideeffect "testl $0, $0; testl $1, $2; jne ${3:l}", "=r,=r,r,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %out1, i8* blockaddress(@test5, %label_true), i8* blockaddress(@test5, %return))
-          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,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %asmresult, i32 %asmresult1, i8* blockaddress(@test5, %label_true), i8* blockaddress(@test5, %return))
-          to label %asm.fallthrough2 [label %label_true, label %return]
-
-asm.fallthrough2:                                 ; preds = %asm.fallthrough
-  %asmresult3 = extractvalue { i32, i32 } %1, 0
-  %asmresult4 = extractvalue { i32, i32 } %1, 1
-  %add = add nsw i32 %asmresult3, %asmresult4
-  br label %return
-
-label_true:                                       ; preds = %asm.fallthrough, %entry
-  br label %return
-
-return:                                           ; preds = %entry, %asm.fallthrough, %label_true, %asm.fallthrough2
-  %retval.0 = phi i32 [ %add, %asm.fallthrough2 ], [ -2, %label_true ], [ -1, %asm.fallthrough ], [ -1, %entry ]
-  ret i32 %retval.0
-}


        


More information about the llvm-commits mailing list