Taras Zakharko via llvm-dev
2019-Oct-02 10:49 UTC
[llvm-dev] Using target-specific flags register directly in LLVM
I have originally posted this on StackOverflow (https://stackoverflow.com/questions/58084302/reading-and-producing-an-extra-return-value-in-flags-in-llvm <https://stackoverflow.com/questions/58084302/reading-and-producing-an-extra-return-value-in-flags-in-llvm>), but there were no replies, so I am trying my luck here. I was watching Herb Sutter's talk on CppCon 2019, and one idea is to use control flag register bits to mark that an exception has been produced during a function call. E.g. (assuming x86 target) a function that raises an error could emit a stc instruction just before returning, and the caller could execute a conditional jump immediately after it returns to check if an error should be handled. It's smart, its efficient (much better than returning the condition flag in a separate register), and it's simple. However, how would one go about implementing something like this within LLVM? I suppose that one can use MachineBasicBlock to emit flag set intructions, but does one have a guarantee that LLVM won't insert an instruction afterwards that might change the flag value? Also, how would one test for the flag value and jump to a LLVM IR block? Note that my motivation is purely curiosity. I am not actually working on a compiler — I just want to know how these things work. Thank you, Taras -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20191002/c70f444f/attachment.html>
Tim Northover via llvm-dev
2019-Oct-02 11:46 UTC
[llvm-dev] Using target-specific flags register directly in LLVM
Hi Taras, On Wed, 2 Oct 2019 at 11:50, Taras Zakharko via llvm-dev <llvm-dev at lists.llvm.org> wrote:> However, how would one go about implementing something like this within LLVM? I suppose that one can use MachineBasicBlock to emit flag set intructions, but does one have a guarantee that LLVM won't insert an instruction afterwards that might change the flag value?I think the dataflow would have to be represented explicitly somehow to avoid these issues. I haven't thought in huge detail, but obvious options are either a new LLVM type (e.g. i1flag) or a new calling-convention with special behaviour around an i1 in returned values. The "swifterror" attribute is another possible channel, but IMO that's a bit of a hack from start to finish so I'd prefer to avoid it. Then function lowering could easily convert that into a (brcond (X86ISD::SETCC C, (CallWithFlagsReturn ...)) TrueBB, FalseBB). The LowerCall code would spot the special value and insert that SETCC part, which then fits neatly into the existing LLVM type system at that stage. The new CallWithFlagsReturn looks like it would be needed so that the InstrEmitter.cpp (line 932 I think) knows to associate that explicit dataflow in DAG with the call's first implicitly defined register in MachineIR (which we'd make sure was EFLAGS)[*]. Once that link is made, LLVM is pretty used to not clobbering special physical registers. Lowering a return would be the same kind of thing in reverse: a CMP on the real value, feeding data into the RET so that it's recognized as going through EFLAGS.> Also, how would one test for the flag value and jump to a LLVM IR block?With no optimizations from the above you'd get something like: call foo setc %al test %al jz wherever which is not good, but functional. Adding DAG (or other) combines to optimize the sequence ought to be pretty easy though. After all it's pretty much the process normal LLVM comparisons go through: start as an i1 in DAG, get optimized to implicit flags-based dataflow. I think Chandler had some other concerns he mentioned, but I'm afraid I've forgotten what they are (or even if they applied to this part of the problem). So assume I might be doing some slightly more vigorous hand-waving than is entirely justified. Cheers. Tim. [*] Alternatively, since calls *clobber* flags anyway, we might just get away with using a single call opcode. As long as we ensure it's compatible with both uses the duplication is arguably just pedantry.