Now extractvalue instruction are replaced by dedicated
OpaqueExtractValue custom opcode, that prevents LLVM from doing strange
things with extractvalues during optimizations (such as e.g. sinking).
This is important since extractvalue instructions and struct-typed
values in general in our LLVM IR are not real first-class citizens, but
only a byproduct of the binary lifting process, and they actually
represent bundles of registers that are returned from isolated
functions.
This pass splits calls `*.with.overflow*` intrinsics into the a pair of
instructions: the underlying operation and a call to an `Helper`-tagged
function that computes whether such operation overflowed.
For instance, we go from:
%2 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %0, i32 %1)
%3 = extractvalue { i32, i1 } %2, 1
br i1 %3, label %..., label %...
To:
%2 = mul i32 %0, %1
%3 = call i1 @mul_overflow_u32(i32 %0, i32 %1)
br i1 %3, label %..., label %...
This saves from handling `struct` in the backend.