Ensure IR->IR CSE does not break CPS calls
Opened this issue · 2 comments
As seen in #11 , CSE for constants is something that is valid to do across a vanilla call in LLVM.
Consider the following program:
declare void @foo(i64)
@extern_glob = external global i8
define void @bar() {
%x_addr = ptrtoint i8* @extern_glob to i64
%x = add i64 %x_addr, 2
call void @foo(i64 %x)
%y_addr = ptrtoint i8* @extern_glob to i64
%y = add i64 %y_addr, 2
call void @foo(i64 %y)
ret void
}
Currently, LLVM's optimizations, like early-cse
or gvn
always inline the address calculation like so:
define void @bar() {
call void @foo(i64 add (i64 ptrtoint (i8* @extern_glob to i64), i64 2))
call void @foo(i64 add (i64 ptrtoint (i8* @extern_glob to i64), i64 2))
ret void
}
But, it's valid to also produce the following:
define void @bar() {
%x_addr = ptrtoint i8* @extern_glob to i64
%x = add i64 %x_addr, 2
call void @foo(i64 %x)
call void @foo(i64 %x)
ret void
}
If the calls were specifically cpscall
s, this type of CSE introduces a value that is live across the cpscall
, which will be allocated an LLVM stack slot.
Questions:
- How do we know the latter will not happen, or rather, why does the latter transformation not occur?
- Can we rely on it never occurring?
- Can we check liveness information during
cpscallprep
to enforce our requirement?
Asked an LLVM dev and apparently the former always happens because it recognizes it as a const expression, and the goal is to reduce the number of instructions during IR->IR simplification.
Thus, it should be fine, but not technically guaranteed. "If the latter does happen, it's probably an LLVM bug."
Note that any common-subexpression issues should always be with constants due to our guarentees about variable liveness.