[llvm] r348640 - [HotColdSplitting] Refine definition of unlikelyExecuted

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 7 12:24:05 PST 2018


Author: vedantk
Date: Fri Dec  7 12:24:04 2018
New Revision: 348640

URL: http://llvm.org/viewvc/llvm-project?rev=348640&view=rev
Log:
[HotColdSplitting] Refine definition of unlikelyExecuted

The splitting pass uses its 'unlikelyExecuted' predicate to statically
decide which blocks are cold.

- Do not treat noreturn calls as if they are cold unless they are actually
  marked cold. This is motivated by functions like exit() and longjmp(), which
  are not beneficial to outline.

- Do not treat inline asm as an outlining barrier. In practice asm("") is
  frequently used to inhibit basic block merging; enabling outlining in this case
  results in substantial memory savings.

- Treat invokes of cold functions as cold.

As a drive-by, remove the 'exceptionHandlingFunctions' predicate, because it's
no longer needed. The pass can identify & outline blocks dominated by EH pads,
so there's no need to special-case __cxa_begin_catch etc.

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

Added:
    llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll
    llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll
Modified:
    llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp
    llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll

Modified: llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp?rev=348640&r1=348639&r2=348640&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp Fri Dec  7 12:24:04 2018
@@ -26,6 +26,7 @@
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CFG.h"
+#include "llvm/IR/CallSite.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Dominators.h"
@@ -98,36 +99,27 @@ bool blockEndsInUnreachable(const BasicB
   return !(isa<ReturnInst>(I) || isa<IndirectBrInst>(I));
 }
 
-static bool exceptionHandlingFunctions(const CallInst *CI) {
-  auto F = CI->getCalledFunction();
-  if (!F)
-    return false;
-  auto FName = F->getName();
-  return FName == "__cxa_begin_catch" ||
-         FName == "__cxa_free_exception" ||
-         FName == "__cxa_allocate_exception" ||
-         FName == "__cxa_begin_catch" ||
-         FName == "__cxa_end_catch";
-}
-
-static bool unlikelyExecuted(const BasicBlock &BB) {
-  if (blockEndsInUnreachable(BB))
-    return true;
+bool unlikelyExecuted(BasicBlock &BB) {
   // Exception handling blocks are unlikely executed.
   if (BB.isEHPad())
     return true;
-  for (const Instruction &I : BB)
-    if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
-      // The block is cold if it calls functions tagged as cold or noreturn.
-      if (CI->hasFnAttr(Attribute::Cold) ||
-          CI->hasFnAttr(Attribute::NoReturn) ||
-          exceptionHandlingFunctions(CI))
+
+  // The block is cold if it calls/invokes a cold function.
+  for (Instruction &I : BB)
+    if (auto CS = CallSite(&I))
+      if (CS.hasFnAttr(Attribute::Cold))
         return true;
 
-      // Assume that inline assembly is hot code.
-      if (isa<InlineAsm>(CI->getCalledValue()))
+  // The block is cold if it has an unreachable terminator, unless it's
+  // preceded by a call to a (possibly warm) noreturn call (e.g. longjmp).
+  if (blockEndsInUnreachable(BB)) {
+    if (auto *CI =
+            dyn_cast_or_null<CallInst>(BB.getTerminator()->getPrevNode()))
+      if (CI->hasFnAttr(Attribute::NoReturn))
         return false;
-    }
+    return true;
+  }
+
   return false;
 }
 

Modified: llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll?rev=348640&r1=348639&r2=348640&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll (original)
+++ llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll Fri Dec  7 12:24:04 2018
@@ -6,12 +6,6 @@ target triple = "x86_64-apple-macosx10.1
 ; CHECK-LABEL: define {{.*}}@foo(
 ; CHECK: landingpad
 ; CHECK: sideeffect(i32 2)
-
-; CHECK-LABEL: define {{.*}}@foo.cold.1(
-; CHECK: sideeffect(i32 0)
-; CHECK: sideeffect(i32 1)
-; CHECK: sink
-
 define void @foo(i32 %cond) personality i8 0 {
 entry:
   invoke void @llvm.donothing() to label %normal unwind label %exception
@@ -32,6 +26,38 @@ normal:
   ret void
 }
 
+; CHECK-LABEL: define {{.*}}@bar(
+; CHECK-NOT: landingpad
+define void @bar(i32 %cond) personality i8 0 {
+entry:
+  br i1 undef, label %exit, label %continue
+
+exit:
+  ret void
+
+continue:
+  invoke void @sink() to label %normal unwind label %exception
+
+exception:
+  ; Note: EH pads are not candidates for region entry points.
+  %cleanup = landingpad i8 cleanup
+  ret void
+
+normal:
+  call void @sideeffect(i32 0)
+  call void @sideeffect(i32 1)
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1(
+; CHECK: sideeffect(i32 0)
+; CHECK: sideeffect(i32 1)
+; CHECK: sink
+
+; CHECK-LABEL: define {{.*}}@bar.cold.1(
+; CHECK: sideeffect(i32 0)
+; CHECK: sideeffect(i32 1)
+
 declare void @sideeffect(i32)
 
 declare void @sink() cold

Added: llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll?rev=348640&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll Fri Dec  7 12:24:04 2018
@@ -0,0 +1,73 @@
+; RUN: opt -hotcoldsplit -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+%struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t }
+%struct.__sigset_t = type { [16 x i64] }
+
+; Don't outline noreturn calls which aren't explicitly marked cold.
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK-NOT: foo.cold.1
+define void @foo(i32, %struct.__jmp_buf_tag*) {
+  %3 = icmp eq i32 %0, 0
+  tail call void @_Z10sideeffectv()
+  br i1 %3, label %5, label %4
+
+; <label>:4:                                      ; preds = %2
+  tail call void @longjmp(%struct.__jmp_buf_tag* %1, i32 0)
+  unreachable
+
+; <label>:5:                                      ; preds = %2
+  ret void
+}
+
+; Do outline noreturn calls marked cold.
+
+; CHECK-LABEL: define {{.*}}@bar(
+; CHECK: call {{.*}}@bar.cold.1(
+define void @bar(i32) {
+  %2 = icmp eq i32 %0, 0
+  tail call void @_Z10sideeffectv()
+  br i1 %2, label %sink, label %exit
+
+sink:
+  tail call void @_Z10sideeffectv()
+  tail call void @_Z10sideeffectv()
+  tail call void @_Z10sideeffectv()
+  call void @llvm.trap()
+  unreachable
+
+exit:
+  ret void
+}
+
+; Do outline noreturn calls preceded by a cold call.
+
+; CHECK-LABEL: define {{.*}}@baz(
+; CHECK: call {{.*}}@baz.cold.1(
+define void @baz(i32, %struct.__jmp_buf_tag*) {
+  %3 = icmp eq i32 %0, 0
+  tail call void @_Z10sideeffectv()
+  br i1 %3, label %5, label %4
+
+; <label>:4:                                      ; preds = %2
+  call void @sink()
+  tail call void @longjmp(%struct.__jmp_buf_tag* %1, i32 0)
+  unreachable
+
+; <label>:5:                                      ; preds = %2
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@bar.cold.1(
+; CHECK: call {{.*}}@llvm.trap(
+
+declare void @sink() cold
+
+declare void @llvm.trap() noreturn cold
+
+declare void @_Z10sideeffectv()
+
+declare void @longjmp(%struct.__jmp_buf_tag*, i32) noreturn nounwind

Added: llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll?rev=348640&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll Fri Dec  7 12:24:04 2018
@@ -0,0 +1,27 @@
+; RUN: opt -hotcoldsplit -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@fun(
+; CHECK: call {{.*}}@fun.cold.1(
+
+; CHECK-LABEL: define {{.*}}@fun.cold.1(
+; CHECK: asm ""
+
+define void @fun() {
+entry:
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  ret void
+
+if.else:
+  call void asm "", ""()
+  call void @sink()
+  call void @sink()
+  call void @sink()
+  ret void
+}
+
+declare void @sink() cold




More information about the llvm-commits mailing list