[LLVMdev] Help with new backend: byte-sized loads being generated for 'int' array access

Hal Finkel hfinkel at anl.gov
Tue Jun 10 08:54:18 PDT 2014


----- Original Message -----
> From: "Jeff Kuskin" <jk500500 at yahoo.com>
> To: "LLVM Developers Mailing List" <llvmdev at cs.uiuc.edu>
> Sent: Tuesday, June 10, 2014 10:04:45 AM
> Subject: [LLVMdev] Help with new backend: byte-sized loads being generated	for 'int' array access
> 
> First, apologies because I'm quite new to LLVM backend development.
>   I very much appreciate any help from more experienced folks.
> 
> 
> I'm running into a problem in which byte-sized loads are _sometimes_
> being generated for a read access to an external array of 4-byte
> ints, depending on how the array is declared.
> 
> I am hoping someone can perhaps point me to possible sources of the
> problem in my backend code.  I would be happy to supply additional
> details; I'm trying to keep this message relatively short.
> 
> 
> 
> The issue arises when I compile the following C code:
> 
>      extern int EI[];
>      int MYFUNC() { return EI[1288]; }
> 
> 
> 
> I run the code through 'clang -emit-llvm' and end up with bitcode of:
> 
>     ; ModuleID = './clang2.c'
>     target datalayout =
>     "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
>     target triple = "dgc"
>     @EI = external global [0 x i32]
>     ; Function Attrs: nounwind
>     define i32 @MYFUNC() #0 {
>     entry:
>       %0 = load i32* getelementptr inbounds ([0 x i32]* @EI, i32 0,
>       i32 1288), align 1
>       ret i32 %0
>     }
> 
>     attributes #0 = { nounwind "less-precise-fpmad"="false"
>                    "no-frame-pointer-elim"="true"
>                    "no-frame-pointer-elim-non-leaf"
>                    "no-infs-fp-math"="false"
>                    "no-nans-fp-math"="false"
>                    "stack-protector-buffer-size"="8"
>                    "unsafe-fp-math"="false" "use-soft-float"="false"
>                    }
>     !llvm.ident = !{!0}
>     !0 = metadata !{metadata !"clang version 3.5.0 (209307)"}
> 
> 
> 
> When I then run the bitcode through llc, the memory load for the
> 'EI[1288]' reference is generated with a series of four byte-sized
> loads, followed by the appropriate shifting and OR'ing to get all
> the bytes into the proper place in the result.
> 
> This is not what I want, of course.  I want a single, word-sized load
> to be generated.  I have various sizes of load instructions defined
> in my TableGen file, an excerpt of which I've included at the end of
> this message.
> 
> Other backends built from the same source tree -- mipsel and xcore,
> for instance -- do indeed generate a single word-sized load, as
> expected, so I'm confident the problem is in my backend code.
> 
> What's interesting is that my backend *DOES* generate a single
> word-sized load if I make either of the following changes to the
> declaration of 'EI':
> 
>    (1) Provide an array size in the EI declaration:
>              extern int EI[5000];
> 
>        This yields the following in the bitcode, replacing the like
>        lines from above:
>            @EI = external global [5000 x i32]
>            ; Function Attrs: nounwind
>            define i32 @MYFUNC() #0 {
>            entry:
>              %0 = load i32* getelementptr inbounds ([5000 x i32]*
>              @EI, i32 0, i32 1288), align 4
>              ret i32 %0
>            }
> 
> 
> 
>    (2) Change EI to be an int*:
>              extern int* EI;
> 
>        This yields the following in the bitcode:
>          @EI = external global i32*
>          ; Function Attrs: nounwind
>          define i32 @MYFUNC() #0 {
>          entry:
>            %0 = load i32** @EI, align 4
>            %arrayidx = getelementptr inbounds i32* %0, i32 1288
>            %1 = load i32* %arrayidx, align 4
>            ret i32 %1
>          }
> 
> 
> 
> I have tried a number of things to figure out this issue, but to no
> avail.  For some reason the 'EI[1288]' reference is being treated as
> possibly unaligned ("align=1"), but I can't figure out why.
> 

For the question of how C is being translated into LLVM IR (why there is the 'align 1' vs 'align 4'), you should ask on the cfe-dev list (not here).

To mention a related point, if your target supports unaligned loads for 4-byte integers, then you need to override the *TargetLowering::allowsUnalignedMemoryAccesses callback for your target.

 -Hal

> 
> 
> 
> TD file excerpt (modeled after the MIPS .td file):
> 
> 
> def DGCAddrDefault :
>         ComplexPattern<iPTR, 2, "selectAddrDefault", [frameindex]>;
> def DGCAddrInt :
>         ComplexPattern<iPTR, 2, "selectAddrInt", [frameindex]>;
> 
> def DGCMemSrc : Operand<iPTR> {
>   let MIOperandInfo = (ops ptr_rc, i32imm);
>   let OperandType = "OPERAND_MEMORY";
> }
> 
> let canFoldAsLoad = 1,
>     mayLoad = 1 in
> {
> def LB : InstrDGC64_s__s_s<
>              (outs IntRegs:$rd),
>              (ins DGCMemSrc:$addr),
>              !strconcat("lb", "\t$rd, $addr"),
>              [(set i32:$rd, (sextloadi8 DGCAddrInt:$addr))],
>              0b10011, 0b000, 0, 0>;
> def LH : InstrDGC64_s__s_s<
>              (outs IntRegs:$rd),
>              (ins DGCMemSrc:$addr),
>              !strconcat("lh", "\t$rd, $addr"),
>              [(set i32:$rd, (sextloadi16 DGCAddrDefault:$addr))],
>              0b10011, 0b001, 0, 0>;
> def LBU : InstrDGC64_s__s_s<
>              (outs IntRegs:$rd),
>              (ins DGCMemSrc:$addr),
>              !strconcat("lbu", "\t$rd, $addr"),
>              [(set i32:$rd, (zextloadi8 DGCAddrDefault:$addr))],
>              0b10011, 0b100, 0, 0>;
> def LHU : InstrDGC64_s__s_s<
>              (outs IntRegs:$rd),
>              (ins DGCMemSrc:$addr),
>              !strconcat("lhu", "\t$rd, $addr"),
>              [(set i32:$rd, (zextloadi16 DGCAddrInt:$addr))],
>              0b10011, 0b101, 0, 0>;
> def LW : InstrDGC64_s__s_s<
>              (outs IntRegs:$rd),
>              (ins DGCMemSrc:$addr),
>              !strconcat("lw", "\t$rd, $addr"),
>              [(set i32:$rd, (load DGCAddrDefault:$addr))],
>              0b10011, 0b010, 0, 0>;
> }
> 
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory




More information about the llvm-dev mailing list