Create a memory operand (PC relative or base register addressing) from FrameIndex

I have an intrinsic function that I turn into a new instruction on RISC-V. My intrinsic takes two arguments and one of them is a pointer to an alloca instruction. When I turn my intrinsic function to an instruction it has two sources and the second source is supposed to be a memory-addressing operand to the alloca instruction from IR similar to a load. However when I print the assembly, I just have a constant.
tmp a1, 50 instead of an asm similar to this tmp a1, 12(sp). One of the issues I have found is that when I turn my intrinsic to an MIR during the instruction selection the operand that is supposed to be an alloca instruction will have changed to FrameIndex:i64<0>.

is it possible to get the addressing similar to a memory instruction from FrameIndex?

IR

%1 = alloca i32, align 4
call void @llvm.tmp.i64.p0(i64 2, ptr %1)

Initial Selection DAG
t11: ch = llvm.tmp t8, TargetConstant:i64<307>, Constant:i64<2>, FrameIndex:i64<1>

Instruction Selection DAG
t35: ch = TMP TargetConstant:i64<307>, t42, t7, t23

I am looking into using getTargetFrameIndex and getTargetConstant functions for the base and offset of the operand during the instruction selection stage of the DAG process. is this the right path?

During instruction selection, the stack frame layout isn’t known yet, so LLVM uses a FrameIndex operand to refer to a region of the stack, before the offset to it is known. For your case, I think using a FrameIndex operand is the right thing to do, and it won’t be possible to replace it with a constant offset during instruction selection.

Once the stack frame layout has been decided, the PrologEpilogInserter pass calls RISCVRegisterInfo::eliminateFrameIndex on any instructions with a FrameIndex operand to convert them to the final operands, typically register+offset. You might need to modify that function to know what to do with your new instruction.

1 Like