Problem in X86 backend

Hi,

I'm having some trouble wirting an instruction in the X86 backend.

I made a new intrinsic and I wrote a custom inserter for my intrinsic in the X86 backend.

Everything works fine, except for one instruction that I can't find how to write.

I want to add this instruction in one of my machine basic block: mov [rdi], 0

How can I achieve that with the LLVM api? I tried several stuff, but none works :frowning:

Cheers

Hi,

I want to add this instruction in one of my machine basic block: mov [rdi], 0
How can I achieve that with the LLVM api? I tried several stuff, but none works :frowning:

I find the best way to do this when I'm unsure is to get the llvm-mc
tool to assemble my instruction and copy what it produces. Your
instruction is actually ambiguous though: you need to say what size
you want the store to be. I'll assume 32-bit:

$ echo "mov dword ptr [rdi], 0" | llvm-mc -x86-asm-syntax=intel
-output-asm-variant=1 -show-inst
mov dword ptr [rdi], 0 ## <MCInst #1611 MOV32mi
                                        ## <MCOperand Reg:39>
                                        ## <MCOperand Imm:1>
                                        ## <MCOperand Reg:0>
                                        ## <MCOperand Imm:0>
                                        ## <MCOperand Reg:0>
                                        ## <MCOperand Imm:0>>

Now, that looks complicated, but x86 has uniform memory
addressing-modes: those first 5 operands are just specifying that
address and you only have to learn about them once; and the last
operand is the "0" you've written (try playing around a bit with the
input).

As for the addressing, the meaning of each operand is given at the top
of lib/Target/X86/X86BaseInfo.h: 0 == Base, 1 == Scale, 2 == Index, 3
== Disp, 4 == Segment.

Cheers.

Tim.

I want to add this instruction in one of my machine basic block: mov [rdi], 0
How can I achieve that with the LLVM api? I tried several stuff, but none works :frowning:

Just realised I didn't actually answer your question after that
explanation. Something like this should work:

BuildMI(MBB, MBBI, dl, TII.get(X86::MOV32mi))
    .addReg(X86::RDI).addImm(1).addReg(0).addImm(0).addReg(0)
    .addImm(0);

All the operands are outside the BuildMI because the register operand
you often put inside is actually one the function defines, but this
store doesn't actually change RDI itself.

(You may want to add a RegState::Kill if that's the last use of RDI).

Cheers.

Tim.

Thx for your answer...
I think I begin to understand better how the backend works...

And thx for that command, I was looking for something like that!

Cheers

Hum, in fact, I'm still a bit lost :wink:

It seems to works in -O0, but in -O1, -O2 and -O3, I got this error (+ the dump of the function):

# Machine code for function foo: Post SSA
Function Live Ins: %RDI in %vreg7

BB#0: derived from LLVM BB %entry
    Live Ins: %RDI
        %vreg7<def> = COPY %RDI; GR64:%vreg7
        %vreg1<def> = MOV64rm %vreg7, 1, %noreg, 8, %noreg; mem:LD8[%args.03](tbaa=<badref>) GR64:%vreg1,%vreg7
        TEST64rr %vreg1, %vreg1, %EFLAGS<imp-def>; GR64:%vreg1
        JE_4 <BB#3>, %EFLAGS<imp-use,kill>
    Successors according to CFG: BB#3(12) BB#1(20)

BB#1:
    Predecessors according to CFG: BB#0
        %vreg9<def> = COPY %vreg1; GR64:%vreg9,%vreg1
        %vreg10<def> = COPY %vreg7; GR64:%vreg10,%vreg7
        %vreg0<def> = LEA64r %vreg7, 1, %noreg, 8, %noreg; GR64:%vreg0,%vreg7
        %vreg11<def> = COPY %vreg0; GR64:%vreg11,%vreg0
    Successors according to CFG: BB#2

BB#2: derived from LLVM BB %while.body
    Predecessors according to CFG: BB#2 BB#1
        %vreg4<def> = COPY %vreg11; GR64:%vreg4,%vreg11
        %vreg3<def> = COPY %vreg10; GR64:%vreg3,%vreg10
        %vreg2<def> = COPY %vreg9; GR64:%vreg2,%vreg9
        ADJCALLSTACKDOWN64 0, %RSP<imp-def>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
        %RDI<def> = COPY %vreg2; GR64:%vreg2
        CALL64pcrel32 <ga:@puts>, <regmask>, %RSP<imp-use>, %RDI<imp-use>, %RSP<imp-def>, ...
        ADJCALLSTACKUP64 0, 0, %RSP<imp-def>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
        %vreg6<def> = MOV64rm %vreg3, 1, %noreg, 16, %noreg; mem:LD8[%args.0](tbaa=<badref>) GR64:%vreg6,%vreg3
        %vreg5<def> = COPY %vreg3; GR64:%vreg5,%vreg3
        %vreg5<def,tied1> = ADD64ri8 %vreg5<tied0>, 16, %EFLAGS<imp-def,dead>; GR64:%vreg5
        TEST64rr %vreg6, %vreg6, %EFLAGS<imp-def>; GR64:%vreg6
        %vreg9<def> = COPY %vreg6; GR64:%vreg9,%vreg6
        %vreg10<def> = COPY %vreg4; GR64:%vreg10,%vreg4
        %vreg11<def> = COPY %vreg5; GR64:%vreg11,%vreg5
        JNE_4 <BB#2>, %EFLAGS<imp-use,kill>
        JMP_4 <BB#3>
    Successors according to CFG: BB#3(4) BB#2(124)

BB#3: derived from LLVM BB %while.end
    Predecessors according to CFG: BB#0 BB#2
    Successors according to CFG: BB#4

BB#4: derived from LLVM BB %while.end
    Predecessors according to CFG: BB#3 BB#5
        CMP64rr %RDI, %RBP<kill>, %EFLAGS<imp-def>
        JE_4 <BB#6>, %EFLAGS<imp-use,kill>
    Successors according to CFG: BB#6 BB#5

BB#5: derived from LLVM BB %while.end
    Predecessors according to CFG: BB#4
        MOV32mi %RDI<kill>, 1, %noreg, 0, %noreg, 0
        JMP_4 <BB#4>
    Successors according to CFG: BB#4

BB#6: derived from LLVM BB %while.end
    Predecessors according to CFG: BB#4
        RETQ

# End machine code for function foo.

*** Bad machine code: Using an undefined physical register ***
- function: foo
- basic block: BB#4 while.end (0x46c4840)
- instruction: CMP64rr %RDI, %RBP<kill>, %EFLAGS<imp-def>
- operand 0: %RDI

*** Bad machine code: Using an undefined physical register ***
- function: foo
- basic block: BB#4 while.end (0x46c4840)
- instruction: CMP64rr %RDI, %RBP<kill>, %EFLAGS<imp-def>
- operand 1: %RBP<kill>

*** Bad machine code: Using an undefined physical register ***
- function: foo
- basic block: BB#5 while.end (0x46c48f0)
- instruction: MOV32mi %RDI<kill>, 1, %noreg, 0, %noreg, 0
- operand 0: %RDI<kill>

Cheers

Hi Julien,

Hum, in fact, I'm still a bit lost :wink:

It seems to works in -O0, but in -O1, -O2 and -O3, I got this error (+ the dump of the function):

# Machine code for function foo: Post SSA
Function Live Ins: %RDI in %vreg7

BB#0: derived from LLVM BB %entry
   Live Ins: %RDI
       %vreg7<def> = COPY %RDI; GR64:%vreg7
       %vreg1<def> = MOV64rm %vreg7, 1, %noreg, 8, %noreg; mem:LD8[%args.03](tbaa=<badref>) GR64:%vreg1,%vreg7
       TEST64rr %vreg1, %vreg1, %EFLAGS<imp-def>; GR64:%vreg1
       JE_4 <BB#3>, %EFLAGS<imp-use,kill>
   Successors according to CFG: BB#3(12) BB#1(20)

BB#1:
   Predecessors according to CFG: BB#0
       %vreg9<def> = COPY %vreg1; GR64:%vreg9,%vreg1
       %vreg10<def> = COPY %vreg7; GR64:%vreg10,%vreg7
       %vreg0<def> = LEA64r %vreg7, 1, %noreg, 8, %noreg; GR64:%vreg0,%vreg7
       %vreg11<def> = COPY %vreg0; GR64:%vreg11,%vreg0
   Successors according to CFG: BB#2

BB#2: derived from LLVM BB %while.body
   Predecessors according to CFG: BB#2 BB#1
       %vreg4<def> = COPY %vreg11; GR64:%vreg4,%vreg11
       %vreg3<def> = COPY %vreg10; GR64:%vreg3,%vreg10
       %vreg2<def> = COPY %vreg9; GR64:%vreg2,%vreg9
       ADJCALLSTACKDOWN64 0, %RSP<imp-def>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
       %RDI<def> = COPY %vreg2; GR64:%vreg2
       CALL64pcrel32 <ga:@puts>, <regmask>, %RSP<imp-use>, %RDI<imp-use>, %RSP<imp-def>, ...
       ADJCALLSTACKUP64 0, 0, %RSP<imp-def>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
       %vreg6<def> = MOV64rm %vreg3, 1, %noreg, 16, %noreg; mem:LD8[%args.0](tbaa=<badref>) GR64:%vreg6,%vreg3
       %vreg5<def> = COPY %vreg3; GR64:%vreg5,%vreg3
       %vreg5<def,tied1> = ADD64ri8 %vreg5<tied0>, 16, %EFLAGS<imp-def,dead>; GR64:%vreg5
       TEST64rr %vreg6, %vreg6, %EFLAGS<imp-def>; GR64:%vreg6
       %vreg9<def> = COPY %vreg6; GR64:%vreg9,%vreg6
       %vreg10<def> = COPY %vreg4; GR64:%vreg10,%vreg4
       %vreg11<def> = COPY %vreg5; GR64:%vreg11,%vreg5
       JNE_4 <BB#2>, %EFLAGS<imp-use,kill>
       JMP_4 <BB#3>
   Successors according to CFG: BB#3(4) BB#2(124)

BB#3: derived from LLVM BB %while.end
   Predecessors according to CFG: BB#0 BB#2
   Successors according to CFG: BB#4

BB#4: derived from LLVM BB %while.end
   Predecessors according to CFG: BB#3 BB#5
       CMP64rr %RDI, %RBP<kill>, %EFLAGS<imp-def>
       JE_4 <BB#6>, %EFLAGS<imp-use,kill>
   Successors according to CFG: BB#6 BB#5

BB#5: derived from LLVM BB %while.end
   Predecessors according to CFG: BB#4
       MOV32mi %RDI<kill>, 1, %noreg, 0, %noreg, 0

Your problem is that kill flag on RDI. Indeed, this is not the last use of RDI in your case and because you set this flag, when jumping to BB#4, the compiler thinks that RDI is not defined.

Also, I am not sure what you are trying to achieve, but are you sure you always want to use RDI? In this case, should it be vreg7 for instance?

-Quentin

Your problem is that kill flag on RDI. Indeed, this is not the last use of RDI in your
case and because you set this flag, when jumping to BB#4, the compiler thinks
that > RDI is not defined.

Also, I am not sure what you are trying to achieve, but are you sure you always
want to use RDI? In this case, should it be vreg7 for instance?

-Quentin

Hi, thx for your answer...

I figured it that out... In fact I changed my code and now I'm using a virtual register, but I still have a problem :frowning: (http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-October/078315.html)

I'm trying to erase the content of the stack in the epilogue of the function...

Cheers

Hi Julien,

Akira already pointed out the problem.
You have basically two definitions of the same virtual register, which is forbidden in SSA.
I.e., you have:
Reg = something
...
Reg = Reg + something else

What you want is
Reg = something
...
Reg2 = Reg + something else
=> you need to create a second virtual register for the second definition.

Cheers,
-Quentin

Envoyé de mon iPhone

Oh ok, that's what I tought but I wasn't sure I did understand
correctly... Thx for the help!

Cheers