> the PL/I method was to group the error handlers at the end and pass the labels of the error handlers to the invoked function as alternative return labels.
Huh. I wonder if it would be possible to modify LLVM to support this for rust. You'd be inlining the match / try / unwrap() calls that usually happen after returning from a method which returns an enum variant. And you'd be inlining it across the function call boundary.
This would change the calling convention for methods that return enum variants, but rust doesn't publish a calling convention yet anyway. And for internal only methods, this might be a significant performance win in IO-heavy workloads.
You might need some complex heuristics to figure out when this is worth it though. Not all enums are Option / Result. I bet plenty functions are faster without this trick.
And if you jump based on the value in a register, is this fast in modern CPUs? How would that compare to making a high prediction accuracy branch?
We have looked at these before. Modern CPUs have a RAS, and you dont want to mess with that. But there are ways to implement this, and some papers that cover the performance impact.
We'd need a very motivated individual to add support for this to LLVM and Cranelift.
The fact that the indirect jump that returns when an error is encountered is not predicted, is never worse than when testing an error code returned by the function, because that conditional jump is also always mispredicted.
The method used by modern languages requires both an indirect jump for return, hopefully predicted, and a mispredicted conditional jump. Moreover, if the invoking function is executed once more, but the next time there is no error, the conditional jump that tests the error code may be mispredicted once more.
Using multiple return labels requires only a single mispredicted unconditional jump and it also omits a bunch of redundant instructions for generating an error code and testing it.
For functions that may encounter multiple types of errors, the economy is much larger because testing the returned error code would have needed either multiple conditional branches or an indirect indexed jump for a switch/case structure.
I think that right now, there is sufficient motivation to implement enough of this to be able to try it out, and then see how it actually behaves in practice.
But Rust works on a really wide range of kinds of processors - CPUs, GPUs, FPGAs - and hardware architectures (dozen CPU architectures, dozen GPU architectures, etc.), and nobody has shown that this is a net win for all of them.
Figuring out for which, if any, this is a net win, is something that will have to be demonstrated.
Huh. I wonder if it would be possible to modify LLVM to support this for rust. You'd be inlining the match / try / unwrap() calls that usually happen after returning from a method which returns an enum variant. And you'd be inlining it across the function call boundary.
This would change the calling convention for methods that return enum variants, but rust doesn't publish a calling convention yet anyway. And for internal only methods, this might be a significant performance win in IO-heavy workloads.
You might need some complex heuristics to figure out when this is worth it though. Not all enums are Option / Result. I bet plenty functions are faster without this trick.
And if you jump based on the value in a register, is this fast in modern CPUs? How would that compare to making a high prediction accuracy branch?