Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi-dimensional VLA indicies not scaled by llvm-gcc #1605

Closed
sunfishcode opened this issue Mar 1, 2007 · 12 comments
Closed

multi-dimensional VLA indicies not scaled by llvm-gcc #1605

sunfishcode opened this issue Mar 1, 2007 · 12 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla llvm-tools All llvm tools that do not have corresponding tag miscompilation

Comments

@sunfishcode
Copy link
Member

Bugzilla Link 1233
Resolution FIXED
Resolved on Feb 22, 2010 12:55
Version 1.0
OS All

Extended Description

I typed this into the online demo:

int foo(int v, int w, int x, int y, int z,
float A[][w][x][y][z],
int g, int h, int i, int j, int k)
{
return A[g][h][i][j][k];
}

It gave me this:

int %foo(int %v, int %w, int %x, int %y, int %z, float* %A, int %g, int %h, int
%i, int %j, int %k) {
entry:
%tmp64.sum = add int %h, %g ; [#uses=1]
%tmp62.sum = add int %tmp64.sum, %i ; [#uses=1]
%tmp60.sum = add int %tmp62.sum, %j ; [#uses=1]
%tmp54.sum = add int %tmp60.sum, %k ; [#uses=1]
%tmp66 = getelementptr float* %A, int %tmp54.sum ; <float*> [#uses=1]
%tmp = load float* %tmp66 ; [#uses=1]
%tmp67 = cast float %tmp to int ; [#uses=1]
ret int %tmp67
}

The VLA indicies are not being scaled; it's just adding them all up verbatim and
doing a one-dimensional getelementptr.

@sunfishcode
Copy link
Member Author

assigned to @lattner

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 1, 2007

The online demo is currently pointing at some UIUC developer's build tree, AFAIK.
It could be in a "not good" state.

Have you replicated this problem on the head of LLVM/llvm-gcc?

If not, please do so. If it still doesn't work, we'll investigate.

@lattner
Copy link
Collaborator

lattner commented Mar 1, 2007

This fails with mainline as well:

define i32 @​foo(i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, float* %A, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k) {
entry:
%tmp79.sum = add i32 %h, %g ; [#uses=1]
%tmp77.sum = add i32 %tmp79.sum, %i ; [#uses=1]
%tmp75.sum = add i32 %tmp77.sum, %j ; [#uses=1]
%tmp69.sum = add i32 %tmp75.sum, %k ; [#uses=1]
%tmp81 = getelementptr float* %A, i32 %tmp69.sum ; <float*> [#uses=1]
%tmp82 = load float* %tmp81 ; [#uses=1]
%tmp8283 = fptosi float %tmp82 to i32 ; [#uses=1]
ret i32 %tmp8283
}

certainly a CFE bug.

@lattner
Copy link
Collaborator

lattner commented Mar 2, 2007

Nice catch. Testcase here:
CFrontend/2007-03-01-VarSizeArrayIdx.c

Patch here:
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070226/045387.html

The patch generates pretty horrible LLVM code (in the VLA case only), but the code generator groks it
well. We compile your testcase to (with fomit-frame-pointer):

_foo:
movl 8(%esp), %eax
imull 12(%esp), %eax
imull 16(%esp), %eax
imull 20(%esp), %eax
movl 36(%esp), %ecx
addl 32(%esp), %ecx
imull 28(%esp), %eax
addl 40(%esp), %ecx
leal (,%eax,4), %eax
addl 44(%esp), %ecx
addl 24(%esp), %eax
cvttss2si (%eax,%ecx,4), %eax
ret

GCC apparently misses reassociating some arithmetic and does significantly worse:

_foo:
pushl %esi
movl 24(%esp), %eax
movl %eax, %ecx
imull 20(%esp), %ecx
movl %ecx, %edx
imull 16(%esp), %edx
movl %edx, %esi
imull 12(%esp), %esi
imull 32(%esp), %esi
imull 44(%esp), %eax
imull 40(%esp), %ecx
imull 36(%esp), %edx
addl %edx, %eax
addl %ecx, %eax
addl 48(%esp), %eax
sall $2, %eax
leal (%eax,%esi,4), %esi
movl 28(%esp), %eax
cvttss2si (%esi,%eax), %eax
popl %esi
ret

I'd appreciate it if you could verify that the code we now produce is correct. I verified a simpler case.

Thanks again for noticing this,

-Chris

@lattner
Copy link
Collaborator

lattner commented Mar 2, 2007

FWIW, here is the generated LLVM code:

define i32 @​foo(i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, float* %A, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k) {
entry:
%tmp6769 = bitcast float* %A to i8* ; <i8*> [#uses=1]
%tmp58 = shl i32 %w, 2 ; [#uses=1]
%tmp60 = mul i32 %tmp58, %x ; [#uses=1]
%tmp62 = mul i32 %tmp60, %y ; [#uses=1]
%tmp63 = mul i32 %tmp62, %z ; [#uses=1]
%tmp70 = mul i32 %tmp63, %g ; [#uses=1]
%tmp71 = getelementptr i8* %tmp6769, i32 %tmp70 ; <i8*> [#uses=1]
%tmp77 = bitcast i8* %tmp71 to float* ; <float*> [#uses=1]
%tmp82.sum = add i32 %i, %h ; [#uses=1]
%tmp80.sum = add i32 %tmp82.sum, %j ; [#uses=1]
%tmp78.sum = add i32 %tmp80.sum, %k ; [#uses=1]
%tmp84 = getelementptr float* %tmp77, i32 %tmp78.sum ; <float*> [#uses=1]
%tmp85 = load float* %tmp84 ; [#uses=1]
%tmp8586 = fptosi float %tmp85 to i32 ; [#uses=1]
ret i32 %tmp8586
}

@sunfishcode
Copy link
Member Author

That new LLVM code still isn't right. The g index is scaled now, but h, i, and j
are still being added without scaling.

@lattner
Copy link
Collaborator

lattner commented Mar 3, 2007

That explains the difference in codegen. Sorry, I was very tired last night. It looks like it requires multiple
subscripts to repro.

@lattner
Copy link
Collaborator

lattner commented Mar 3, 2007

Okay, here's the second half of the patch, which handles the ARRAY_REF array case (previous patch
handled ARRAY_REF pointer case):
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070226/045418.html

With this, we now compile:

int foo(int v, int w, int x, int y, int z,
float A[][w][x],
int g, int h, int i, int j, int k){
return A[g][10000][0];
}

into:

_foo:
movl 28(%esp), %eax
imull 8(%esp), %eax
leal 40000(,%eax,4), %eax
imull 12(%esp), %eax
movl 24(%esp), %ecx
cvttss2si (%ecx,%eax), %eax
ret

... which looks right to me.

GCC produces this, which is also right, but just worse code:

_foo:
movl 12(%esp), %eax
movl %eax, %edx
imull 8(%esp), %edx
imull $40000, %eax, %eax
imull 28(%esp), %edx
leal (%eax,%edx,4), %edx
movl 24(%esp), %eax
cvttss2si (%edx,%eax), %eax
ret 

We now compile your full case to:

_foo2:
movl 8(%esp), %eax
imull 28(%esp), %eax
addl 32(%esp), %eax
imull 12(%esp), %eax
addl 36(%esp), %eax
imull 16(%esp), %eax
addl 40(%esp), %eax
imull 20(%esp), %eax
addl 44(%esp), %eax
movl 24(%esp), %ecx
cvttss2si (%ecx,%eax,4), %eax
ret

GCC produces:

_foo2:
pushl %esi
movl 24(%esp), %eax
movl %eax, %ecx
imull 20(%esp), %ecx
imull 44(%esp), %eax
movl %ecx, %edx
imull 16(%esp), %edx
imull 40(%esp), %ecx
movl %edx, %esi
imull 36(%esp), %edx
imull 12(%esp), %esi
imull 32(%esp), %esi
addl %edx, %eax
addl %ecx, %eax
addl 48(%esp), %eax
sall $2, %eax
leal (%eax,%esi,4), %esi
movl 28(%esp), %eax
cvttss2si (%esi,%eax), %eax
popl %esi
ret

Please verify that the new codegen is correct. Thanks again,

-Chris

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 3, 2007

This still doesn't work on i686-pc-linux-gnu

@lattner
Copy link
Collaborator

lattner commented Mar 8, 2007

Is this still failing for you? It works for me, and this isn't target-specific code.

-Chris

@sunfishcode
Copy link
Member Author

The latest output posted for the full test case executes correctly for me on
i686-pc-linux-gnu in a simple program.

@lattner
Copy link
Collaborator

lattner commented Mar 13, 2007

Sounds good, I will assume it was just something transient in Reid's tree.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 3, 2021
troelsbjerre pushed a commit to troelsbjerre/llvm-project that referenced this issue Jan 10, 2024
…70d63b13dd51638c1424

[lldb] Make UBSan tests remote ready
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla llvm-tools All llvm tools that do not have corresponding tag miscompilation
Projects
None yet
Development

No branches or pull requests

3 participants