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.