462 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			OCaml
		
	
	
	
	
	
		
		
			
		
	
	
			462 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			OCaml
		
	
	
	
	
	
| 
								 | 
							
								(*
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2003, 2007-14 Matteo Frigo
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is free software; you can redistribute it and/or modify
							 | 
						||
| 
								 | 
							
								 * it under the terms of the GNU General Public License as published by
							 | 
						||
| 
								 | 
							
								 * the Free Software Foundation; either version 2 of the License, or
							 | 
						||
| 
								 | 
							
								 * (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								 * but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						||
| 
								 | 
							
								 * GNU General Public License for more details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * You should have received a copy of the GNU General Public License
							 | 
						||
| 
								 | 
							
								 * along with this program; if not, write to the Free Software
							 | 
						||
| 
								 | 
							
								 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(*
							 | 
						||
| 
								 | 
							
								 * This module contains the definition of a C-like abstract
							 | 
						||
| 
								 | 
							
								 * syntax tree, and functions to convert ML values into C
							 | 
						||
| 
								 | 
							
								 * programs
							 | 
						||
| 
								 | 
							
								 *)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								open Expr
							 | 
						||
| 
								 | 
							
								open Annotate
							 | 
						||
| 
								 | 
							
								open List
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let realtype = "R"
							 | 
						||
| 
								 | 
							
								let realtypep = realtype ^ " *"
							 | 
						||
| 
								 | 
							
								let extended_realtype = "E"
							 | 
						||
| 
								 | 
							
								let constrealtype = "const " ^ realtype
							 | 
						||
| 
								 | 
							
								let constrealtypep = constrealtype ^ " *"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let stridetype = "stride"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(***********************************
							 | 
						||
| 
								 | 
							
								 * C program structure 
							 | 
						||
| 
								 | 
							
								 ***********************************)
							 | 
						||
| 
								 | 
							
								type c_decl = 
							 | 
						||
| 
								 | 
							
								  | Decl of string * string
							 | 
						||
| 
								 | 
							
								  | Tdecl of string                (* arbitrary text declaration *)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and c_ast =
							 | 
						||
| 
								 | 
							
								  | Asch of annotated_schedule
							 | 
						||
| 
								 | 
							
								  | Simd_leavefun
							 | 
						||
| 
								 | 
							
								  | Return of c_ast
							 | 
						||
| 
								 | 
							
								  | For of c_ast * c_ast * c_ast * c_ast
							 | 
						||
| 
								 | 
							
								  | If of c_ast * c_ast
							 | 
						||
| 
								 | 
							
								  | Block of (c_decl list) * (c_ast list)
							 | 
						||
| 
								 | 
							
								  | Binop of string * c_ast * c_ast
							 | 
						||
| 
								 | 
							
								  | Expr_assign of c_ast * c_ast
							 | 
						||
| 
								 | 
							
								  | Stmt_assign of c_ast * c_ast
							 | 
						||
| 
								 | 
							
								  | Comma of c_ast * c_ast
							 | 
						||
| 
								 | 
							
								  | Integer of int
							 | 
						||
| 
								 | 
							
								  | CVar of string
							 | 
						||
| 
								 | 
							
								  | CCall of string * c_ast
							 | 
						||
| 
								 | 
							
								  | CPlus of c_ast list
							 | 
						||
| 
								 | 
							
								  | ITimes of c_ast * c_ast
							 | 
						||
| 
								 | 
							
								  | CUminus of c_ast
							 | 
						||
| 
								 | 
							
								and c_fcn = Fcn of string * string * (c_decl list) * c_ast
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let ctimes = function
							 | 
						||
| 
								 | 
							
								  | (Integer 1), a -> a
							 | 
						||
| 
								 | 
							
								  | a, (Integer 1) -> a
							 | 
						||
| 
								 | 
							
								  | a, b -> ITimes (a, b)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(*
							 | 
						||
| 
								 | 
							
								 * C AST unparser 
							 | 
						||
| 
								 | 
							
								 *)
							 | 
						||
| 
								 | 
							
								let foldr_string_concat l = fold_right (^) l ""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let rec unparse_expr_c =
							 | 
						||
| 
								 | 
							
								  let yes x = x and no x = "" in
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let rec unparse_plus maybe = 
							 | 
						||
| 
								 | 
							
								    let maybep = maybe " + " in
							 | 
						||
| 
								 | 
							
								    function
							 | 
						||
| 
								 | 
							
								    | [] -> ""
							 | 
						||
| 
								 | 
							
								    | (Uminus (Times (a, b))) :: (Uminus c) :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FNMA" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | (Uminus c) :: (Uminus (Times (a, b))) :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FNMA" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | (Uminus (Times (a, b))) :: c :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FNMS" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | c :: (Uminus (Times (a, b))) :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FNMS" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | (Times (a, b)) :: (Uminus c) :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FMS" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | (Uminus c) :: (Times (a, b)) :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FMS" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | (Times (a, b)) :: c :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FMA" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | c :: (Times (a, b)) :: d -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (op "FMA" a b c) ^ (unparse_plus yes d)
							 | 
						||
| 
								 | 
							
								    | (Uminus a :: b) -> 
							 | 
						||
| 
								 | 
							
									" - " ^ (parenthesize a) ^ (unparse_plus yes b)
							 | 
						||
| 
								 | 
							
								    | (a :: b) -> 
							 | 
						||
| 
								 | 
							
									maybep ^ (parenthesize a) ^ (unparse_plus yes b)
							 | 
						||
| 
								 | 
							
								  and parenthesize x = match x with
							 | 
						||
| 
								 | 
							
								  | (Load _) -> unparse_expr_c x
							 | 
						||
| 
								 | 
							
								  | (Num _) -> unparse_expr_c x
							 | 
						||
| 
								 | 
							
								  | _ -> "(" ^ (unparse_expr_c x) ^ ")"
							 | 
						||
| 
								 | 
							
								  and op nam a b c =
							 | 
						||
| 
								 | 
							
								    nam ^ "(" ^ (unparse_expr_c a) ^ ", " ^ (unparse_expr_c b) ^ ", " ^
							 | 
						||
| 
								 | 
							
								    (unparse_expr_c c) ^ ")"
							 | 
						||
| 
								 | 
							
								      			      
							 | 
						||
| 
								 | 
							
								  in function
							 | 
						||
| 
								 | 
							
								    | Load v -> Variable.unparse v
							 | 
						||
| 
								 | 
							
								    | Num n -> Number.to_konst n
							 | 
						||
| 
								 | 
							
								    | Plus [] -> "0.0 /* bug */"
							 | 
						||
| 
								 | 
							
								    | Plus [a] -> " /* bug */ " ^ (unparse_expr_c a)
							 | 
						||
| 
								 | 
							
								    | Plus a -> (unparse_plus no a)
							 | 
						||
| 
								 | 
							
								    | Times (a, b) -> (parenthesize a) ^ " * " ^ (parenthesize b)
							 | 
						||
| 
								 | 
							
								    | Uminus (Plus [a; Uminus b]) -> unparse_plus no [b; Uminus a]
							 | 
						||
| 
								 | 
							
								    | Uminus a -> "- " ^ (parenthesize a)
							 | 
						||
| 
								 | 
							
								    | _ -> failwith "unparse_expr_c"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and unparse_expr_generic = 
							 | 
						||
| 
								 | 
							
								  let rec u x = unparse_expr_generic x
							 | 
						||
| 
								 | 
							
								  and unary op a = Printf.sprintf "%s(%s)" op (u a)
							 | 
						||
| 
								 | 
							
								  and binary op a b = Printf.sprintf "%s(%s, %s)" op (u a) (u b)
							 | 
						||
| 
								 | 
							
								  and ternary op a b c = Printf.sprintf "%s(%s, %s, %s)" op (u a) (u b) (u c)
							 | 
						||
| 
								 | 
							
								  and quaternary op a b c d = 
							 | 
						||
| 
								 | 
							
								    Printf.sprintf "%s(%s, %s, %s, %s)" op (u a) (u b) (u c) (u d)
							 | 
						||
| 
								 | 
							
								  and unparse_plus = function
							 | 
						||
| 
								 | 
							
								    | [(Uminus (Times (a, b))); Times (c, d)] -> quaternary "FNMMS" a b c d
							 | 
						||
| 
								 | 
							
								    | [Times (c, d); (Uminus (Times (a, b)))] -> quaternary "FNMMS" a b c d
							 | 
						||
| 
								 | 
							
								    | [Times (c, d); (Times (a, b))] -> quaternary "FMMA" a b c d
							 | 
						||
| 
								 | 
							
								    | [(Uminus (Times (a, b))); c] -> ternary "FNMS" a b c
							 | 
						||
| 
								 | 
							
								    | [c; (Uminus (Times (a, b)))] -> ternary "FNMS" a b c
							 | 
						||
| 
								 | 
							
								    | [(Uminus c); (Times (a, b))] -> ternary "FMS" a b c
							 | 
						||
| 
								 | 
							
								    | [(Times (a, b)); (Uminus c)] -> ternary "FMS" a b c
							 | 
						||
| 
								 | 
							
								    | [c; (Times (a, b))] -> ternary "FMA" a b c
							 | 
						||
| 
								 | 
							
								    | [(Times (a, b)); c] -> ternary "FMA" a b c
							 | 
						||
| 
								 | 
							
								    | [a; Uminus b] -> binary "SUB" a b
							 | 
						||
| 
								 | 
							
								    | [a; b] -> binary "ADD" a b
							 | 
						||
| 
								 | 
							
								    | a :: b :: c -> binary "ADD" a (Plus (b :: c))
							 | 
						||
| 
								 | 
							
								    | _ -> failwith "unparse_plus"
							 | 
						||
| 
								 | 
							
								  in function
							 | 
						||
| 
								 | 
							
								    | Load v -> Variable.unparse v 
							 | 
						||
| 
								 | 
							
								    | Num n -> Number.to_konst n
							 | 
						||
| 
								 | 
							
								    | Plus a -> unparse_plus a
							 | 
						||
| 
								 | 
							
								    | Times (a, b) -> binary "MUL" a b
							 | 
						||
| 
								 | 
							
								    | Uminus a -> unary "NEG" a
							 | 
						||
| 
								 | 
							
								    | _ -> failwith "unparse_expr"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and unparse_expr x = 
							 | 
						||
| 
								 | 
							
								  if !Magic.generic_arith then
							 | 
						||
| 
								 | 
							
								    unparse_expr_generic x
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    unparse_expr_c x
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and unparse_assignment (Assign (v, x)) =
							 | 
						||
| 
								 | 
							
								  (Variable.unparse v) ^ " = " ^ (unparse_expr x) ^ ";\n"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and unparse_annotated force_bracket = 
							 | 
						||
| 
								 | 
							
								  let rec unparse_code = function
							 | 
						||
| 
								 | 
							
								      ADone -> ""
							 | 
						||
| 
								 | 
							
								    | AInstr i -> unparse_assignment i
							 | 
						||
| 
								 | 
							
								    | ASeq (a, b) -> 
							 | 
						||
| 
								 | 
							
								        (unparse_annotated false a) ^ (unparse_annotated false b)
							 | 
						||
| 
								 | 
							
								  and declare_variables l = 
							 | 
						||
| 
								 | 
							
								    let rec uvar = function
							 | 
						||
| 
								 | 
							
									[] -> failwith "uvar"
							 | 
						||
| 
								 | 
							
								      |	[v] -> (Variable.unparse v) ^ ";\n"
							 | 
						||
| 
								 | 
							
								      | a :: b -> (Variable.unparse a) ^ ", " ^ (uvar b)
							 | 
						||
| 
								 | 
							
								    in let rec vvar l = 
							 | 
						||
| 
								 | 
							
								      let s = if !Magic.compact then 15 else 1 in
							 | 
						||
| 
								 | 
							
								      if (List.length l <= s) then
							 | 
						||
| 
								 | 
							
									match l with
							 | 
						||
| 
								 | 
							
									  [] -> ""
							 | 
						||
| 
								 | 
							
									| _ -> extended_realtype ^ " " ^ (uvar l)
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
									(vvar (Util.take s l)) ^ (vvar (Util.drop s l))
							 | 
						||
| 
								 | 
							
								    in vvar (List.filter Variable.is_temporary l)
							 | 
						||
| 
								 | 
							
								  in function
							 | 
						||
| 
								 | 
							
								      Annotate (_, _, decl, _, code) ->
							 | 
						||
| 
								 | 
							
								        if (not force_bracket) && (Util.null decl) then 
							 | 
						||
| 
								 | 
							
								          unparse_code code
							 | 
						||
| 
								 | 
							
								        else "{\n" ^
							 | 
						||
| 
								 | 
							
								          (declare_variables decl) ^
							 | 
						||
| 
								 | 
							
								          (unparse_code code) ^
							 | 
						||
| 
								 | 
							
									  "}\n"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and unparse_decl = function
							 | 
						||
| 
								 | 
							
								  | Decl (a, b) -> a ^ " " ^ b ^ ";\n"
							 | 
						||
| 
								 | 
							
								  | Tdecl x -> x
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and unparse_ast = 
							 | 
						||
| 
								 | 
							
								  let rec unparse_plus = function
							 | 
						||
| 
								 | 
							
								    | [] -> ""
							 | 
						||
| 
								 | 
							
								    | (CUminus a :: b) -> " - " ^ (parenthesize a) ^ (unparse_plus b)
							 | 
						||
| 
								 | 
							
								    | (a :: b) -> " + " ^ (parenthesize a) ^ (unparse_plus b)
							 | 
						||
| 
								 | 
							
								  and parenthesize x = match x with
							 | 
						||
| 
								 | 
							
								  | (CVar _) -> unparse_ast x
							 | 
						||
| 
								 | 
							
								  | (CCall _) -> unparse_ast x
							 | 
						||
| 
								 | 
							
								  | (Integer _) -> unparse_ast x
							 | 
						||
| 
								 | 
							
								  | _ -> "(" ^ (unparse_ast x) ^ ")"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  in
							 | 
						||
| 
								 | 
							
								  function
							 | 
						||
| 
								 | 
							
								    | Asch a -> (unparse_annotated true a)
							 | 
						||
| 
								 | 
							
								    | Simd_leavefun -> "" (* used only in SIMD code *)
							 | 
						||
| 
								 | 
							
								    | Return x -> "return " ^ unparse_ast x ^ ";"
							 | 
						||
| 
								 | 
							
								    | For (a, b, c, d) ->
							 | 
						||
| 
								 | 
							
									"for (" ^
							 | 
						||
| 
								 | 
							
									unparse_ast a ^ "; " ^ unparse_ast b ^ "; " ^ unparse_ast c
							 | 
						||
| 
								 | 
							
									^ ")" ^ unparse_ast d
							 | 
						||
| 
								 | 
							
								    | If (a, d) ->
							 | 
						||
| 
								 | 
							
									"if (" ^
							 | 
						||
| 
								 | 
							
									unparse_ast a 
							 | 
						||
| 
								 | 
							
									^ ")" ^ unparse_ast d
							 | 
						||
| 
								 | 
							
								    | Block (d, s) ->
							 | 
						||
| 
								 | 
							
									if (s == []) then ""
							 | 
						||
| 
								 | 
							
									else 
							 | 
						||
| 
								 | 
							
								          "{\n"                                      ^ 
							 | 
						||
| 
								 | 
							
								          foldr_string_concat (map unparse_decl d)   ^ 
							 | 
						||
| 
								 | 
							
								          foldr_string_concat (map unparse_ast s)    ^
							 | 
						||
| 
								 | 
							
								          "}\n"      
							 | 
						||
| 
								 | 
							
								    | Binop (op, a, b) -> (unparse_ast a) ^ op ^ (unparse_ast b)
							 | 
						||
| 
								 | 
							
								    | Expr_assign (a, b) -> (unparse_ast a) ^ " = " ^ (unparse_ast b)
							 | 
						||
| 
								 | 
							
								    | Stmt_assign (a, b) -> (unparse_ast a) ^ " = " ^ (unparse_ast b) ^ ";\n"
							 | 
						||
| 
								 | 
							
								    | Comma (a, b) -> (unparse_ast a) ^ ", " ^ (unparse_ast b)
							 | 
						||
| 
								 | 
							
								    | Integer i -> string_of_int i
							 | 
						||
| 
								 | 
							
								    | CVar s -> s
							 | 
						||
| 
								 | 
							
								    | CCall (s, x) -> s ^ "(" ^ (unparse_ast x) ^ ")"
							 | 
						||
| 
								 | 
							
								    | CPlus [] -> "0 /* bug */"
							 | 
						||
| 
								 | 
							
								    | CPlus [a] -> " /* bug */ " ^ (unparse_ast a)
							 | 
						||
| 
								 | 
							
								    | CPlus (a::b) -> (parenthesize a) ^ (unparse_plus b)
							 | 
						||
| 
								 | 
							
								    | ITimes (a, b) -> (parenthesize a) ^ " * " ^ (parenthesize b)
							 | 
						||
| 
								 | 
							
								    | CUminus a -> "- " ^ (parenthesize a)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and unparse_function = function
							 | 
						||
| 
								 | 
							
								    Fcn (typ, name, args, body) ->
							 | 
						||
| 
								 | 
							
								      let rec unparse_args = function
							 | 
						||
| 
								 | 
							
								          [Decl (a, b)] -> a ^ " " ^ b 
							 | 
						||
| 
								 | 
							
									| (Decl (a, b)) :: s -> a ^ " " ^ b  ^ ", "
							 | 
						||
| 
								 | 
							
								            ^  unparse_args s
							 | 
						||
| 
								 | 
							
									| [] -> ""
							 | 
						||
| 
								 | 
							
									| _ -> failwith "unparse_function"
							 | 
						||
| 
								 | 
							
								      in 
							 | 
						||
| 
								 | 
							
								      (typ ^ " " ^ name ^ "(" ^ unparse_args args ^ ")\n" ^
							 | 
						||
| 
								 | 
							
								       unparse_ast body)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(*************************************************************
							 | 
						||
| 
								 | 
							
								 * traverse a a function and return a list of all expressions,
							 | 
						||
| 
								 | 
							
								 * in the execution order
							 | 
						||
| 
								 | 
							
								 **************************************************************)
							 | 
						||
| 
								 | 
							
								let rec fcn_to_expr_list = fun (Fcn (_, _, _, body)) -> ast_to_expr_list body 
							 | 
						||
| 
								 | 
							
								and acode_to_expr_list = function
							 | 
						||
| 
								 | 
							
								    AInstr (Assign (_, x)) -> [x]
							 | 
						||
| 
								 | 
							
								  | ASeq (a, b) -> 
							 | 
						||
| 
								 | 
							
								      (asched_to_expr_list a) @ (asched_to_expr_list b)
							 | 
						||
| 
								 | 
							
								  | _ -> []
							 | 
						||
| 
								 | 
							
								and asched_to_expr_list (Annotate (_, _, _, _, code)) =
							 | 
						||
| 
								 | 
							
								  acode_to_expr_list code
							 | 
						||
| 
								 | 
							
								and ast_to_expr_list = function
							 | 
						||
| 
								 | 
							
								    Asch a -> asched_to_expr_list a
							 | 
						||
| 
								 | 
							
								  | Block (_, a) -> flatten (map ast_to_expr_list a)
							 | 
						||
| 
								 | 
							
								  | For (_, _, _, body) ->  ast_to_expr_list body
							 | 
						||
| 
								 | 
							
								  | If (_, body) ->  ast_to_expr_list body
							 | 
						||
| 
								 | 
							
								  | _ -> []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(***********************
							 | 
						||
| 
								 | 
							
								 * Extracting Constants
							 | 
						||
| 
								 | 
							
								 ***********************)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(* add a new key & value to a list of (key,value) pairs, where
							 | 
						||
| 
								 | 
							
								   the keys are floats and each key is unique up to almost_equal *)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let extract_constants f =
							 | 
						||
| 
								 | 
							
								  let constlist = flatten (map expr_to_constants (ast_to_expr_list f))
							 | 
						||
| 
								 | 
							
								  in map
							 | 
						||
| 
								 | 
							
								       (fun n ->
							 | 
						||
| 
								 | 
							
									  Tdecl 
							 | 
						||
| 
								 | 
							
									    ("DK(" ^ (Number.to_konst n) ^ ", " ^ (Number.to_string n) ^ 
							 | 
						||
| 
								 | 
							
									       ");\n"))
							 | 
						||
| 
								 | 
							
								       (unique_constants constlist)
							 | 
						||
| 
								 | 
							
								       
							 | 
						||
| 
								 | 
							
								(******************************
							 | 
						||
| 
								 | 
							
								   Extracting operation counts 
							 | 
						||
| 
								 | 
							
								 ******************************)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let count_stack_vars =
							 | 
						||
| 
								 | 
							
								  let rec count_acode = function
							 | 
						||
| 
								 | 
							
								    | ASeq (a, b) -> max (count_asched a) (count_asched b)
							 | 
						||
| 
								 | 
							
								    | _ -> 0
							 | 
						||
| 
								 | 
							
								  and count_asched (Annotate (_, _, decl, _, code)) =
							 | 
						||
| 
								 | 
							
								    (length decl) + (count_acode code)
							 | 
						||
| 
								 | 
							
								  and count_ast = function
							 | 
						||
| 
								 | 
							
								    | Asch a -> count_asched a
							 | 
						||
| 
								 | 
							
								    | Block (d, a) -> (length d) + (Util.max_list (map count_ast a))
							 | 
						||
| 
								 | 
							
								    | For (_, _, _, body) -> count_ast body
							 | 
						||
| 
								 | 
							
								    | If (_, body) -> count_ast body
							 | 
						||
| 
								 | 
							
								    | _ -> 0
							 | 
						||
| 
								 | 
							
								  in function (Fcn (_, _, _, body)) -> count_ast body
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let count_memory_acc f =
							 | 
						||
| 
								 | 
							
								  let rec count_var v =
							 | 
						||
| 
								 | 
							
								    if (Variable.is_locative v)	then 1 else 0
							 | 
						||
| 
								 | 
							
								  and count_acode = function
							 | 
						||
| 
								 | 
							
								    | AInstr (Assign (v, _)) -> count_var v
							 | 
						||
| 
								 | 
							
								    | ASeq (a, b) -> (count_asched a) + (count_asched b)
							 | 
						||
| 
								 | 
							
								    | _ -> 0
							 | 
						||
| 
								 | 
							
								  and count_asched = function
							 | 
						||
| 
								 | 
							
								      Annotate (_, _, _, _, code) -> count_acode code
							 | 
						||
| 
								 | 
							
								  and count_ast = function
							 | 
						||
| 
								 | 
							
								    | Asch a -> count_asched a
							 | 
						||
| 
								 | 
							
								    | Block (_, a) -> (Util.sum_list (map count_ast a))
							 | 
						||
| 
								 | 
							
								    | Comma (a, b) -> (count_ast a) + (count_ast b)
							 | 
						||
| 
								 | 
							
								    | For (_, _, _, body) -> count_ast body
							 | 
						||
| 
								 | 
							
								    | If (_, body) -> count_ast body
							 | 
						||
| 
								 | 
							
								    | _ -> 0
							 | 
						||
| 
								 | 
							
								  and count_acc_expr_func acc = function
							 | 
						||
| 
								 | 
							
								    | Load v -> acc + (count_var v)
							 | 
						||
| 
								 | 
							
								    | Plus a -> fold_left count_acc_expr_func acc a
							 | 
						||
| 
								 | 
							
								    | Times (a, b) -> fold_left count_acc_expr_func acc [a; b]
							 | 
						||
| 
								 | 
							
								    | Uminus a -> count_acc_expr_func acc a
							 | 
						||
| 
								 | 
							
								    | _ -> acc
							 | 
						||
| 
								 | 
							
								  in let (Fcn (typ, name, args, body)) = f
							 | 
						||
| 
								 | 
							
								  in (count_ast body) + 
							 | 
						||
| 
								 | 
							
								    fold_left count_acc_expr_func 0 (fcn_to_expr_list f)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let good_for_fma = To_alist.good_for_fma
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let build_fma = function
							 | 
						||
| 
								 | 
							
								  | [a; Times (b, c)] when good_for_fma (b, c) -> Some (a, b, c)
							 | 
						||
| 
								 | 
							
								  | [Times (b, c); a] when good_for_fma (b, c) -> Some (a, b, c)
							 | 
						||
| 
								 | 
							
								  | [a; Uminus (Times (b, c))] when good_for_fma (b, c) -> Some (a, b, c)
							 | 
						||
| 
								 | 
							
								  | [Uminus (Times (b, c)); a] when good_for_fma (b, c) -> Some (a, b, c)
							 | 
						||
| 
								 | 
							
								  | _ -> None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let rec count_flops_expr_func (adds, mults, fmas) = function
							 | 
						||
| 
								 | 
							
								  | Plus [] -> (adds, mults, fmas)
							 | 
						||
| 
								 | 
							
								  | Plus ([_; _] as a) -> 
							 | 
						||
| 
								 | 
							
								      begin
							 | 
						||
| 
								 | 
							
									match build_fma a with
							 | 
						||
| 
								 | 
							
									  | None ->
							 | 
						||
| 
								 | 
							
									      fold_left count_flops_expr_func 
							 | 
						||
| 
								 | 
							
										(adds + (length a) - 1, mults, fmas) a
							 | 
						||
| 
								 | 
							
									  | Some (a, b, c) ->
							 | 
						||
| 
								 | 
							
									      fold_left count_flops_expr_func (adds, mults, fmas+1) [a; b; c]
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								  | Plus (a :: b) -> 
							 | 
						||
| 
								 | 
							
								      count_flops_expr_func (adds, mults, fmas) (Plus [a; Plus b])
							 | 
						||
| 
								 | 
							
								  | Times (NaN MULTI_A,_)  -> (adds, mults, fmas)
							 | 
						||
| 
								 | 
							
								  | Times (NaN MULTI_B,_)  -> (adds, mults, fmas)
							 | 
						||
| 
								 | 
							
								  | Times (NaN I,b) -> count_flops_expr_func (adds, mults, fmas) b
							 | 
						||
| 
								 | 
							
								  | Times (NaN CONJ,b) -> count_flops_expr_func (adds, mults, fmas) b
							 | 
						||
| 
								 | 
							
								  | Times (a,b) -> fold_left count_flops_expr_func (adds, mults+1, fmas) [a; b]
							 | 
						||
| 
								 | 
							
								  | CTimes (a,b) -> 
							 | 
						||
| 
								 | 
							
								      fold_left count_flops_expr_func (adds+1, mults+2, fmas) [a; b]
							 | 
						||
| 
								 | 
							
								  | CTimesJ (a,b) -> 
							 | 
						||
| 
								 | 
							
								      fold_left count_flops_expr_func (adds+1, mults+2, fmas) [a; b]
							 | 
						||
| 
								 | 
							
								  | Uminus a -> count_flops_expr_func (adds, mults, fmas) a
							 | 
						||
| 
								 | 
							
								  | _ -> (adds, mults, fmas)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let count_flops f = 
							 | 
						||
| 
								 | 
							
								    fold_left count_flops_expr_func (0, 0, 0) (fcn_to_expr_list f)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let count_constants f = 
							 | 
						||
| 
								 | 
							
								    length (unique_constants (flatten (map expr_to_constants (fcn_to_expr_list f))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let arith_complexity f =
							 | 
						||
| 
								 | 
							
								  let (a, m, fmas) = count_flops f
							 | 
						||
| 
								 | 
							
								  and v = count_stack_vars f
							 | 
						||
| 
								 | 
							
								  and c = count_constants f
							 | 
						||
| 
								 | 
							
								  and mem = count_memory_acc f
							 | 
						||
| 
								 | 
							
								  in (a, m, fmas, v, c, mem)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(* print the operation costs *)
							 | 
						||
| 
								 | 
							
								let print_cost f =
							 | 
						||
| 
								 | 
							
								  let Fcn (_, _, _, _) = f 
							 | 
						||
| 
								 | 
							
								  and (a, m, fmas, v, c, mem) = arith_complexity f
							 | 
						||
| 
								 | 
							
								  in
							 | 
						||
| 
								 | 
							
								  "/*\n"^
							 | 
						||
| 
								 | 
							
								  " * This function contains " ^
							 | 
						||
| 
								 | 
							
								  (string_of_int (a + fmas)) ^ " FP additions, "  ^
							 | 
						||
| 
								 | 
							
								  (string_of_int (m + fmas)) ^ " FP multiplications,\n" ^
							 | 
						||
| 
								 | 
							
								  " * (or, " ^
							 | 
						||
| 
								 | 
							
								  (string_of_int a) ^ " additions, "  ^
							 | 
						||
| 
								 | 
							
								  (string_of_int m) ^ " multiplications, " ^
							 | 
						||
| 
								 | 
							
								  (string_of_int fmas) ^ " fused multiply/add),\n" ^
							 | 
						||
| 
								 | 
							
								  " * " ^ (string_of_int v) ^ " stack variables, " ^
							 | 
						||
| 
								 | 
							
								  (string_of_int c) ^ " constants, and " ^
							 | 
						||
| 
								 | 
							
								  (string_of_int mem) ^ " memory accesses\n" ^
							 | 
						||
| 
								 | 
							
								  " */\n"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(*****************************************
							 | 
						||
| 
								 | 
							
								 * functions that create C arrays 
							 | 
						||
| 
								 | 
							
								 *****************************************)
							 | 
						||
| 
								 | 
							
								type stride = 
							 | 
						||
| 
								 | 
							
								  | SVar of string
							 | 
						||
| 
								 | 
							
								  | SConst of string
							 | 
						||
| 
								 | 
							
								  | SInteger of int
							 | 
						||
| 
								 | 
							
								  | SNeg of stride
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type sstride =
							 | 
						||
| 
								 | 
							
								  | Simple of int
							 | 
						||
| 
								 | 
							
								  | Constant of (string * int)
							 | 
						||
| 
								 | 
							
								  | Composite of (string * int)
							 | 
						||
| 
								 | 
							
								  | Negative of sstride
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let rec simplify_stride stride i =
							 | 
						||
| 
								 | 
							
								    match (stride, i) with
							 | 
						||
| 
								 | 
							
								      (_, 0) -> Simple 0
							 | 
						||
| 
								 | 
							
								    | (SInteger n, i) -> Simple (n * i)
							 | 
						||
| 
								 | 
							
								    | (SConst s, i) -> Constant (s, i)
							 | 
						||
| 
								 | 
							
								    | (SVar s, i) -> Composite (s, i)
							 | 
						||
| 
								 | 
							
								    | (SNeg x, i) -> 
							 | 
						||
| 
								 | 
							
									match (simplify_stride x i) with
							 | 
						||
| 
								 | 
							
									| Negative y -> y
							 | 
						||
| 
								 | 
							
									| y -> Negative y
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								let rec cstride_to_string = function
							 | 
						||
| 
								 | 
							
								  | Simple i -> string_of_int i
							 | 
						||
| 
								 | 
							
								  | Constant (s, i) -> 
							 | 
						||
| 
								 | 
							
								        if !Magic.lisp_syntax then
							 | 
						||
| 
								 | 
							
									  "(* " ^ s ^ " " ^ (string_of_int i) ^ ")"
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									  s ^ " * " ^ (string_of_int i)
							 | 
						||
| 
								 | 
							
								  | Composite (s, i) -> 
							 | 
						||
| 
								 | 
							
								        if !Magic.lisp_syntax then
							 | 
						||
| 
								 | 
							
									  "(* " ^ s ^ " " ^ (string_of_int i) ^ ")"
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									  "WS(" ^ s ^ ", " ^ (string_of_int i) ^ ")"
							 | 
						||
| 
								 | 
							
								  | Negative x -> "-" ^ cstride_to_string x
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let aref name index = 
							 | 
						||
| 
								 | 
							
								  if !Magic.lisp_syntax then
							 | 
						||
| 
								 | 
							
								    Printf.sprintf "(aref %s %s)"  name index
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    Printf.sprintf "%s[%s]"  name index
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let array_subscript name stride k = 
							 | 
						||
| 
								 | 
							
								  aref name (cstride_to_string (simplify_stride stride k))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let varray_subscript name vstride stride v i = 
							 | 
						||
| 
								 | 
							
								  let vindex = simplify_stride vstride v
							 | 
						||
| 
								 | 
							
								  and iindex = simplify_stride stride i
							 | 
						||
| 
								 | 
							
								  in 
							 | 
						||
| 
								 | 
							
								  let index = 
							 | 
						||
| 
								 | 
							
								    match (vindex, iindex) with
							 | 
						||
| 
								 | 
							
								      (Simple vi, Simple ii) -> string_of_int (vi + ii)
							 | 
						||
| 
								 | 
							
								    | (Simple 0, x) -> cstride_to_string x
							 | 
						||
| 
								 | 
							
								    | (x, Simple 0) -> cstride_to_string x
							 | 
						||
| 
								 | 
							
								    | _ -> (cstride_to_string vindex) ^ " + " ^ (cstride_to_string iindex)
							 | 
						||
| 
								 | 
							
								  in aref name index
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let real_of s = "c_re(" ^ s ^ ")"
							 | 
						||
| 
								 | 
							
								let imag_of s = "c_im(" ^ s ^ ")"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let flops_of f =
							 | 
						||
| 
								 | 
							
								  let (add, mul, fma) = count_flops f in
							 | 
						||
| 
								 | 
							
								  Printf.sprintf "{ %d, %d, %d, 0 }" add mul fma
							 |