[llvm] r314005 - [XRay] support conditional return on PPC.

Tim Shen via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 22 11:30:02 PDT 2017


Author: timshen
Date: Fri Sep 22 11:30:02 2017
New Revision: 314005

URL: http://llvm.org/viewvc/llvm-project?rev=314005&view=rev
Log:
[XRay] support conditional return on PPC.

Summary: Conditional returns were not taken into consideration at all. Implement them by turning them into jumps and normal returns. This means there is a slightly higher performance penalty for conditional returns, but this is the best we can do, and it still disturbs little of the rest.

Reviewers: dberris, echristo

Subscribers: sanjoy, nemanjai, hiraditya, kbarton, llvm-commits

Differential Revision: https://reviews.llvm.org/D38102

Added:
    llvm/trunk/test/CodeGen/PowerPC/xray-conditional-return.ll
    llvm/trunk/test/CodeGen/PowerPC/xray-ret-is-terminator.ll
Modified:
    llvm/trunk/include/llvm/Target/Target.td
    llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp
    llvm/trunk/lib/Target/PowerPC/PPC.h
    llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp

Modified: llvm/trunk/include/llvm/Target/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=314005&r1=314004&r2=314005&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/Target.td (original)
+++ llvm/trunk/include/llvm/Target/Target.td Fri Sep 22 11:30:02 2017
@@ -1049,6 +1049,7 @@ def PATCHABLE_RET : Instruction {
   let AsmString = "# XRay Function Patchable RET.";
   let usesCustomInserter = 1;
   let hasSideEffects = 1;
+  let isTerminator = 1;
   let isReturn = 1;
 }
 def PATCHABLE_FUNCTION_EXIT : Instruction {

Modified: llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp?rev=314005&r1=314004&r2=314005&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp (original)
+++ llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp Fri Sep 22 11:30:02 2017
@@ -34,6 +34,15 @@ using namespace llvm;
 
 namespace {
 
+struct InstrumentationOptions {
+  // Whether to emit PATCHABLE_TAIL_CALL.
+  bool HandleTailcall;
+
+  // Whether to emit PATCHABLE_RET/PATCHABLE_FUNCTION_EXIT for all forms of
+  // return, e.g. conditional return.
+  bool HandleAllReturns;
+};
+
 struct XRayInstrumentation : public MachineFunctionPass {
   static char ID;
 
@@ -59,7 +68,8 @@ private:
   // This is the approach to go on CPUs which have a single RET instruction,
   //   like x86/x86_64.
   void replaceRetWithPatchableRet(MachineFunction &MF,
-                                  const TargetInstrInfo *TII);
+                                  const TargetInstrInfo *TII,
+                                  InstrumentationOptions);
 
   // Prepend the original return instruction with the exit sled code ("patchable
   //   function exit" pseudo-instruction), preserving the original return
@@ -70,25 +80,28 @@ private:
   //   have to call the trampoline and return from it to the original return
   //   instruction of the function being instrumented.
   void prependRetWithPatchableExit(MachineFunction &MF,
-                                   const TargetInstrInfo *TII);
+                                   const TargetInstrInfo *TII,
+                                   InstrumentationOptions);
 };
 
 } // end anonymous namespace
 
 void XRayInstrumentation::replaceRetWithPatchableRet(
-    MachineFunction &MF, const TargetInstrInfo *TII) {
+    MachineFunction &MF, const TargetInstrInfo *TII,
+    InstrumentationOptions op) {
   // We look for *all* terminators and returns, then replace those with
   // PATCHABLE_RET instructions.
   SmallVector<MachineInstr *, 4> Terminators;
   for (auto &MBB : MF) {
     for (auto &T : MBB.terminators()) {
       unsigned Opc = 0;
-      if (T.isReturn() && T.getOpcode() == TII->getReturnOpcode()) {
+      if (T.isReturn() &&
+          (op.HandleAllReturns || T.getOpcode() == TII->getReturnOpcode())) {
         // Replace return instructions with:
         //   PATCHABLE_RET <Opcode>, <Operand>...
         Opc = TargetOpcode::PATCHABLE_RET;
       }
-      if (TII->isTailCall(T)) {
+      if (TII->isTailCall(T) && op.HandleTailcall) {
         // Treat the tail call as a return instruction, which has a
         // different-looking sled than the normal return case.
         Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
@@ -108,14 +121,24 @@ void XRayInstrumentation::replaceRetWith
 }
 
 void XRayInstrumentation::prependRetWithPatchableExit(
-    MachineFunction &MF, const TargetInstrInfo *TII) {
+    MachineFunction &MF, const TargetInstrInfo *TII,
+    InstrumentationOptions op) {
   for (auto &MBB : MF)
-    for (auto &T : MBB.terminators())
-      if (T.isReturn()) {
-        // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT.
-        BuildMI(MBB, T, T.getDebugLoc(),
-                TII->get(TargetOpcode::PATCHABLE_FUNCTION_EXIT));
+    for (auto &T : MBB.terminators()) {
+      unsigned Opc = 0;
+      if (T.isReturn() &&
+          (op.HandleAllReturns || T.getOpcode() == TII->getReturnOpcode())) {
+        Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;
       }
+      if (TII->isTailCall(T) && op.HandleTailcall) {
+        Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
+      }
+      if (Opc != 0) {
+        // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT or
+        //   PATCHABLE_TAIL_CALL .
+        BuildMI(MBB, T, T.getDebugLoc(), TII->get(Opc));
+      }
+    }
 }
 
 bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) {
@@ -171,20 +194,35 @@ bool XRayInstrumentation::runOnMachineFu
   case Triple::ArchType::arm:
   case Triple::ArchType::thumb:
   case Triple::ArchType::aarch64:
-  case Triple::ArchType::ppc64le:
   case Triple::ArchType::mips:
   case Triple::ArchType::mipsel:
   case Triple::ArchType::mips64:
-  case Triple::ArchType::mips64el:
+  case Triple::ArchType::mips64el: {
     // For the architectures which don't have a single return instruction
-    prependRetWithPatchableExit(MF, TII);
+    InstrumentationOptions op;
+    op.HandleTailcall = false;
+    op.HandleAllReturns = true;
+    prependRetWithPatchableExit(MF, TII, op);
+    break;
+  }
+  case Triple::ArchType::ppc64le: {
+    // PPC has conditional returns. Turn them into branch and plain returns.
+    InstrumentationOptions op;
+    op.HandleTailcall = false;
+    op.HandleAllReturns = true;
+    replaceRetWithPatchableRet(MF, TII, op);
     break;
-  default:
+  }
+  default: {
     // For the architectures that have a single return instruction (such as
     //   RETQ on x86_64).
-    replaceRetWithPatchableRet(MF, TII);
+    InstrumentationOptions op;
+    op.HandleTailcall = true;
+    op.HandleAllReturns = false;
+    replaceRetWithPatchableRet(MF, TII, op);
     break;
   }
+  }
   return true;
 }
 

Modified: llvm/trunk/lib/Target/PowerPC/PPC.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPC.h?rev=314005&r1=314004&r2=314005&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPC.h (original)
+++ llvm/trunk/lib/Target/PowerPC/PPC.h Fri Sep 22 11:30:02 2017
@@ -26,8 +26,10 @@ namespace llvm {
   class PassRegistry;
   class FunctionPass;
   class MachineInstr;
+  class MachineOperand;
   class AsmPrinter;
   class MCInst;
+  class MCOperand;
 
   FunctionPass *createPPCCTRLoops();
 #ifndef NDEBUG
@@ -49,6 +51,9 @@ namespace llvm {
   FunctionPass *createPPCExpandISELPass();
   void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
                                     AsmPrinter &AP, bool isDarwin);
+  bool LowerPPCMachineOperandToMCOperand(const MachineOperand &MO,
+                                         MCOperand &OutMO, AsmPrinter &AP,
+                                         bool isDarwin);
 
   void initializePPCVSXFMAMutatePass(PassRegistry&);
   void initializePPCBoolRetToIntPass(PassRegistry&);

Modified: llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp?rev=314005&r1=314004&r2=314005&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp Fri Sep 22 11:30:02 2017
@@ -19,6 +19,7 @@
 #include "InstPrinter/PPCInstPrinter.h"
 #include "MCTargetDesc/PPCMCExpr.h"
 #include "MCTargetDesc/PPCMCTargetDesc.h"
+#include "MCTargetDesc/PPCPredicates.h"
 #include "PPC.h"
 #include "PPCInstrInfo.h"
 #include "PPCMachineFunctionInfo.h"
@@ -1089,7 +1090,61 @@ void PPCLinuxAsmPrinter::EmitInstruction
     recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER);
     break;
   }
-  case TargetOpcode::PATCHABLE_FUNCTION_EXIT: {
+  case TargetOpcode::PATCHABLE_RET: {
+    unsigned RetOpcode = MI->getOperand(0).getImm();
+    MCInst RetInst;
+    RetInst.setOpcode(RetOpcode);
+    for (const auto &MO :
+         make_range(std::next(MI->operands_begin()), MI->operands_end())) {
+      MCOperand MCOp;
+      if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this, false))
+        RetInst.addOperand(MCOp);
+    }
+
+    bool IsConditional;
+    if (RetOpcode == PPC::BCCLR) {
+      IsConditional = true;
+    } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
+               RetOpcode == PPC::TCRETURNai8) {
+      break;
+    } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
+      IsConditional = false;
+    } else {
+      EmitToStreamer(*OutStreamer, RetInst);
+      break;
+    }
+
+    MCSymbol *FallthroughLabel;
+    if (IsConditional) {
+      // Before:
+      //   bgtlr cr0
+      //
+      // After:
+      //   ble cr0, .end
+      // .p2align 3
+      // .begin:
+      //   blr    # lis 0, FuncId[16..32]
+      //   nop    # li  0, FuncId[0..15]
+      //   std 0, -8(1)
+      //   mflr 0
+      //   bl __xray_FunctionExit
+      //   mtlr 0
+      //   blr
+      // .end:
+      //
+      // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
+      // of instructions change.
+      FallthroughLabel = OutContext.createTempSymbol();
+      EmitToStreamer(
+          *OutStreamer,
+          MCInstBuilder(PPC::BCC)
+              .addImm(PPC::InvertPredicate(
+                  static_cast<PPC::Predicate>(MI->getOperand(1).getImm())))
+              .addReg(MI->getOperand(2).getReg())
+              .addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext)));
+      RetInst = MCInst();
+      RetInst.setOpcode(PPC::BLR8);
+    }
     // .p2align 3
     // .begin:
     //   b(lr)? # lis 0, FuncId[16..32]
@@ -1098,24 +1153,14 @@ void PPCLinuxAsmPrinter::EmitInstruction
     //   mflr 0
     //   bl __xray_FunctionExit
     //   mtlr 0
-    // .end:
     //   b(lr)?
     //
     // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
     // of instructions change.
-    const MachineInstr *Next = [&] {
-      MachineBasicBlock::const_iterator It(MI);
-      assert(It != MI->getParent()->end());
-      ++It;
-      assert(It->isReturn());
-      return &*It;
-    }();
     OutStreamer->EmitCodeAlignment(8);
     MCSymbol *BeginOfSled = OutContext.createTempSymbol();
     OutStreamer->EmitLabel(BeginOfSled);
-    MCInst TmpInst;
-    LowerPPCMachineInstrToMCInst(Next, TmpInst, *this, false);
-    EmitToStreamer(*OutStreamer, TmpInst);
+    EmitToStreamer(*OutStreamer, RetInst);
     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
     EmitToStreamer(
         *OutStreamer,
@@ -1127,17 +1172,18 @@ void PPCLinuxAsmPrinter::EmitInstruction
                            OutContext.getOrCreateSymbol("__xray_FunctionExit"),
                            OutContext)));
     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
+    EmitToStreamer(*OutStreamer, RetInst);
+    if (IsConditional)
+      OutStreamer->EmitLabel(FallthroughLabel);
     recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT);
     break;
   }
+  case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
+    llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
   case TargetOpcode::PATCHABLE_TAIL_CALL:
     // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
     // normal function exit from a tail exit.
-  case TargetOpcode::PATCHABLE_RET:
-    // PPC's tail call instruction, e.g. PPC::TCRETURNdi8, doesn't really
-    // lower to a PPC::B instruction. The PPC::B instruction is generated
-    // before it, and handled by the normal case.
-    llvm_unreachable("Tail call is handled in the normal case. See comments"
+    llvm_unreachable("Tail call is handled in the normal case. See comments "
                      "around this assert.");
   }
 }

Modified: llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp?rev=314005&r1=314004&r2=314005&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp Fri Sep 22 11:30:02 2017
@@ -143,45 +143,48 @@ void llvm::LowerPPCMachineInstrToMCInst(
   OutMI.setOpcode(MI->getOpcode());
   
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
-    const MachineOperand &MO = MI->getOperand(i);
-    
     MCOperand MCOp;
-    switch (MO.getType()) {
-    default:
-      MI->print(errs());
-      llvm_unreachable("unknown operand type");
-    case MachineOperand::MO_Register:
-      assert(!MO.getSubReg() && "Subregs should be eliminated!");
-      assert(MO.getReg() > PPC::NoRegister &&
-             MO.getReg() < PPC::NUM_TARGET_REGS &&
-             "Invalid register for this target!");
-      MCOp = MCOperand::createReg(MO.getReg());
-      break;
-    case MachineOperand::MO_Immediate:
-      MCOp = MCOperand::createImm(MO.getImm());
-      break;
-    case MachineOperand::MO_MachineBasicBlock:
-      MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(
-                                      MO.getMBB()->getSymbol(), AP.OutContext));
-      break;
-    case MachineOperand::MO_GlobalAddress:
-    case MachineOperand::MO_ExternalSymbol:
-      MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
-      break;
-    case MachineOperand::MO_JumpTableIndex:
-      MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
-      break;
-    case MachineOperand::MO_ConstantPoolIndex:
-      MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
-      break;
-    case MachineOperand::MO_BlockAddress:
-      MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP,
-                          isDarwin);
-      break;
-    case MachineOperand::MO_RegisterMask:
-      continue;
-    }
-    
-    OutMI.addOperand(MCOp);
+    if (LowerPPCMachineOperandToMCOperand(MI->getOperand(i), MCOp, AP,
+                                          isDarwin))
+      OutMI.addOperand(MCOp);
+  }
+}
+
+bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO,
+                                             MCOperand &OutMO, AsmPrinter &AP,
+                                             bool isDarwin) {
+  switch (MO.getType()) {
+  default:
+    llvm_unreachable("unknown operand type");
+  case MachineOperand::MO_Register:
+    assert(!MO.getSubReg() && "Subregs should be eliminated!");
+    assert(MO.getReg() > PPC::NoRegister &&
+           MO.getReg() < PPC::NUM_TARGET_REGS &&
+           "Invalid register for this target!");
+    OutMO = MCOperand::createReg(MO.getReg());
+    return true;
+  case MachineOperand::MO_Immediate:
+    OutMO = MCOperand::createImm(MO.getImm());
+    return true;
+  case MachineOperand::MO_MachineBasicBlock:
+    OutMO = MCOperand::createExpr(
+        MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext));
+    return true;
+  case MachineOperand::MO_GlobalAddress:
+  case MachineOperand::MO_ExternalSymbol:
+    OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
+    return true;
+  case MachineOperand::MO_JumpTableIndex:
+    OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
+    return true;
+  case MachineOperand::MO_ConstantPoolIndex:
+    OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
+    return true;
+  case MachineOperand::MO_BlockAddress:
+    OutMO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP,
+                         isDarwin);
+    return true;
+  case MachineOperand::MO_RegisterMask:
+    return false;
   }
 }

Added: llvm/trunk/test/CodeGen/PowerPC/xray-conditional-return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/xray-conditional-return.ll?rev=314005&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/xray-conditional-return.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/xray-conditional-return.ll Fri Sep 22 11:30:02 2017
@@ -0,0 +1,79 @@
+; RUN: llc -filetype=asm -o - -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
+
+define void @Foo(i32 signext %a, i32 signext %b) #0 {
+; CHECK-LABEL: @Foo
+; CHECK:   cmpw [[CR:[0-9]+]]
+; CHECK-NEXT:   ble [[CR]], [[LABEL:\.[a-zA-Z0-9]+]]
+; CHECK-NEXT:   .p2align  3
+; CHECK-NEXT: {{\.[a-zA-Z0-9]+}}:
+; CHECK-NEXT:   blr
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   std 0
+; CHECK-NEXT:   mflr 0
+; CHECK-NEXT:   bl __xray_FunctionExit
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   mtlr 0
+; CHECK-NEXT:   blr
+; CHECK-NEXT: [[LABEL]]:
+entry:
+  %cmp = icmp sgt i32 %a, %b
+  br i1 %cmp, label %return, label %if.end
+
+; CHECK:      .p2align  3
+; CHECK-NEXT: {{\.[a-zA-Z0-9]+}}:
+; CHECK-NEXT:   blr
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   std 0
+; CHECK-NEXT:   mflr 0
+; CHECK-NEXT:   bl __xray_FunctionExit
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   mtlr 0
+; CHECK-NEXT:   blr
+if.end:
+  tail call void @Bar()
+  br label %return
+
+return:
+  ret void
+}
+
+define void @Foo2(i32 signext %a, i32 signext %b) #0 {
+; CHECK-LABEL: @Foo2
+; CHECK:   cmpw [[CR:[0-9]+]]
+; CHECK-NEXT:   bge [[CR]], [[LABEL:\.[a-zA-Z0-9]+]]
+; CHECK-NEXT:   .p2align  3
+; CHECK-NEXT: {{\.[a-zA-Z0-9]+}}:
+; CHECK-NEXT:   blr
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   std 0
+; CHECK-NEXT:   mflr 0
+; CHECK-NEXT:   bl __xray_FunctionExit
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   mtlr 0
+; CHECK-NEXT:   blr
+; CHECK-NEXT: [[LABEL]]:
+entry:
+  %cmp = icmp slt i32 %a, %b
+  br i1 %cmp, label %return, label %if.end
+
+; CHECK:      .p2align  3
+; CHECK-NEXT: {{\.[a-zA-Z0-9]+}}:
+; CHECK-NEXT:   blr
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   std 0
+; CHECK-NEXT:   mflr 0
+; CHECK-NEXT:   bl __xray_FunctionExit
+; CHECK-NEXT:   nop
+; CHECK-NEXT:   mtlr 0
+; CHECK-NEXT:   blr
+if.end:
+  tail call void @Bar()
+  br label %return
+
+return:
+  ret void
+}
+
+declare void @Bar()
+
+attributes #0 = { "function-instrument"="xray-always" }

Added: llvm/trunk/test/CodeGen/PowerPC/xray-ret-is-terminator.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/xray-ret-is-terminator.ll?rev=314005&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/xray-ret-is-terminator.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/xray-ret-is-terminator.ll Fri Sep 22 11:30:02 2017
@@ -0,0 +1,32 @@
+; RUN: llc -o - -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
+
+define void @ILLBeBack() #0 {
+; CHECK-LABEL @ILLBeBack
+; CHECK: beq {{[0-9]+}}, [[LABEL:\.[a-zA-Z0-9_]+]]
+; CHECK: bl __xray_FunctionExit
+; CHECK: [[LABEL]]:
+bb:
+  br i1 undef, label %bb1, label %bb8
+
+bb1:
+  %tmp = tail call i64 asm sideeffect "", "=&r,=*m,b,r,*m,~{cc}"(i64* nonnull undef, i64* nonnull undef, i64 1, i64* nonnull undef)
+  %tmp2 = icmp eq i64 %tmp, 0
+  br i1 %tmp2, label %bb3, label %bb8
+
+bb3:
+  %tmp4 = tail call i64 asm sideeffect "", "=&r,=*m,b,r,r,*m,~{cc}"(i64* undef, i64* undef, i64 0, i64 undef, i64* undef)
+  %tmp5 = icmp eq i64 0, %tmp4
+  br i1 %tmp5, label %bb6, label %bb3
+
+bb6:
+  br i1 undef, label %bb7, label %bb8
+
+bb7:
+  tail call void () undef()
+  ret void
+
+bb8:
+  ret void
+}
+
+attributes #0 = { "function-instrument"="xray-always" }




More information about the llvm-commits mailing list