This commit modifies SimplifyCFGPass to allow sinking of calls that
differ in tail call kind. Specifically if tail call kinds for sink
candidates are TCK_Tail and TCK_None it is safe to sink the call
and assign TCK_None as a kind for the merged instruction.
Could be illustrated by the following example:
c extern void escape(void*); extern int magic(void); extern void tailfn(void); void foofn() { int x; if (magic()) { tailfn(); } else { escape(&x); tailfn(); } }
Could be rewritten as:
c void foofn() { int x; if (!magic()) escape(&x); tailfn(); }
W/o this commit such transformation does not happen, because
TailCallElimPass computes different tail call kinds for two tailfn
calls:
entry: %x = alloca i32, align 4 %call = tail call i32 @magic() %tobool.not = icmp eq i32 %call, 0 br i1 %tobool.not, label %if.else, label %if.then if.then: tail call void @tailfn() br label %if.end if.else: call void @escape(ptr noundef nonnull %x) call void @tailfn() br label %if.end
When SimplifyCFGPass considers what instructions to sink to a common
successor it uses the function Instruction::isSameOperationAs to
identify sink candidates. However this function returns false if call
instructions have different values of tail call kind flag.
This commit extends Instruction::isSameOperationAs with a flag to
ignore tail call kind and extends SimplifyCFGPass with logic to
compute a common tail call kind for a merged instruction.