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

[mips] After a26f1bf67ec, Bad machine code: Using an undefined physical register #51033

Closed
DimitryAndric opened this issue Aug 31, 2021 · 12 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla

Comments

@DimitryAndric
Copy link
Collaborator

Bugzilla Link 51691
Resolution FIXED
Resolved on Oct 22, 2021 00:34
Version trunk
OS All
Blocks #50580 #51489
CC @emaste,@jrtc27,@LebedevRI,@arsenm,@nickdesaulniers,@atanasyan,@tstellar
Fixed by commit(s) f5755c0 47f53ee

Extended Description

This backend error appeared when compiling the FreeBSD base system for mips or mips64 with clang 13:

*** Bad machine code: Using an undefined physical register ***

  • function: checkfstab
  • basic block: %bb.27 if.end51 (0x80768a568)
  • instruction: %161:gpr32 = COPY $v1
  • operand 1: $v1
    fatal error: error in backend: Found 1 machine code errors.

Bisection shows this error starts occurring after a26f1bf67ec ("[PassManager] Run additional LICM before LoopRotate "), so I am suspecting that this exposes a latent bug somewhere in the Mips backend? (As these test cases seem to work fine on other architectures.)

Minimized test case for 32-bit mips:

// clang -cc1 -triple mips-- -S -mrelocation-model static -target-cpu mips2 -O2 preen-min.c
typedef struct {
int a[0];
} b;
b c;
extern _Thread_local b *d;
int e, f, ay;
struct {
int g;
int h;
} * k;
char *ax;
b *l() {
if (d)
return d;
return &c;
}
int m() {
int i = 0, j = i;
f = l()->a[j];
return e;
}
char *n();
void o();
void q() {
if (k)
o(&k->h, k);
}
void o(char *r, int *s, int *t) {
char aw = *s;
char *p = n();
if (p)
p = &aw;
for (; *p && m(); p++)
for (; 0; ay = *t)
;
ax = r;
}

Minimized test case for 64-bit mips (looking very similar, though derived from a very different source file):

// clang -cc1 -triple mips64-- -S -target-cpu mips3 -O2 -ftls-model=initial-exec tw-min.c
typedef struct {
int a[0];
} b;
b *c;
extern _Thread_local b *d;
int e, f;
b *g() {
if (d)
return d;
return c;
}
int h(j) {
int i = j;
e = g()->a[i];
return 1;
}
void k() {
int *a;
for (a = 0; f;)
if (0 ?: h) {
int b;
a++;
if (*a) {
b = 0;
a++;
}
for (; h(*a);)
;
}
}

@DimitryAndric
Copy link
Collaborator Author

assigned to @jrtc27

@nickdesaulniers
Copy link
Member

*** Bad machine code: Using an undefined physical register ***

  • instruction: %161:gpr32 = COPY $v1
    so I am suspecting that this exposes a latent bug somewhere in the Mips backend?

Yes; it looks like an error from the backend where it expected a physical register. Register allocation should be turning all virtual registers into physical registers.

If you do clang ... -mllvm -print-after-all 2>&1 | less then grep through Dump After, you should be able to determine which pass either introduces that instruction, or if register allocation somehow leaves that register unallocated.

It could be that a pass is being run after register allocation that thinks it's still permitted to use virtual registers, but I'm pretty sure that's not allowed.

Bisection shows this error starts occurring after a26f1bf67ec ("[PassManager] Run additional LICM before LoopRotate "),

That a change to middle end optimization pass orderings exposed a bug in the backend is likely just a red herring. Thanks for taking the time to report though with reproducers!

@DimitryAndric
Copy link
Collaborator Author

*** Bad machine code: Using an undefined physical register ***

  • instruction: %161:gpr32 = COPY $v1
    so I am suspecting that this exposes a latent bug somewhere in the Mips backend?

Yes; it looks like an error from the backend where it expected a physical
register. Register allocation should be turning all virtual registers into
physical registers.

If you do clang ... -mllvm -print-after-all 2>&1 | less then grep through
Dump After, you should be able to determine which pass either introduces
that instruction, or if register allocation somehow leaves that register
unallocated.

The last "Dump After" lines are:

*** IR Dump After Live Stack Slot Analysis (livestacks) ***:

*** IR Dump After Virtual Register Map (virtregmap) ***:

*** IR Dump After Live Register Matrix (liveregmatrix) ***:

so that Live Register Matrix seems a pretty likely candidate. :)

@jrtc27
Copy link
Collaborator

jrtc27 commented Sep 27, 2021

Undefined physical register means that the register in question does not have a live definition at time of use (and is not reserved).

@jrtc27
Copy link
Collaborator

jrtc27 commented Sep 27, 2021

@jrtc27
Copy link
Collaborator

jrtc27 commented Sep 27, 2021

Ok it looks like the generated use of $v1 straddles a PseudoSELECT_I, whose expansion splits the basic block into multiple, and then dead-mi-elimination thinks the definition in an earlier basic block is dead. Presumably the expansion is missing a recompilation of live-ins/outs of the basic blocks in question.

@jrtc27
Copy link
Collaborator

jrtc27 commented Oct 17, 2021

@DimitryAndric
Copy link
Collaborator Author

Fixed by f5755c0, thanks!

@jrtc27
Copy link
Collaborator

jrtc27 commented Oct 19, 2021

Not fixed in 13 though, so that's still affected. Don't know if this should stay open until it's back ported, otherwise it might be lost as a blocking bug of the 13.0.1 release?

@DimitryAndric
Copy link
Collaborator Author

Oh right, let's keep it open then, so it gets the attention of the 13.0.1 release manager (Tom ?)

@tstellar
Copy link
Collaborator

Merged: 47f53ee

@tstellar
Copy link
Collaborator

mentioned in issue #51489

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

No branches or pull requests

4 participants