Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f6a836d

Browse files
author
Slava Pestov
committed
compiler.cfg.linear-scan now supports partial sync-points where all registers are spilled; taking advantage of this, there are new trigonometric intrinsics which yield a 2x performance boost on benchmark.struct-arrays and a 25% boost on benchmark.partial-sums
1 parent a7a39d3 commit f6a836d

File tree

17 files changed

+258
-92
lines changed

17 files changed

+258
-92
lines changed

‎basis/compiler/cfg/build-stack-frame/build-stack-frame.factor‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ GENERIC: compute-stack-frame* ( insn -- )
1414
frame-required? on
1515
stack-frame [ max-stack-frame ] change ;
1616

17-
M: ##alien-invoke compute-stack-frame*
18-
stack-frame>> request-stack-frame ;
19-
20-
M: ##alien-indirect compute-stack-frame*
21-
stack-frame>> request-stack-frame ;
17+
UNION: stack-frame-insn
18+
##alien-invoke
19+
##alien-indirect
20+
##alien-callback ;
2221

23-
M: ##alien-callback compute-stack-frame*
22+
M: stack-frame-insn compute-stack-frame*
2423
stack-frame>> request-stack-frame ;
2524

2625
M: ##call compute-stack-frame*
@@ -40,6 +39,8 @@ M: insn compute-stack-frame*
4039
] when ;
4140

4241
\ _spill t frame-required? set-word-prop
42+
\ ##unary-float-function t frame-required? set-word-prop
43+
\ ##binary-float-function t frame-required? set-word-prop
4344

4445
: compute-stack-frame ( insns -- )
4546
frame-required? off

‎basis/compiler/cfg/hats/hats.factor‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ IN: compiler.cfg.hats
4747
: ^^div-float ( src1 src2 -- dst ) ^^r2 ##div-float ; inline
4848
: ^^max-float ( src1 src2 -- dst ) ^^r2 ##max-float ; inline
4949
: ^^min-float ( src1 src2 -- dst ) ^^r2 ##min-float ; inline
50+
: ^^unary-float-function ( src func -- dst ) ^^r2 ##unary-float-function ; inline
51+
: ^^binary-float-function ( src1 src2 func -- dst ) ^^r3 ##binary-float-function ; inline
5052
: ^^sqrt ( src -- dst ) ^^r1 ##sqrt ; inline
5153
: ^^float>integer ( src -- dst ) ^^r1 ##float>integer ; inline
5254
: ^^integer>float ( src -- dst ) ^^r1 ##integer>float ; inline

‎basis/compiler/cfg/instructions/instructions.factor‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ INSN: ##min-float < ##binary ;
112112
INSN: ##max-float < ##binary ;
113113
INSN: ##sqrt < ##unary ;
114114

115+
! libc intrinsics
116+
INSN: ##unary-float-function < ##unary func ;
117+
INSN: ##binary-float-function < ##binary func ;
118+
115119
! Float/integer conversion
116120
INSN: ##float>integer < ##unary ;
117121
INSN: ##integer>float < ##unary ;
@@ -252,6 +256,11 @@ UNION: vreg-insn
252256
_compare-imm-branch
253257
_dispatch ;
254258

259+
! Instructions that kill all live vregs but cannot trigger GC
260+
UNION: partial-sync-insn
261+
##unary-float-function
262+
##binary-float-function ;
263+
255264
! Instructions that kill all live vregs
256265
UNION: kill-vreg-insn
257266
##call
@@ -270,6 +279,8 @@ UNION: output-float-insn
270279
##min-float
271280
##max-float
272281
##sqrt
282+
##unary-float-function
283+
##binary-float-function
273284
##integer>float
274285
##unbox-float
275286
##alien-float
@@ -284,6 +295,8 @@ UNION: input-float-insn
284295
##min-float
285296
##max-float
286297
##sqrt
298+
##unary-float-function
299+
##binary-float-function
287300
##float>integer
288301
##box-float
289302
##set-alien-float

‎basis/compiler/cfg/intrinsics/float/float.factor‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ IN: compiler.cfg.intrinsics.float
1818

1919
: emit-fsqrt ( -- )
2020
ds-pop ^^sqrt ds-push ;
21+
22+
: emit-unary-float-function ( func -- )
23+
[ ds-pop ] dip ^^unary-float-function ds-push ;
24+
25+
: emit-binary-float-function ( func -- )
26+
[ 2inputs ] dip ^^binary-float-function ds-push ;

‎basis/compiler/cfg/intrinsics/intrinsics.factor‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,27 @@ IN: compiler.cfg.intrinsics
108108
math.floats.private:float-max
109109
} enable-intrinsics ;
110110

111+
: enable-float-functions ( -- )
112+
! Everything except for fsqrt
113+
{
114+
math.libm:facos
115+
math.libm:fasin
116+
math.libm:fatan
117+
math.libm:fatan2
118+
math.libm:fcos
119+
math.libm:fsin
120+
math.libm:ftan
121+
math.libm:fcosh
122+
math.libm:fsinh
123+
math.libm:ftanh
124+
math.libm:fexp
125+
math.libm:flog
126+
math.libm:fpow
127+
math.libm:facosh
128+
math.libm:fasinh
129+
math.libm:fatanh
130+
} enable-intrinsics ;
131+
111132
: enable-min/max ( -- )
112133
{
113134
math.integers.private:fixnum-min
@@ -157,6 +178,22 @@ IN: compiler.cfg.intrinsics
157178
{ \ math.floats.private:float-min [ drop [ ^^min-float ] emit-float-op ] }
158179
{ \ math.floats.private:float-max [ drop [ ^^max-float ] emit-float-op ] }
159180
{ \ math.libm:fsqrt [ drop emit-fsqrt ] }
181+
{ \ math.libm:facos [ drop "acos" emit-unary-float-function ] }
182+
{ \ math.libm:fasin [ drop "asin" emit-unary-float-function ] }
183+
{ \ math.libm:fatan [ drop "atan" emit-unary-float-function ] }
184+
{ \ math.libm:fatan2 [ drop "atan2" emit-binary-float-function ] }
185+
{ \ math.libm:fcos [ drop "cos" emit-unary-float-function ] }
186+
{ \ math.libm:fsin [ drop "sin" emit-unary-float-function ] }
187+
{ \ math.libm:ftan [ drop "tan" emit-unary-float-function ] }
188+
{ \ math.libm:fcosh [ drop "cosh" emit-unary-float-function ] }
189+
{ \ math.libm:fsinh [ drop "sinh" emit-unary-float-function ] }
190+
{ \ math.libm:ftanh [ drop "tanh" emit-unary-float-function ] }
191+
{ \ math.libm:fexp [ drop "exp" emit-unary-float-function ] }
192+
{ \ math.libm:flog [ drop "log" emit-unary-float-function ] }
193+
{ \ math.libm:fpow [ drop "pow" emit-binary-float-function ] }
194+
{ \ math.libm:facosh [ drop "acosh" emit-unary-float-function ] }
195+
{ \ math.libm:fasinh [ drop "asinh" emit-unary-float-function ] }
196+
{ \ math.libm:fatanh [ drop "atanh" emit-unary-float-function ] }
160197
{ \ slots.private:slot [ emit-slot ] }
161198
{ \ slots.private:set-slot [ emit-set-slot ] }
162199
{ \ strings.private:string-nth [ drop emit-string-nth ] }

‎basis/compiler/cfg/linear-scan/allocation/allocation.factor‎

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
! Copyright (C) 2008, 2009 Slava Pestov.
22
! See http://factorcode.org/license.txt for BSD license.
33
USING: accessors assocs heaps kernel namespaces sequences fry math
4-
math.order combinators arrays sorting compiler.utilities
4+
math.order combinators arrays sorting compiler.utilities locals
55
compiler.cfg.linear-scan.live-intervals
66
compiler.cfg.linear-scan.allocation.spilling
77
compiler.cfg.linear-scan.allocation.splitting
@@ -34,22 +34,48 @@ IN: compiler.cfg.linear-scan.allocation
3434
[ drop assign-blocked-register ]
3535
} cond ;
3636

37-
: handle-interval ( live-interval -- )
38-
[
39-
start>>
37+
: handle-sync-point ( n -- )
38+
[ active-intervals get values ] dip
39+
[ '[ [ _ spill ] each ] each ]
40+
[ drop [ delete-all ] each ]
41+
2bi ;
42+
43+
:: handle-progress ( n sync? -- )
44+
n {
4045
[ progress set ]
4146
[ deactivate-intervals ]
42-
[ activate-intervals ] tri
43-
] [ assign-register ] bi ;
47+
[ sync? [ handle-sync-point ] [ drop ] if ]
48+
[ activate-intervals ]
49+
} cleave ;
50+
51+
GENERIC: handle ( obj -- )
52+
53+
M: live-interval handle ( live-interval -- )
54+
[ start>> f handle-progress ] [ assign-register ] bi ;
55+
56+
M: sync-point handle ( sync-point -- )
57+
n>> t handle-progress ;
58+
59+
: smallest-heap ( heap1 heap2 -- heap )
60+
! If heap1 and heap2 have the same key, favors heap1.
61+
[ [ heap-peek nip ] bi@ <= ] most ;
4462

4563
: (allocate-registers) ( -- )
46-
unhandled-intervals get [ handle-interval ] slurp-heap ;
64+
{
65+
{ [ unhandled-intervals get heap-empty? ] [ unhandled-sync-points get ] }
66+
{ [ unhandled-sync-points get heap-empty? ] [ unhandled-intervals get ] }
67+
! If a live interval begins at the same location as a sync point,
68+
! process the sync point before the live interval. This ensures that the
69+
! return value of C function calls doesn't get spilled and reloaded
70+
! unnecessarily.
71+
[ unhandled-sync-points get unhandled-intervals get smallest-heap ]
72+
} cond dup heap-empty? [ drop ] [ heap-pop drop handle (allocate-registers) ] if ;
4773

4874
: finish-allocation ( -- )
4975
active-intervals inactive-intervals
5076
[ get values [ handled-intervals get push-all ] each ] bi@ ;
5177

52-
: allocate-registers ( live-intervals machine-registers -- live-intervals )
78+
: allocate-registers ( live-intervals sync-point machine-registers -- live-intervals )
5379
init-allocator
5480
init-unhandled
5581
(allocate-registers)

‎basis/compiler/cfg/linear-scan/allocation/spilling/spilling.factor‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ERROR: bad-live-ranges interval ;
2929
2bi ;
3030

3131
: assign-spill ( live-interval -- )
32-
dup vreg>> assign-spill-slot >>spill-to drop ;
32+
dup vreg>> vreg-spill-slot >>spill-to drop ;
3333

3434
: spill-before ( before -- before/f )
3535
! If the interval does not have any usages before the spill location,
@@ -46,7 +46,7 @@ ERROR: bad-live-ranges interval ;
4646
] if ;
4747

4848
: assign-reload ( live-interval -- )
49-
dup vreg>> assign-spill-slot >>reload-from drop ;
49+
dup vreg>> vreg-spill-slot >>reload-from drop ;
5050

5151
: spill-after ( after -- after/f )
5252
! If the interval has no more usages after the spill location,

‎basis/compiler/cfg/linear-scan/allocation/state/state.factor‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,25 +120,30 @@ SYMBOL: unhandled-intervals
120120
rep-size cfg get
121121
[ swap [ align dup ] [ + ] bi ] change-spill-area-size drop ;
122122

123+
! Minheap of sync points which still need to be processed
124+
SYMBOL: unhandled-sync-points
125+
123126
! Mapping from vregs to spill slots
124127
SYMBOL: spill-slots
125128

126-
: assign-spill-slot ( vreg -- n )
129+
: vreg-spill-slot ( vreg -- n )
127130
spill-slots get [ rep-of next-spill-slot ] cache ;
128131

129132
: init-allocator ( registers -- )
130133
registers set
131134
<min-heap> unhandled-intervals set
135+
<min-heap> unhandled-sync-points set
132136
[ V{ } clone ] reg-class-assoc active-intervals set
133137
[ V{ } clone ] reg-class-assoc inactive-intervals set
134138
V{ } clone handled-intervals set
135139
cfg get 0 >>spill-area-size drop
136140
H{ } clone spill-slots set
137141
-1 progress set ;
138142

139-
: init-unhandled ( live-intervals -- )
140-
[ [ start>> ] keep ] { } map>assoc
141-
unhandled-intervals get heap-push-all ;
143+
: init-unhandled ( live-intervals sync-points -- )
144+
[ [ [ start>> ] keep ] { } map>assoc unhandled-intervals get heap-push-all ]
145+
[ [ [ n>> ] keep ] { } map>assoc unhandled-sync-points get heap-push-all ]
146+
bi* ;
142147

143148
! A utility used by register-status and spill-status words
144149
: free-positions ( new -- assoc )

‎basis/compiler/cfg/linear-scan/assignment/assignment.factor‎

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ SYMBOL: pending-interval-assoc
2828
: remove-pending ( live-interval -- )
2929
vreg>> pending-interval-assoc get delete-at ;
3030

31+
: (vreg>reg) ( vreg pending -- reg )
32+
! If a live vreg is not in the pending set, then it must
33+
! have been spilled.
34+
?at [ spill-slots get at <spill-slot> ] unless ;
35+
36+
: vreg>reg ( vreg -- reg )
37+
pending-interval-assoc get (vreg>reg) ;
38+
39+
: vregs>regs ( vregs -- assoc )
40+
dup assoc-empty? [
41+
pending-interval-assoc get
42+
'[ _ (vreg>reg) ] assoc-map
43+
] unless ;
44+
3145
! Minheap of live intervals which still need a register allocation
3246
SYMBOL: unhandled-intervals
3347

@@ -96,8 +110,6 @@ SYMBOL: register-live-outs
96110

97111
GENERIC: assign-registers-in-insn ( insn -- )
98112

99-
: vreg>reg ( vreg -- reg ) pending-interval-assoc get at ;
100-
101113
RENAMING: assign [ vreg>reg ] [ vreg>reg ] [ vreg>reg ]
102114

103115
M: vreg-insn assign-registers-in-insn
@@ -123,7 +135,7 @@ M: vreg-insn assign-registers-in-insn
123135
[
124136
[
125137
2dup spill-on-gc?
126-
[ swap [ assign-spill-slot ] [ rep-of ] bi 3array , ] [ 2drop ] if
138+
[ swap [ vreg-spill-slot ] [ rep-of ] bi 3array , ] [ 2drop ] if
127139
] assoc-each
128140
] { } make ;
129141

@@ -137,23 +149,13 @@ M: ##gc assign-registers-in-insn
137149

138150
M: insn assign-registers-in-insn drop ;
139151

140-
: compute-live-values ( vregs -- assoc )
141-
! If a live vreg is not in active or inactive, then it must have been
142-
! spilled.
143-
dup assoc-empty? [
144-
pending-interval-assoc get
145-
'[ _ ?at [ ] [ spill-slots get at <spill-slot> ] if ] assoc-map
146-
] unless ;
147-
148152
: begin-block ( bb -- )
149153
dup basic-block set
150154
dup block-from activate-new-intervals
151-
[ live-in compute-live-values ] keep
152-
register-live-ins get set-at ;
155+
[ live-in vregs>regs ] keep register-live-ins get set-at ;
153156

154157
: end-block ( bb -- )
155-
[ live-out compute-live-values ] keep
156-
register-live-outs get set-at ;
158+
[ live-out vregs>regs ] keep register-live-outs get set-at ;
157159

158160
ERROR: bad-vreg vreg ;
159161

‎basis/compiler/cfg/linear-scan/debugger/debugger.factor‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ IN: compiler.cfg.linear-scan.debugger
99
[
1010
[ clone ] map dup [ [ vreg>> ] keep ] H{ } map>assoc
1111
live-intervals set
12+
f
1213
] dip
1314
allocate-registers drop ;
1415

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /