[llvm] r284456 - [XRay] Support for for tail calls for ARM no-Thumb

Dean Michael Berris via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 17 22:54:16 PDT 2016


Author: dberris
Date: Tue Oct 18 00:54:15 2016
New Revision: 284456

URL: http://llvm.org/viewvc/llvm-project?rev=284456&view=rev
Log:
[XRay] Support for for tail calls for ARM no-Thumb

This patch adds simplified support for tail calls on ARM with XRay instrumentation.

Known issue: compiled with generic flags: `-O3 -g -fxray-instrument -Wall
-std=c++14  -ffunction-sections -fdata-sections` (this list doesn't include my
specific flags like --target=armv7-linux-gnueabihf etc.), the following program

    #include <cstdio>
    #include <cassert>
    #include <xray/xray_interface.h>

    [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fC() {
      std::printf("In fC()\n");
    }

    [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fB() {
      std::printf("In fB()\n");
      fC();
    }

    [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fA() {
      std::printf("In fA()\n");
      fB();
    }

    // Avoid infinite recursion in case the logging function is instrumented (so calls logging
    //   function again).
    [[clang::xray_never_instrument]] void simplyPrint(int32_t functionId, XRayEntryType xret)
    {
      printf("XRay: functionId=%d type=%d.\n", int(functionId), int(xret));
    }

    int main(int argc, char* argv[]) {
      __xray_set_handler(simplyPrint);

      printf("Patching...\n");
      __xray_patch();
      fA();

      printf("Unpatching...\n");
      __xray_unpatch();
      fA();

      return 0;
    }

gives the following output:

    Patching...
    XRay: functionId=3 type=0.
    In fA()
    XRay: functionId=3 type=1.
    XRay: functionId=2 type=0.
    In fB()
    XRay: functionId=2 type=1.
    XRay: functionId=1 type=0.
    XRay: functionId=1 type=1.
    In fC()
    Unpatching...
    In fA()
    In fB()
    In fC()

So for function fC() the exit sled seems to be called too much before function
exit: before printing In fC().

Debugging shows that the above happens because printf from fC is also called as
a tail call. So first the exit sled of fC is executed, and only then printf is
jumped into. So it seems we can't do anything about this with the current
approach (i.e. within the simplification described in
https://reviews.llvm.org/D23988 ).

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

Added:
    llvm/trunk/test/CodeGen/ARM/xray-tail-call-sled.ll
Modified:
    llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp
    llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
    llvm/trunk/lib/Target/ARM/ARMAsmPrinter.h
    llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp

Modified: llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp?rev=284456&r1=284455&r2=284456&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp (original)
+++ llvm/trunk/lib/CodeGen/XRayInstrumentation.cpp Tue Oct 18 00:54:15 2016
@@ -95,10 +95,17 @@ void XRayInstrumentation::prependRetWith
 {
   for (auto &MBB : MF) {
     for (auto &T : MBB.terminators()) {
+      unsigned Opc = 0;
       if (T.isReturn()) {
-        // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT
-        BuildMI(MBB, T, T.getDebugLoc(),
-                TII->get(TargetOpcode::PATCHABLE_FUNCTION_EXIT));
+        Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;
+      }
+      if (TII->isTailCall(T)) {
+        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));
       }
     }
   }

Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp?rev=284456&r1=284455&r2=284456&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Tue Oct 18 00:54:15 2016
@@ -2050,6 +2050,9 @@ void ARMAsmPrinter::EmitInstruction(cons
   case ARM::PATCHABLE_FUNCTION_EXIT:
     LowerPATCHABLE_FUNCTION_EXIT(*MI);
     return;
+  case ARM::PATCHABLE_TAIL_CALL:
+    LowerPATCHABLE_TAIL_CALL(*MI);
+    return;
   }
 
   MCInst TmpInst;

Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.h?rev=284456&r1=284455&r2=284456&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.h Tue Oct 18 00:54:15 2016
@@ -112,6 +112,7 @@ public:
   // XRay-specific lowering for ARM.
   void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
   void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
+  void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
   // Helper function that emits the XRay sleds we've collected for a particular
   // function.
   void EmitXRayTable();

Modified: llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp?rev=284456&r1=284455&r2=284456&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp Tue Oct 18 00:54:15 2016
@@ -219,6 +219,11 @@ void ARMAsmPrinter::LowerPATCHABLE_FUNCT
   EmitSled(MI, SledKind::FUNCTION_EXIT);
 }
 
+void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
+{
+  EmitSled(MI, SledKind::TAIL_CALL);
+}
+
 void ARMAsmPrinter::EmitXRayTable()
 {
   if (Sleds.empty())

Added: llvm/trunk/test/CodeGen/ARM/xray-tail-call-sled.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/xray-tail-call-sled.ll?rev=284456&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/xray-tail-call-sled.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/xray-tail-call-sled.ll Tue Oct 18 00:54:15 2016
@@ -0,0 +1,53 @@
+; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s
+
+define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" {
+; CHECK:       .p2align	2
+; CHECK-LABEL: Lxray_sled_0:
+; CHECK-NEXT:  b	#20
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-LABEL: Ltmp0:
+  ret i32 0
+; CHECK-NEXT:  mov	r0, #0
+; CHECK-NEXT:  .p2align	2
+; CHECK-LABEL: Lxray_sled_1:
+; CHECK-NEXT:  b	#20
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-LABEL: Ltmp1:
+; CHECK-NEXT:  bx	lr
+}
+
+define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" {
+; CHECK:       .p2align	2
+; CHECK-LABEL: Lxray_sled_2:
+; CHECK-NEXT:  b	#20
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-LABEL: Ltmp2:
+; CHECK:       .p2align	2
+; CHECK-LABEL: Lxray_sled_3:
+; CHECK-NEXT:  b	#20
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-NEXT:  nop
+; CHECK-LABEL: Ltmp3:
+  %retval = tail call i32 @callee()
+; CHECK:       b	callee
+  ret i32 %retval
+}




More information about the llvm-commits mailing list