brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · ad0aef2 Raw
72 lines · plain
1; Tests that CoroSplit can normalize a presplit coroutine whose body contains2; an indirectbr (a computed goto, e.g. glibc printf_positional's format3; dispatch) feeding a block with a multi-incoming PHI.4;5; Such an edge is a critical edge out of an indirectbr: the successor's address6; is taken, so the ordinary SplitEdge cannot split it and used to return null,7; which rewritePHIs then dereferenced via setName -> SIGSEGV in8; coro::normalizeCoroutine. normalizeCoroutine now runs9; SplitIndirectBrCriticalEdges first, which clones the PHI-only target so the10; indirectbr keeps a single un-split edge and the direct predecessors get their11; own clone, after which rewritePHIs succeeds.12;13; RUN: opt < %s -passes='cgscc(coro-split)' -S | FileCheck %s14 15define ptr @f(ptr %dst) presplitcoroutine {16entry:17  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)18  %hdl = call ptr @llvm.coro.begin(token %id, ptr null)19  call void @print(i32 0)20  %sp = call i8 @llvm.coro.suspend(token none, i1 false)21  switch i8 %sp, label %suspend [i8 0, label %resume22                                 i8 1, label %cleanup]23resume:24  ; computed-goto: an indirectbr with a runtime target so it is not25  ; constant-folded before CoroSplit normalizes the function.26  %addr = load ptr, ptr %dst27  indirectbr ptr %addr, [label %target, label %other]28 29other:30  br label %target31 32target:33  ; multi-incoming PHI; one predecessor (%resume) is the indirectbr, so the34  ; resume->target edge is a critical edge out of an indirectbr.35  %p = phi i32 [ 1, %resume ], [ 2, %other ]36  call void @print(i32 %p)37  br label %cleanup38 39cleanup:40  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)41  br label %suspend42 43suspend:44  call void @llvm.coro.end(ptr %hdl, i1 0, token none)45  ret ptr %hdl46}47 48; The coroutine must split cleanly (no crash). The indirectbr is preserved with49; both of its targets, and the indirectbr's PHI-only target is cloned for the50; direct predecessor so the values still merge correctly (1 via the indirectbr,51; 2 via %other).52 53; CHECK-LABEL: define ptr @f(54; CHECK:         indirectbr ptr %addr, [label %target, label %other]55; CHECK:       other:56; CHECK:         br label %target.clone57; CHECK:       target:58; CHECK:         %ind = phi i32 [ 1, %resume ]59; CHECK:         %merge = phi i3260; CHECK:       target.clone:61; CHECK:         %p.clone = phi i32 [ 2, %other ]62 63; The resume clone exists (i.e. the coroutine was actually split).64; CHECK-LABEL: define internal fastcc void @f.resume(65 66declare ptr @llvm.coro.free(token, ptr)67declare i8  @llvm.coro.suspend(token, i1)68declare token @llvm.coro.id(i32, ptr, ptr, ptr)69declare ptr @llvm.coro.begin(token, ptr)70declare void @llvm.coro.end(ptr, i1, token)71declare void @print(i32)72