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

Spills of implicit-defs seem useless #32658

Closed
llvmbot opened this issue Jun 5, 2017 · 10 comments
Closed

Spills of implicit-defs seem useless #32658

llvmbot opened this issue Jun 5, 2017 · 10 comments
Labels
bugzilla Issues migrated from bugzilla llvm:regalloc

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Jun 5, 2017

Bugzilla Link 33311
Resolution FIXED
Resolved on Jun 05, 2017 16:49
Version trunk
OS Windows NT
Reporter LLVM Bugzilla Contributor
CC @MatzeB,@qcolombet,@stoklund

Extended Description

While analyzing the hottest function in SPEC2000/mesa I noticed the following code sequence:

str w8, sp,#260
str w8, sp,#244
str w8, sp,#256
str w8, sp,#248
str w8, sp,#252

str s1, sp,#284
str s1, sp,#280
str s1, sp,#288
str s1, sp,#276
str s1, sp,#272

At first it wasn't clear to me why these instructions weren't being paired by the load store optimizer. These stores are spills of implicit-defs being inserted by the register allocator. AFAICT these implicit-defs are coming from variables that are undefined on some path in the CFG. I think the fix would be to not spill these implicit-defs and update the register allocator's internal data structures accordingly, but this is well outside my area of expertise.

To better understand how frequently this issue occurs I inserted a statistic in the InlineSpiller to count the number of implicit-def spills. Across SPEC200X there were ~200 static spills of which 61 came from SPEC2000/mesa.

@qcolombet
Copy link
Collaborator

Hi Chad,

Thanks for the report.
Could you attach an LLVM-IR reproducer?

These stores are spills of implicit-defs being inserted by the register allocator.

Just from the sound of it that seems legit. If they are used later and can't live in register, we have to put them somewhere. The fact that they are undef on some path may hint some code gen problem, but it is not even sure.

Cheers,
Quentin

@MatzeB
Copy link
Contributor

MatzeB commented Jun 5, 2017

I just created a reproducer:

target triple="aarch64--"

@​g = external global i32

define i32 @​foobar() {
entry:
br i1 undef, label %if.then, label %if.end

if.then:
%ifv = load volatile i32, i32* @​g
call void asm sideeffect "", "{x0},{x1},{x2},{x3},{x4},{x5},{x6},{x7},{x8},{x9},{x10},{x11},{x12},{x13},{x14},{x15},{x16},{x17},{x18},{x19},{x20},{x21},{x22},{x23},{x24},{x25},{x26},{x27},{x28},{fp},~{lr}"() nounwind
br label %if.end

if.end:
%v = phi i32 [ undef, %entry ], [ %ifv, %if.then ]
call void asm sideeffect "", "{x0},{x1},{x2},{x3},{x4},{x5},{x6},{x7},{x8},{x9},{x10},{x11},{x12},{x13},{x14},{x15},{x16},{x17},{x18},{x19},{x20},{x21},{x22},{x23},{x24},{x25},{x26},{x27},{x28},{fp},~{lr}"() nounwind

store volatile i32 %v, i32* @​g
ret i32 42
}

@MatzeB
Copy link
Contributor

MatzeB commented Jun 5, 2017

Some points about this:

  • I wouldn't expect this to be too important for performance as this usually only affects paths leading into loops
  • It may be interesting for codesize (though 200 over the whole of SPEC isn't that much)
  • On the other hand I would expect this to be relatively easy to fix in the storeRegToStackSlot() implementation or ideally factor out the code using that with some general utility that checks for IMPLICIT_DEF first

@qcolombet
Copy link
Collaborator

I wonder if we actually want to fix that.

If I understand correctly, the complain is about spilling undef values, which actually come from the IR. I understand that undef don't need to be spilled by nature, but what about the developer while looking at his code?

Wouldn't they think, there is a reg alloc bug, the spill slot is not filed on blah path before being reloaded.

In the end, is this a real problem? (Garbage in, garbage out.)

Am I missing something?

@MatzeB
Copy link
Contributor

MatzeB commented Jun 5, 2017

In the end, is this a real problem? (Garbage in, garbage out.)

Not quite, sometimes a program contains paths that actually cannot happen in practice but the compiler cannot deduce that. A classical pattern would look like this:

int x;
if (InFooBarMode()) {
x = computeStuff();
} else {
// we should not spill x here
}
doOtherStuff();
if (inFooBarMode()) {
use(x);
}

I wouldn't say it's a big problem, but it's real and worth fixing.

@qcolombet
Copy link
Collaborator

In the end, is this a real problem? (Garbage in, garbage out.)

Not quite, sometimes a program contains paths that actually cannot happen in
practice but the compiler cannot deduce that. A classical pattern would look
like this:

int x;
if (InFooBarMode()) {
x = computeStuff();
} else {
// we should not spill x here
}
doOtherStuff();
if (inFooBarMode()) {
use(x);
}

I wouldn't say it's a big problem, but it's real and worth fixing.

Argh, I hate code written like that!
I would say they deserve what they get :).

Anyhow, will look.

@llvmbot
Copy link
Collaborator Author

llvmbot commented Jun 5, 2017

Some points about this:

  • I wouldn't expect this to be too important for performance as this usually
    only affects paths leading into loops

I have the same expectation, which is why I filed a bug rather than attempt a fix myself. That and the fact that this is outside of my area of expertise.

  • It may be interesting for codesize (though 200 over the whole of SPEC
    isn't that much)
  • On the other hand I would expect this to be relatively easy to fix in the
    storeRegToStackSlot() implementation or ideally factor out the code using
    that with some general utility that checks for IMPLICIT_DEF first

@llvmbot
Copy link
Collaborator Author

llvmbot commented Jun 5, 2017

I just created a reproducer:

target triple="aarch64--"

@​g = external global i32

define i32 @​foobar() {
entry:
br i1 undef, label %if.then, label %if.end

if.then:
%ifv = load volatile i32, i32* @​g
call void asm sideeffect "",
"{x0},{x1},{x2},{x3},{x4},{x5},{x6},{x7},{x8},{x9},{x10},{x11},
{x12},{x13},{x14},{x15},{x16},{x17},{x18},{x19},{x20},{x21},{x22},
{x23},{x24},
{x25},{x26},{x27},{x28},{fp},~{lr}"() nounwind
br label %if.end

if.end:
%v = phi i32 [ undef, %entry ], [ %ifv, %if.then ]
call void asm sideeffect "",
"{x0},{x1},{x2},{x3},{x4},{x5},{x6},{x7},{x8},{x9},{x10},{x11},
{x12},{x13},{x14},{x15},{x16},{x17},{x18},{x19},{x20},{x21},{x22},
{x23},{x24},
{x25},{x26},{x27},{x28},{fp},~{lr}"() nounwind

store volatile i32 %v, i32* @​g
ret i32 42
}

I can bugpoint you a test case from mesa, if you're still interested. Sorry for the belated response.

@qcolombet
Copy link
Collaborator

I can bugpoint you a test case from mesa, if you're still interested. Sorry
for the belated response.

That's fine, don't bother.
I am making the final testing and I'll push a fix shortly.

@qcolombet
Copy link
Collaborator

Fixed in r304752

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
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:regalloc
Projects
None yet
Development

No branches or pull requests

3 participants