[LLVMdev] LICM promoting memory to scalar

Balaram Makam bmakam at codeaurora.org
Tue Sep 2 15:46:13 PDT 2014


All,

If we can speculatively execute a load instruction, why isn’t it safe to hoist it out by promoting it to a scalar in LICM pass?


There is a comment in LICM pass that if a load/store is conditional then it is not safe because it would break the LLVM concurrency model (See commit 73bfa4a).
It has an IR test for checking this in test/Transforms/LICM/scalar-promote-memmodel.ll

However, I have a sample code where GCC is able to promote the memory to scalar and hoist/sink load/store out of loop but LLVM cannot.
Is GCC being aggressive here or LLVM missing out an opportunity?

Here is my sample code:

extern int globalvar;
void foo(int n , int incr) {
  unsigned int i;
  for (i = 0 ; i < n; i += incr ) {
    if (i < n/2)
      globalvar += incr;
  }
return;
}

GCC output:

$ aarch64-linux-gnu-g++ -S -o -  -O3  -ffast-math -march=armv8-a+simd test.cpp
        .arch armv8-a+fp+simd
        .file   "test.cpp"
        .text
        .align  2
        .global _Z3fooii
        .type   _Z3fooii, %function
_Z3fooii:
.LFB0:
        .cfi_startproc
        cbz     w0, .L1
        adrp    x6, globalvar
        add     w5, w0, w0, lsr 31
        ldr     w3, [x6,#:lo12:globalvar]			 <== hoist load of globalvar
        mov     w2, 0
        asr     w5, w5, 1
.L4:
        cmp     w5, w2
        add     w2, w2, w1
        add     w4, w3, w1
        csel    w3, w4, w3, hi
        cmp     w2, w0
        bcc     .L4
        str     w3, [x6,#:lo12:globalvar]			<== sink store of globalvar
.L1:
        ret
        .cfi_endproc
.LFE0:
        .size   _Z3fooii, .-_Z3fooii
        .ident  "GCC: (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) 4.9.0"

LLVM output:

$ clang-aarch64-x++ -S -o - -O3 -ffast-math -fslp-vectorize test.cpp
        .text
        .file   "test.cpp"
        .globl  _Z3fooii
        .align  2
        .type   _Z3fooii, at function
_Z3fooii:                               // @_Z3fooii
// BB#0:                                // %entry
        cbz     w0, .LBB0_5
// BB#1:                                // %for.body.lr.ph
        mov      w8, wzr
        cmp      w0, #0                 // =0
        cinc     w9, w0, lt
        asr     w9, w9, #1
        adrp    x10, globalvar
.LBB0_2:                                // %for.body
                                        // =>This Inner Loop Header: Depth=1
        cmp      w8, w9
        b.hs    .LBB0_4
// BB#3:                                // %if.then
                                        //   in Loop: Header=BB0_2 Depth=1
        ldr     w11, [x10, :lo12:globalvar]           		<===== load inside loop
        add      w11, w11, w1
        str     w11, [x10, :lo12:globalvar]          		 <==== store inside loop
.LBB0_4:                                // %for.inc
                                        //   in Loop: Header=BB0_2 Depth=1
        add      w8, w8, w1
        cmp      w8, w0
        b.lo    .LBB0_2
.LBB0_5:                                // %for.end
        ret
.Ltmp1:
        .size   _Z3fooii, .Ltmp1-_Z3fooii


        .ident  "clang version 3.6.0 "

Thanks,
Balaram





More information about the llvm-dev mailing list