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
> 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 readnoneI would not produce any llvm global for it. So some insanity like register long a asm("rsp"); long f(long x) { long ret = a; a = x; return ret; } would compile to define i64 @f(i64 %x) { %ret = call i64 @llvm.read_register("rsp"); call void @llvm.write_register("rsp", i64 %x) ret %ret } declare void @llvm.write_register(i8*, i64) declare i64 @llvm.read_register(i8*)>> 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...Yes, it is really odd. It says "Global register variables reserve registers throughout the program.", which is obviously not the case since not all compile units might see it.> >> For example, is it legal to move the read of rsp out of a >> loop? > > No. It should be a volatile read/write.Agreed. With the intrinsic the semantics are easy to represent. Cheers, Rafael
----- Original Message -----> From: "Rafael Espíndola" <rafael.espindola at gmail.com> > To: "Renato Golin" <renato.golin at linaro.org> > Cc: "Clang Dev" <cfe-dev at cs.uiuc.edu>, "LLVM Dev" <llvmdev at cs.uiuc.edu> > Sent: Thursday, March 27, 2014 11:30:46 AM > Subject: Re: [cfe-dev] [LLVMdev] Named register variables GNU-style > > > 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 > > I would not produce any llvm global for it. So some insanity like > > register long a asm("rsp"); > long f(long x) { > long ret = a; > a = x; > return ret; > } > > would compile to > > define i64 @f(i64 %x) { > %ret = call i64 @llvm.read_register("rsp"); > call void @llvm.write_register("rsp", i64 %x) > ret %ret > } > declare void @llvm.write_register(i8*, i64) > declare i64 @llvm.read_register(i8*)+1 -Hal> > >> 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... > > Yes, it is really odd. It says "Global register variables reserve > registers throughout the program.", which is obviously not the case > since not all compile units might see it. > > > > >> For example, is it legal to move the read of rsp out of a > >> loop? > > > > No. It should be a volatile read/write. > > Agreed. With the intrinsic the semantics are easy to represent. > > Cheers, > Rafael > _______________________________________________ > cfe-dev mailing list > cfe-dev at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev >-- Hal Finkel Assistant Computational Scientist Leadership Computing Facility Argonne National Laboratory
On 27 Mar 2014 16:30, "Rafael Espíndola" <rafael.espindola at gmail.com> wrote:> > > 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 > > I would not produce any llvm global for it. So some insanity like > > register long a asm("rsp"); > long f(long x) { > long ret = a; > a = x; > return ret; > } > > would compile to > > define i64 @f(i64 %x) { > %ret = call i64 @llvm.read_register("rsp"); > call void @llvm.write_register("rsp", i64 %x) > ret %ret > } > declare void @llvm.write_register(i8*, i64) > declare i64 @llvm.read_register(i8*)That was actually my first idea, but I got confused on the implementation. :-) I'll try it again. Cheers, Renato> >> 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... > > Yes, it is really odd. It says "Global register variables reserve > registers throughout the program.", which is obviously not the case > since not all compile units might see it. > > > > >> For example, is it legal to move the read of rsp out of a > >> loop? > > > > No. It should be a volatile read/write. > > Agreed. With the intrinsic the semantics are easy to represent. > > Cheers, > Rafael-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140327/878a60f6/attachment.html>
On Thu, Mar 27, 2014 at 9:30 AM, Rafael Espíndola < rafael.espindola at gmail.com> wrote:> > 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 > > I would not produce any llvm global for it. So some insanity like > > register long a asm("rsp"); > long f(long x) { > long ret = a; > a = x; > return ret; > } > > would compile to > > define i64 @f(i64 %x) { > %ret = call i64 @llvm.read_register("rsp"); > call void @llvm.write_register("rsp", i64 %x) > ret %ret > } > declare void @llvm.write_register(i8*, i64) > declare i64 @llvm.read_register(i8*)I don't think that works. Per the GCC documentation, a global register variable reserves the register entirely for use with that name in a translation unit. We don't seem to want exactly that model, but the approach you're suggesting doesn't seem to capture the semantics. For instance: register long a asm("r12"); void f(long n) { n *= 3; a += n; } ... could do the wrong thing if the multiplication happens to use r12.>> 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... > > Yes, it is really odd. It says "Global register variables reserve > registers throughout the program.", which is obviously not the case > since not all compile units might see it. > > > > >> For example, is it legal to move the read of rsp out of a > >> loop? > > > > No. It should be a volatile read/write. > > Agreed. With the intrinsic the semantics are easy to represent. > > Cheers, > Rafael > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140327/23ba1b97/attachment.html>