Skip to content

Commit 83729e6

Browse files
[SelectionDAG] Disable FastISel for swiftasync functions (llvm#70741)
Most (x86) swiftasync functions tend to use both SelectionDAGISel and FastISel lowering: * FastISel argument lowering can only handle C calling convention. * FastISel fails mid-BB in a number of ways, including in simple `ret void` instructions under certain circumstances. This dance of SelectionDAG (argument) -> FastISel (some instructions) -> SelectionDAG(remaining instructions) is lossy; in particular, Argument information lowering is cleared after that first SelectionDAG run. Since swiftasync functions rely heavily on proper Argument lowering for debug information, this patch disables the use of FastISel in such functions.
1 parent 9aefa5c commit 83729e6

File tree

2 files changed

+66
-14
lines changed

2 files changed

+66
-14
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,16 @@ static RegisterScheduler
204204
defaultListDAGScheduler("default", "Best scheduler for the target",
205205
createDefaultScheduler);
206206

207+
static bool dontUseFastISelFor(const Function &Fn) {
208+
// Don't enable FastISel for functions with swiftasync Arguments.
209+
// Debug info on those is reliant on good Argument lowering, and FastISel is
210+
// not capable of lowering the entire function. Mixing the two selectors tend
211+
// to result in poor lowering of Arguments.
212+
return any_of(Fn.args(), [](const Argument &Arg) {
213+
return Arg.hasAttribute(Attribute::AttrKind::SwiftAsync);
214+
});
215+
}
216+
207217
namespace llvm {
208218

209219
//===--------------------------------------------------------------------===//
@@ -219,21 +229,23 @@ namespace llvm {
219229
: IS(ISel) {
220230
SavedOptLevel = IS.OptLevel;
221231
SavedFastISel = IS.TM.Options.EnableFastISel;
222-
if (NewOptLevel == SavedOptLevel)
223-
return;
224-
IS.OptLevel = NewOptLevel;
225-
IS.TM.setOptLevel(NewOptLevel);
226-
LLVM_DEBUG(dbgs() << "\nChanging optimization level for Function "
227-
<< IS.MF->getFunction().getName() << "\n");
228-
LLVM_DEBUG(dbgs() << "\tBefore: -O" << static_cast<int>(SavedOptLevel) << " ; After: -O"
229-
<< static_cast<int>(NewOptLevel) << "\n");
230-
if (NewOptLevel == CodeGenOptLevel::None) {
231-
IS.TM.setFastISel(IS.TM.getO0WantsFastISel());
232-
LLVM_DEBUG(
233-
dbgs() << "\tFastISel is "
234-
<< (IS.TM.Options.EnableFastISel ? "enabled" : "disabled")
235-
<< "\n");
232+
if (NewOptLevel != SavedOptLevel) {
233+
IS.OptLevel = NewOptLevel;
234+
IS.TM.setOptLevel(NewOptLevel);
235+
LLVM_DEBUG(dbgs() << "\nChanging optimization level for Function "
236+
<< IS.MF->getFunction().getName() << "\n");
237+
LLVM_DEBUG(dbgs() << "\tBefore: -O" << static_cast<int>(SavedOptLevel)
238+
<< " ; After: -O" << static_cast<int>(NewOptLevel)
239+
<< "\n");
240+
if (NewOptLevel == CodeGenOptLevel::None)
241+
IS.TM.setFastISel(IS.TM.getO0WantsFastISel());
236242
}
243+
if (dontUseFastISelFor(IS.MF->getFunction()))
244+
IS.TM.setFastISel(false);
245+
LLVM_DEBUG(
246+
dbgs() << "\tFastISel is "
247+
<< (IS.TM.Options.EnableFastISel ? "enabled" : "disabled")
248+
<< "\n");
237249
}
238250

239251
~OptLevelChanger() {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; RUN: llc %s --fast-isel=true --stop-after=finalize-isel -o %t \
2+
; RUN: -experimental-debug-variable-locations=false --global-isel=false
3+
; RUN: FileCheck %s < %t
4+
; RUN: FileCheck %s --check-prefix=INTRINSICS < %t
5+
6+
7+
source_filename = "ir_x86.ll"
8+
target triple = "x86_64-*"
9+
10+
define swifttailcc void @foo(ptr swiftasync %0) !dbg !43 {
11+
call void asm sideeffect "", "r"(ptr %0), !dbg !62
12+
; FastISEL doesn't preserve %0 here. Check that this function is lowered with SelectionDAG.
13+
call void @llvm.dbg.value(metadata ptr %0, metadata !54, metadata !DIExpression(DW_OP_plus_uconst, 4242)), !dbg !62
14+
ret void, !dbg !62
15+
}
16+
17+
; CHECK-NOT: DBG_VALUE $noreg
18+
; INTRINSICS: ![[VAR:[0-9]*]] = !DILocalVariable(name: "msg",
19+
; INTRINSICS: DBG_VALUE {{.*}}, ![[VAR]], !DIExpression(DW_OP_plus_uconst, 4242)
20+
21+
22+
declare void @llvm.dbg.value(metadata, metadata, metadata)
23+
24+
!llvm.module.flags = !{!6, !7, !8, !9, !10}
25+
!llvm.dbg.cu = !{!16}
26+
27+
!6 = !{i32 7, !"Dwarf Version", i32 4}
28+
!7 = !{i32 2, !"Debug Info Version", i32 3}
29+
!8 = !{i32 1, !"wchar_size", i32 4}
30+
!9 = !{i32 8, !"PIC Level", i32 2}
31+
!10 = !{i32 7, !"uwtable", i32 2}
32+
!16 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !17, producer: "blah", emissionKind: FullDebug)
33+
!17 = !DIFile(filename: "blah", directory: "blah")
34+
!43 = distinct !DISubprogram(name: "blah", linkageName: "blah", file: !17, line: 87, type: !44, scopeLine: 87, unit: !16, retainedNodes: !48)
35+
!44 = !DISubroutineType(types: !45)
36+
!45 = !{!46}
37+
!46 = !DICompositeType(tag: DW_TAG_structure_type, name: "blah")
38+
!48 = !{!54}
39+
!54 = !DILocalVariable(name: "msg", arg: 1, scope: !43, file: !17, line: 87, type: !46)
40+
!62 = !DILocation(line: 87, column: 30, scope: !43)

0 commit comments

Comments
 (0)