~ubuntu-branches/ubuntu/maverick/blender/maverick

« back to all changes in this revision

Viewing changes to extern/fftw/genfft-k7/genUtil.ml

  • Committer: Bazaar Package Importer
  • Author(s): Khashayar Naderehvandi, Khashayar Naderehvandi, Alessio Treglia
  • Date: 2009-01-22 16:53:59 UTC
  • mfrom: (14.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090122165359-v0996tn7fbit64ni
Tags: 2.48a+dfsg-1ubuntu1
[ Khashayar Naderehvandi ]
* Merge from debian experimental (LP: #320045), Ubuntu remaining changes:
  - Add patch correcting header file locations.
  - Add libvorbis-dev and libgsm1-dev to Build-Depends.
  - Use avcodec_decode_audio2() in source/blender/src/hddaudio.c

[ Alessio Treglia ]
* Add missing previous changelog entries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(*
 
2
 * Copyright (c) 2001 Stefan Kral
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 *
 
18
 *)
 
19
 
 
20
 
 
21
open List
 
22
open Util
 
23
open Expr
 
24
open Variable
 
25
open Number
 
26
open VSimdBasics
 
27
open VSimdUnparsing
 
28
open VScheduler
 
29
open VAnnotatedScheduler
 
30
open K7Basics
 
31
open K7RegisterAllocationBasics
 
32
open K7RegisterReallocation
 
33
open K7Unparsing
 
34
open K7Translate
 
35
open K7FlatInstructionScheduling
 
36
open K7InstructionSchedulingBasics
 
37
open Printf
 
38
open AssignmentsToVfpinstrs
 
39
open Complex
 
40
 
 
41
let vect_schedule vect_optimized =
 
42
  let _ = info "vectorized scheduling..." in
 
43
  let vect_scheduled = schedule vect_optimized in
 
44
  let _ = info "vectorized annotating..." in
 
45
  let vect_annotated = annotate vect_scheduled in
 
46
  let _ = info "vectorized linearizing..." in
 
47
    annotatedscheduleToVsimdinstrs vect_annotated
 
48
 
 
49
let vect_optimize varinfo n dag =
 
50
  let _ = info "simplifying..." in
 
51
  let optim = Algsimp.algsimp dag in
 
52
  let alist = To_alist.to_assignments optim in
 
53
 
 
54
(*
 
55
  let _ = 
 
56
    List.iter
 
57
      (fun x -> Printf.printf "%s\n" (Expr.assignment_to_string x)) 
 
58
      alist
 
59
  in 
 
60
*)
 
61
 
 
62
  let _ = info "mapping assignments to vfpinstrs..." in
 
63
  let code1 = AssignmentsToVfpinstrs.assignmentsToVfpinstrs varinfo alist in
 
64
  let _ = info "vectorizing..." in
 
65
  let (operandsize,code2) = K7Vectorization.vectorize varinfo n code1 in
 
66
 
 
67
  let _ = info "optimizing..." in
 
68
  let code3 = VK7Optimization.apply_optrules code2 in
 
69
 
 
70
  let code4 = vect_schedule code3 in
 
71
 
 
72
  let _ = info "improving..." in
 
73
  let code5 = VImproveSchedule.improve_schedule code4 in
 
74
 
 
75
(*
 
76
  let _ = 
 
77
    List.iter
 
78
      (fun x -> Printf.printf "%s\n" (VFpUnparsing.vfpinstrToString x)) 
 
79
      code1
 
80
  in
 
81
*)
 
82
 
 
83
(*
 
84
  let _ = 
 
85
    List.iter
 
86
      (fun x -> Printf.printf "%s\n" (VSimdUnparsing.vsimdinstrToString x)) 
 
87
      code2
 
88
  in
 
89
*)
 
90
  (operandsize, code5)
 
91
 
 
92
 
 
93
(****************************************************************************)
 
94
 
 
95
let get2ndhalfcode base one dst ld_n = 
 
96
  if ld_n < 0 then
 
97
    [K7V_IntCpyUnaryOp(K7_ICopy, base, dst)]
 
98
    (* issue a warning or sth similar *)
 
99
    (* failwith "get2ndhalfcode: ld_n < 0 not supported!" *)
 
100
  else if ld_n <= 3 then
 
101
    [K7V_IntLoadEA(K7V_RISID(base,one,1 lsl ld_n,0), dst)]
 
102
  else
 
103
    [K7V_IntCpyUnaryOp(K7_ICopy, one, dst);
 
104
     K7V_IntUnaryOp(K7_IShlImm ld_n, dst);
 
105
     K7V_IntBinOp(K7_IAdd, base, dst)]
 
106
 
 
107
 
 
108
let loadfnargs xs = map (fun (src,dst) -> (dst, [K7V_IntLoadMem(src,dst)])) xs
 
109
 
 
110
(****************************************************************************)
 
111
let asmline x = print_string (x ^ "\n")
 
112
 
 
113
(* Warning: this function produces side-effects. *)
 
114
let emit_instr (_,_,instr) = 
 
115
  k7rinstrAdaptStackPointerAdjustment instr;
 
116
  asmline (K7Unparsing.k7rinstrToString instr)
 
117
 
 
118
let emit_instr' (t,cplen,i) = 
 
119
  k7rinstrAdaptStackPointerAdjustment i;
 
120
  Printf.printf "\t/*  t=%d, cp=%d  */\t" t cplen;
 
121
  print_string (K7Unparsing.k7rinstrToString i);
 
122
  print_newline ()
 
123
 
 
124
let emit_instr0' i = 
 
125
  k7rinstrAdaptStackPointerAdjustment i;
 
126
  Printf.printf "\t/*  t=?, cp=?  */\t";
 
127
  print_string (K7Unparsing.k7rinstrToString i);
 
128
  print_newline ()
 
129
 
 
130
let emit_instrk7v' i = 
 
131
  Printf.printf "\t/*  t=?, cp=?  */\t";
 
132
  print_string (K7Unparsing.k7vinstrToString i);
 
133
  print_newline ()
 
134
 
 
135
let emit_instrv' i = 
 
136
  Printf.printf "\t/*  t=?, cp=?  */\t";
 
137
  print_string (VSimdUnparsing.vsimdinstrToString i);
 
138
  print_newline ()
 
139
 
 
140
(****************************************************************************)
 
141
 
 
142
 
 
143
(* determine stackframe size in bytes *)
 
144
let getStackFrameSize instrs =
 
145
  let processInstr ((operand_size_bytes,max_bytes) as s0) = function
 
146
    | K7R_SimdSpill(_,idx) -> 
 
147
        (operand_size_bytes, max max_bytes ((idx+1) * operand_size_bytes))
 
148
    | K7R_SimdPromiseCellSize operand_size ->
 
149
        (k7operandsizeToInteger operand_size, max_bytes)
 
150
    | _ -> s0 in
 
151
 
 
152
  snd (fold_left processInstr (k7operandsizeToInteger K7_QWord,min_int) instrs)
 
153
                        
 
154
(****************************************************************************)
 
155
 
 
156
type simdconstant = 
 
157
  | SC_NumberPair of Number.number * Number.number
 
158
  | SC_SimdPos of vsimdpos
 
159
 
 
160
let eq_numberpair (n,m) (n',m') = 
 
161
  Number.equal n n' && Number.equal m m'
 
162
 
 
163
let eq_simdconstant a b = match (a,b) with
 
164
  | (SC_SimdPos a, SC_SimdPos b) ->
 
165
      a=b
 
166
  | (SC_NumberPair(n,m), SC_NumberPair(n',m')) -> 
 
167
      eq_numberpair (n,m) (n',m')
 
168
  | _ -> 
 
169
      false
 
170
 
 
171
let k7rinstrsToConstants = 
 
172
  let rec rinstrsToConsts bag = function
 
173
    | [] -> List.rev bag
 
174
    | x::xs ->
 
175
        (match x with
 
176
          | K7R_SimdUnaryOp(K7_FPChs p,_)
 
177
            when not (exists (eq_simdconstant (SC_SimdPos p)) bag) ->
 
178
              rinstrsToConsts ((SC_SimdPos p)::bag) xs 
 
179
          | K7R_SimdUnaryOp(K7_FPMulConst(n,m),_)
 
180
            when not (exists (eq_simdconstant (SC_NumberPair (n,m))) bag) ->
 
181
              rinstrsToConsts ((SC_NumberPair (n,m))::bag) xs 
 
182
          | _ -> rinstrsToConsts bag xs)
 
183
  in rinstrsToConsts []
 
184
 
 
185
let myconst_to_decl = function
 
186
  | SC_SimdPos V_Lo -> 
 
187
      (vsimdposToChsconstnamestring V_Lo)   ^ ": .long 0x80000000, 0x00000000"
 
188
  | SC_SimdPos V_Hi -> 
 
189
      (vsimdposToChsconstnamestring V_Hi)   ^ ": .long 0x00000000, 0x80000000"
 
190
  | SC_SimdPos V_LoHi -> 
 
191
      (vsimdposToChsconstnamestring V_LoHi) ^ ": .long 0x80000000, 0x80000000"
 
192
  | SC_NumberPair(n,m) ->
 
193
      sprintf "%s%s: .float %s, %s"
 
194
              (Number.to_konst n)
 
195
              (Number.to_konst m)
 
196
              (Number.to_string n)
 
197
              (Number.to_string m)
 
198
 
 
199
(****************************************************************************)
 
200
 
 
201
let instr_wants_down_pass1 = function
 
202
  | K7R_SimdPromiseCellSize _ -> false
 
203
  | K7R_SimdLoadStoreBarrier -> true
 
204
  | K7R_IntLoadMem _ -> true
 
205
  | K7R_IntStoreMem _ -> false
 
206
  | K7R_IntLoadEA _ -> true
 
207
  | K7R_IntUnaryOp _ -> true
 
208
  | K7R_IntUnaryOpMem _ -> true
 
209
  | K7R_IntCpyUnaryOp _ -> true
 
210
  | K7R_IntBinOp _ -> true
 
211
  | K7R_IntBinOpMem _ -> true
 
212
  | K7R_SimdLoad _ -> true
 
213
  | K7R_SimdStore _ -> false
 
214
  | K7R_SimdSpill _ -> false
 
215
  | K7R_SimdUnaryOp(K7_FPMulConst _,_) -> false
 
216
  | K7R_SimdUnaryOp _ -> true
 
217
  | K7R_SimdCpyUnaryOp _ -> true
 
218
  | K7R_SimdCpyUnaryOpMem _ -> true
 
219
  | K7R_SimdBinOp _ -> false
 
220
  | K7R_SimdBinOpMem _ -> false
 
221
  | K7R_Label _ -> false
 
222
  | K7R_Jump _ -> false
 
223
  | K7R_CondBranch _ -> false
 
224
  | K7R_FEMMS -> false
 
225
  | K7R_Ret -> false
 
226
 
 
227
let instr_wants_down_pass2 = function
 
228
  | K7R_SimdCpyUnaryOpMem _ -> false
 
229
  | instr -> instr_wants_down_pass1 instr
 
230
 
 
231
let rec move_down_instrs instr_wants_down = 
 
232
  let rec moveonedown i = function
 
233
    | [] -> [i]
 
234
    | x::xs as xxs -> 
 
235
        if k7rinstrCannotRollOverK7rinstr (get3of3 i) (get3of3 x) then 
 
236
          i::xxs 
 
237
        else 
 
238
          x::(moveonedown i xs)
 
239
  in function
 
240
    | [] -> []
 
241
    | x::xs -> 
 
242
        let xs' = move_down_instrs instr_wants_down xs in
 
243
          if instr_wants_down (get3of3 x) then moveonedown x xs' else x::xs'
 
244
 
 
245
(****************************************************************************)
 
246
 
 
247
let k7rinstrIsAGIMovable = function
 
248
  | K7R_SimdLoad _ -> true
 
249
  | K7R_SimdStore _ -> true
 
250
  | K7R_SimdCpyUnaryOpMem _ -> true
 
251
  | K7R_SimdBinOpMem _ -> true
 
252
  | K7R_SimdSpill _ -> true
 
253
  | _ -> false
 
254
 
 
255
let k7rinstrCanMoveOverAGI a b = match (a,b) with
 
256
  | (K7R_SimdLoad _, K7R_SimdStore _) -> true
 
257
  | (K7R_SimdLoad _, K7R_SimdCpyUnaryOpMem _) -> true
 
258
  | (K7R_SimdLoad _, K7R_SimdSpill _) -> true
 
259
  | (K7R_SimdLoad _, K7R_SimdBinOpMem _) -> true
 
260
  | (K7R_SimdLoad _, K7R_SimdUnaryOp _) -> true
 
261
  | (K7R_SimdCpyUnaryOpMem _, K7R_SimdSpill _) -> true
 
262
  | (K7R_SimdUnaryOp _, K7R_SimdSpill _) -> true
 
263
  | (K7R_SimdStore _, K7R_SimdBinOpMem _) -> true
 
264
  | (K7R_SimdStore _, K7R_SimdCpyUnaryOpMem _) -> true
 
265
  | (K7R_SimdStore _, K7R_SimdSpill _) -> true
 
266
  | (K7R_SimdStore _, K7R_SimdUnaryOp _) -> true
 
267
  | _ -> false
 
268
 
 
269
let avoid_address_generation_interlock instrs = 
 
270
  let stop (_,_,x) (_,_,y) = 
 
271
    k7rinstrCannotRollOverK7rinstr x y || 
 
272
    (not (k7rinstrCanMoveOverAGI x y)) in
 
273
  let rec loop = function
 
274
    | [] -> []
 
275
    | ((_,_,instr) as x)::xs ->
 
276
        if k7rinstrIsAGIMovable instr then
 
277
          insertList stop x (loop xs)
 
278
        else
 
279
          x::(loop xs)
 
280
  in loop instrs
 
281
 
 
282
(****************************************************************************)
 
283
 
 
284
let k7rinstrsToPromiseEarly xs =
 
285
  let flag = ref false in
 
286
  let rec k7rinstrsToPromiseEarly__int = function
 
287
    | [] -> []
 
288
    | (K7R_Label _ as x1)::(K7R_SimdPromiseCellSize _ as x2)::xs ->
 
289
        x1::x2::(k7rinstrsToPromiseEarly__int xs)
 
290
    | x1::(K7R_SimdPromiseCellSize _ as x2)::xs ->
 
291
        flag := true;
 
292
        x2::(k7rinstrsToPromiseEarly__int (x1::xs))
 
293
    | x::xs ->
 
294
        x::(k7rinstrsToPromiseEarly__int xs)
 
295
  in (!flag,k7rinstrsToPromiseEarly__int xs)
 
296
 
 
297
 
 
298
let rec optimize ref_t0 instrs0 =
 
299
  let _ = info (sprintf "optimizing: len %d, ref_t %d." 
 
300
                        (length instrs0) ref_t0) in
 
301
  let instrs1 = k7rinstrsToRegisterReallocated
 
302
                  (move_down_instrs 
 
303
                        instr_wants_down_pass2
 
304
                        (move_down_instrs instr_wants_down_pass1 instrs0)) in
 
305
  let instrs = k7rinstrsToInstructionscheduled instrs1 in
 
306
  let (ref_t,_,_) = list_last instrs in
 
307
    if ref_t < ref_t0 then
 
308
      optimize ref_t instrs
 
309
    else
 
310
      instrs0
 
311
 
 
312
(****************************************************************************)
 
313
 
 
314
let rec addIndexToListElems i0 = function
 
315
  | [] -> []
 
316
  | x::xs -> (i0,x)::(addIndexToListElems (succ i0) xs)
 
317
 
 
318
let procedure_proepilog stackframe_size_bytes nargs code = 
 
319
  let regs_to_save =
 
320
        addIndexToListElems 1
 
321
                (filter (fun r -> exists (k7rinstrUsesK7rintreg r) code) 
 
322
                        k7rintregs_calleesaved) in
 
323
  let total_stackframe_size = 
 
324
    0 + (if true || (nargs mod 2 = 1) then 4 else 0)
 
325
      + (if stackframe_size_bytes < 0 then 0 else stackframe_size_bytes) 
 
326
      + (if regs_to_save = [] then 0 else 16) in
 
327
  [K7R_FEMMS] @
 
328
  (if total_stackframe_size > 0 then 
 
329
     [K7R_IntUnaryOp(K7_ISubImm total_stackframe_size, k7rintreg_stackpointer)]
 
330
   else
 
331
     []) @
 
332
  (map (fun (i,r) -> K7R_IntStoreMem(r,K7_MFunArg (-i))) regs_to_save) @
 
333
  code @
 
334
  (map (fun (i,r) -> K7R_IntLoadMem(K7_MFunArg (-i), r)) regs_to_save) @
 
335
  (if total_stackframe_size > 0 then 
 
336
     [K7R_IntUnaryOp(K7_IAddImm total_stackframe_size, k7rintreg_stackpointer)]
 
337
   else
 
338
     []) @
 
339
  [K7R_FEMMS; K7R_Ret]
 
340
 
 
341
(****************************************************************************)
 
342
let datasection all_consts =
 
343
  if all_consts <> [] then begin
 
344
    asmline (".section .rodata");
 
345
    asmline ("\t" ^ ".balign 64");
 
346
    List.iter (fun c -> asmline (myconst_to_decl c)) all_consts;
 
347
    asmline (".text");
 
348
  end
 
349
 
 
350
let compileToAsm name nargs (initcode, k7vinstrs) =
 
351
  let _ = info "compileToAsm..." in
 
352
  let realcode = K7RegisterAllocator.regalloc initcode k7vinstrs in
 
353
  let stackframe_size_bytes = getStackFrameSize realcode in
 
354
  let realcode = procedure_proepilog stackframe_size_bytes nargs realcode in
 
355
  let _ = info "scheduling instructions..." in
 
356
  let realcode = fixpoint k7rinstrsToPromiseEarly realcode in
 
357
  let realcode' =
 
358
      avoid_address_generation_interlock 
 
359
          (optimize 1000000 (k7rinstrsToInstructionscheduled realcode)) in
 
360
 
 
361
  let _ = info "before unparseToAsm" in
 
362
  let all_consts = k7rinstrsToConstants (map get3of3 realcode') in
 
363
  begin
 
364
    (* preserve Stefan's copyright, which otherwise does not appear
 
365
       anywhere else *)
 
366
    print_string ("/* The following asm code is Copyright (c) 2000-2001 Stefan Kral */\n");
 
367
    datasection all_consts;
 
368
    k7rinstrInitStackPointerAdjustment 0;
 
369
    asmline ".text";
 
370
    asmline "\t.balign 64";
 
371
    asmline (name ^ ":");
 
372
    iter emit_instr realcode';
 
373
  end
 
374
 
 
375
(******************************************************************)
 
376
 
 
377
let standard_arg_parse_fail _ = failwith "too many arguments"
 
378
 
 
379
 
 
380
let size = ref None
 
381
let sign = ref (-1)
 
382
 
 
383
let speclist = [
 
384
  "-n", Arg.Int(fun i -> size := Some i), " generate a codelet of size <n>";
 
385
  "-sign",
 
386
  Arg.Int(fun i -> 
 
387
    if (i > 0) then
 
388
      sign := 1
 
389
    else
 
390
      sign := (-1)),
 
391
  " sign of transform";
 
392
]
 
393
 
 
394
let parse user_speclist usage =
 
395
  Arg.parse 
 
396
    (user_speclist @ speclist @ Magic.speclist)
 
397
    standard_arg_parse_fail 
 
398
    usage
 
399
 
 
400
let check_size () =
 
401
  match !size with
 
402
  | Some i -> i
 
403
  | None -> failwith "must specify -n"
 
404
 
 
405
let register_fcn name =  "fftwf_codelet_" ^ name
 
406
 
 
407
(* output the command line *)
 
408
let cmdline () =
 
409
  fold_right (fun a b -> a ^ " " ^ b) (Array.to_list Sys.argv) ""
 
410
 
 
411
let boilerplate cvsid =
 
412
  Printf.printf "%s"
 
413
    ("/* Generated by: " ^ (cmdline ()) ^ "*/\n\n" ^
 
414
     "/*\n" ^
 
415
     " * Generator Id's : \n" ^
 
416
     " * " ^ Algsimp.cvsid ^ "\n" ^
 
417
     " * " ^ Fft.cvsid ^ "\n" ^
 
418
     " * " ^ cvsid ^ "\n" ^
 
419
     " */\n\n")
 
420
 
 
421
 
 
422
 
 
423
let store_array_c n f =
 
424
  List.flatten
 
425
    (List.map (fun i -> store_var (access_output i) (f i)) (iota n))
 
426
 
 
427
let load_array_c n =
 
428
  array n (fun i -> load_var (access_input i))
 
429
 
 
430
let load_constant_array_c n =
 
431
  array n (fun i -> load_var (access_twiddle i))