mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 14:04:26 -04:00 
			
		
		
		
	Fix "Widening multiply-accumulate operation uses wrong value extension" for 4.7, 4.7-linaro and 4.6-linaro, which backported the broken code to 4.6. Vanilla 4.6 is unaffected. Fixes #13420. Signed-off-by: Jonas Gorski <jogo@openwrt.org> SVN-Revision: 36486
		
			
				
	
	
		
			71 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| diff -urN a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
 | |
| --- a/gcc/tree-ssa-math-opts.c	2012-12-12 18:05:23.000000000 +0100
 | |
| +++ b/gcc/tree-ssa-math-opts.c	2013-04-29 15:54:00.051998936 +0200
 | |
| @@ -1280,6 +1280,47 @@
 | |
|    return result;
 | |
|  }
 | |
|  
 | |
| +/* Return true if stmt is a type conversion operation that can be stripped
 | |
| +   when used in a widening multiply operation.  */
 | |
| +static bool
 | |
| +widening_mult_conversion_strippable_p (tree result_type, gimple stmt)
 | |
| +{
 | |
| +  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
 | |
| +
 | |
| +  if (TREE_CODE (result_type) == INTEGER_TYPE)
 | |
| +    {
 | |
| +      tree op_type;
 | |
| +      tree inner_op_type;
 | |
| +
 | |
| +      if (!CONVERT_EXPR_CODE_P (rhs_code))
 | |
| +	return false;
 | |
| +
 | |
| +      op_type = TREE_TYPE (gimple_assign_lhs (stmt));
 | |
| +
 | |
| +      /* If the type of OP has the same precision as the result, then
 | |
| +	 we can strip this conversion.  The multiply operation will be
 | |
| +	 selected to create the correct extension as a by-product.  */
 | |
| +      if (TYPE_PRECISION (result_type) == TYPE_PRECISION (op_type))
 | |
| +	return true;
 | |
| +
 | |
| +      /* We can also strip a conversion if it preserves the signed-ness of
 | |
| +	 the operation and doesn't narrow the range.  */
 | |
| +      inner_op_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
 | |
| +
 | |
| +      /* If the inner-most type is unsigned, then we can strip any
 | |
| +	 intermediate widening operation.  If it's signed, then the
 | |
| +	 intermediate widening operation must also be signed.  */
 | |
| +      if ((TYPE_UNSIGNED (inner_op_type)
 | |
| +	   || TYPE_UNSIGNED (op_type) == TYPE_UNSIGNED (inner_op_type))
 | |
| +	  && TYPE_PRECISION (op_type) > TYPE_PRECISION (inner_op_type))
 | |
| +	return true;
 | |
| +
 | |
| +      return false;
 | |
| +    }
 | |
| +
 | |
| +  return rhs_code == FIXED_CONVERT_EXPR;
 | |
| +}
 | |
| +
 | |
|  /* Return true if RHS is a suitable operand for a widening multiplication,
 | |
|     assuming a target type of TYPE.
 | |
|     There are two cases:
 | |
| @@ -1296,17 +1337,13 @@
 | |
|  {
 | |
|    gimple stmt;
 | |
|    tree type1, rhs1;
 | |
| -  enum tree_code rhs_code;
 | |
|  
 | |
|    if (TREE_CODE (rhs) == SSA_NAME)
 | |
|      {
 | |
|        stmt = SSA_NAME_DEF_STMT (rhs);
 | |
|        if (is_gimple_assign (stmt))
 | |
|  	{
 | |
| -	  rhs_code = gimple_assign_rhs_code (stmt);
 | |
| -	  if (TREE_CODE (type) == INTEGER_TYPE
 | |
| -	      ? !CONVERT_EXPR_CODE_P (rhs_code)
 | |
| -	      : rhs_code != FIXED_CONVERT_EXPR)
 | |
| +	  if (! widening_mult_conversion_strippable_p (type, stmt))
 | |
|  	    rhs1 = rhs;
 | |
|  	  else
 | |
|  	    {
 |