On Thu, Oct 11, 2012 at 9:38 AM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > Building trees, then gimplifying it, is unnecessarily expensive. > This patch changes build_check_stmt to emit GIMPLE directly, and > a couple of small cleanups here and there. Also, I'm using a different > alias set for the shadow memory accesses, those obviously can't alias any > other accesses. > > Ok for asan? > > 2012-10-11 Jakub Jelinek <ja...@redhat.com> > > * Makefile.in (GTFILES): Add $(srcdir)/asan.c. > * asan.c (shadow_ptr_types): New variable. > (report_error_func): Change is_store argument to bool, don't append > newline to function name. > (PROB_VERY_UNLIKELY, PROB_ALWAYS): Define. > (build_check_stmt): Change is_store argument to bool. Emit GIMPLE > directly instead of creating trees and gimplifying them. Mark > the error reporting function as very unlikely. > (instrument_derefs): Change is_store argument to bool. Use > int_size_in_bytes to compute size_in_bytes, simplify size check. > Use build_fold_addr_expr instead of build_addr. > (transform_statements): Adjust instrument_derefs caller. > Use gimple_assign_single_p as stmt test. Don't look at MEM refs > in rhs2. > (asan_instrument): Don't push/pop gimplify context. > Initialize shadow_ptr_types if not yet initialized. > * asan.h (ASAN_SHADOW_SHIFT): Adjust comment. > > --- gcc/Makefile.in.jj 2012-10-11 16:09:02.000000000 +0200 > +++ gcc/Makefile.in 2012-10-11 16:51:59.666672099 +0200 > @@ -3681,6 +3681,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/inp > $(srcdir)/lto-streamer.h \ > $(srcdir)/target-globals.h \ > $(srcdir)/ipa-inline.h \ > + $(srcdir)/asan.c \ > @all_gtfiles@ > > # Compute the list of GT header files from the corresponding C sources, > --- gcc/asan.c.jj 2012-10-11 16:33:58.000000000 +0200 > +++ gcc/asan.c 2012-10-11 18:20:35.265675838 +0200 > @@ -79,18 +79,20 @@ along with GCC; see the file COPYING3. > to create redzones for stack and global object and poison them. > */ > > +static GTY(()) tree shadow_ptr_types[2]; > + > /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}. > IS_STORE is either 1 (for a store) or 0 (for a load). > SIZE_IN_BYTES is one of 1, 2, 4, 8, 16. */ > > static tree > -report_error_func (int is_store, int size_in_bytes) > +report_error_func (bool is_store, int size_in_bytes) > { > tree fn_type; > tree def; > char name[100]; > > - sprintf (name, "__asan_report_%s%d\n", > + sprintf (name, "__asan_report_%s%d", > is_store ? "store" : "load", size_in_bytes); > fn_type = build_function_type_list (void_type_node, ptr_type_node, > NULL_TREE); > def = build_fn_decl (name, fn_type); > @@ -118,6 +120,9 @@ asan_init_func (void) > } > > > +#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1) > +#define PROB_ALWAYS (REG_BR_PROB_BASE) > +
Does it belong here ? -- looks like they can be generally useful for others. > /* Instrument the memory access instruction BASE. > Insert new statements before ITER. > LOCATION is source code location. > @@ -127,21 +132,17 @@ asan_init_func (void) > static void > build_check_stmt (tree base, > gimple_stmt_iterator *iter, > - location_t location, int is_store, int size_in_bytes) > + location_t location, bool is_store, int size_in_bytes) > { > gimple_stmt_iterator gsi; > basic_block cond_bb, then_bb, join_bb; > edge e; > - tree cond, t, u; > - tree base_addr; > - tree shadow_value; > + tree t, base_addr, shadow; > gimple g; > - gimple_seq seq, stmts; > - tree shadow_type = size_in_bytes == 16 ? > - short_integer_type_node : char_type_node; > - tree shadow_ptr_type = build_pointer_type (shadow_type); > - tree uintptr_type = lang_hooks.types.type_for_mode (ptr_mode, > - /*unsignedp=*/true); > + tree shadow_ptr_type = shadow_ptr_types[size_in_bytes == 16]; > + tree shadow_type = TREE_TYPE (shadow_ptr_type); > + tree uintptr_type > + = build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1); > > /* We first need to split the current basic block, and start altering > the CFG. This allows us to insert the statements we're about to > @@ -166,14 +167,15 @@ build_check_stmt (tree base, > > /* Create the bb that contains the crash block. */ > then_bb = create_empty_bb (cond_bb); Missing frequency update for then_bb ? > - make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); > + e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); > + e->probability = PROB_VERY_UNLIKELY; > make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU); > > /* Mark the pseudo-fallthrough edge from cond_bb to join_bb. */ > e = find_edge (cond_bb, join_bb); > e->flags = EDGE_FALSE_VALUE; > e->count = cond_bb->count; > - e->probability = REG_BR_PROB_BASE; > + e->probability = PROB_ALWAYS - PROB_VERY_UNLIKELY; > > /* Update dominance info. Note that bb_join's data was > updated by split_block. */ > @@ -183,75 +185,123 @@ build_check_stmt (tree base, > set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb); > } > > - base_addr = create_tmp_reg (uintptr_type, "__asan_base_addr"); > + gsi = gsi_last_bb (cond_bb); > + g = gimple_build_assign_with_ops (TREE_CODE (base), > + make_ssa_name (TREE_TYPE (base), NULL), > + base, NULL_TREE); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > > - seq = NULL; > - t = fold_convert_loc (location, uintptr_type, > - unshare_expr (base)); > - t = force_gimple_operand (t, &stmts, false, NULL_TREE); > - gimple_seq_add_seq (&seq, stmts); > - g = gimple_build_assign (base_addr, t); > + g = gimple_build_assign_with_ops (NOP_EXPR, > + make_ssa_name (uintptr_type, NULL), > + gimple_assign_lhs (g), NULL_TREE); > gimple_set_location (g, location); > - gimple_seq_add_stmt (&seq, g); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + base_addr = gimple_assign_lhs (g); > Set base_addr name here? thanks, David > /* Build > - (base_addr >> ASAN_SHADOW_SHIFT) | targetm.asan_shadow_offset (). */ > + (base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */ > > - t = build2 (RSHIFT_EXPR, uintptr_type, base_addr, > - build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT)); > - t = build2 (PLUS_EXPR, uintptr_type, t, > - build_int_cst (uintptr_type, targetm.asan_shadow_offset ())); > - t = build1 (INDIRECT_REF, shadow_type, > - build1 (VIEW_CONVERT_EXPR, shadow_ptr_type, t)); > - t = force_gimple_operand (t, &stmts, false, NULL_TREE); > - gimple_seq_add_seq (&seq, stmts); > - shadow_value = create_tmp_reg (shadow_type, "__asan_shadow"); > - g = gimple_build_assign (shadow_value, t); > + t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT); > + g = gimple_build_assign_with_ops (RSHIFT_EXPR, > + make_ssa_name (uintptr_type, NULL), > + base_addr, t); > gimple_set_location (g, location); > - gimple_seq_add_stmt (&seq, g); > - t = build2 (NE_EXPR, boolean_type_node, shadow_value, > - build_int_cst (shadow_type, 0)); > - if (size_in_bytes < 8) > - { > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > > - /* Slow path for 1-, 2- and 4- byte accesses. > - Build ((base_addr & 7) + (size_in_bytes - 1)) >= shadow_value. */ > - > - u = build2 (BIT_AND_EXPR, uintptr_type, > - base_addr, > - build_int_cst (uintptr_type, 7)); > - u = build1 (CONVERT_EXPR, shadow_type, u); > - u = build2 (PLUS_EXPR, shadow_type, u, > - build_int_cst (shadow_type, size_in_bytes - 1)); > - u = build2 (GE_EXPR, uintptr_type, u, shadow_value); > - } > - else > - u = build_int_cst (boolean_type_node, 1); > - t = build2 (TRUTH_AND_EXPR, boolean_type_node, t, u); > - t = force_gimple_operand (t, &stmts, false, NULL_TREE); > - gimple_seq_add_seq (&seq, stmts); > - cond = create_tmp_reg (boolean_type_node, "__asan_crash_cond"); > - g = gimple_build_assign (cond, t); > + t = build_int_cst (uintptr_type, targetm.asan_shadow_offset ()); > + g = gimple_build_assign_with_ops (PLUS_EXPR, > + make_ssa_name (uintptr_type, NULL), > + gimple_assign_lhs (g), t); > gimple_set_location (g, location); > - gimple_seq_add_stmt (&seq, g); > - g = gimple_build_cond (NE_EXPR, cond, boolean_false_node, NULL_TREE, > - NULL_TREE); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + > + g = gimple_build_assign_with_ops (NOP_EXPR, > + make_ssa_name (shadow_ptr_type, NULL), > + gimple_assign_lhs (g), NULL_TREE); > gimple_set_location (g, location); > - gimple_seq_add_stmt (&seq, g); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > > - /* Generate call to the run-time library (e.g. __asan_report_load8). */ > + t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g), > + build_int_cst (shadow_ptr_type, 0)); > + g = gimple_build_assign_with_ops (MEM_REF, > + make_ssa_name (shadow_type, NULL), > + t, NULL_TREE); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + shadow = gimple_assign_lhs (g); > > - gsi = gsi_last_bb (cond_bb); > - gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); > - seq = NULL; > - g = gimple_build_call (report_error_func (is_store, size_in_bytes), > - 1, base_addr); > - gimple_seq_add_stmt (&seq, g); > + if (size_in_bytes < 8) > + { > + /* Slow path for 1, 2 and 4 byte accesses. > + Test (shadow != 0) > + & ((base_addr & 7) + (size_in_bytes - 1)) >= shadow). */ > + g = gimple_build_assign_with_ops (NE_EXPR, > + make_ssa_name (boolean_type_node, > + NULL), > + shadow, > + build_int_cst (shadow_type, 0)); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + t = gimple_assign_lhs (g); > + > + g = gimple_build_assign_with_ops (BIT_AND_EXPR, > + make_ssa_name (uintptr_type, > + NULL), > + base_addr, > + build_int_cst (uintptr_type, 7)); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + > + g = gimple_build_assign_with_ops (NOP_EXPR, > + make_ssa_name (shadow_type, > + NULL), > + gimple_assign_lhs (g), NULL_TREE); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + > + if (size_in_bytes > 1) > + { > + g = gimple_build_assign_with_ops (PLUS_EXPR, > + make_ssa_name (shadow_type, > + NULL), > + gimple_assign_lhs (g), > + build_int_cst (shadow_type, > + size_in_bytes - > 1)); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + } > + > + g = gimple_build_assign_with_ops (GE_EXPR, > + make_ssa_name (boolean_type_node, > + NULL), > + gimple_assign_lhs (g), > + shadow); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + > + g = gimple_build_assign_with_ops (BIT_AND_EXPR, > + make_ssa_name (boolean_type_node, > + NULL), > + t, gimple_assign_lhs (g)); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > + t = gimple_assign_lhs (g); > + } > + else > + t = shadow; > > - /* Insert the check code in the THEN block. */ > + g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0), > + NULL_TREE, NULL_TREE); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > > + /* Generate call to the run-time library (e.g. __asan_report_load8). */ > gsi = gsi_start_bb (then_bb); > - gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); > + g = gimple_build_call (report_error_func (is_store, size_in_bytes), > + 1, base_addr); > + gimple_set_location (g, location); > + gsi_insert_after (&gsi, g, GSI_NEW_STMT); > > *iter = gsi_start_bb (join_bb); > } > @@ -262,14 +312,12 @@ build_check_stmt (tree base, > > static void > instrument_derefs (gimple_stmt_iterator *iter, tree t, > - location_t location, int is_store) > + location_t location, bool is_store) > { > tree type, base; > - int size_in_bytes; > + HOST_WIDE_INT size_in_bytes; > > type = TREE_TYPE (t); > - if (type == error_mark_node) > - return; > switch (TREE_CODE (t)) > { > case ARRAY_REF: > @@ -280,25 +328,25 @@ instrument_derefs (gimple_stmt_iterator > default: > return; > }