Skip to content

Commit e378b59

Browse files
hiradityayuxuanchen1997
authored andcommitted
Fix 40056: Prevent outlining of blocks with token type instructions (#99759)
Hot cold splitting should not outline: 1. Basic blocks with token type instructions 1. Functions with scoped EH personality (As suggested by Vedant in #40056 (comment)) Fixes: #40056
1 parent 4f41d43 commit e378b59

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

llvm/lib/Transforms/IPO/HotColdSplitting.cpp

+21-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/IR/CFG.h"
4040
#include "llvm/IR/DiagnosticInfo.h"
4141
#include "llvm/IR/Dominators.h"
42+
#include "llvm/IR/EHPersonalities.h"
4243
#include "llvm/IR/Function.h"
4344
#include "llvm/IR/Instruction.h"
4445
#include "llvm/IR/Instructions.h"
@@ -168,10 +169,24 @@ static bool mayExtractBlock(const BasicBlock &BB) {
168169
//
169170
// Resumes that are not reachable from a cleanup landing pad are considered to
170171
// be unreachable. It’s not safe to split them out either.
172+
171173
if (BB.hasAddressTaken() || BB.isEHPad())
172174
return false;
173175
auto Term = BB.getTerminator();
174-
return !isa<InvokeInst>(Term) && !isa<ResumeInst>(Term);
176+
if (isa<InvokeInst>(Term) || isa<ResumeInst>(Term))
177+
return false;
178+
179+
// Do not outline basic blocks that have token type instructions. e.g.,
180+
// exception:
181+
// %0 = cleanuppad within none []
182+
// call void @"?terminate@@YAXXZ"() [ "funclet"(token %0) ]
183+
// br label %continue-exception
184+
if (llvm::any_of(
185+
BB, [](const Instruction &I) { return I.getType()->isTokenTy(); })) {
186+
return false;
187+
}
188+
189+
return true;
175190
}
176191

177192
/// Mark \p F cold. Based on this assumption, also optimize it for minimum size.
@@ -258,6 +273,11 @@ bool HotColdSplitting::shouldOutlineFrom(const Function &F) const {
258273
F.hasFnAttribute(Attribute::SanitizeMemory))
259274
return false;
260275

276+
// Do not outline scoped EH personality functions.
277+
if (F.hasPersonalityFn())
278+
if (isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
279+
return false;
280+
261281
return true;
262282
}
263283

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=-1 -S < %s | FileCheck %s
2+
; Hot cold splitting should not outline:
3+
; 1. Basic blocks with token type instructions
4+
; 2. Functions with scoped EH personality
5+
6+
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
7+
target triple = "x86_64-pc-windows-msvc19.0.0"
8+
9+
; CHECK-LABEL: define {{.*}}@with_funclet
10+
; CHECK-NOT: with_funclet.cold
11+
define void @with_funclet() personality ptr @__CxxFrameHandler3 {
12+
entry:
13+
invoke void @fYAXXZ()
14+
to label %normal unwind label %exception
15+
16+
normal: ; preds = %entry
17+
ret void
18+
19+
exception: ; preds = %entry
20+
%0 = cleanuppad within none []
21+
call void @terminateYAXXZ() [ "funclet"(token %0) ]
22+
br label %continueexception
23+
24+
continueexception: ; preds = %exception
25+
ret void
26+
}
27+
28+
; CHECK-LABEL: define {{.*}}@with_personality
29+
; CHECK-NOT: with_personality.cold
30+
define void @with_personality(i32 %cond) personality ptr @__CxxFrameHandler3 {
31+
entry:
32+
%cond.addr = alloca i32
33+
store i32 %cond, ptr %cond.addr
34+
%0 = load i32, ptr %cond.addr
35+
%tobool = icmp ne i32 %0, 0
36+
br i1 %tobool, label %if.then, label %if.end2
37+
38+
if.then: ; preds = %entry
39+
%1 = load i32, ptr %cond.addr
40+
%cmp = icmp sgt i32 %1, 10
41+
br i1 %cmp, label %if.then1, label %if.else
42+
43+
if.then1: ; preds = %if.then
44+
call void @sideeffect(i32 0)
45+
br label %if.end
46+
47+
if.else: ; preds = %if.then
48+
call void @sideeffect(i32 1)
49+
br label %if.end
50+
51+
if.end: ; preds = %if.else, %if.then1
52+
call void (...) @sink()
53+
ret void
54+
55+
if.end2: ; preds = %entry
56+
call void @sideeffect(i32 2)
57+
ret void
58+
}
59+
60+
declare i32 @__CxxFrameHandler3(...)
61+
62+
declare void @fYAXXZ()
63+
64+
declare void @bar() #0
65+
66+
declare void @terminateYAXXZ()
67+
68+
declare void @sideeffect(i32)
69+
70+
declare void @sink(...) #0
71+
72+
attributes #0 = { cold }

0 commit comments

Comments
 (0)