| /* &&foo should be hoisted, but on most targets, excess register pressure |
| forces it to be rematerialized before "data != &&foo". On targets that |
| have a "branch if registers are equal" instruction, this leads to the |
| branch having two LABEL_REFs: one for the branch target and one for |
| &&foo. When reloading &&foo into a register, reload would wrongly |
| say that &&foo was the target of the branch, and the real target would |
| then be removed as dead. */ |
| /* { dg-do link } */ |
| /* { dg-require-effective-target label_values } */ |
| #define NVARS 30 |
| #define MULTI(X) \ |
| X( 0), X( 1), X( 2), X( 3), X( 4), X( 5), X( 6), X( 7), X( 8), X( 9), \ |
| X(10), X(11), X(12), X(13), X(14), X(15), X(16), X(17), X(18), X(19), \ |
| X(20), X(21), X(22), X(23), X(24), X(25), X(26), X(27), X(28), X(29) |
| |
| #define DECLARE(INDEX) i##INDEX = gv[INDEX] |
| #define COPY(INDEX) gv[INDEX] = i##INDEX |
| |
| volatile int gv[NVARS]; |
| void *volatile data; |
| |
| int |
| main (void) |
| { |
| __label__ foo; |
| |
| if (gv[0] == 1) |
| goto foo; |
| data = &&foo; |
| do |
| { |
| int MULTI (DECLARE); |
| MULTI (COPY); |
| MULTI (COPY); |
| MULTI (COPY); |
| if (data != &&foo) |
| gv[0] = 1; |
| else |
| gv[1] = 2; |
| } |
| while (gv[0] > 0); |
| foo: |
| return 0; |
| } |