[LLVMdev] LLVM Backend for Z80. ADD -> replaced -> OR

Matt Johnson johnso87 at crhc.illinois.edu
Wed Apr 25 12:06:20 PDT 2012


Hi Peter,

On 04/25/2012 01:58 PM, Peter Hanzel wrote:
> Hello.
> I have played with DataLayout and found a solution with is uknown to me.
> I added S16 and also s0:16:16, but it had not worked.
> Then I found that in Z80FrameLowering.h I am calling TargetFrameLowering
> with stack aligment set to 8. So I changed it to 2 bytes. But this also
> didn't  help.
> Then I changed llc to show TargetDataLayout and found that a option is
> set to a0:0:64.
> So I changed my Z80DataLayout to a0:0:16. And voila, it started to work
> and ADD was not longer replaced by OR. Only for add+1 to or, which is
> correct.

The 'a' option in DataLayout specifies the alignment in bits of 
aggregate objects (structs and arrays) in memory.  Since you had
specified before that structs were 8-byte-aligned, the compiler
"knew" that the low 3 bits of aggregate addresses would be 0, so
it did strength reduction on the addition to transform it to an OR.

If structs/arrays in memory are actually only 2-byte-aligned on Z80,
a0:0:16 is the right thing to do; it will only permit this kind of
strength reduction for operations on a single low bit.  If
structs/arrays actually don't have any known alignment (a struct could
start at address 0x3, for example), you should change it to a0:0:8
(single-byte alignment).

-Matt

> So now I don't understand that a option in datalyout.
> According doc it is alignment for aggregate type.
> But anyhow thanks for help and pointing me in right direction.
> Peter.
> On Wed, Apr 25, 2012 at 4:31 PM, Fan Dawei <fandawei.s at gmail.com
> <mailto:fandawei.s at gmail.com>> wrote:
>
>     Hi Peter,
>
>     I think the problem is that you did not explicitly define
>     stack alignment in Z80TargetMachine.cpp
>
>     DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-n8")
>
>     Try to add S16 to the string if your stack is 2-byte aligned. Refer
>     to http://llvm.org/docs/LangRef.html#datalayout .
>
>     If it does not work, try to specify the layout in the input module
>     using target layout directive.
>
>     David
>
>     On Wed, Apr 25, 2012 at 4:57 PM, Peter Hanzel <hanzelpeter at gmail.com
>     <mailto:hanzelpeter at gmail.com>> wrote:
>
>         Hello.
>
>         I am playing with LLVM and trying to make Z80 (Zilog Z80) backend.
>         The source code is attached.
>
>         I have succesfully made some simple test. But now I have problem
>         with ADD instruction.
>         The source C code is:
>
>         typedef struct
>         {
>         unsigned char id1;
>         unsigned char id2;
>         unsigned char id3;
>
>         } testS;
>
>         void simple()
>         {
>         testS test;
>         test.id1 = 0x40;
>         test.id2 = 0x80;
>         test.id3 = 0xc0;
>         }
>
>         It produces this LLVM IR:
>
>         %struct.testS = type { i8, i8, i8 }
>
>         define void @simple() nounwind {
>         entry:
>           %test = alloca %struct.testS, align 1
>           %id1 = getelementptr inbounds %struct.testS* %test, i32 0, i32 0
>           store i8 64, i8* %id1, align 1
>           %id2 = getelementptr inbounds %struct.testS* %test, i32 0, i32 1
>           store i8 -128, i8* %id2, align 1
>           %id3 = getelementptr inbounds %struct.testS* %test, i32 0, i32 2
>           store i8 -64, i8* %id3, align 1
>           ret void
>         }
>
>         And with llc -filetype=asm -march=z80 a get this .s file:
>
>         .file "simple4.bc"
>         .text
>         .globl simple
>         .type simple, at function
>         simple:                                 # @simple
>         # BB#0:                                 # %entry
>         ld HL, 8
>         add HL,SP <--- problem line
>         ld DE, 1
>         ld BC, 2
>         ld (SP+6), BC
>         ld B, H
>         ld C, L
>         or BC, DE
>         ld (SP+4), BC
>         ld (HL),64
>         ld D, H
>         ld E, L
>         ld BC, (SP+6)
>         or DE, BC
>         ld BC, (SP+4)
>         ld H, B
>         ld L, C
>         ld (HL),-128
>         ld H, D
>         ld L, E
>         ld (HL),-64
>         $tmp0:
>         .size simple, ($tmp0)-simple
>
>
>         The problem is that llc replaces ADD instruction with OR.
>
>         Without defining OR16 function, the .S is not generated and
>         claims that it cannot select OR instruction.
>         So I added OR16 (that's the or BC,DE piece of code).
>
>         But problem is that I am using the first two lines:
>
>         ld HL, 8
>         add HL,SP
>
>         For FrameIndex and the HL register will contain SP which is only
>         two 2bytes aligned.
>         So "OR with 1" will work, but for second assigned :OR with 2"
>         will not work.
>
>         I suspect that llc is assuming that HL will contain 8 (that's
>         the start) and or-ing 8 with 1 or with 2 is ok.
>         But my HL has also added SP to it.
>         This is how my ISD::FrameIndex instruction look like:
>
>         def addHLdisp : Z80Instr<(outs HL16:$dst), (ins i16imm:$disp,
>         GPR16:$src),
>         "ld $dst, $disp\n\tadd $dst,$src",
>         [(set HL16:$dst, (add GPR16:$src, (i16 imm:$disp)))]>;
>
>         So it say that HL16:$dst wich is only HL register, will be changed.
>         I also tried to change it to
>         <(outs HL16:$dst), (ins i16imm:$disp, SP16:$src),
>
>         But the output is the same.
>
>         Can someone tell me what I am doing wrong?
>
>         Peter.
>
>
>
>
>
>
>
>
>
>         _______________________________________________
>         LLVM Developers mailing list
>         LLVMdev at cs.uiuc.edu <mailto:LLVMdev at cs.uiuc.edu>
>         http://llvm.cs.uiuc.edu <http://llvm.cs.uiuc.edu/>
>         http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev



More information about the llvm-dev mailing list