[LLVMdev] Testing LLVM on OS X

Chris Lattner sabre at nondot.org
Sun May 9 15:47:01 PDT 2004


On Tue, 4 May 2004, Chris Lattner wrote:

> On Tue, 4 May 2004, Chris Lattner wrote:
> > I suspect that a large reason that LLVM does worst than a native C
> > compiler with the CBE+GCC is that LLVM generates very low-level C code,
> > and I'm not convinced that GCC is doing a very good job (ie, without
> > syntactic loops).
>
> Yup, this is EXACTLY what is going on.
>
> I took this very simple C function:
>
> int Array[1000];
> void test(int X) {
>   int i;
>   for (i = 0; i < 1000; ++i)
>     Array[i] += X;
> }
>
> Compile with -O3 on OS/X gave me this:
>
> _test:
>         mflr r5
>         bcl 20,31,"L00000000001$pb"
> "L00000000001$pb":
>         mflr r2
>         mtlr r5
>         addis r4,r2,ha16(L_Array$non_lazy_ptr-"L00000000001$pb")
>         li r2,0
>         lwz r9,lo16(L_Array$non_lazy_ptr-"L00000000001$pb")(r4)
>         li r4,1000
>         mtctr r4
> L9:
>         lwzx r7,r2,r9          ; load
>         add r6,r7,r3           ; add
>         stwx r6,r2,r9          ; store
>         addi r2,r2,4           ; Increment pointer
>         bdnz L9                ; Decrement count register, branch while not zero
>         blr
>
> This is nice code, good GCC.  :)

Okay, I changed the C backend to emit syntactic loops around the real
loops, and it seems to make a big difference.  LLVM now generates this
code (note that the actual loop is not actually responsible for control
flow, it's unreachable):

void test(int l7_X) {
  unsigned l8_indvar;
  unsigned l8_indvar__PHI_TEMPORARY;
  int *l14_tmp_2E_4;
  int l7_tmp_2E_7;
  unsigned l8_indvar_2E_next;

  l8_indvar__PHI_TEMPORARY = 0u;   /* for PHI node */
  goto l13_no_exit;

  do {     /* Syntactic loop 'no_exit' to make GCC happy */
l13_no_exit:
  l8_indvar = l8_indvar__PHI_TEMPORARY;
  l14_tmp_2E_4 = &Array[l8_indvar];
  l7_tmp_2E_7 = *l14_tmp_2E_4;
  *l14_tmp_2E_4 = (l7_tmp_2E_7 + l7_X);
  l8_indvar_2E_next = l8_indvar + 1u;
  l8_indvar__PHI_TEMPORARY = l8_indvar_2E_next;   /* for PHI node */
  if ((l8_indvar_2E_next == 1000u)) {
    goto l13_return;
  } else {
    goto l13_no_exit;
  }

  } while (1); /* end of syntactic loop 'no_exit' */
l13_return:
  return;
}

Instead of:

> void test(int l7_X) {
>   unsigned l8_indvar;
>   unsigned l8_indvar__PHI_TEMPORARY;
>   int *l14_tmp_2E_5;
>   int l7_tmp_2E_9;
>   unsigned l8_indvar_2E_next;
>
>   l8_indvar__PHI_TEMPORARY = 0u;   /* for PHI node */
>
> l13_no_exit:
>   l8_indvar = l8_indvar__PHI_TEMPORARY;
>   l14_tmp_2E_5 = &Array[l8_indvar];
>   l7_tmp_2E_9 = *l14_tmp_2E_5;
>   *l14_tmp_2E_5 = (l7_tmp_2E_9 + l7_X);
>   l8_indvar_2E_next = l8_indvar + 1u;
>   if (!(l8_indvar_2E_next == 1000u)) {
>     l8_indvar__PHI_TEMPORARY = l8_indvar_2E_next;   /* for PHI node */
>     goto l13_no_exit;
>   }
>   return;
> }

The new CBE generated code causes GCC to compile the function into:

_test:
        mflr r5
        bcl 20,31,"L00000000001$pb"
"L00000000001$pb":
        mflr r4
        mtlr r5
        addis r2,r4,ha16(_Array-"L00000000001$pb")
        li r4,1000
        mtctr r4
        la r9,lo16(_Array-"L00000000001$pb")(r2)
        li r2,0
L10:
L2:
        lwzx r7,r2,r9
        add r6,r7,r3
        stwx r6,r2,r9
        addi r2,r2,4
        bdnz L10
L7:
        blr

... which is exactly what we want.  Patrick, I would appreciate it if you
could rerun your tests on PPC and let me know if this helps.  :)

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/




More information about the llvm-dev mailing list