compiler.*: a bunch more compiler docs
parent
e2c91852e4
commit
0c2559ef6e
|
@ -0,0 +1,65 @@
|
|||
USING: compiler.cfg.instructions help.markup help.syntax ;
|
||||
IN: compiler.cfg.alias-analysis
|
||||
|
||||
HELP: useless-compare?
|
||||
{ $values
|
||||
{ "insn" "a " { $link ##compare } " instruction" }
|
||||
{ "?" "a boolean" }
|
||||
}
|
||||
{ $description "Checks if the comparison instruction is required." } ;
|
||||
|
||||
ARTICLE: "compiler.cfg.alias-analysis"
|
||||
"Alias analysis for stack operations, array elements and tuple slots"
|
||||
"We try to eliminate redundant slot operations using some simple heuristics."
|
||||
$nl
|
||||
"All heap-allocated objects which are loaded from the stack, or other object slots are pessimistically assumed to belong to the same alias class."
|
||||
$nl
|
||||
"Freshly-allocated objects get their own alias class."
|
||||
$nl
|
||||
"Simple pseudo-C example showing load elimination:"
|
||||
{ $code
|
||||
"int *x, *y, z: inputs"
|
||||
"int a, b, c, d, e: locals"
|
||||
}
|
||||
"Before alias analysis:"
|
||||
{ $code
|
||||
"a = x[2]"
|
||||
"b = x[2]"
|
||||
"c = x[3]"
|
||||
"y[2] = z"
|
||||
"d = x[2]"
|
||||
"e = y[2]"
|
||||
"f = x[3]"
|
||||
}
|
||||
"After alias analysis:"
|
||||
{ $code
|
||||
"a = x[2]"
|
||||
"b = a /* ELIMINATED */"
|
||||
"c = x[3]"
|
||||
"y[2] = z"
|
||||
"d = x[2] /* if x=y, d=z, if x!=y, d=b; NOT ELIMINATED */"
|
||||
"e = z /* ELIMINATED */"
|
||||
"f = c /* ELIMINATED */"
|
||||
}
|
||||
"Simple pseudo-C example showing store elimination:"
|
||||
$nl
|
||||
"Before alias analysis:"
|
||||
{ $code
|
||||
"x[0] = a"
|
||||
"b = x[n]"
|
||||
"x[0] = c"
|
||||
"x[1] = d"
|
||||
"e = x[0]"
|
||||
"x[1] = c"
|
||||
}
|
||||
"After alias analysis:"
|
||||
{ $code
|
||||
"x[0] = a /* dead if n = 0, live otherwise; NOT ELIMINATED */"
|
||||
"b = x[n]"
|
||||
"x[0] = c"
|
||||
"/* x[1] = d */ /* ELIMINATED */"
|
||||
"e = c"
|
||||
"x[1] = c"
|
||||
} ;
|
||||
|
||||
ABOUT: "compiler.cfg.alias-analysis"
|
|
@ -8,60 +8,6 @@ namespaces sequences sets ;
|
|||
FROM: namespaces => set ;
|
||||
IN: compiler.cfg.alias-analysis
|
||||
|
||||
! We try to eliminate redundant slot operations using some
|
||||
! simple heuristics.
|
||||
!
|
||||
! All heap-allocated objects which are loaded from the stack, or
|
||||
! other object slots are pessimistically assumed to belong to
|
||||
! the same alias class.
|
||||
!
|
||||
! Freshly-allocated objects get their own alias class.
|
||||
!
|
||||
! Simple pseudo-C example showing load elimination:
|
||||
!
|
||||
! int *x, *y, z: inputs
|
||||
! int a, b, c, d, e: locals
|
||||
!
|
||||
! Before alias analysis:
|
||||
!
|
||||
! a = x[2]
|
||||
! b = x[2]
|
||||
! c = x[3]
|
||||
! y[2] = z
|
||||
! d = x[2]
|
||||
! e = y[2]
|
||||
! f = x[3]
|
||||
!
|
||||
! After alias analysis:
|
||||
!
|
||||
! a = x[2]
|
||||
! b = a /* ELIMINATED */
|
||||
! c = x[3]
|
||||
! y[2] = z
|
||||
! d = x[2] /* if x=y, d=z, if x!=y, d=b; NOT ELIMINATED */
|
||||
! e = z /* ELIMINATED */
|
||||
! f = c /* ELIMINATED */
|
||||
!
|
||||
! Simple pseudo-C example showing store elimination:
|
||||
!
|
||||
! Before alias analysis:
|
||||
!
|
||||
! x[0] = a
|
||||
! b = x[n]
|
||||
! x[0] = c
|
||||
! x[1] = d
|
||||
! e = x[0]
|
||||
! x[1] = c
|
||||
!
|
||||
! After alias analysis:
|
||||
!
|
||||
! x[0] = a /* dead if n = 0, live otherwise; NOT ELIMINATED */
|
||||
! b = x[n]
|
||||
! x[0] = c
|
||||
! /* x[1] = d */ /* ELIMINATED */
|
||||
! e = c
|
||||
! x[1] = c
|
||||
|
||||
! Local copy propagation
|
||||
SYMBOL: copies
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ HELP: basic-block
|
|||
{ { $slot "successors" } { "A " { $link vector } " of basic blocks that may be executed directly after this block. Most blocks only have one successor but a block that checks where an if-condition should branch to would have two for example." } }
|
||||
{ { $slot "predecessors" } { "The opposite of successors -- a " { $link vector } " of basic blocks from which the execution may have arrived into this block." } }
|
||||
{ { $slot "instructions" } { "A " { $link vector } " of " { $link insn } " tuples which form the instructions of the basic block." } }
|
||||
{ { $slot "kill-block?" } { "The first and the last block in a cfg and all blocks containing " { $link ##call } " instructions are kill blocks." } }
|
||||
}
|
||||
} ;
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ IN: compiler.cfg.gc-checks
|
|||
|
||||
<PRIVATE
|
||||
|
||||
HELP: add-gc-checks
|
||||
{ $values { "insns-seq" "a sequence of instruction sequences" } }
|
||||
{ $description "Insert a GC check at the end of every chunk but the last one. This ensures that every section other than the first has a GC check in the section immediately preceeding it." } ;
|
||||
|
||||
HELP: allocation-size
|
||||
{ $values { "insns" { $link sequence } " of " { $link insn } } { "n" number } }
|
||||
{ $description "Calculates the total number of bytes allocated by the instructions in a block." }
|
||||
|
|
|
@ -57,9 +57,6 @@ M: ##box-displaced-alien allocation-size* drop 5 cells ;
|
|||
[ allocation-size* data-alignment get align ] map-sum ;
|
||||
|
||||
: add-gc-checks ( insns-seq -- )
|
||||
! Insert a GC check at the end of every chunk but the last
|
||||
! one. This ensures that every section other than the first
|
||||
! has a GC check in the section immediately preceeding it.
|
||||
2 <clumps> [
|
||||
first2 allocation-size
|
||||
cc<= int-rep next-vreg-rep int-rep next-vreg-rep
|
||||
|
|
|
@ -2,6 +2,10 @@ USING: combinators.private compiler.units effects help.markup help.syntax
|
|||
quotations ;
|
||||
IN: compiler.tree.propagation.call-effect
|
||||
|
||||
HELP: already-inlined-quot?
|
||||
{ $values { "quot" quotation } { "?" "a boolean" } }
|
||||
{ $description "Some bookkeeping to make sure that crap like [ dup curry call( quot -- ) ] dup curry call( quot -- ) ] doesn't hang the compiler." } ;
|
||||
|
||||
HELP: cached-effect-valid?
|
||||
{ $values { "quot" quotation } { "?" "a boolean" } }
|
||||
{ $description { $link t } " if the cached effect is valid." } ;
|
||||
|
@ -26,7 +30,6 @@ HELP: update-inline-cache
|
|||
{ $values { "word/quot" "word or quotation" } { "ic" inline-cache } }
|
||||
{ $description "Sets the inline caches " { $slot "value" } " to the given word/quot and updates its " { $slot "counter" } " to the value of the " { $link effect-counter } "." } ;
|
||||
|
||||
|
||||
ARTICLE: "compiler.tree.propagation.call-effect" "Expansions of call( and execute( words"
|
||||
"call( and execute( have complex expansions."
|
||||
$nl
|
||||
|
|
|
@ -111,9 +111,6 @@ M: quotation cached-effect
|
|||
: execute-effect>quot ( effect -- quot )
|
||||
inline-cache new '[ drop _ _ execute-effect-ic ] ;
|
||||
|
||||
! Some bookkeeping to make sure that crap like
|
||||
! [ dup curry call( quot -- ) ] dup curry call( quot -- ) ]
|
||||
! doesn't hang the compiler.
|
||||
GENERIC: already-inlined-quot? ( quot -- ? )
|
||||
|
||||
M: curry already-inlined-quot? quot>> already-inlined-quot? ;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
USING: compiler.tree help.markup help.syntax kernel quotations words ;
|
||||
IN: compiler.tree.propagation.inlining
|
||||
|
||||
HELP: custom-inlining?
|
||||
{ $values { "word" word } { "quot/f" "a quotation or " { $link f } } }
|
||||
{ $description "Returns the custom inlining " { $link quotation } " for a word if it has one." } ;
|
||||
|
||||
HELP: (do-inlining)
|
||||
{ $values { "#call" #call } { "word" word } { "?" boolean } }
|
||||
{ $description
|
||||
"Performs inlining of a word."
|
||||
$nl
|
||||
"If the generic was defined in an outer compilation unit, then it doesn't have a definition yet; the definition is built at the end of the compilation unit. We do not attempt inlining at this stage since the stack discipline is not finalized yet, so dispatch# might return an out of bounds value. This case comes up if a parsing word calls the compiler at parse time (doing so is discouraged, but it should still work.)"
|
||||
} ;
|
||||
|
||||
ARTICLE: "compiler.tree.propagation.inlining" "Method inlining and dispatch elimination"
|
||||
"Splicing nodes:"
|
||||
{ $subsections splicing-call open-code-#call splicing-body } ;
|
||||
|
||||
ABOUT: "compiler.tree.propagation.inlining"
|
|
@ -8,7 +8,6 @@ generic.math generic.single generic.standard kernel locals math
|
|||
math.partial-dispatch namespaces quotations sequences words ;
|
||||
IN: compiler.tree.propagation.inlining
|
||||
|
||||
! Splicing nodes
|
||||
: splicing-call ( #call word -- nodes )
|
||||
[ [ in-d>> ] [ out-d>> ] bi ] dip <#call> 1array ;
|
||||
|
||||
|
@ -95,7 +94,7 @@ SYMBOL: history
|
|||
: never-inline-word? ( word -- ? )
|
||||
{ [ deferred? ] [ "default" word-prop ] [ \ call eq? ] } 1|| ;
|
||||
|
||||
: custom-inlining? ( word -- ? )
|
||||
: custom-inlining? ( word -- quot/f )
|
||||
"custom-inlining" word-prop ;
|
||||
|
||||
: inline-custom ( #call word -- ? )
|
||||
|
@ -104,14 +103,6 @@ SYMBOL: history
|
|||
object swap eliminate-dispatch ;
|
||||
|
||||
: (do-inlining) ( #call word -- ? )
|
||||
#! If the generic was defined in an outer compilation unit,
|
||||
#! then it doesn't have a definition yet; the definition
|
||||
#! is built at the end of the compilation unit. We do not
|
||||
#! attempt inlining at this stage since the stack discipline
|
||||
#! is not finalized yet, so dispatch# might return an out
|
||||
#! of bounds value. This case comes up if a parsing word
|
||||
#! calls the compiler at parse time (doing so is
|
||||
#! discouraged, but it should still work.)
|
||||
{
|
||||
{ [ dup never-inline-word? ] [ 2drop f ] }
|
||||
{ [ dup always-inline-word? ] [ inline-word ] }
|
||||
|
|
|
@ -1,17 +1,30 @@
|
|||
USING: cpu.x86.assembler.operands.private help.markup help.syntax layouts
|
||||
math ;
|
||||
USING: cpu.x86.assembler cpu.x86.assembler.operands.private help.markup
|
||||
help.syntax layouts math ;
|
||||
IN: cpu.x86
|
||||
|
||||
HELP: %boolean
|
||||
{ $values
|
||||
{ "dst" "register" }
|
||||
{ "cc" "comparision symbol" }
|
||||
{ "temp" "temporary register" }
|
||||
}
|
||||
{ $description "Helper word for emitting conditional move instructions." }
|
||||
{ $see-also CMOVL CMOVLE CMOVG CMOVGE CMOVE CMOVNE } ;
|
||||
|
||||
HELP: JLE
|
||||
{ $values "dst" "destination offset (relative to the instruction pointer register)" }
|
||||
{ $description "Emits a 'jle' instruction." } ;
|
||||
|
||||
HELP: reserved-stack-space
|
||||
{ $values { "n" integer } }
|
||||
{ $description "Size in bytes of the register parameter area. It only exists on the windows x86.64 architecture, where it is 32 bytes and allocated by the caller. On all other platforms it is 0." } ;
|
||||
|
||||
HELP: stack-reg
|
||||
{ $values { "reg" "a register symbol" } }
|
||||
{ $description
|
||||
"Symbol of the machine register that holds the (cpu) stack address."
|
||||
} ;
|
||||
|
||||
HELP: reserved-stack-space
|
||||
{ $values { "n" integer } }
|
||||
{ $description "Size in bytes of the register parameter area. It only exists on the windows x86.64 architecture, where it is 32 bytes and allocated by the caller. On all other platforms it is 0." } ;
|
||||
|
||||
HELP: ds-reg
|
||||
{ $values { "reg" "a register symbol" } }
|
||||
{ $description
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
USING: help.markup help.syntax kernel kernel.private sequences words ;
|
||||
USING: combinators help.markup help.syntax kernel kernel.private sequences
|
||||
words ;
|
||||
IN: stack-checker.known-words
|
||||
|
||||
HELP: check-declaration
|
||||
|
@ -12,6 +13,9 @@ HELP: define-primitive
|
|||
HELP: infer-call
|
||||
{ $description "Performs inferencing for the " { $link call } " word." } ;
|
||||
|
||||
HELP: infer-call-effect
|
||||
{ $description "Performs inferencing for the " { $link call-effect } " word." } ;
|
||||
|
||||
HELP: infer-local-reader
|
||||
{ $values { "word" word } }
|
||||
{ $description "This is a hack for combinators " { $vocab-link "combinators.short-circuit.smart" } "." } ;
|
||||
|
|
Loading…
Reference in New Issue