128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Factor
		
	
	
! Copyright (C) 2010 Slava Pestov.
 | 
						|
! See http://factorcode.org/license.txt for BSD license.
 | 
						|
USING: accessors combinators combinators.short-circuit
 | 
						|
compiler.cfg.hats compiler.cfg.instructions
 | 
						|
compiler.cfg.utilities compiler.cfg.value-numbering.graph
 | 
						|
compiler.cfg.value-numbering.math
 | 
						|
compiler.cfg.value-numbering.rewrite cpu.architecture fry kernel
 | 
						|
make math sequences ;
 | 
						|
IN: compiler.cfg.value-numbering.alien
 | 
						|
 | 
						|
M: ##box-displaced-alien rewrite
 | 
						|
    dup displacement>> vreg>insn zero-insn?
 | 
						|
    [ [ dst>> ] [ base>> ] bi <copy> ] [ drop f ] if ;
 | 
						|
 | 
						|
! ##box-displaced-alien f 1 2 3 <class>
 | 
						|
! ##unbox-c-ptr 4 1 <class>
 | 
						|
! =>
 | 
						|
! ##box-displaced-alien f 1 2 3 <class>
 | 
						|
! ##unbox-c-ptr 5 3 <class>
 | 
						|
! ##add 4 5 2
 | 
						|
 | 
						|
: rewrite-unbox-alien ( insn box-insn -- insn )
 | 
						|
    [ dst>> ] [ src>> ] bi* <copy> ;
 | 
						|
 | 
						|
: rewrite-unbox-displaced-alien ( insn box-insn -- insns )
 | 
						|
    [
 | 
						|
        [ dst>> ]
 | 
						|
        [ [ base>> ] [ base-class>> ] [ displacement>> ] tri ] bi*
 | 
						|
        [ ^^unbox-c-ptr ] dip
 | 
						|
        ##add,
 | 
						|
    ] { } make ;
 | 
						|
 | 
						|
: rewrite-unbox-any-c-ptr ( insn -- insn/f )
 | 
						|
    dup src>> vreg>insn
 | 
						|
    {
 | 
						|
        { [ dup ##box-alien? ] [ rewrite-unbox-alien ] }
 | 
						|
        { [ dup ##box-displaced-alien? ] [ rewrite-unbox-displaced-alien ] }
 | 
						|
        [ 2drop f ]
 | 
						|
    } cond ;
 | 
						|
 | 
						|
M: ##unbox-any-c-ptr rewrite rewrite-unbox-any-c-ptr ;
 | 
						|
 | 
						|
M: ##unbox-alien rewrite rewrite-unbox-any-c-ptr ;
 | 
						|
 | 
						|
! Fuse ##add-imm into ##load-memory(-imm) and ##store-memory(-imm)
 | 
						|
! just update the offset in the instruction
 | 
						|
: fuse-base-offset? ( insn -- ? )
 | 
						|
    base>> vreg>insn ##add-imm? ;
 | 
						|
 | 
						|
: fuse-base-offset ( insn -- insn' )
 | 
						|
    dup base>> vreg>insn
 | 
						|
    [ src1>> ] [ src2>> ] bi
 | 
						|
    [ >>base ] [ '[ _ + ] change-offset ] bi* ;
 | 
						|
 | 
						|
! Fuse ##add-imm into ##load-memory and ##store-memory
 | 
						|
! just update the offset in the instruction
 | 
						|
: fuse-displacement-offset? ( insn -- ? )
 | 
						|
    { [ scale>> 0 = ] [ displacement>> vreg>insn ##add-imm? ] } 1&& ;
 | 
						|
 | 
						|
: fuse-displacement-offset ( insn -- insn' )
 | 
						|
    dup displacement>> vreg>insn
 | 
						|
    [ src1>> ] [ src2>> ] bi
 | 
						|
    [ >>displacement ] [ '[ _ + ] change-offset ] bi* ;
 | 
						|
 | 
						|
! Fuse ##add into ##load-memory-imm and ##store-memory-imm
 | 
						|
! construct a new ##load-memory or ##store-memory with the
 | 
						|
! ##add's operand as the displacement
 | 
						|
: fuse-displacement? ( insn -- ? )
 | 
						|
    {
 | 
						|
        [ offset>> 0 = complex-addressing? or ]
 | 
						|
        [ base>> vreg>insn ##add? ]
 | 
						|
    } 1&& ;
 | 
						|
 | 
						|
GENERIC: alien-insn-value ( insn -- value )
 | 
						|
 | 
						|
M: ##load-memory-imm alien-insn-value dst>> ;
 | 
						|
M: ##store-memory-imm alien-insn-value src>> ;
 | 
						|
 | 
						|
GENERIC: new-alien-insn ( value base displacement scale offset rep c-type insn -- insn )
 | 
						|
 | 
						|
M: ##load-memory-imm new-alien-insn drop ##load-memory new-insn ;
 | 
						|
M: ##store-memory-imm new-alien-insn drop ##store-memory new-insn ;
 | 
						|
 | 
						|
: fuse-displacement ( insn -- insn' )
 | 
						|
    {
 | 
						|
        [ alien-insn-value ]
 | 
						|
        [ base>> vreg>insn [ src1>> ] [ src2>> ] bi ]
 | 
						|
        [ drop 0 ]
 | 
						|
        [ offset>> ]
 | 
						|
        [ rep>> ]
 | 
						|
        [ c-type>> ]
 | 
						|
        [ ]
 | 
						|
    } cleave new-alien-insn ;
 | 
						|
 | 
						|
! Fuse ##shl-imm into ##load-memory or ##store-memory
 | 
						|
: scale-insn? ( insn -- ? )
 | 
						|
    { [ ##shl-imm? ] [ src2>> { 1 2 3 } member? ] } 1&& ;
 | 
						|
 | 
						|
: fuse-scale? ( insn -- ? )
 | 
						|
    { [ scale>> 0 = ] [ displacement>> vreg>insn scale-insn? ] } 1&& ;
 | 
						|
 | 
						|
: fuse-scale ( insn -- insn' )
 | 
						|
    dup displacement>> vreg>insn
 | 
						|
    [ src1>> ] [ src2>> ] bi
 | 
						|
    [ >>displacement ] [ >>scale ] bi* ;
 | 
						|
 | 
						|
: rewrite-memory-op ( insn -- insn/f )
 | 
						|
    complex-addressing? [
 | 
						|
        {
 | 
						|
            { [ dup fuse-base-offset? ] [ fuse-base-offset ] }
 | 
						|
            { [ dup fuse-displacement-offset? ] [ fuse-displacement-offset ] }
 | 
						|
            { [ dup fuse-scale? ] [ fuse-scale ] }
 | 
						|
            [ drop f ]
 | 
						|
        } cond
 | 
						|
    ] [ drop f ] if ;
 | 
						|
 | 
						|
: rewrite-memory-imm-op ( insn -- insn/f )
 | 
						|
    {
 | 
						|
        { [ dup fuse-base-offset? ] [ fuse-base-offset ] }
 | 
						|
        { [ dup fuse-displacement? ] [ fuse-displacement ] }
 | 
						|
        [ drop f ]
 | 
						|
    } cond ;
 | 
						|
 | 
						|
M: ##load-memory rewrite rewrite-memory-op ;
 | 
						|
M: ##load-memory-imm rewrite rewrite-memory-imm-op ;
 | 
						|
M: ##store-memory rewrite rewrite-memory-op ;
 | 
						|
M: ##store-memory-imm rewrite rewrite-memory-imm-op ;
 |