diff options
| author | 2023-06-26 00:29:07 +0200 | |
|---|---|---|
| committer | 2023-06-26 00:29:07 +0200 | |
| commit | b94fe89c9ddfcb85dcddebfd218fa7f00b8e6608 (patch) | |
| tree | 153c345c5811343bb0f8f5190ead67f9f70b0d97 /ir.h | |
| parent | bdb0276b534b817afb0b79f8e63196eed5d8bd7f (diff) | |
backend: fix mem2reg & regalloc
they were broken, especially for unstructured control flow. most
significant fix is to register allocator for temporaries that are used
before the first definition in the source order, e.g.:
@1:
%x = add %y, 1
b @3
@2
%y = ...
b @1
it's legal for %x to use %y there (assuming @2 dominates @1) but from
the point of view of the register allocator %y is defined and freed
and then used again, which broke things. the fix is to introduce phis
for this situation:
@1:
%y.1 = phi @2 %y
%x = add %y.1, 1
b @3
@2
%y = ...
b @1
then regalloc phi handling code makes it work
Diffstat (limited to 'ir.h')
| -rw-r--r-- | ir.h | 5 |
1 files changed, 5 insertions, 0 deletions
@@ -121,6 +121,7 @@ enum jumpkind { JXXX, Jb, Jret, }; struct block { int id; int npred; + int visit; union { struct block *_pred0; struct block **_pred; @@ -206,6 +207,7 @@ extern struct calltab {vec_of(struct call);} calltab; extern struct phitab {vec_of(union ref *);} phitab; extern struct dattab {vec_of(struct irdat);} dattab; extern struct addr addrht[]; +extern int visitmark; #define mkinstr(O, C, ...) ((struct instr) { .op = (O), .cls = (C), .reg=0, __VA_ARGS__ }) #define mkarginstr(ty, x) mkinstr(Oarg, 0, mktyperef(ty), (x)) void irinit(struct function *); @@ -240,6 +242,9 @@ void deluses(int ins); void delinstr(struct block *, int idx); void delphi(struct block *, int idx); void fillblkids(struct function *); +#define startbbvisit() (void)(++visitmark) +#define wasvisited(blk) ((blk)->visit == visitmark) +#define markvisited(blk) ((blk)->visit = visitmark) /* IR builder functions */ union ref addinstr(struct function *, struct instr); |