Selecting a particular register for RISCV store instruction

Hi all, I am trying to select a certain register I added to RISCV for a store instruction. How can I do that and which files should I edit? Will I necessarily have to look into SelectionDAG or is it possible without getting into it?

Register classes are defined in RISCVRegisterInfo.td and used by RISCVInstrInfo*.td. Whether you need to touch C++ code or can stay in TableGen land depends on what exactly you’re trying to do.

Suppose I compile this simple C code-

#include<stdio.h>
int main()
{
int a = 7;
return a;
}

When I look at the disassembly of the object code, for sw instruction I want a register xy to show up. Instead it shows s0 in the disassembly eg. at line starting with 101de. I think I have been able to add the register by editing RISCVRegisterInfo.td but want the sw instruction to only work with xy.


00000000000101d4 <main>:
   101d4: 01 11        	addi	sp, sp, -32
   101d6: 06 ec        	sd	ra, 24(sp)
   101d8: 22 e8        	sd	s0, 16(sp)
   101da: 00 10        	addi	s0, sp, 32
   101dc: 01 46        	li	a2, 0
   101de: 23 26 c4 fe  	sw	a2, -20(s0)
   101e2: 1d 46        	li	a2, 7
   101e4: 23 24 c4 fe  	sw	a2, -24(s0)
   101e8: 03 25 84 fe  	lw	a0, -24(s0)
   101ec: e2 60        	ld	ra, 24(sp)
   101ee: 42 64        	ld	s0, 16(sp)
   101f0: 05 61        	addi	sp, sp, 32
   101f2: 82 80        	ret

You’re going to need to be more specific than that. Also I don’t know how you expect to encode that when all 32 values for the 5-bit rs1 field are taken by the existing x0-x31 general-purpose integer registers.

I was able to figure it out, it was a silly mistake, I was using the wrong disassembler instead of the llvm’s disassembler. I am able to use my added register. Will try to be more specific from next time.

To give you more context regarding my problem we are working on adding a custom 16 bit register to RISCV and we need a new type to be added which only stores or loads from that particular register. Right now I am still playing around, (making changes and seeing what works whether it actually makes sense or not). So I changed the RISCVReg encoding to use my added register instead of one particular GPR.

After this I changed the sw instruction to use my XYreg register class. This way I am able to compile the above and use XY register for sw instructions. I realize this is an incorrect way to do this and I am looking for guidance on how I should approach my problem. I was thinking as a next step to add a new type for my added register so that XY a = 7; in C code would load and store from my particular register.

We have a bunch of code in C already written this way that is being compiled using a proprietary compiler, so finally what I want is the compilation process from C to object code to work for this line XY a = 7; using changes I do to LLVM and not use the proprietary compiler at all.

Additionally, I added a new derived type for that register in LLVM using the extending LLVM tutorial https://llvm.org/docs/ExtendingLLVM.html for adding a new derived type following code already present for int type. I was hoping this would at least compile XY a = 7; but I am assuming I would also require changes to clang? If anyone could help me answer this question or could provide general guidance I would be extremely grateful.
Thank you.

I don’t understand why you would need a new type to add a 16-bit register. What problem are you trying to solve?

I’m trying to simulate a different proprietary compiler in a way using LLVM.
The new type is to reuse the already written C code we have which has lines like

XY xy_in;
int temp1 = 7;
xy_in = *(XY*)&(temp1);

The current proprietary compiler we were using compiles this into loading into a specific register XY. The C code makes it look really similar to a type, so I thought adding XY as a type might be a good idea.
The disassembly of the compiled code has load and store instructions that load and store into the xy instruction and I want to simulate that with llvm. Please let me know if I can provide more clarification.

How else could I use my added register directly through C code? Will changes be needed to be made to clang? Or is this a very unusual task?

C doesn’t expose registers. Every variable is conceptually in memory, and a type doesn’t change that. What is the purpose of this register? Do you want something that acts like memory mapped / volatile reads of this register? Is it used separately from the program? The closest thing we probably have is the read_register/write_register intrinsic, but those are not very useful depending on the context.