Patchwork [ARM,4/6] Improve Neon intrinsics testsuite.

login
register
mail settings
Submitter Julian Brown
Date July 30, 2012, 7:38 p.m.
Message ID <20120730203838.09d6749a@octopus>
Download mbox | patch
Permalink /patch/174082/
State New
Headers show

Comments

Julian Brown - July 30, 2012, 7:38 p.m.
On Mon, 30 Jul 2012 12:51:47 +0100
Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> wrote:

>    This patch converts the testsuite generator to actually produce
> something more sensible than the current set of tests. It changes
> these to generate the following form for a test instead of the
> previous set of tests.
> 
> It's careful to use the hard-fp variant so that we actually
> produce an instruction (atleast a move of the appropriate form) and
> uses a dummy floating point parameter to ensure this. This ensures
> that most tests are alright. This does increase test times quite a bit
> and I'm considering a follow-up to the build system that tries to do
> some of these tests in parallel.
> 
> It's been useful and instructive so far and has found a few issues
> in the compiler and probably been the twistiest passage in this maze
> of twisty little passages.

The Ocaml bits mostly look fine to me, modulo a few formatting nits
(redundant brackets, begin/end pairs) fixed in the attached version,
which works the same as before AFAICT. I also factored out the
kind-of-duplicate print_args functions into a generalised version --
not amazingly useful, but mildly more concise.

HTH,

Julian

Patch

Index: neon-testgen.ml
===================================================================
--- neon-testgen.ml	(revision 189983)
+++ neon-testgen.ml	(working copy)
@@ -1,5 +1,6 @@ 
 (* Auto-generate ARM Neon intrinsics tests.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software 
+   Foundation, Inc.
    Contributed by CodeSourcery.
 
    This file is part of GCC.
@@ -51,80 +52,84 @@ 
   Printf.fprintf chan "/* This file was autogenerated by neon-testgen.  */\n\n";
   Printf.fprintf chan "/* { dg-do assemble } */\n";
   Printf.fprintf chan "/* { dg-require-effective-target arm_neon_ok } */\n";
-  Printf.fprintf chan "/* { dg-options \"-save-temps -O0\" } */\n";
+  Printf.fprintf chan "/* { dg-options \"-save-temps\" } */\n";
   Printf.fprintf chan "/* { dg-add-options arm_neon } */\n";
-  Printf.fprintf chan "\n#include \"arm_neon.h\"\n\n";
-  Printf.fprintf chan "void test_%s (void)\n{\n" test_name
+  Printf.fprintf chan "\n#include \"arm_neon.h\"\n\n"
 
-(* Emit declarations of local variables that are going to be passed
+(* Convert a list ORIGLIST to a string, calling MAP with a
+   monotonically-increasing index and the element for each element of that
+   list, and separating entries with SEP.  *)
+
+let idx_concat sep map origlist =
+  let buf = Buffer.create 30 in
+  let rec scan idx = function
+    [] ->
+      Buffer.contents buf
+  | [item] ->
+      Buffer.add_string buf (map idx item);
+      Buffer.contents buf
+  | item::items ->
+      Buffer.add_string buf (map idx item);
+      Buffer.add_string buf sep;
+      scan (succ idx) items in
+  scan 0 origlist
+
+(* Emit function with parameters and local variables that are going to be passed
    to an intrinsic, together with one to take a returned value if needed.  *)
-let emit_automatics chan c_types features =
-  let emit () =
-    ignore (
-      List.fold_left (fun arg_number -> fun (flags, ty) ->
-                        let pointer_bit =
-                          if List.mem Pointer flags then "*" else ""
-                        in
-                          (* Const arguments to builtins are directly
-                             written in as constants.  *)
-                          if not (List.mem Const flags) then
-                            Printf.fprintf chan "  %s %sarg%d_%s;\n"
-                                           ty pointer_bit arg_number ty;
-                        arg_number + 1)
-                     0 (List.tl c_types))
+let emit_test_prologue chan c_types features test_name const_valuator =
+  let print_arg arg_number (flags, ty) =
+    (* If the argument is of const type, then directly write in the
+       constant now.  *)
+    let pointer_bit = if List.mem Pointer flags then "*" else "" in
+    Printf.sprintf "%s %s arg%d_%s" ty pointer_bit arg_number ty
   in
-    match c_types with
-      (_, return_ty) :: tys ->
-        if return_ty <> "void" then begin
-          (* The intrinsic returns a value.  We need to do explict register
-             allocation for vget_low tests or they fail because of copy
-             elimination.  *)
-          ((if List.mem Fixed_vector_reg features then
-              Printf.fprintf chan "  register %s out_%s asm (\"d18\");\n"
-                             return_ty return_ty
-            else if List.mem Fixed_core_reg features then
-              Printf.fprintf chan "  register %s out_%s asm (\"r0\");\n"
-                             return_ty return_ty
-            else
-              Printf.fprintf chan "  %s out_%s;\n" return_ty return_ty);
-	   emit ())
-        end else
-          (* The intrinsic does not return a value.  *)
-          emit ()
-    | _ -> assert false
+  match c_types with
+    (_, return_ty) :: tys ->
+      Printf.fprintf chan
+        "%s __attribute__ ((pcs (\"aapcs-vfp\")))\ntest_%s (float dummy_param, "
+	return_ty test_name;
+      output_string chan (idx_concat ",\n\t" print_arg (List.tl c_types));
+      Printf.fprintf chan ")\n{\n";
+      if return_ty <> "void" then begin
+        (* The intrinsic returns a value.  We need to do explict register
+           allocation for vget_low tests or they fail because of copy
+           elimination.  *)
+        if List.mem Fixed_vector_reg features then
+          Printf.fprintf chan "  register %s out_%s asm (\"d18\");\n"
+                         return_ty return_ty
+        else if List.mem Fixed_core_reg features then
+          Printf.fprintf chan "  register %s out_%s asm (\"r0\");\n"
+                         return_ty return_ty
+        else
+          Printf.fprintf chan "  %s out_%s;\n" return_ty return_ty
+      end 
+  | _ -> assert false
 
 (* Emit code to call an intrinsic.  *)
 let emit_call chan const_valuator c_types name elt_ty =
-  (if snd (List.hd c_types) <> "void" then
-     Printf.fprintf chan "  out_%s = " (snd (List.hd c_types))
-   else
-     Printf.fprintf chan "  ");
+  if snd (List.hd c_types) <> "void" then
+    Printf.fprintf chan "  out_%s = " (snd (List.hd c_types))
+  else
+    Printf.fprintf chan "  ";
   Printf.fprintf chan "%s_%s (" (intrinsic_name name) (string_of_elt elt_ty);
-  let print_arg chan arg_number (flags, ty) =
+  let print_arg arg_number (flags, ty) =
     (* If the argument is of const type, then directly write in the
        constant now.  *)
     if List.mem Const flags then
       match const_valuator with
         None ->
           if List.mem Pointer flags then
-            Printf.fprintf chan "0"
+            Printf.sprintf "arg%d_%s " arg_number ty
           else
-            Printf.fprintf chan "1"
-      | Some f -> Printf.fprintf chan "%s" (string_of_int (f arg_number))
+            Printf.sprintf "1 "
+      | Some f -> Printf.sprintf "%s " (string_of_int (f arg_number))
     else
-      Printf.fprintf chan "arg%d_%s" arg_number ty
+      Printf.sprintf "arg%d_%s" arg_number ty
   in
-  let rec print_args arg_number tys =
-    match tys with
-      [] -> ()
-    | [ty] -> print_arg chan arg_number ty
-    | ty::tys ->
-      print_arg chan arg_number ty;
-      Printf.fprintf chan ", ";
-      print_args (arg_number + 1) tys
-  in
-    print_args 0 (List.tl c_types);
-    Printf.fprintf chan ");\n"
+  output_string chan (idx_concat ", " print_arg (List.tl c_types));
+  Printf.fprintf chan ");\n";
+  if snd (List.hd c_types) <> "void" then
+    Printf.fprintf chan "  return out_%s;\n" (snd (List.hd c_types))
 
 (* Emit epilogue code to a test source file.  *)
 let emit_epilogue chan features regexps =
@@ -265,12 +270,12 @@ 
   in
     (* Emit file and function prologues.  *)
     emit_prologue chan test_name;
-    (* Emit local variable declarations.  *)
-    emit_automatics chan c_types features;
+    (* Emit prologue for the test function.  *)
+    emit_test_prologue chan c_types features test_name const_valuator;
     Printf.fprintf chan "\n";
     (* Emit the call to the intrinsic.  *)
     emit_call chan const_valuator c_types name elt_ty;
-    (* Emit the function epilogue and the DejaGNU scan-assembler directives.  *)
+    (* Emit the DejaGNU scan-assembler directives.  *)
     emit_epilogue chan features regexps;
     (* Close the test file.  *)
     close_out chan