compiler.cfg: use x86 TEST instruction to optimize 'bitand 0 ='

db4
Slava Pestov 2010-05-14 08:14:22 -04:00
parent 22625469bc
commit 5a67711bfd
9 changed files with 481 additions and 21 deletions

View File

@ -713,6 +713,14 @@ INSN: ##compare-integer-imm-branch
use: src1/int-rep
literal: src2 cc ;
INSN: ##test-branch
use: src1/int-rep src2/int-rep
literal: cc ;
INSN: ##test-imm-branch
use: src1/int-rep
literal: src2 cc ;
PURE-INSN: ##compare-integer
def: dst/tagged-rep
use: src1/int-rep src2/int-rep
@ -725,6 +733,18 @@ use: src1/int-rep
literal: src2 cc
temp: temp/int-rep ;
PURE-INSN: ##test
def: dst/tagged-rep
use: src1/int-rep src2/int-rep
literal: cc
temp: temp/int-rep ;
PURE-INSN: ##test-imm
def: dst/tagged-rep
use: src1/int-rep
literal: src2 cc
temp: temp/int-rep ;
! Float conditionals
INSN: ##compare-float-ordered-branch
use: src1/double-rep src2/double-rep
@ -798,6 +818,8 @@ UNION: conditional-branch-insn
##compare-imm-branch
##compare-integer-branch
##compare-integer-imm-branch
##test-branch
##test-imm-branch
##compare-float-ordered-branch
##compare-float-unordered-branch
##test-vector-branch

View File

@ -211,24 +211,48 @@ M: ##compare-integer-imm optimize-insn
[ call-next-method ]
} cond ;
M: ##test-imm optimize-insn
{
{ [ dup { [ src1-tagged? ] [ src2-tagged-bitwise? ] } 1&& ] [ >tagged-imm ] }
[ call-next-method ]
} cond ;
M: ##compare-integer-imm-branch optimize-insn
{
{ [ dup { [ src1-tagged? ] [ src2-tagged-arithmetic? ] } 1&& ] [ >tagged-imm ] }
[ call-next-method ]
} cond ;
M: ##test-imm-branch optimize-insn
{
{ [ dup { [ src1-tagged? ] [ src2-tagged-bitwise? ] } 1&& ] [ >tagged-imm ] }
[ call-next-method ]
} cond ;
M: ##compare-integer optimize-insn
{
{ [ dup { [ src1-tagged? ] [ src2-tagged? ] } 1&& ] [ unchanged ] }
[ call-next-method ]
} cond ;
M: ##test optimize-insn
{
{ [ dup { [ src1-tagged? ] [ src2-tagged? ] } 1&& ] [ unchanged ] }
[ call-next-method ]
} cond ;
M: ##compare-integer-branch optimize-insn
{
{ [ dup { [ src1-tagged? ] [ src2-tagged? ] } 1&& ] [ unchanged ] }
[ call-next-method ]
} cond ;
M: ##test-branch optimize-insn
{
{ [ dup { [ src1-tagged? ] [ src2-tagged? ] } 1&& ] [ unchanged ] }
[ call-next-method ]
} cond ;
! Identities:
! tag(neg(untag(x))) = x
! tag(neg(x)) = x * -2^tag-bits

View File

@ -632,7 +632,23 @@ cpu x86.64? [
} test-peephole
] unit-test
! Tag/untag elimination for ##compare-integer
! Tag/untag elimination for ##compare-integer and ##test
[
V{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##test f 2 0 1 cc= }
T{ ##replace f 2 D 0 }
}
] [
V{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##test f 2 0 1 cc= }
T{ ##replace f 2 D 0 }
} test-peephole
] unit-test
[
V{
T{ ##peek f 0 D 0 }
@ -663,6 +679,20 @@ cpu x86.64? [
} test-peephole
] unit-test
[
V{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##test-branch f 0 1 cc= }
}
] [
V{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##test-branch f 0 1 cc= }
} test-peephole
] unit-test
[
V{
T{ ##peek f 0 D 0 }
@ -677,6 +707,20 @@ cpu x86.64? [
} test-peephole
] unit-test
[
V{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##test-imm-branch f 0 $[ 10 tag-fixnum ] cc= }
}
] [
V{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##test-imm-branch f 0 10 cc= }
} test-peephole
] unit-test
! Tag/untag elimination for ##neg
[
V{

View File

@ -123,6 +123,10 @@ M: ##compare-integer-imm has-peephole-opts? drop t ;
M: ##compare-integer has-peephole-opts? drop t ;
M: ##compare-integer-imm-branch has-peephole-opts? drop t ;
M: ##compare-integer-branch has-peephole-opts? drop t ;
M: ##test-imm has-peephole-opts? drop t ;
M: ##test has-peephole-opts? drop t ;
M: ##test-imm-branch has-peephole-opts? drop t ;
M: ##test-branch has-peephole-opts? drop t ;
GENERIC: compute-insn-costs ( insn -- )

View File

@ -1,8 +1,11 @@
! Copyright (C) 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators kernel math math.order namespaces
sequences vectors combinators.short-circuit compiler.cfg
compiler.cfg.comparisons compiler.cfg.instructions
sequences vectors combinators.short-circuit
cpu.architecture
compiler.cfg
compiler.cfg.comparisons
compiler.cfg.instructions
compiler.cfg.registers
compiler.cfg.value-numbering.math
compiler.cfg.value-numbering.graph
@ -34,6 +37,23 @@ IN: compiler.cfg.value-numbering.comparisons
[ src1>> vreg>integer ] [ src2>> ] [ cc>> ] tri
[ <=> ] dip evaluate-cc ;
: fold-test-imm? ( insn -- ? )
src1>> vreg>insn ##load-integer? ;
: evaluate-test-imm ( insn -- ? )
[ src1>> vreg>integer ] [ src2>> ] [ cc>> ] tri
[ bitand ] dip {
{ cc= [ 0 = ] }
{ cc/= [ 0 = not ] }
} case ;
: rewrite-into-test? ( insn -- ? )
{
[ drop test-instruction? ]
[ cc>> { cc= cc/= } member-eq? ]
[ src2>> 0 = ]
} 1&& ;
: >compare< ( insn -- in1 in2 cc )
[ src1>> ] [ src2>> ] [ cc>> ] tri ; inline
@ -50,6 +70,8 @@ UNION: scalar-compare-insn
##compare-imm
##compare-integer
##compare-integer-imm
##test
##test-imm
##compare-float-unordered
##compare-float-ordered ;
@ -68,6 +90,8 @@ UNION: general-compare-insn scalar-compare-insn ##test-vector ;
{ [ dup ##compare-imm? ] [ >compare< \ ##compare-imm-branch new-insn ] }
{ [ dup ##compare-integer? ] [ >compare< \ ##compare-integer-branch new-insn ] }
{ [ dup ##compare-integer-imm? ] [ >compare< \ ##compare-integer-imm-branch new-insn ] }
{ [ dup ##test? ] [ >compare< \ ##test-branch new-insn ] }
{ [ dup ##test-imm? ] [ >compare< \ ##test-imm-branch new-insn ] }
{ [ dup ##compare-float-unordered? ] [ >compare< \ ##compare-float-unordered-branch new-insn ] }
{ [ dup ##compare-float-ordered? ] [ >compare< \ ##compare-float-ordered-branch new-insn ] }
{ [ dup ##test-vector? ] [ >test-vector< \ ##test-vector-branch new-insn ] }
@ -81,6 +105,9 @@ UNION: general-compare-insn scalar-compare-insn ##test-vector ;
: fold-compare-imm-branch ( insn -- insn/f )
evaluate-compare-imm fold-branch ;
: >test-branch ( insn -- insn )
[ src1>> ] [ src1>> ] [ cc>> ] tri \ ##test-branch new-insn ;
M: ##compare-imm-branch rewrite
{
{ [ dup rewrite-boolean-comparison? ] [ rewrite-boolean-comparison ] }
@ -94,6 +121,16 @@ M: ##compare-imm-branch rewrite
M: ##compare-integer-imm-branch rewrite
{
{ [ dup fold-compare-integer-imm? ] [ fold-compare-integer-imm-branch ] }
{ [ dup rewrite-into-test? ] [ >test-branch ] }
[ drop f ]
} cond ;
: fold-test-imm-branch ( insn -- insn/f )
evaluate-test-imm fold-branch ;
M: ##test-imm-branch rewrite
{
{ [ dup fold-test-imm? ] [ fold-test-imm-branch ] }
[ drop f ]
} cond ;
@ -184,6 +221,8 @@ M: ##compare-integer rewrite
{ [ dup ##compare-imm? ] [ >compare< next-vreg \ ##compare-imm new-insn ] }
{ [ dup ##compare-integer? ] [ >compare< next-vreg \ ##compare-integer new-insn ] }
{ [ dup ##compare-integer-imm? ] [ >compare< next-vreg \ ##compare-integer-imm new-insn ] }
{ [ dup ##test? ] [ >compare< next-vreg \ ##test new-insn ] }
{ [ dup ##test-imm? ] [ >compare< next-vreg \ ##test-imm new-insn ] }
{ [ dup ##compare-float-unordered? ] [ >compare< next-vreg \ ##compare-float-unordered new-insn ] }
{ [ dup ##compare-float-ordered? ] [ >compare< next-vreg \ ##compare-float-ordered new-insn ] }
} cond
@ -202,8 +241,68 @@ M: ##compare-imm rewrite
: fold-compare-integer-imm ( insn -- insn' )
dup evaluate-compare-integer-imm >boolean-insn ;
: >test ( insn -- insn' )
{ [ dst>> ] [ src1>> ] [ src1>> ] [ cc>> ] [ temp>> ] } cleave
\ ##test new-insn ;
M: ##compare-integer-imm rewrite
{
{ [ dup fold-compare-integer-imm? ] [ fold-compare-integer-imm ] }
{ [ dup rewrite-into-test? ] [ >test ] }
[ drop f ]
} cond ;
: (simplify-test) ( insn -- src1 src2 cc )
[ src1>> vreg>insn [ src1>> ] [ src2>> ] bi ] [ cc>> ] bi ; inline
: simplify-test ( insn -- insn )
dup (simplify-test) drop [ >>src1 ] [ >>src2 ] bi* ; inline
: simplify-test-branch ( insn -- insn )
dup (simplify-test) drop [ >>src1 ] [ >>src2 ] bi* ; inline
: (simplify-test-imm) ( insn -- src1 src2 cc )
[ src1>> vreg>insn [ src1>> ] [ src2>> ] bi ] [ cc>> ] bi ; inline
: simplify-test-imm ( insn -- insn )
[ dst>> ] [ (simplify-test-imm) ] [ temp>> ] tri \ ##test-imm new-insn ; inline
: simplify-test-imm-branch ( insn -- insn )
(simplify-test-imm) \ ##test-imm-branch new-insn ; inline
: >test-imm ( insn ? -- insn' )
(>compare-imm) [ vreg>integer ] dip next-vreg
\ ##test-imm new-insn ; inline
: >test-imm-branch ( insn ? -- insn' )
(>compare-imm-branch) [ vreg>integer ] dip
\ ##test-imm-branch new-insn ; inline
M: ##test rewrite
{
{ [ dup src1>> vreg>insn ##load-integer? ] [ t >test-imm ] }
{ [ dup src2>> vreg>insn ##load-integer? ] [ f >test-imm ] }
{ [ dup diagonal? not ] [ drop f ] }
{ [ dup src1>> vreg>insn ##and? ] [ simplify-test ] }
{ [ dup src1>> vreg>insn ##and-imm? ] [ simplify-test-imm ] }
[ drop f ]
} cond ;
M: ##test-branch rewrite
{
{ [ dup src1>> vreg>insn ##load-integer? ] [ t >test-imm-branch ] }
{ [ dup src2>> vreg>insn ##load-integer? ] [ f >test-imm-branch ] }
{ [ dup diagonal? not ] [ drop f ] }
{ [ dup src1>> vreg>insn ##and? ] [ simplify-test-branch ] }
{ [ dup src1>> vreg>insn ##and-imm? ] [ simplify-test-imm-branch ] }
[ drop f ]
} cond ;
: fold-test-imm ( insn -- insn' )
dup evaluate-test-imm >boolean-insn ;
M: ##test-imm rewrite
{
{ [ dup fold-test-imm? ] [ fold-test-imm ] }
[ drop f ]
} cond ;

View File

@ -18,6 +18,8 @@ IN: compiler.cfg.value-numbering.tests
[ ##compare-integer-imm? ]
[ ##compare-float-unordered? ]
[ ##compare-float-ordered? ]
[ ##test? ]
[ ##test-imm? ]
[ ##test-vector? ]
[ ##test-vector-branch? ]
} 1|| [ f >>temp ] when
@ -265,6 +267,36 @@ cpu x86.64? [
} value-numbering-step trim-temps
] unit-test
[
{
T{ ##peek f 29 D -1 }
T{ ##peek f 30 D -2 }
T{ ##test f 33 29 30 cc= }
T{ ##test-branch f 29 30 cc= }
}
] [
{
T{ ##peek f 29 D -1 }
T{ ##peek f 30 D -2 }
T{ ##test f 33 29 30 cc= }
T{ ##compare-imm-branch f 33 f cc/= }
} value-numbering-step trim-temps
] unit-test
[
{
T{ ##peek f 29 D -1 }
T{ ##test-imm f 33 29 30 cc= }
T{ ##test-imm-branch f 29 30 cc= }
}
] [
{
T{ ##peek f 29 D -1 }
T{ ##test-imm f 33 29 30 cc= }
T{ ##compare-imm-branch f 33 f cc/= }
} value-numbering-step trim-temps
] unit-test
[
{
T{ ##peek f 1 D -1 }
@ -995,6 +1027,217 @@ cpu x86.32? [
} value-numbering-step
] unit-test
[
{
T{ ##load-integer f 1 12 }
T{ ##load-reference f 3 t }
}
] [
{
T{ ##load-integer f 1 12 }
T{ ##test-imm f 3 1 13 cc/= }
} value-numbering-step
] unit-test
[
{
T{ ##load-integer f 1 15 }
T{ ##load-reference f 3 f }
}
] [
{
T{ ##load-integer f 1 15 }
T{ ##test-imm f 3 1 16 cc/= }
} value-numbering-step
] unit-test
[
{
T{ ##load-integer f 1 12 }
T{ ##load-reference f 3 f }
}
] [
{
T{ ##load-integer f 1 12 }
T{ ##test-imm f 3 1 13 cc= }
} value-numbering-step
] unit-test
[
{
T{ ##load-integer f 1 15 }
T{ ##load-reference f 3 t }
}
] [
{
T{ ##load-integer f 1 15 }
T{ ##test-imm f 3 1 16 cc= }
} value-numbering-step
] unit-test
! Rewriting a ##test of an ##and into a ##test
[
{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##and f 2 0 1 }
T{ ##test f 3 0 1 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##peek f 1 D 1 }
T{ ##and f 2 0 1 }
T{ ##test f 3 2 2 cc= }
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##and-imm f 2 0 12 }
T{ ##test-imm f 3 0 12 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##and-imm f 2 0 12 }
T{ ##test f 3 2 2 cc= }
} value-numbering-step
] unit-test
! Rewriting ##test into ##test-imm
[
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test-imm f 2 0 10 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test f 2 0 1 cc= }
} value-numbering-step trim-temps
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test-imm f 2 0 10 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test f 2 1 0 cc= }
} value-numbering-step trim-temps
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test-imm-branch f 0 10 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test-branch f 0 1 cc= }
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test-imm-branch f 0 10 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 1 10 }
T{ ##test-branch f 1 0 cc= }
} value-numbering-step
] unit-test
! Rewriting ##compare into ##test
cpu x86? [
[
{
T{ ##peek f 0 D 0 }
T{ ##test f 1 0 0 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm f 1 0 0 cc= }
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##test f 1 0 0 cc/= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm f 1 0 0 cc/= }
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm f 1 0 0 cc<= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm f 1 0 0 cc<= }
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##test-branch f 0 0 cc= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm-branch f 0 0 cc= }
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##test-branch f 0 0 cc/= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm-branch f 0 0 cc/= }
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm-branch f 0 0 cc<= }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##compare-integer-imm-branch f 0 0 cc<= }
} value-numbering-step
] unit-test
] when
! Reassociation
[
{

View File

@ -242,6 +242,8 @@ CODEGEN: ##write-barrier %write-barrier
CODEGEN: ##write-barrier-imm %write-barrier-imm
CODEGEN: ##compare %compare
CODEGEN: ##compare-imm %compare-imm
CODEGEN: ##test %test
CODEGEN: ##test-imm %test-imm
CODEGEN: ##compare-integer %compare
CODEGEN: ##compare-integer-imm %compare-integer-imm
CODEGEN: ##compare-float-ordered %compare-float-ordered
@ -268,6 +270,8 @@ CONDITIONAL: ##compare-branch %compare-branch
CONDITIONAL: ##compare-imm-branch %compare-imm-branch
CONDITIONAL: ##compare-integer-branch %compare-branch
CONDITIONAL: ##compare-integer-imm-branch %compare-integer-imm-branch
CONDITIONAL: ##test-branch %test-branch
CONDITIONAL: ##test-imm-branch %test-imm-branch
CONDITIONAL: ##compare-float-ordered-branch %compare-float-ordered-branch
CONDITIONAL: ##compare-float-unordered-branch %compare-float-unordered-branch
CONDITIONAL: ##test-vector-branch %test-vector-branch

View File

@ -475,15 +475,23 @@ HOOK: %call-gc cpu ( gc-roots -- )
HOOK: %prologue cpu ( n -- )
HOOK: %epilogue cpu ( n -- )
HOOK: %compare cpu ( dst temp cc src1 src2 -- )
HOOK: %compare-imm cpu ( dst temp cc src1 src2 -- )
HOOK: %compare-integer-imm cpu ( dst temp cc src1 src2 -- )
HOOK: %compare-float-ordered cpu ( dst temp cc src1 src2 -- )
HOOK: %compare-float-unordered cpu ( dst temp cc src1 src2 -- )
HOOK: test-instruction? cpu ( -- ? )
M: object test-instruction? f ;
HOOK: %compare cpu ( dst src1 src2 cc temp -- )
HOOK: %compare-imm cpu ( dst src1 src2 cc temp -- )
HOOK: %compare-integer-imm cpu ( dst src1 src2 cc temp -- )
HOOK: %test cpu ( dst src1 src2 cc temp -- )
HOOK: %test-imm cpu ( dst src1 src2 cc temp -- )
HOOK: %compare-float-ordered cpu ( dst src1 src2 cc temp -- )
HOOK: %compare-float-unordered cpu ( dst src1 src2 cc temp -- )
HOOK: %compare-branch cpu ( label cc src1 src2 -- )
HOOK: %compare-imm-branch cpu ( label cc src1 src2 -- )
HOOK: %compare-integer-imm-branch cpu ( label cc src1 src2 -- )
HOOK: %test-branch cpu ( label cc src1 src2 -- )
HOOK: %test-imm-branch cpu ( label cc src1 src2 -- )
HOOK: %compare-float-ordered-branch cpu ( label cc src1 src2 -- )
HOOK: %compare-float-unordered-branch cpu ( label cc src1 src2 -- )

View File

@ -72,6 +72,8 @@ M: x86 complex-addressing? t ;
M: x86 fused-unboxing? t ;
M: x86 test-instruction? t ;
M: x86 immediate-store? immediate-comparand? ;
M: x86 %load-immediate dup 0 = [ drop dup XOR ] [ MOV ] if ;
@ -525,28 +527,30 @@ M:: x86 %compare ( dst src1 src2 cc temp -- )
src1 src2 CMP
dst cc temp %boolean ;
: use-test? ( src1 src2 cc -- ? )
[ register? ] [ 0 = ] [ { cc= cc/= } member? ] tri* and and ;
M:: x86 %test ( dst src1 src2 cc temp -- )
src1 src2 TEST
dst cc temp %boolean ;
: (%compare-tagged) ( src1 src2 -- )
[ HEX: ffffffff CMP ] dip rc-absolute rel-literal ;
: (%compare-integer-imm) ( src1 src2 cc -- )
3dup use-test? [ 2drop dup TEST ] [ drop CMP ] if ;
M:: x86 %compare-integer-imm ( dst src1 src2 cc temp -- )
src1 src2 cc (%compare-integer-imm)
src1 src2 CMP
dst cc temp %boolean ;
: (%compare-imm) ( src1 src2 cc -- )
M:: x86 %test-imm ( dst src1 src2 cc temp -- )
src1 src2 TEST
dst cc temp %boolean ;
: (%compare-imm) ( src1 src2 -- )
{
{ [ over fixnum? ] [ [ tag-fixnum ] dip (%compare-integer-imm) ] }
{ [ over not ] [ 2drop \ f type-number CMP ] }
[ drop (%compare-tagged) ]
{ [ dup fixnum? ] [ tag-fixnum CMP ] }
{ [ dup not ] [ drop \ f type-number CMP ] }
[ (%compare-tagged) ]
} cond ;
M:: x86 %compare-imm ( dst src1 src2 cc temp -- )
src1 src2 cc (%compare-imm)
src1 src2 (%compare-imm)
dst cc temp %boolean ;
: %branch ( label cc -- )
@ -564,11 +568,19 @@ M:: x86 %compare-branch ( label src1 src2 cc -- )
label cc %branch ;
M:: x86 %compare-integer-imm-branch ( label src1 src2 cc -- )
src1 src2 cc (%compare-integer-imm)
src1 src2 CMP
label cc %branch ;
M:: x86 %test-branch ( label src1 src2 cc -- )
src1 src2 TEST
label cc %branch ;
M:: x86 %test-imm-branch ( label src1 src2 cc -- )
src1 src2 TEST
label cc %branch ;
M:: x86 %compare-imm-branch ( label src1 src2 cc -- )
src1 src2 cc (%compare-imm)
src1 src2 (%compare-imm)
label cc %branch ;
M: x86 %add-float double-rep two-operand ADDSD ;