Create new jump intrinsic

I’m trying to add my intrinsic to generate a jump on constant value.
I did:
1.Added jmp intrinsics description to Intrinsics.td

// Intrinsic for jump on constant
def int_jmp : Intrinsic<[], [llvm_ptr_ty], [IntrReadMem, IntrInaccessibleMemOrArgMemOnly, IntrNoReturn]>;

2.Created a pattern in X86InstrInfo.td

def : Pat<(int_jmp addr:$src), 
            (JMP64r 
              (SUBREG_TO_REG (i64 0),
                (MOV32rm addr:$src), sub_32bit))>;

Now it is generated in intinsics.inc, but the codogen skips this and no instructions are generated.

*** IR Dump After Module Verifier ***
define internal void @foo(i8* %0, i32 %1, i32 %2) {
entry:
  call void @llvm.jmp(i8* %0)
  ret void
}
# *** IR Dump After Finalize ISel and expand pseudo-instructions ***:
# Machine code for function foo: IsSSA, TracksLiveness
Function Live Ins: $rdi in %0, $esi in %2, $edx in %4

bb.0.entry:
  liveins: $rdi, $esi, $edx
  %4:gr32 = COPY $edx
  %2:gr32 = COPY $esi
  %0:gr64 = COPY $rdi
  %1:gr64 = COPY killed %0:gr64
  %3:gr32 = COPY killed %2:gr32
  %5:gr32 = COPY killed %4:gr32
  RETQ

# End machine code for function foo.

Am I doing something wrong?

I think you can use indirectbr to do the same thing, e.g.,

define void @foo(i8* %0) {
    %2 = bitcast i8* %0 to i32*
    %3 = load i32, i32* %2
    %4 = zext i32 %3 to i64
    %5 = inttoptr i64 %4 to i8*
    indirectbr i8* %5, []
    ret void
}

The instruction indirectbr can be built by CreateIndirectBr in front end.

1 Like

Using indirectbr like that is not advisable. It gets optimized into unreachable because there are no valid destinations.

The basic problem is that the intrinsic still doesn’t have enough effects for LLVM to integrate it into the DAG. It should probably be IntrWriteMem too, and maybe even IntrHasSideEffects.

But what about a normal call?

define void @foo(i8* %ptr) {
  %fptr = bitcast i8* %ptr to void()*
  tail call void %fptr() noreturn
  ret void
}

I suppose you might not actually get a tail call, which could be problematic.

Unfortunately, I can’t use “call” as it will be used to generate machine code templates, in this case I needed “jmp”, I was surprised but using indirectbr I managed to generate a jump, before that I used it only for block transitions. I also considered setjmp/longjmp but they generate extra instructions for me.

I suspect that it will not be possible to use JMP64r in the intrinsic, since it isIndirectBranch.

I don’t quite understand what you mean there and why it means a call is unacceptable.