Sfoglia il codice sorgente

fix edge deletion bug in sccp

When an edge is deleted, the phis and predecessors of the
destination block have to be updated.  This is what blkdel()
was doing, but at a level too coarse.  The new function
edgedel() allows to remove a single edge (and takes care of
multiple edges).
Quentin Carbonneaux 8 anni fa
parent
commit
8215b50a10
3 ha cambiato i file con 34 aggiunte e 28 eliminazioni
  1. 1 1
      all.h
  2. 25 23
      cfg.c
  3. 8 4
      fold.c

+ 1 - 1
all.h

@@ -547,7 +547,7 @@ void err(char *, ...) __attribute__((noreturn));
 
 
 /* cfg.c */
 /* cfg.c */
 Blk *blknew(void);
 Blk *blknew(void);
-void blkdel(Blk *);
+void edgedel(Blk *, Blk **);
 void fillpreds(Fn *);
 void fillpreds(Fn *);
 void fillrpo(Fn *);
 void fillrpo(Fn *);
 void filldom(Fn *);
 void filldom(Fn *);

+ 25 - 23
cfg.c

@@ -12,32 +12,33 @@ blknew()
 }
 }
 
 
 void
 void
-blkdel(Blk *b)
+edgedel(Blk *bs, Blk **pbd)
 {
 {
-	Blk *s, **ps, *succ[3];
+	Blk *bd;
 	Phi *p;
 	Phi *p;
 	uint a;
 	uint a;
+	int mult;
 
 
-	succ[0] = b->s1;
-	succ[1] = b->s2 == b->s1 ? 0 : b->s2;
-	succ[2] = 0;
-	for (ps=succ; (s=*ps); ps++) {
-		for (p=s->phi; p; p=p->link) {
-			for (a=0; p->blk[a]!=b; a++)
-				assert(a+1<p->narg);
-			p->narg--;
-			memmove(&p->blk[a], &p->blk[a+1],
-				sizeof p->blk[0] * (p->narg-a));
-			memmove(&p->arg[a], &p->arg[a+1],
-				sizeof p->arg[0] * (p->narg-a));
-		}
-		if (s->npred != 0) {
-			for (a=0; s->pred[a]!=b; a++)
-				assert(a+1<s->npred);
-			s->npred--;
-			memmove(&s->pred[a], &s->pred[a+1],
-				sizeof s->pred[0] * (s->npred-a));
-		}
+	bd = *pbd;
+	mult = 1 + (bs->s1 == bs->s2);
+	*pbd = 0;
+	if (!bd || mult > 1)
+		return;
+	for (p=bd->phi; p; p=p->link) {
+		for (a=0; p->blk[a]!=bs; a++)
+			assert(a+1<p->narg);
+		p->narg--;
+		memmove(&p->blk[a], &p->blk[a+1],
+			sizeof p->blk[0] * (p->narg-a));
+		memmove(&p->arg[a], &p->arg[a+1],
+			sizeof p->arg[0] * (p->narg-a));
+	}
+	if (bd->npred != 0) {
+		for (a=0; bd->pred[a]!=bs; a++)
+			assert(a+1<bd->npred);
+		bd->npred--;
+		memmove(&bd->pred[a], &bd->pred[a+1],
+			sizeof bd->pred[0] * (bd->npred-a));
 	}
 	}
 }
 }
 
 
@@ -110,7 +111,8 @@ fillrpo(Fn *f)
 	f->rpo = alloc(f->nblk * sizeof f->rpo[0]);
 	f->rpo = alloc(f->nblk * sizeof f->rpo[0]);
 	for (p=&f->start; (b=*p);) {
 	for (p=&f->start; (b=*p);) {
 		if (b->id == -1u) {
 		if (b->id == -1u) {
-			blkdel(b);
+			edgedel(b, &b->s1);
+			edgedel(b, &b->s2);
 			*p = b->link;
 			*p = b->link;
 		} else {
 		} else {
 			b->id -= n;
 			b->id -= n;

+ 8 - 4
fold.c

@@ -275,7 +275,8 @@ fold(Fn *fn)
 			d = 1;
 			d = 1;
 			if (debug['F'])
 			if (debug['F'])
 				fprintf(stderr, "%s ", b->name);
 				fprintf(stderr, "%s ", b->name);
-			blkdel(b);
+			edgedel(b, &b->s1);
+			edgedel(b, &b->s2);
 			*pb = b->link;
 			*pb = b->link;
 			continue;
 			continue;
 		}
 		}
@@ -296,11 +297,14 @@ fold(Fn *fn)
 					renref(&i->arg[n]);
 					renref(&i->arg[n]);
 		renref(&b->jmp.arg);
 		renref(&b->jmp.arg);
 		if (b->jmp.type == Jjnz && rtype(b->jmp.arg) == RCon) {
 		if (b->jmp.type == Jjnz && rtype(b->jmp.arg) == RCon) {
-				b->jmp.type = Jjmp;
-				if (czero(&fn->con[b->jmp.arg.val], 0))
+				if (czero(&fn->con[b->jmp.arg.val], 0)) {
+					edgedel(b, &b->s1);
 					b->s1 = b->s2;
 					b->s1 = b->s2;
+					b->s2 = 0;
+				} else
+					edgedel(b, &b->s2);
+				b->jmp.type = Jjmp;
 				b->jmp.arg = R;
 				b->jmp.arg = R;
-				b->s2 = 0;
 		}
 		}
 		pb = &b->link;
 		pb = &b->link;
 	}
 	}