code: plan9front

Download patch

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);
 	}
 }