Skip to content

Commit 1de5880

Browse files
authored
Emit enter handler during codegen instead of after optimization (#57308)
This means that the lowerHandlers pass is now useless. Which is good because it relied too much on optimizations not happening. Thanks @topolarity for all the knowledge on try catch lowering
1 parent 73506ed commit 1de5880

File tree

11 files changed

+26
-359
lines changed

11 files changed

+26
-359
lines changed

doc/src/devdocs/llvm-passes.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ This pass performs most of the GC rooting work required to track pointers betwee
3737
* Opt Name: `module(FinalLowerGC)`
3838

3939
This pass lowers a few last intrinsics to their final form targeting functions in the `libjulia` library. Separating this from `LateGCLowering` enables other backends (GPU compilation) to supply their own custom lowerings for these intrinsics, enabling the Julia pipeline to be used on those backends as well.
40-
41-
### LowerHandlers
42-
43-
* Filename: `llvm-lower-handlers.cpp`
44-
* Class Name: `LowerExcHandlersPass`
45-
* Opt Name: `function(LowerExcHandlers)`
46-
47-
This pass lowers exception handling intrinsics into calls to runtime functions that are actually called when handling exceptions.
48-
4940
### RemoveNI
5041

5142
* Filename: `llvm-remove-ni.cpp`

doc/src/devdocs/llvm.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ The code for lowering Julia AST to LLVM IR or interpreting it directly is in dir
2929
| `llvm-gc-invariant-verifier.cpp` | Custom LLVM pass to verify Julia GC invariants |
3030
| `llvm-julia-licm.cpp` | Custom LLVM pass to hoist/sink Julia-specific intrinsics |
3131
| `llvm-late-gc-lowering.cpp` | Custom LLVM pass to root GC-tracked values |
32-
| `llvm-lower-handlers.cpp` | Custom LLVM pass to lower try-catch blocks |
3332
| `llvm-multiversioning.cpp` | Custom LLVM pass to generate sysimg code on multiple architectures |
3433
| `llvm-propagate-addrspaces.cpp` | Custom LLVM pass to canonicalize addrspaces |
3534
| `llvm-ptls.cpp` | Custom LLVM pass to lower TLS operations |

src/Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ GC_CODEGEN_SRCS += llvm-late-gc-lowering-stock
7575
endif
7676
CODEGEN_SRCS := codegen jitlayers aotcompile debuginfo disasm llvm-simdloop \
7777
llvm-pass-helpers llvm-ptls \
78-
llvm-lower-handlers llvm-propagate-addrspaces \
78+
llvm-propagate-addrspaces \
7979
llvm-multiversioning llvm-alloc-opt llvm-alloc-helpers cgmemmgr llvm-remove-addrspaces \
8080
llvm-remove-ni llvm-julia-licm llvm-demote-float16 llvm-cpufeatures pipeline llvm_api \
8181
$(GC_CODEGEN_SRCS)
@@ -360,7 +360,6 @@ $(BUILDDIR)/llvm-final-gc-lowering.o $(BUILDDIR)/llvm-final-gc-lowering.dbg.obj:
360360
$(BUILDDIR)/llvm-gc-invariant-verifier.o $(BUILDDIR)/llvm-gc-invariant-verifier.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h
361361
$(BUILDDIR)/llvm-julia-licm.o $(BUILDDIR)/llvm-julia-licm.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(SRCDIR)/llvm-alloc-helpers.h $(SRCDIR)/llvm-pass-helpers.h
362362
$(BUILDDIR)/llvm-late-gc-lowering.o $(BUILDDIR)/llvm-late-gc-lowering.dbg.obj: $(SRCDIR)/llvm-gc-interface-passes.h
363-
$(BUILDDIR)/llvm-lower-handlers.o $(BUILDDIR)/llvm-lower-handlers.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h
364363
$(BUILDDIR)/llvm-multiversioning.o $(BUILDDIR)/llvm-multiversioning.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(SRCDIR)/processor.h
365364
$(BUILDDIR)/llvm-pass-helpers.o $(BUILDDIR)/llvm-pass-helpers.dbg.obj: $(SRCDIR)/llvm-pass-helpers.h $(SRCDIR)/llvm-codegen-shared.h
366365
$(BUILDDIR)/llvm-propagate-addrspaces.o $(BUILDDIR)/llvm-propagate-addrspaces.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h

src/codegen.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,17 +1464,6 @@ static const auto gc_preserve_end_func = new JuliaFunction<> {
14641464
[](LLVMContext &C) { return FunctionType::get(getVoidTy(C), {Type::getTokenTy(C)}, false); },
14651465
nullptr,
14661466
};
1467-
static const auto except_enter_func = new JuliaFunction<>{
1468-
"julia.except_enter",
1469-
[](LLVMContext &C) {
1470-
auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
1471-
auto RT = StructType::get(getInt32Ty(C), getPointerTy(C));
1472-
return FunctionType::get(RT, {T_pjlvalue}, false); },
1473-
[](LLVMContext &C) { return AttributeList::get(C,
1474-
Attributes(C, {Attribute::ReturnsTwice}),
1475-
AttributeSet(),
1476-
None); },
1477-
};
14781467
static const auto pointer_from_objref_func = new JuliaFunction<>{
14791468
"julia.pointer_from_objref",
14801469
[](LLVMContext &C) { return FunctionType::get(JuliaType::get_pjlvalue_ty(C),
@@ -1931,6 +1920,7 @@ class jl_codectx_t {
19311920
SmallVector<jl_varinfo_t, 0> slots;
19321921
std::map<int, jl_varinfo_t> phic_slots;
19331922
std::map<int, std::pair<Value*, Value*> > scope_restore;
1923+
std::map<jl_value_t*, AllocaInst*> eh_buffers;
19341924
SmallVector<jl_cgval_t, 0> SAvalues;
19351925
SmallVector<std::tuple<jl_cgval_t, BasicBlock *, AllocaInst *, PHINode *, SmallVector<PHINode*,0>, jl_value_t *>, 0> PhiNodes;
19361926
SmallVector<bool, 0> ssavalue_assigned;
@@ -6561,8 +6551,8 @@ static void emit_stmtpos(jl_codectx_t &ctx, jl_value_t *expr, int ssaval_result)
65616551
return;
65626552
}
65636553
else if (head == jl_leave_sym) {
6564-
int hand_n_leave = 0;
65656554
Value *scope_to_restore = nullptr, *token = nullptr;
6555+
SmallVector<AllocaInst*> handler_to_end;
65666556
for (size_t i = 0; i < jl_expr_nargs(ex); ++i) {
65676557
jl_value_t *arg = args[i];
65686558
if (arg == jl_nothing)
@@ -6588,13 +6578,18 @@ static void emit_stmtpos(jl_codectx_t &ctx, jl_value_t *expr, int ssaval_result)
65886578
ctx.builder.CreateCall(prepare_call(gc_preserve_end_func), {token});
65896579
}
65906580
if (jl_enternode_catch_dest(enter_stmt)) {
6581+
handler_to_end.push_back(ctx.eh_buffers[enter_stmt]);
65916582
// We're not actually setting up the exception frames for these, so
65926583
// we don't need to exit them.
6593-
hand_n_leave += 1;
65946584
scope_to_restore = nullptr; // restored by exception handler
65956585
}
65966586
}
6597-
ctx.builder.CreateCall(prepare_call(jlleave_noexcept_func), {get_current_task(ctx), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), hand_n_leave)});
6587+
ctx.builder.CreateCall(prepare_call(jlleave_noexcept_func), {get_current_task(ctx), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), handler_to_end.size())});
6588+
auto *handler_sz64 = ConstantInt::get(Type::getInt64Ty(ctx.builder.getContext()),
6589+
sizeof(jl_handler_t));
6590+
for (AllocaInst *handler : handler_to_end) {
6591+
ctx.builder.CreateLifetimeEnd(handler, handler_sz64);
6592+
}
65986593
if (scope_to_restore) {
65996594
Value *scope_ptr = get_scope_field(ctx);
66006595
jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe).decorateInst(
@@ -9759,13 +9754,22 @@ static jl_llvm_functions_t
97599754
ctx.ssavalue_assigned[cursor] = true;
97609755
// Actually enter the exception frame
97619756
auto ct = get_current_task(ctx);
9762-
CallInst *sj = ctx.builder.CreateCall(prepare_call(except_enter_func), {ct});
9757+
auto *handler_sz64 = ConstantInt::get(Type::getInt64Ty(ctx.builder.getContext()),
9758+
sizeof(jl_handler_t));
9759+
AllocaInst* ehbuff = emit_static_alloca(ctx, sizeof(jl_handler_t), Align(16));
9760+
ctx.eh_buffers[stmt] = ehbuff;
9761+
ctx.builder.CreateLifetimeStart(ehbuff, handler_sz64);
9762+
ctx.builder.CreateCall(prepare_call(jlenter_func), {ct, ehbuff});
9763+
CallInst *sj;
9764+
if (ctx.emission_context.TargetTriple.isOSWindows())
9765+
sj = ctx.builder.CreateCall(prepare_call(setjmp_func), {ehbuff});
9766+
else
9767+
sj = ctx.builder.CreateCall(prepare_call(setjmp_func), {ehbuff, ConstantInt::get(Type::getInt32Ty(ctx.builder.getContext()), 0)});
97639768
// We need to mark this on the call site as well. See issue #6757
97649769
sj->setCanReturnTwice();
9765-
Value *isz = ctx.builder.CreateICmpEQ(ctx.builder.CreateExtractValue(sj, 0), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
9766-
Value *ehbuf = ctx.builder.CreateExtractValue(sj, 1);
9770+
Value *isz = ctx.builder.CreateICmpEQ(sj, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
97679771
BasicBlock *tryblk = BasicBlock::Create(ctx.builder.getContext(), "try", f);
9768-
BasicBlock *catchpop = BasicBlock::Create(ctx.builder.getContext(), "catch_pop", f);
9772+
BasicBlock *catchpop = BasicBlock::Create(ctx.builder.getContext(), "catch_enter", f);
97699773
BasicBlock *handlr = NULL;
97709774
handlr = BB[lname];
97719775
workstack.push_back(lname - 1);
@@ -9774,11 +9778,12 @@ static jl_llvm_functions_t
97749778
ctx.builder.SetInsertPoint(catchpop);
97759779
{
97769780
ctx.builder.CreateCall(prepare_call(jlleave_func), {get_current_task(ctx), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1)});
9781+
ctx.builder.CreateLifetimeEnd(ehbuff, handler_sz64);
97779782
ctx.builder.CreateBr(handlr);
97789783
}
97799784
ctx.builder.SetInsertPoint(tryblk);
97809785
auto ehptr = emit_ptrgep(ctx, ct, offsetof(jl_task_t, eh));
9781-
ctx.builder.CreateAlignedStore(ehbuf, ehptr, ctx.types().alignof_ptr);
9786+
ctx.builder.CreateAlignedStore(ehbuff, ehptr, ctx.types().alignof_ptr);
97829787
}
97839788
// For the two-arg version of :enter, twiddle the scope
97849789
if (jl_enternode_scope(stmt)) {
@@ -10354,7 +10359,6 @@ static void init_jit_functions(void)
1035410359
add_named_global(gc_preserve_begin_func, (void*)NULL);
1035510360
add_named_global(gc_preserve_end_func, (void*)NULL);
1035610361
add_named_global(pointer_from_objref_func, (void*)NULL);
10357-
add_named_global(except_enter_func, (void*)NULL);
1035810362
add_named_global(julia_call, (void*)NULL);
1035910363
add_named_global(julia_call2, (void*)NULL);
1036010364
add_named_global(jllockvalue_func, &jl_lock_value);

src/llvm-julia-passes.inc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ FUNCTION_PASS("DemoteFloat16", DemoteFloat16Pass())
1414
FUNCTION_PASS("LateLowerGCFrame", LateLowerGCPass())
1515
FUNCTION_PASS("AllocOpt", AllocOptPass())
1616
FUNCTION_PASS("PropagateJuliaAddrspaces", PropagateJuliaAddrspacesPass())
17-
FUNCTION_PASS("LowerExcHandlers", LowerExcHandlersPass())
1817
FUNCTION_PASS("GCInvariantVerifier", GCInvariantVerifierPass())
1918
FUNCTION_PASS("FinalLowerGC", FinalLowerGCPass())
2019
#endif

0 commit comments

Comments
 (0)