ref: 61f4c085c402af665b436f6d010d61107551d8a3
parent: a327175a3c01d18e3e4c061ce4579cc420ee3561
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Sep 30 18:50:42 EDT 2023
7c: fix constant propagation for negative 64-bit constants the issue is that MOVW $imm, R does not sign extend to 64-bit, leaving the upper 32 bit of the register as zeros. this means we have to be carefull when propagating negative constants across loads. add a "as" argument for the move instruction type, we can always substitute if we have the same move operation, then, we test for special cases where it doesnt matter. to reproduce the issue: void main(void) { long foobar = -1; vlong x = -1; print("%d\n", x == -1); } with the change: /fd/5:2,9 - /fd/4:2,10 RETURN TEXT main+0(SB),0,$32 MOVW $-1,R1 + MOV $-1,R3 MOV $.string<>+0(SB),R0 - CMN $1,R1 + CMN $1,R3 BNE 3(PC) MOVW $1,R5 B 2(PC)
--- a/sys/src/cmd/7c/gc.h
+++ b/sys/src/cmd/7c/gc.h
@@ -329,7 +329,7 @@
int subprop(Reg*);
int copyprop(Reg*);
int shiftprop(Reg*);
-void constprop(Adr*, Adr*, Reg*);
+void constprop(int, Adr*, Adr*, Reg*);
int copy1(Adr*, Adr*, Reg*, int);
int copyu(Prog*, Adr*, Adr*);
--- a/sys/src/cmd/7c/peep.c
+++ b/sys/src/cmd/7c/peep.c
@@ -286,7 +286,7 @@
if(p->as == AMOV || p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
if(regtyp(&p->to)) {
if(p->from.type == D_CONST || p->from.type == D_FCONST)
- constprop(&p->from, &p->to, r->s1);
+ constprop(p->as, &p->from, &p->to, r->s1);
else if(regtyp(&p->from))
if(p->from.type == p->to.type) {
if(copyprop(r)) {
@@ -898,7 +898,7 @@
* The v1->v2 should be eliminated by copy propagation.
*/
void
-constprop(Adr *c1, Adr *v1, Reg *r)
+constprop(int as, Adr *c1, Adr *v1, Reg *r)
{
Prog *p;
@@ -918,7 +918,8 @@
print("; merge; return\n");
return;
}
- if((p->as == AMOVW || p->as == AMOVWU || p->as == AMOV || p->as == AFMOVD || p->as == AFMOVS)
+ if((p->as == as || p->as == AMOVW || p->as == AMOVWU
+ || (p->as == AMOV && c1->offset >= 0)) /* immediate loads do not sign extend */
&& copyas(&p->from, c1)) {
if(debug['C'])
print("; sub%D/%D", &p->from, v1);
@@ -931,7 +932,7 @@
if(debug['C'])
print("\n");
if(r->s2)
- constprop(c1, v1, r->s2);
+ constprop(as, c1, v1, r->s2);
}
}