[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