diff --git a/basis/compiler/cfg/instructions/instructions.factor b/basis/compiler/cfg/instructions/instructions.factor index cc02edc315..30c3811cdf 100644 --- a/basis/compiler/cfg/instructions/instructions.factor +++ b/basis/compiler/cfg/instructions/instructions.factor @@ -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 diff --git a/basis/compiler/cfg/representations/peephole/peephole.factor b/basis/compiler/cfg/representations/peephole/peephole.factor index c3e7fa06a5..d86259971f 100644 --- a/basis/compiler/cfg/representations/peephole/peephole.factor +++ b/basis/compiler/cfg/representations/peephole/peephole.factor @@ -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 diff --git a/basis/compiler/cfg/representations/representations-tests.factor b/basis/compiler/cfg/representations/representations-tests.factor index ef64908f78..9955814ed9 100644 --- a/basis/compiler/cfg/representations/representations-tests.factor +++ b/basis/compiler/cfg/representations/representations-tests.factor @@ -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{ diff --git a/basis/compiler/cfg/representations/selection/selection.factor b/basis/compiler/cfg/representations/selection/selection.factor index 6cabe27e85..330e5d8e2a 100644 --- a/basis/compiler/cfg/representations/selection/selection.factor +++ b/basis/compiler/cfg/representations/selection/selection.factor @@ -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 -- ) diff --git a/basis/compiler/cfg/value-numbering/comparisons/comparisons.factor b/basis/compiler/cfg/value-numbering/comparisons/comparisons.factor index f28092d8cc..ed037c4d06 100644 --- a/basis/compiler/cfg/value-numbering/comparisons/comparisons.factor +++ b/basis/compiler/cfg/value-numbering/comparisons/comparisons.factor @@ -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 ; diff --git a/basis/compiler/cfg/value-numbering/value-numbering-tests.factor b/basis/compiler/cfg/value-numbering/value-numbering-tests.factor index 00d8652279..be387c3f32 100644 --- a/basis/compiler/cfg/value-numbering/value-numbering-tests.factor +++ b/basis/compiler/cfg/value-numbering/value-numbering-tests.factor @@ -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 [ { diff --git a/basis/compiler/codegen/codegen.factor b/basis/compiler/codegen/codegen.factor index 32c5181150..9d3e76d25b 100755 --- a/basis/compiler/codegen/codegen.factor +++ b/basis/compiler/codegen/codegen.factor @@ -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 diff --git a/basis/cpu/architecture/architecture.factor b/basis/cpu/architecture/architecture.factor index f04737a9df..5dff607abd 100644 --- a/basis/cpu/architecture/architecture.factor +++ b/basis/cpu/architecture/architecture.factor @@ -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 -- ) diff --git a/basis/cpu/x86/x86.factor b/basis/cpu/x86/x86.factor index 6b8447eb95..f4738b990b 100644 --- a/basis/cpu/x86/x86.factor +++ b/basis/cpu/x86/x86.factor @@ -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 ;