From 63e19d9eaabd89844442a053ca29d9075d3e8888 Mon Sep 17 00:00:00 2001 From: Jonathan Ragan-Kelley Date: Thu, 1 Sep 2011 18:34:45 -0400 Subject: [PATCH 1/5] Added Arg expression --- src/cg_llvm.ml | 25 +++++++++++++++++-------- src/ir.ml | 3 ++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/cg_llvm.ml b/src/cg_llvm.ml index e16a629e552e..1a13bfe1aff2 100644 --- a/src/cg_llvm.ml +++ b/src/cg_llvm.ml @@ -9,12 +9,13 @@ let entrypoint_name = "_im_main" let caml_entrypoint_name = entrypoint_name ^ "_caml_runner" let c_entrypoint_name = entrypoint_name ^ "_runner" -exception ArgumentTypeMismatch of arg * arg exception UnsupportedType of val_type exception MissingEntrypoint exception UnimplementedInstruction exception UnalignedVectorMemref exception CGFailed of string +exception ArgExprOfBufferArgument (* The Arg expr can't dereference a Buffer, only Scalars *) +exception ArgTypeMismatch of val_type * val_type let buffer_t c = pointer_type (i8_type c) @@ -127,20 +128,21 @@ let codegen (c:llcontext) (e:entrypoint) = (* start codegen at entry block of main *) let b = builder_at_end c (entry_block entrypoint_fn) in - let arg_get name = - let arg = ArgMap.find name argmap in - match arg with Scalar (s,_), _ | Buffer s, _ -> assert (s = name); - arg + let arg_find name = + let arg,idx = ArgMap.find name argmap in + match arg with Scalar (s,_) | Buffer s -> assert (s = name); + (arg,idx) in - let arg_idx name = match arg_get name with (_,i) -> i in + let arg_get name = match arg_find name with (arg,_) -> arg in + let arg_idx name = match arg_find name with (_,i) -> i in let arg_val name = param entrypoint_fn (arg_idx name) in let ptr_to_buffer buf = - match arg_get buf with + match arg_find buf with | (Buffer s), i -> assert (s = buf); param entrypoint_fn i - | arg, _ -> raise (ArgumentTypeMismatch(Buffer(buf), arg)) + | arg, _ -> raise (Wtf "ptr_to_buffer of non-Buffer argument name") in let rec cg_expr = function @@ -197,6 +199,13 @@ let codegen (c:llcontext) (e:entrypoint) = (* Loop variables *) | Var(name) -> sym_get name + | Arg(vt, name) -> + (match arg_get name with + | Scalar (_,avt) when vt = avt -> raise (ArgTypeMismatch(vt,avt)) + | Buffer _ -> raise ArgExprOfBufferArgument + | _ -> ()); + arg_val name + (* Making vectors *) | MakeVector(l) -> cg_makevector(l, val_type_of_expr (MakeVector l), 0) diff --git a/src/ir.ml b/src/ir.ml index 723368020e24..f99442a6d5a5 100644 --- a/src/ir.ml +++ b/src/ir.ml @@ -78,7 +78,7 @@ type expr = (* scalar arguments *) (* TODO: specify type interpretation explicitly for easier val_type_of_expr? *) - (*| Arg of val_type * string *) + | Arg of val_type * string (* basic binary ops *) | Bop of binop * expr * expr @@ -130,6 +130,7 @@ let rec val_type_of_expr = function if (lt <> rt) then raise (ArithmeticTypeMismatch(lt,rt)); lt | Var _ -> i32 (* Vars are only defined as integer programs so must be ints *) + | Arg vt,_ -> vt (* boolean expressions on vector types return bool vectors of equal length*) (* boolean expressions on scalars return scalar bools *) | Cmp(_, l, r) -> From 7ae8a8dafcfa9851e8655c2809e07e15169c2f15 Mon Sep 17 00:00:00 2001 From: Jonathan Ragan-Kelley Date: Fri, 2 Sep 2011 16:09:25 -0400 Subject: [PATCH 2/5] Change Map bounds from int to expr --- src/cg_llvm.ml | 6 +++--- src/ir.ml | 4 ++-- src/vectorize.ml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cg_llvm.ml b/src/cg_llvm.ml index 1a13bfe1aff2..407c92e1abf9 100644 --- a/src/cg_llvm.ml +++ b/src/cg_llvm.ml @@ -296,7 +296,7 @@ let codegen (c:llcontext) (e:entrypoint) = and cg_for var_name min max body = (* Emit the start code first, without 'variable' in scope. *) - let start_val = const_int int_imm_t min in + let start_val = min (* const_int int_imm_t min *) in (* Make the new basic block for the loop header, inserting after current * block. *) @@ -326,7 +326,7 @@ let codegen (c:llcontext) (e:entrypoint) = let next_var = build_add variable (const_int int_imm_t 1) (var_name ^ "_nextvar") b in (* Compute the end condition. *) - let end_cond = build_icmp Icmp.Slt next_var (const_int int_imm_t max) "" b in + let end_cond = build_icmp Icmp.Slt next_var max "" b in (* Create the "after loop" block and insert it. *) let loop_end_bb = insertion_block b in @@ -358,7 +358,7 @@ let codegen (c:llcontext) (e:entrypoint) = let ptr = cg_memref mr (val_type_of_expr e) in build_store (cg_expr e) ptr b | Map(n, min, max, stmt) -> - cg_for n min max stmt + cg_for n (cg_expr min) (cg_expr max) stmt | Block (first::second::rest) -> ignore(cg_stmt first); cg_stmt (Block (second::rest)) diff --git a/src/ir.ml b/src/ir.ml index f99442a6d5a5..5910a29189cc 100644 --- a/src/ir.ml +++ b/src/ir.ml @@ -130,7 +130,7 @@ let rec val_type_of_expr = function if (lt <> rt) then raise (ArithmeticTypeMismatch(lt,rt)); lt | Var _ -> i32 (* Vars are only defined as integer programs so must be ints *) - | Arg vt,_ -> vt + | Arg (vt,_) -> vt (* boolean expressions on vector types return bool vectors of equal length*) (* boolean expressions on scalars return scalar bools *) | Cmp(_, l, r) -> @@ -164,7 +164,7 @@ type stmt = * sub-ranges *) (* | If of expr * stmt *) (* | IfElse of expr * stmt * stmt *) - | Map of string * int * int * stmt + | Map of string * expr * expr * stmt (* | For of domain * stmt *) (* TODO: For might need landing pad: always executes before, only if *any* iteration * fired. Same for Map - useful for loop invariant code motion. Easier for diff --git a/src/vectorize.ml b/src/vectorize.ml index 14592d696a8e..e78f6df21204 100644 --- a/src/vectorize.ml +++ b/src/vectorize.ml @@ -176,7 +176,7 @@ let rec vectorize_stmt stmt var width = match stmt with | Map (name, min, max, stmt) when name = var -> (* TODO: Currently we assume width divides min and max *) - Map (name, min/width, max/width, vec stmt) + Map (name, min /~ IntImm(width), max /~ IntImm(width), vec stmt) | Map (name, min, max, stmt) -> Map (name, min, max, vec stmt) | Block l -> Block (map vec l) | Store (expr, mr) -> begin From d60c4bc20340267489d1d655a5e5e8dafc906c2e Mon Sep 17 00:00:00 2001 From: Jonathan Ragan-Kelley Date: Fri, 2 Sep 2011 16:11:06 -0400 Subject: [PATCH 3/5] Fixed bug in expr.Arg codegen type check --- src/cg_llvm.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cg_llvm.ml b/src/cg_llvm.ml index 407c92e1abf9..3967caed4c52 100644 --- a/src/cg_llvm.ml +++ b/src/cg_llvm.ml @@ -201,7 +201,7 @@ let codegen (c:llcontext) (e:entrypoint) = | Arg(vt, name) -> (match arg_get name with - | Scalar (_,avt) when vt = avt -> raise (ArgTypeMismatch(vt,avt)) + | Scalar (_,avt) when vt <> avt -> raise (ArgTypeMismatch(vt,avt)) | Buffer _ -> raise ArgExprOfBufferArgument | _ -> ()); arg_val name From 1edf4fb11f6194ab20ee5c860277c2a288da5e47 Mon Sep 17 00:00:00 2001 From: Jonathan Ragan-Kelley Date: Fri, 2 Sep 2011 16:15:52 -0400 Subject: [PATCH 4/5] Added non-buffer Args to C wrapper codegen. Switched brightness example and cg_test_runner.cpp to use dynamic width, height, channels arguments. --- src/brightness.ml | 7 +++---- src/cg_llvm.ml | 37 +++++++++++++++---------------------- src/cg_test_runner.cpp | 2 +- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/brightness.ml b/src/brightness.ml index 230e432625ed..bfa1257cae01 100644 --- a/src/brightness.ml +++ b/src/brightness.ml @@ -1,5 +1,4 @@ open Ir -open Vectorize let brightness = Cast(UInt(8), UIntImm(100)) @@ -25,9 +24,9 @@ let sadd(a, b) = in Select(a >~ (max_val -~ b), max_val, a +~ b) -let prgm w h c = +let prgm = Vectorize.vectorize_stmt - (Map("i", 0, (w*h*c), + (Map("i", IntImm(0), Cast(i32, Arg(i64, "w")) *~ Cast(i32, Arg(i64, "h")) *~ Cast(i32, Arg(i64, "c")), store ( sadd(load, brightness) ) @@ -36,5 +35,5 @@ let prgm w h c = 16 let () = - Cg_llvm.codegen_to_file "brightness.bc" ([ Buffer "in"; Buffer "out" ], prgm 800 600 3) + Cg_llvm.codegen_to_file "brightness.bc" ([ Buffer "in"; Buffer "out"; Scalar("w", i64); Scalar("h", i64); Scalar("c", i64)], prgm) (*Test_runner.main prgm "brightness"*) diff --git a/src/cg_llvm.ml b/src/cg_llvm.ml index 3967caed4c52..ddd109f17429 100644 --- a/src/cg_llvm.ml +++ b/src/cg_llvm.ml @@ -489,40 +489,33 @@ let codegen_c_wrapper c m f = let buffer_t = buffer_t c in let i32_t = i32_type c in + let i64_t = i64_type c in - let is_buffer p = type_of p = buffer_t in -(* - let wrapper_args = Array.map - (fun p -> - if is_buffer p then pointer_type (buffer_t c) - else type_of p) - (params f) in - *) - + (* define wrapper entrypoint: void name(void* args[]) *) let wrapper = define_function (c_entrypoint_name) (function_type (void_type c) [|pointer_type buffer_t|]) m in - let args = param wrapper 0 in - let b = builder_at_end c (entry_block wrapper) in - let cg_load_arg i = + (* codegen load and cast from arg array slot i to lltype t *) + let cg_load_arg i t = (* fetch object pointer = (( void* )args)[i] *) - let arg_ptr = build_gep args [| const_int i32_t i |] "" b in - (* deref object pointer *) - let ptr = build_load arg_ptr "" b in - (* cast to buffer_t for passing into im function *) - build_pointercast ptr buffer_t "" b + let args_array = param wrapper 0 in + let arg_ptr = build_gep args_array [| const_int i32_t i |] "" b in + (* deref arg pointer *) + let arg = build_load arg_ptr "" b in + (* cast to target buffer or int type for passing into im function *) + if t = buffer_t then + build_pointercast arg t "" b + else + build_intcast (build_ptrtoint arg i64_t "" b) t "" b in + (* build inner function argument list from args array *) let args = Array.mapi - (fun i p -> - if is_buffer p then - cg_load_arg i - else - param wrapper i) + (fun i p -> cg_load_arg i (type_of p)) (params f) in (* codegen the call *) diff --git a/src/cg_test_runner.cpp b/src/cg_test_runner.cpp index 93fd16ab873e..01f64c3d96b3 100644 --- a/src/cg_test_runner.cpp +++ b/src/cg_test_runner.cpp @@ -57,7 +57,7 @@ int main(int argc, const char* argv[]) { out = (unsigned char*)malloc_aligned(width*height*channels); printf("running...\n"); - char* args[] = {(char*)in, (char*)out}; + char* args[] = {(char*)in, (char*)out, (char*)width, (char*)height, (char*)channels}; _im_main_runner(args); save_png(outpath, width, height, channels, out); From c04a6f080ea5ee691907be94cd5b4df46954b42a Mon Sep 17 00:00:00 2001 From: Jonathan Ragan-Kelley Date: Fri, 2 Sep 2011 16:38:51 -0400 Subject: [PATCH 5/5] Simplified Scalar Args to better support int32s Improved cg_test_runner.cpp to use ArgT union type --- src/brightness.ml | 4 ++-- src/cg_llvm.ml | 7 +------ src/cg_test_runner.cpp | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/brightness.ml b/src/brightness.ml index bfa1257cae01..bf7b40b6eba5 100644 --- a/src/brightness.ml +++ b/src/brightness.ml @@ -26,7 +26,7 @@ let sadd(a, b) = let prgm = Vectorize.vectorize_stmt - (Map("i", IntImm(0), Cast(i32, Arg(i64, "w")) *~ Cast(i32, Arg(i64, "h")) *~ Cast(i32, Arg(i64, "c")), + (Map("i", IntImm(0), Arg(i32, "w") *~ Arg(i32, "h") *~ Arg(i32, "c"), store ( sadd(load, brightness) ) @@ -35,5 +35,5 @@ let prgm = 16 let () = - Cg_llvm.codegen_to_file "brightness.bc" ([ Buffer "in"; Buffer "out"; Scalar("w", i64); Scalar("h", i64); Scalar("c", i64)], prgm) + Cg_llvm.codegen_to_file "brightness.bc" ([ Buffer "in"; Buffer "out"; Scalar("w", i32); Scalar("h", i32); Scalar("c", i32)], prgm) (*Test_runner.main prgm "brightness"*) diff --git a/src/cg_llvm.ml b/src/cg_llvm.ml index ddd109f17429..2392bbbd248c 100644 --- a/src/cg_llvm.ml +++ b/src/cg_llvm.ml @@ -505,12 +505,7 @@ let codegen_c_wrapper c m f = let args_array = param wrapper 0 in let arg_ptr = build_gep args_array [| const_int i32_t i |] "" b in (* deref arg pointer *) - let arg = build_load arg_ptr "" b in - (* cast to target buffer or int type for passing into im function *) - if t = buffer_t then - build_pointercast arg t "" b - else - build_intcast (build_ptrtoint arg i64_t "" b) t "" b + build_load (build_pointercast arg_ptr (pointer_type t) "" b) "" b in (* build inner function argument list from args array *) diff --git a/src/cg_test_runner.cpp b/src/cg_test_runner.cpp index 01f64c3d96b3..37ff5da6e416 100644 --- a/src/cg_test_runner.cpp +++ b/src/cg_test_runner.cpp @@ -12,8 +12,14 @@ #include #include +typedef union { + void* ptr; + int64_t i64; + int32_t i32; +} ArgT; + extern "C" { - void _im_main_runner(char* args[]); + void _im_main_runner(ArgT args[]); } #ifndef PATH_MAX @@ -57,7 +63,12 @@ int main(int argc, const char* argv[]) { out = (unsigned char*)malloc_aligned(width*height*channels); printf("running...\n"); - char* args[] = {(char*)in, (char*)out, (char*)width, (char*)height, (char*)channels}; + ArgT args[5]; + args[0].ptr = in; + args[1].ptr = out; + args[2].i32 = width; + args[3].i32 = height; + args[4].i32 = channels; _im_main_runner(args); save_png(outpath, width, height, channels, out);