120 likes | 238 Views
Languages and Compiler Design II IR Canonicalization. Material provided by Prof. Jingke Li Stolen with pride and modified by Herb Mayer PSU Spring 2010 rev.: 4/16/2010. Agenda. Definition Problems with IR Representation IR Tree Canonicalization Implementation Handling CALL Nodes
E N D
Languages and Compiler Design IIIR Canonicalization Material provided by Prof. Jingke Li Stolen with pride and modified by Herb Mayer PSU Spring 2010 rev.: 4/16/2010 CS322
Agenda • Definition • Problems with IR Representation • IR Tree Canonicalization • Implementation • Handling CALL Nodes • Handling Other EXP Nodes • Handling STMT Nodes CS322
Definition • Definition: In Computer Science, canonicalization is the formal process of converting data with more than one representation from one into another, "standard“ ( or "normal", or canonical) form of representation • Sometimes abbreviated c14n, where 14 represents the number of letters between the ‘c’ and ‘n’. Synonyms are standardization or normalization • Not to be confused with the process in the Catholic Church of declaring a person a saint = canonization CS322
Problems with IR Representation Two areas in our IR tree language may cause representational problems: • Multiple CALL nodes within the same expression may cause problems with call-related register usage when mapped to lower-level code • ESEQ and CALL nodes within expressions may bring side effects to different evaluation orders of sub-expressions, causing problems for low-level optimizations CS322
IR Tree Canonicalization To resolve these problems, we could perform tree canonicalization: • Assign each return value immediately into a TEMP; turn a CALL node into an ESEQ node: (CALL (NAME f) ((CONST 1))) => (ESEQ [MOVE (TEMP 100) (CALL (NAME f) ((CONST 1)))] (TEMP 100)) • Pull statements in ESEQ nodes out of an expression tree, effectively eliminating all ESEQ nodes: [ASSIGN (TEMP 101) (BINOP + (CONST 2) (CALL (NAME f) ((CONST 1))))] => [ASSIGN (TEMP 101) (BINOP + (CONST 2) (ESEQ [MOVE (TEMP 100) (CALL (NAME f) ((CONST 1)))] (TEMP 100)))] => [MOVE (TEMP 100) (CALL (NAME f) ((CONST 1)))] [ASSIGN (TEMP 101) (BINOP + (CONST 2) (TEMP 100))] The resulting tree is called a canonical IR tree CS322
Implementation Canonicalization can be implemented as a visitor program over IR trees. Visitor touches every expression node, extracts statements out, and up-levels them. public class Canon implements IrVI { public PROG visit( PROG t ) { return new PROG(t.funcs.accept(this)); } //end PROG public FUNClist visit( FUNClist t ) { FUNClist funcs = new FUNClist(); for( int i = 0; i < t.size(); i++ ) { funcs.add(((FUNC) t.elementAt( I )).accept( this )); } //end for return funcs; } //end FUNClist public FUNC visit( FUNC t ) { return new FUNC( t.label, t.varCnt, t.argCnt, (STMTlist) t.stmts.accept(this)); } //end FUNC } //end Canon CS322
Handling CALL Nodes New temp saves return value; then replace the node with an ESEQ node: public EXP visit( CALL t ) { EXP args = t.args.accept( this ); STMT s = getStmt(args); TEMP tmp = new TEMP(); STMT s1 = new MOVE( tmp, new CALL( t.func, (EXPlist) getExp( args ))); return new ESEQ( mergeStmts( s, s1 ), tmp ); } //end EXP private STMT getStmt( EXP e ) { if( e instanceof ESEQ) return ((ESEQ) e).stmt; return null; } //end STMT private EXP getExp( EXP e ) { if( e instanceof ESEQ ) return(( ESEQ ) e ).exp; return e; } //end EXPs CS322
Handling Other EXP Nodes Assuming components are commutative. public EXP visit( MEM t ) { EXP exp = t.exp.accept( this ); STMT s = getStmt( exp ); if( s != null ) return new ESEQ(s, new MEM( getExp(exp) )); return t; } //end EXP public EXP visit( BINOP t ) { EXP left = t.left.accept( this ); EXP right = t.right.accept( this ); STMT s = mergeStmts(getStmt( left ), getStmt( right )); if( s != null ) return new ESEQ(s, new BINOP( t.op, getExp( left ), getExp( right ))); return t; } //end EXP CS322
Handling Other EXP Nodes, Cont’d public EXP visit( EXPlist t ) { STMT s = null; EXPlist args = new EXPlist(); for( int i = 0; i < t.size(); i++ ) { EXP e = ((EXP) t.elementAt(i)).accept( this ); STMT s1 = getStmt(e); if( s1 != null ) s = mergeStmts( s, s1 ); args.add( getExp( e )); } //end for if( s != null ) return new ESEQ(s, args); return t; } //end EXP public EXP visit( ESEQ t ) { STMT stmt = t.stmt.accept(this); EXP exp = t.exp.accept(this); STMT s = mergeStmts(stmt, getStmt(exp)); if( s != null ) return new ESEQ( s, getExp( exp )); return t; } //end EXP CS322
Handling STMT Nodes public STMT visit( MOVE t ) { EXP dst = t.dst.accept(this); EXP src = t.src.accept(this); STMT s = mergeStmts( getStmt(dst), getStmt(src) ); if( s != null) return mergeStmts( s, new MOVE(getExp(dst), getExp(src))); return t; } //end STMT public STMT visit( CJUMP t ) { EXP left = t.left.accept( this ); EXP right = t.right.accept( this ); STMT s = mergeStmts(getStmt( left ), getStmt( right )); if( s != null) return mergeStmts(s, new CJUMP( t.op, getExp(left), getExp( right ), t.target )); return t; } //end STMT CS322
Handling STMT Nodes, Cont’d public STMT visit(CALLST t) { EXP args = t.args.accept(this); STMT s = getStmt(args); if( s != null ) return mergeStmts( s, new CALLST( t.func, (EXPlist) getExp( args ))); return t; } //end STMT public STMT visit(RETURN t) { EXP exp = t.exp.accept(this); STMT s = getStmt(exp); if( s != null ) return mergeStmts(s, new RETURN( getExp( exp ) )); return t; } //end STMT CS322