diff options
| author | Zdenek Dvorak <dvorakz@suse.cz> | 2007-06-10 22:39:22 +0200 | 
|---|---|---|
| committer | Zdenek Dvorak <rakdver@gcc.gnu.org> | 2007-06-10 20:39:22 +0000 | 
| commit | 79f5e442625680fbd5c12517419e990609bb2810 (patch) | |
| tree | aa6fde364b39cc3fab0e7d98faf468b947ade3d2 /gcc/expr.c | |
| parent | 6bdff197e6b8397129441e85a53fbb3c738c3d57 (diff) | |
| download | gcc-79f5e442625680fbd5c12517419e990609bb2810.zip gcc-79f5e442625680fbd5c12517419e990609bb2810.tar.gz gcc-79f5e442625680fbd5c12517419e990609bb2810.tar.bz2  | |
tree-data-ref.c (dr_analyze_alias): Handle case smt is NULL.
	* tree-data-ref.c (dr_analyze_alias): Handle case smt is NULL.
	* tree-predcom.c (mark_virtual_ops_for_renaming): Exported.
	* tree-ssa-loop-prefetch.c: Include optabs.h.
	(FENCE_FOLLOWING_MOVNT): New macro.
	(struct mem_ref): Add independent_p and storent_p fields.
	(record_ref): Initalize the new fields.
	(gather_memory_references_ref): Return true if the reference
	could be analysed.
	(gather_memory_references): Check whether all memory accesses
	in loop were recorded.
	(should_issue_prefetch_p): Return false for nontemporal stores.
	(nontemporal_store_p, mark_nontemporal_store, emit_mfence_after_loop,
	may_use_storent_in_loop_p, mark_nontemporal_stores): New functions.
	(determine_loop_nest_reuse): Detect independent memory references.
	(loop_prefetch_arrays): Call mark_nontemporal_stores.
	* tree-flow.h (mark_virtual_ops_for_renaming): Declare.
	* Makefile.in (tree-ssa-loop-prefetch.o): Add OPTABS_H dependency.
	* config/i386/i386.h (x86_mfence): Declare.
	(FENCE_FOLLOWING_MOVNT): Return x86_mfence.
	* config/i386/i386.c (x86_mfence): New variable.
	(ix86_init_mmx_sse_builtins): Initialize x86_mfence.
	* tree-pretty-print.c (dump_generic_node): Mark nontemporal stores.
	* optabs.c (init_optabs): Initialize storent_optab.
	* optabs.h (enum optab_index): Add OTI_storent.
	(storent_optab): Declare.
	* genopinit.c (optabs): Add initialization for storent_optab.
	* tree.h (MOVE_NONTEMPORAL): New macro.
	* expr.c (expand_assignment, store_expr, store_constructor_field,
	store_constructor, store_field, expand_expr_real_1): Propagate
	nontemporality of the expanded store.
	(emit_storent_insn): New function.
	* expr.h (expand_assignment, store_expr): Declaration changed.
	* function.c (assign_parm_setup_reg): Pass false as nontemporality
	to expand_assignment.
	* stmt.c (expand_asm_expr): Ditto.
	* calls.c (initialize_argument_information): Pass false as
	nontemporality to store_expr.
	* config/i386/sse.md (storentv4sf, storentv2df, storentv2di,
	storentsi): New.
	* gcc.dg/tree-ssa/prefetch-7.c: New test.
From-SVN: r125604
Diffstat (limited to 'gcc/expr.c')
| -rw-r--r-- | gcc/expr.c | 120 | 
1 files changed, 90 insertions, 30 deletions
@@ -142,7 +142,7 @@ static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,  				     tree, tree, int, int);  static void store_constructor (tree, rtx, int, HOST_WIDE_INT);  static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode, -			tree, tree, int); +			tree, tree, int, bool);  static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (tree, tree); @@ -4074,10 +4074,11 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,  } -/* Expand an assignment that stores the value of FROM into TO.  */ +/* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL +   is true, try generating a nontemporal store.  */  void -expand_assignment (tree to, tree from) +expand_assignment (tree to, tree from, bool nontemporal)  {    rtx to_rtx = 0;    rtx result; @@ -4164,12 +4165,13 @@ expand_assignment (tree to, tree from)  	  if (TREE_CODE (TREE_TYPE (from)) == COMPLEX_TYPE)  	    {  	      gcc_assert (bitpos == 0); -	      result = store_expr (from, to_rtx, false); +	      result = store_expr (from, to_rtx, false, nontemporal);  	    }  	  else  	    {  	      gcc_assert (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1)); -	      result = store_expr (from, XEXP (to_rtx, bitpos != 0), false); +	      result = store_expr (from, XEXP (to_rtx, bitpos != 0), false, +				   nontemporal);  	    }  	}        else @@ -4195,7 +4197,8 @@ expand_assignment (tree to, tree from)  	    result = NULL;  	  else  	    result = store_field (to_rtx, bitsize, bitpos, mode1, from, -				  TREE_TYPE (tem), get_alias_set (to)); +				  TREE_TYPE (tem), get_alias_set (to), +				  nontemporal);  	}        if (result) @@ -4302,13 +4305,46 @@ expand_assignment (tree to, tree from)    /* Compute FROM and store the value in the rtx we got.  */    push_temp_slots (); -  result = store_expr (from, to_rtx, 0); +  result = store_expr (from, to_rtx, 0, nontemporal);    preserve_temp_slots (result);    free_temp_slots ();    pop_temp_slots ();    return;  } +/* Emits nontemporal store insn that moves FROM to TO.  Returns true if this +   succeeded, false otherwise.  */ + +static bool +emit_storent_insn (rtx to, rtx from) +{ +  enum machine_mode mode = GET_MODE (to), imode; +  enum insn_code code = storent_optab->handlers[mode].insn_code; +  rtx pattern; + +  if (code == CODE_FOR_nothing) +    return false; + +  imode = insn_data[code].operand[0].mode; +  if (!insn_data[code].operand[0].predicate (to, imode)) +    return false; + +  imode = insn_data[code].operand[1].mode; +  if (!insn_data[code].operand[1].predicate (from, imode)) +    { +      from = copy_to_mode_reg (imode, from); +      if (!insn_data[code].operand[1].predicate (from, imode)) +	return false; +    } + +  pattern = GEN_FCN (code) (to, from); +  if (pattern == NULL_RTX) +    return false; + +  emit_insn (pattern); +  return true; +} +  /* Generate code for computing expression EXP,     and storing the value into TARGET. @@ -4320,10 +4356,12 @@ expand_assignment (tree to, tree from)     be more thorough?     If CALL_PARAM_P is nonzero, this is a store into a call param on the -   stack, and block moves may need to be treated specially.  */ +   stack, and block moves may need to be treated specially. +  +   If NONTEMPORAL is true, try using a nontemporal store instruction.  */  rtx -store_expr (tree exp, rtx target, int call_param_p) +store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)  {    rtx temp;    rtx alt_rtl = NULL_RTX; @@ -4344,7 +4382,8 @@ store_expr (tree exp, rtx target, int call_param_p)  	 part.  */        expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,  		   call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL); -      return store_expr (TREE_OPERAND (exp, 1), target, call_param_p); +      return store_expr (TREE_OPERAND (exp, 1), target, call_param_p, +			 nontemporal);      }    else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)      { @@ -4358,11 +4397,13 @@ store_expr (tree exp, rtx target, int call_param_p)        do_pending_stack_adjust ();        NO_DEFER_POP;        jumpifnot (TREE_OPERAND (exp, 0), lab1); -      store_expr (TREE_OPERAND (exp, 1), target, call_param_p); +      store_expr (TREE_OPERAND (exp, 1), target, call_param_p, +		  nontemporal);        emit_jump_insn (gen_jump (lab2));        emit_barrier ();        emit_label (lab1); -      store_expr (TREE_OPERAND (exp, 2), target, call_param_p); +      store_expr (TREE_OPERAND (exp, 2), target, call_param_p, +		  nontemporal);        emit_label (lab2);        OK_DEFER_POP; @@ -4433,7 +4474,12 @@ store_expr (tree exp, rtx target, int call_param_p)      }    else      { -      temp = expand_expr_real (exp, target, GET_MODE (target), +      rtx tmp_target; + +      /* If we want to use a nontemporal store, force the value to +	 register first.  */ +      tmp_target = nontemporal ? NULL_RTX : target; +      temp = expand_expr_real (exp, tmp_target, GET_MODE (target),  			       (call_param_p  				? EXPAND_STACK_PARM : EXPAND_NORMAL),  			       &alt_rtl); @@ -4591,6 +4637,11 @@ store_expr (tree exp, rtx target, int call_param_p)  	emit_block_move (target, temp, expr_size (exp),  			 (call_param_p  			  ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); +      else if (nontemporal +	       && emit_storent_insn (target, temp)) +	/* If we managed to emit a nontemporal store, there is nothing else to +	   do.  */ +	;        else  	{  	  temp = force_operand (temp, target); @@ -4941,7 +4992,7 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,        store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);      }    else -    store_field (target, bitsize, bitpos, mode, exp, type, alias_set); +    store_field (target, bitsize, bitpos, mode, exp, type, alias_set, false);  }  /* Store the value of constructor EXP into the rtx TARGET. @@ -5291,7 +5342,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)  		      = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),  						   &unsignedp, 0));  		    SET_DECL_RTL (index, index_r); -		    store_expr (lo_index, index_r, 0); +		    store_expr (lo_index, index_r, 0, false);  		    /* Build the head of the loop.  */  		    do_pending_stack_adjust (); @@ -5318,7 +5369,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)  		      store_constructor (value, xtarget, cleared,  					 bitsize / BITS_PER_UNIT);  		    else -		      store_expr (value, xtarget, 0); +		      store_expr (value, xtarget, 0, false);  		    /* Generate a conditional jump to exit the loop.  */  		    exit_cond = build2 (LT_EXPR, integer_type_node, @@ -5329,7 +5380,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)  		       the loop.  */  		    expand_assignment (index,  				       build2 (PLUS_EXPR, TREE_TYPE (index), -					       index, integer_one_node)); +					       index, integer_one_node), +				       false);  		    emit_jump (loop_start); @@ -5360,7 +5412,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)  					  expand_normal (position),  					  highest_pow2_factor (position));  		xtarget = adjust_address (xtarget, mode, 0); -		store_expr (value, xtarget, 0); +		store_expr (value, xtarget, 0, false);  	      }  	    else  	      { @@ -5522,11 +5574,14 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)     ALIAS_SET is the alias set for the destination.  This value will     (in general) be different from that for TARGET, since TARGET is a -   reference to the containing structure.  */ +   reference to the containing structure. +    +   If NONTEMPORAL is true, try generating a nontemporal store.  */  static rtx  store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, -	     enum machine_mode mode, tree exp, tree type, int alias_set) +	     enum machine_mode mode, tree exp, tree type, int alias_set, +	     bool nontemporal)  {    HOST_WIDE_INT width_mask = 0; @@ -5561,7 +5616,8 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,        if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))  	emit_move_insn (object, target); -      store_field (blk_object, bitsize, bitpos, mode, exp, type, alias_set); +      store_field (blk_object, bitsize, bitpos, mode, exp, type, alias_set, +		   nontemporal);        emit_move_insn (target, object); @@ -5574,7 +5630,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,        /* We're storing into a struct containing a single __complex.  */        gcc_assert (!bitpos); -      return store_expr (exp, target, 0); +      return store_expr (exp, target, 0, nontemporal);      }    /* If the structure is in a register or if the component @@ -5675,7 +5731,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,        if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)  	set_mem_alias_set (to_rtx, alias_set); -      return store_expr (exp, to_rtx, 0); +      return store_expr (exp, to_rtx, 0, nontemporal);      }  } @@ -7831,7 +7887,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,  	    /* Store data into beginning of memory target.  */  	    store_expr (TREE_OPERAND (exp, 0),  			adjust_address (target, TYPE_MODE (valtype), 0), -			modifier == EXPAND_STACK_PARM); +			modifier == EXPAND_STACK_PARM, +			false);  	  else  	    { @@ -7844,7 +7901,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,  				 * BITS_PER_UNIT),  				(HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),  			   0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0), -			   type, 0); +			   type, 0, false);  	    }  	  /* Return the entire union.  */ @@ -8760,13 +8817,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,         op1 = gen_label_rtx ();         jumpifnot (TREE_OPERAND (exp, 0), op0);         store_expr (TREE_OPERAND (exp, 1), temp, - 		  modifier == EXPAND_STACK_PARM); + 		  modifier == EXPAND_STACK_PARM, +		  false);         emit_jump_insn (gen_jump (op1));         emit_barrier ();         emit_label (op0);         store_expr (TREE_OPERAND (exp, 2), temp, - 		  modifier == EXPAND_STACK_PARM); + 		  modifier == EXPAND_STACK_PARM, +		  false);         emit_label (op1);         OK_DEFER_POP; @@ -8781,7 +8840,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,  	tree lhs = TREE_OPERAND (exp, 0);  	tree rhs = TREE_OPERAND (exp, 1);  	gcc_assert (ignore); -	expand_assignment (lhs, rhs); +	expand_assignment (lhs, rhs, false);  	return const0_rtx;        } @@ -8813,13 +8872,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,  	    do_jump (TREE_OPERAND (rhs, 1),  		     value ? label : 0,  		     value ? 0 : label); -	    expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value)); +	    expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value), +			       MOVE_NONTEMPORAL (exp));  	    do_pending_stack_adjust ();  	    emit_label (label);  	    return const0_rtx;  	  } -	expand_assignment (lhs, rhs); +	expand_assignment (lhs, rhs, MOVE_NONTEMPORAL (exp));  	return const0_rtx;        }  | 
