Folks, I just had a discussion about __builtin_stack_pointer in the GCC list, and there were a number of arguments against it, and it got me thinking I didn't have strong arguments against GNU's named register extension. Does anyone remember the arguments for not implementing that extension? My view is that making it an intrinsic (say @llvm.register(name)) would have the exact same semantics as __builtin_<register_name> has, in that it'll be carried down all the way to SelectionDAG and be just a CopyFromReg from that reg's name. The fact that they remain as intrinsics will guarantee that they will last until SelectionDag and not commoned up or heavily modified. I'm not sure how to make Clang do that, but it shouldn't be too hard to short-circuit the asm handler if we're dealing with a declaration/instantiation and "register" is a specifier of the type. The arguments supporting the builtins is that, in case of stack pointer, it's not target specific, thus avoiding ifdefs. The counter-argument is that most usage of the named register extension is already target specific (together with everything around it), so that extra value is very limited. Also, since kernel and library code (heavy users of named registers) will have to support old compilers, this will *have* to be ifdefd anyway. The arguments against builtins are that named register is more generic, is already in use for more than the stack pointer and is reasonably straightforward to both understand and implement. Both builtins and named registers don't give you the guarantees that you would like from such a high-level construct, and users are already aware that this is the case, so we don't have to worry that much about it. Also, reading back some comments, it seems that the biggest concern was that inline asm wasn't really a first-class citizen in the LLVM back-end, but I think that has changes with M, right? My questions are: 1. Were the initial concerns dealt with by the introduction of MC? 2. Is there any remaining argument against named registers that stronger than the ones supporting it? 3. Is my draft for implementing named registers acceptable? cheers, --renato
On 27 March 2014 09:55, Renato Golin <renato.golin at linaro.org> wrote:> Folks, > > I just had a discussion about __builtin_stack_pointer in the GCC list, > and there were a number of arguments against it, and it got me > thinking I didn't have strong arguments against GNU's named register > extension. Does anyone remember the arguments for not implementing > that extension?In clang or llvm? I think we can implement it in clang by lowering them with a similar trick that we do for local ones. For local register variables, clang just keeps a note that it has to add a constraint when it creates an inline assembly. For global ones, it should also codegen every non inline asm to use an llvm intrinsic (llvm.read_register/llvm.write_register for example). This is not exactly the semantics gcc uses since the register would still be allocatable, but should cover 99% of the uses, including reading the stack pointer in the kernel. I don't think we should implement this directly in LLVM, since it introduces the really odd notion that reading of an value is observable. For example, is it legal to move the read of rsp out of a loop? By using an intrinsic at the llvm level we trivially represent and preserve all the reads and writes from the source program. Cheers, Rafael
On 27 March 2014 15:30, Rafael EspĂndola <rafael.espindola at gmail.com> wrote:> For global ones, it should also codegen every non inline asm to use an > llvm intrinsic (llvm.read_register/llvm.write_register for example).That's my idea, yes. I'm not sure how Clang would transform the named registers into the intrinsic, but something along the lines of: i8* @SP = "SP"; define void @step() nounwind { entry: %0 = call i32 @llvm.read_register(i8* @SP) %1 = add i32 %0, i32 4 call void @llvm.write_register(i8* @SP, %1) } declare void @llvm.write_register(i8*, i32) nounwind readnone declare i32 @llvm.read_register(i8*) nounwind readnone> This is not exactly the semantics gcc uses since the register would > still be allocatable, but should cover 99% of the uses, including > reading the stack pointer in the kernel.http://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html It seems that the semantics is to avoid PCS registers, or they will be clobbered... Nevertheless, we can reserve the register on demand, as we already do with R9, for instance.> For example, is it legal to move the read of rsp out of a > loop?No. It should be a volatile read/write.> By using an intrinsic at the llvm level we trivially represent > and preserve all the reads and writes from the source program.Exactly! cheers, --renato
----- Original Message -----> From: "Renato Golin" <renato.golin at linaro.org> > To: "LLVM Dev" <llvmdev at cs.uiuc.edu>, "Clang Dev" <cfe-dev at cs.uiuc.edu> > Sent: Thursday, March 27, 2014 8:55:47 AM > Subject: [LLVMdev] Named register variables GNU-style > > Folks, > > I just had a discussion about __builtin_stack_pointer in the GCC > list, > and there were a number of arguments against it,Can you summarize?> and it got me > thinking I didn't have strong arguments against GNU's named register > extension. Does anyone remember the arguments for not implementing > that extension? > > My view is that making it an intrinsic (say @llvm.register(name)) > would have the exact same semantics as __builtin_<register_name> has, > in that it'll be carried down all the way to SelectionDAG and be just > a CopyFromReg from that reg's name.I think this also would be a nice feature to have, and fairly straightforward to implement. That having been said, are there not cases where only the backend knows in what register the stack pointer is held? A sophisticated backend might even spill the stack pointer during some portions of the function to create a range in which it was allocatable, and I certainly would not want to preclude such an implementation. -Hal> > The fact that they remain as intrinsics will guarantee that they will > last until SelectionDag and not commoned up or heavily modified. I'm > not sure how to make Clang do that, but it shouldn't be too hard to > short-circuit the asm handler if we're dealing with a > declaration/instantiation and "register" is a specifier of the type. > > The arguments supporting the builtins is that, in case of stack > pointer, it's not target specific, thus avoiding ifdefs. The > counter-argument is that most usage of the named register extension > is > already target specific (together with everything around it), so that > extra value is very limited. Also, since kernel and library code > (heavy users of named registers) will have to support old compilers, > this will *have* to be ifdefd anyway. > > The arguments against builtins are that named register is more > generic, is already in use for more than the stack pointer and is > reasonably straightforward to both understand and implement. > > Both builtins and named registers don't give you the guarantees that > you would like from such a high-level construct, and users are > already > aware that this is the case, so we don't have to worry that much > about > it. > > Also, reading back some comments, it seems that the biggest concern > was that inline asm wasn't really a first-class citizen in the LLVM > back-end, but I think that has changes with M, right? > > My questions are: > > 1. Were the initial concerns dealt with by the introduction of MC? > > 2. Is there any remaining argument against named registers that > stronger than the ones supporting it? > > 3. Is my draft for implementing named registers acceptable? > > cheers, > --renato > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-- Hal Finkel Assistant Computational Scientist Leadership Computing Facility Argonne National Laboratory
On 3/27/2014 8:55 AM, Renato Golin wrote:> > I just had a discussion about __builtin_stack_pointer in the GCC list, > and there were a number of arguments against it, and it got me > thinking I didn't have strong arguments against GNU's named register > extension. Does anyone remember the arguments for not implementing > that extension?Is there any sane reason to actually implement it? Are there any cases when inline asm would work well enough? We have the __builtin_stack_pointer now, which is somewhat questionable[1], however this should not serve a precedent to implement further "extensions" like this. Argument against it..? "Why?" -Krzysztof [1] As someone has pointed out, the stack pointer builtin only makes sense on targets that actually have a "stack pointer". Not all architectures do, and even on those that do, the register could be used for other purposes in some cases. I'm guessing that the main use scenarios come from OS kernels or device drivers, but even there inline asm would likely suffice. -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
On 27 March 2014 19:35, Krzysztof Parzyszek <kparzysz at codeaurora.org> wrote:> Is there any sane reason to actually implement it?Bare metal code is never sane, but that's not an excuse not to write it. C is a very complete language, especially modern variations like C11, but there's still a lot that can't be done in C and for good reasons. Kernel code and optimal libraries can stretch the compiler a lot more than user code, and often enough, there's simply no way to represent ideas in C. One of these examples is unwind code. Then you ask...> Are there any cases when inline asm would work well enough?Well, assembly is very powerful and so, but it's also very hard to understand what's going on. Inline assembly is an extension to the language, and because of that, different compilers implement them in different ways. Most of GCC's implementation is hidden in layers upon layers of legacy code that not many people dare to touch, but that compiles code that can't stop being compiled, nor easily migrated (for technical and legal reasons). The interaction between inline assembly and C is, therefore, not easy to implement, and it's even harder to get it "right" (ie. similar to the "other" compiler). The most you could write in C the better for *compilers*, and minimising the exposure by using register variables is actually not a bad idea. But mostly, the __builtin_stack_frame is, in essence, a special case of the generic pattern of named registers, and gives us the same level of guarantees, so, in the end, there isn't much *technical* difference in doing one and the other, with the added benefit that named registers are already widely used and you won't need to add ifdefs for new compilers.> We have the > __builtin_stack_pointer now, which is somewhat questionable[1], however this > should not serve a precedent to implement further "extensions" like this.No we don't. Not yet. ;) I was about to commit when I thought I should get a point of view from all sides, including (and especially) GCC. The first issue here is that, if GCC doesn't "buy in", having a __builtin_stack_pointer in Clang is as good as not having it. The second issue is that, if we're going to implement an extension, and there is already a technically equivalent solution in existence, there's no reason to create a different one. Lastly, and (much) more importantly, their technical arguments were significantly better than mine.> Argument against it..? "Why?"Why? Because the less asm and more C code we have, the better. Because inline asm semantics is a lot more obtuse than named registers. Because builtins are just special cases of named registers. Because target-independence is not possible in that kind of code. Some arguments... ** With builtins, we don't need ifdefs, if all compilers implement it. -- Yes, we do, for old compilers (GCC and Clang), and kernel/glibc will need it for decades to come ** Builtins make the code target-intependent -- No they don't, only the register part. The rest of the code surrounding is highly target-specific. That's because you only need that level of detail on code that is very target specific. That kind of code is normally in separate files. ** Builtins remove the need for named registers -- No they don't. glibc uses other registers for special purpose code. ** Builtins would work on all targets -- No they won't. What do you do in targets that the compiler doesn't implement the builtin because there is no equivalent of a stack pointer? Other arguments in favour of named registers: -- Without this extension, it is e.g. hard to force some input or output arguments of inline asm into specific machine registers, the only other way is to use constraints, but most targets don't have constraints for every specific register -- The guarantees that a builtin would give us are very little more than the ones by named registers, and not enough value to justify the implementation of yet-another extension that other compilers won't implement. You see, I'm not a big fan of extensions, nor I think we should blindly follow GCC on whatever they do, but in this particular case, we don't have a strong enough case to make. Even taking the legacy argument off the table, the technical arguments comparing named registers and specially crafted builtins are still in favour of named registers, at least IMHO. cheers, --renato