parseref() has code to reuse address constants, but this is not done in other passes such as fold or isel. Introduce a new function newcon() which takes a Con and returns a Ref for that constant, and use this whenever creating address constants. This is necessary to fix folding of address constants when one operand is already folded. For example, in %a =l add $x, 1 %b =l add %a, 2 %c =w loadw %b %a and %b were folded to $x+1 and $x+3 respectively, but then the second add is visited again since it uses %a. This gets folded to $x+3 as well, but as a new distinct constant. This results in %b getting labeled as bottom instead of either constant, disabling the replacement of %b by a constant in subsequent instructions (such as the loadw).
Unified · Split
| @@ -431,6 +431,7 @@ int clsmerge(short *, short); · 430 unmodified lines | ||
| 431 | 431 | int phicls(int, Tmp *); |
| 432 | 432 | Ref newtmp(char *, int, Fn *); |
| 433 | 433 | void chuse(Ref, int, Fn *); |
| 434 | +Ref newcon(Con *, Fn *); | |
| 434 | 435 | Ref getcon(int64_t, Fn *); |
| 435 | 436 | int addcon(Con *, Con *); |
| 436 | 437 | void blit(Ref, uint, Ref, uint, Fn *); |
| @@ -117,12 +117,9 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) · 116 unmodified lines | ||
| 117 | 117 | m = &fn->mem[r0.val]; |
| 118 | 118 | if (req(m->base, R)) |
| 119 | 119 | if (m->offset.type == CAddr) { |
| 120 | − n = fn->ncon; | |
| 121 | − vgrow(&fn->con, ++fn->ncon); | |
| 122 | − fn->con[n] = m->offset; | |
| 123 | − m->offset.type = CUndef; | |
| 124 | 120 | r0 = newtmp("isel", Kl, fn); |
| 125 | − emit(Oaddr, Kl, r0, CON(n), R); | |
| 121 | + emit(Oaddr, Kl, r0, newcon(&m->offset, fn), R); | |
| 122 | + m->offset.type = CUndef; | |
| 126 | 123 | m->base = r0; |
| 127 | 124 | } |
| 128 | 125 | } |
| @@ -496,7 +496,7 @@ foldflt(Con *res, int op, int w, Con *cl, Con *cr) · 495 unmodified lines | ||
| 496 | 496 | static int |
| 497 | 497 | opfold(int op, int cls, Con *cl, Con *cr, Fn *fn) |
| 498 | 498 | { |
| 499 | − int nc; | |
| 499 | + Ref r; | |
| 500 | 500 | Con c; |
| 501 | 501 | |
| 502 | 502 | if ((op == Odiv || op == Oudiv |
| @@ -507,13 +507,7 @@ opfold(int op, int cls, Con *cl, Con *cr, Fn *fn) · 4 unmodified lines | ||
| 507 | 507 | return Bot; |
| 508 | 508 | } else |
| 509 | 509 | foldflt(&c, op, cls == Kd, cl, cr); |
| 510 | − if (c.type == CBits) | |
| 511 | − nc = getcon(c.bits.i, fn).val; | |
| 512 | − else { | |
| 513 | − nc = fn->ncon; | |
| 514 | − vgrow(&fn->con, ++fn->ncon); | |
| 515 | − } | |
| 510 | + r = newcon(&c, fn); | |
| 516 | 511 | assert(!(cls == Ks || cls == Kd) || c.flt); |
| 517 | − fn->con[nc] = c; | |
| 518 | − return nc; | |
| 512 | + return r.val; | |
| 519 | 513 | } |
| @@ -118,7 +118,8 @@ load(Slice sl, bits msk, Loc *l) · 117 unmodified lines | ||
| 118 | 118 | { |
| 119 | 119 | Alias *a; |
| 120 | 120 | Ref r, r1; |
| 121 | − int ld, cls, all, c; | |
| 121 | + int ld, cls, all; | |
| 122 | + Con c; | |
| 122 | 123 | |
| 123 | 124 | ld = (int[]){ |
| 124 | 125 | [1] = Oloadub, |
| @@ -151,13 +152,11 @@ load(Slice sl, bits msk, Loc *l) · 26 unmodified lines | ||
| 151 | 152 | break; |
| 152 | 153 | case ACon: |
| 153 | 154 | case ASym: |
| 154 | − c = curf->ncon++; | |
| 155 | − vgrow(&curf->con, curf->ncon); | |
| 156 | − curf->con[c].type = CAddr; | |
| 157 | − curf->con[c].label = a->label; | |
| 158 | − curf->con[c].bits.i = a->offset; | |
| 159 | − curf->con[c].local = 0; | |
| 160 | − r = CON(c); | |
| 155 | + c.type = CAddr; | |
| 156 | + c.label = a->label; | |
| 157 | + c.bits.i = a->offset; | |
| 158 | + c.local = 0; | |
| 159 | + r = newcon(&c, curf); | |
| 161 | 160 | break; |
| 162 | 161 | } |
| 163 | 162 | } |
| @@ -381,7 +381,6 @@ static Ref · 380 unmodified lines | ||
| 381 | 381 | parseref() |
| 382 | 382 | { |
| 383 | 383 | Con c; |
| 384 | − int i; | |
| 385 | 384 | |
| 386 | 385 | memset(&c, 0, sizeof c); |
| 387 | 386 | switch (next()) { |
| @@ -405,14 +404,7 @@ parseref() · 17 unmodified lines | ||
| 405 | 404 | c.type = CAddr; |
| 406 | 405 | c.label = intern(tokval.str); |
| 407 | 406 | Look: |
| 408 | − for (i=0; i<curf->ncon; i++) | |
| 409 | − if (curf->con[i].type == c.type | |
| 410 | − && curf->con[i].bits.i == c.bits.i | |
| 411 | − && curf->con[i].label == c.label) | |
| 412 | − return CON(i); | |
| 413 | − vgrow(&curf->con, ++curf->ncon); | |
| 414 | − curf->con[i] = c; | |
| 415 | − return CON(i); | |
| 407 | + return newcon(&c, curf); | |
| 416 | 408 | default: |
| 417 | 409 | return R; |
| 418 | 410 | } |
| @@ -349,6 +349,25 @@ chuse(Ref r, int du, Fn *fn) · 348 unmodified lines | ||
| 349 | 349 | fn->tmp[r.val].nuse += du; |
| 350 | 350 | } |
| 351 | 351 | |
| 352 | +Ref | |
| 353 | +newcon(Con *c0, Fn *fn) | |
| 354 | +{ | |
| 355 | + Con *c1; | |
| 356 | + int i; | |
| 357 | + | |
| 358 | + for (i=0; i<fn->ncon; i++) { | |
| 359 | + c1 = &fn->con[i]; | |
| 360 | + if (c0->type == c1->type | |
| 361 | + && c0->bits.i == c1->bits.i | |
| 362 | + && c0->label == c1->label | |
| 363 | + && c0->local == c1->local) | |
| 364 | + return CON(i); | |
| 365 | + } | |
| 366 | + vgrow(&fn->con, ++fn->ncon); | |
| 367 | + fn->con[i] = *c0; | |
| 368 | + return CON(i); | |
| 369 | +} | |
| 370 | + | |
| 352 | 371 | Ref |
| 353 | 372 | getcon(int64_t val, Fn *fn) |
| 354 | 373 | { |