sparc-miscompile.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. diff -Nur gcc-4.8.2.orig/gcc/tree-ssa-forwprop.c gcc-4.8.2/gcc/tree-ssa-forwprop.c
  2. --- gcc-4.8.2.orig/gcc/tree-ssa-forwprop.c 2013-02-25 16:31:31.000000000 +0100
  3. +++ gcc-4.8.2/gcc/tree-ssa-forwprop.c 2014-03-22 19:37:04.797991879 +0100
  4. @@ -688,6 +688,130 @@
  5. recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
  6. }
  7. + /* DEF_RHS contains the address of the 0th element in an array.
  8. + USE_STMT uses type of DEF_RHS to compute the address of an
  9. + arbitrary element within the array. The (variable) byte offset
  10. + of the element is contained in OFFSET.
  11. +
  12. + We walk back through the use-def chains of OFFSET to verify that
  13. + it is indeed computing the offset of an element within the array
  14. + and extract the index corresponding to the given byte offset.
  15. +
  16. + We then try to fold the entire address expression into a form
  17. + &array[index].
  18. +
  19. + If we are successful, we replace the right hand side of USE_STMT
  20. + with the new address computation. */
  21. +
  22. + static bool
  23. + forward_propagate_addr_into_variable_array_index (tree offset,
  24. + tree def_rhs,
  25. + gimple_stmt_iterator *use_stmt_gsi)
  26. + {
  27. + tree index, tunit;
  28. + gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi);
  29. + tree new_rhs, tmp;
  30. +
  31. + if (TREE_CODE (TREE_OPERAND (def_rhs, 0)) == ARRAY_REF)
  32. + tunit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)));
  33. + else if (TREE_CODE (TREE_TYPE (TREE_OPERAND (def_rhs, 0))) == ARRAY_TYPE)
  34. + tunit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (TREE_TYPE (def_rhs))));
  35. + else
  36. + return false;
  37. + if (!host_integerp (tunit, 1))
  38. + return false;
  39. +
  40. + /* Get the offset's defining statement. */
  41. + offset_def = SSA_NAME_DEF_STMT (offset);
  42. +
  43. + /* Try to find an expression for a proper index. This is either a
  44. + multiplication expression by the element size or just the ssa name we came
  45. + along in case the element size is one. In that case, however, we do not
  46. + allow multiplications because they can be computing index to a higher
  47. + level dimension (PR 37861). */
  48. + if (integer_onep (tunit))
  49. + {
  50. + if (is_gimple_assign (offset_def)
  51. + && gimple_assign_rhs_code (offset_def) == MULT_EXPR)
  52. + return false;
  53. +
  54. + index = offset;
  55. + }
  56. + else
  57. + {
  58. + /* The statement which defines OFFSET before type conversion
  59. + must be a simple GIMPLE_ASSIGN. */
  60. + if (!is_gimple_assign (offset_def))
  61. + return false;
  62. +
  63. + /* The RHS of the statement which defines OFFSET must be a
  64. + multiplication of an object by the size of the array elements.
  65. + This implicitly verifies that the size of the array elements
  66. + is constant. */
  67. + if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
  68. + && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
  69. + && tree_int_cst_equal (gimple_assign_rhs2 (offset_def), tunit))
  70. + {
  71. + /* The first operand to the MULT_EXPR is the desired index. */
  72. + index = gimple_assign_rhs1 (offset_def);
  73. + }
  74. + /* If we have idx * tunit + CST * tunit re-associate that. */
  75. + else if ((gimple_assign_rhs_code (offset_def) == PLUS_EXPR
  76. + || gimple_assign_rhs_code (offset_def) == MINUS_EXPR)
  77. + && TREE_CODE (gimple_assign_rhs1 (offset_def)) == SSA_NAME
  78. + && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
  79. + && (tmp = div_if_zero_remainder (EXACT_DIV_EXPR,
  80. + gimple_assign_rhs2 (offset_def),
  81. + tunit)) != NULL_TREE)
  82. + {
  83. + gimple offset_def2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (offset_def));
  84. + if (is_gimple_assign (offset_def2)
  85. + && gimple_assign_rhs_code (offset_def2) == MULT_EXPR
  86. + && TREE_CODE (gimple_assign_rhs2 (offset_def2)) == INTEGER_CST
  87. + && tree_int_cst_equal (gimple_assign_rhs2 (offset_def2), tunit))
  88. + {
  89. + index = fold_build2 (gimple_assign_rhs_code (offset_def),
  90. + TREE_TYPE (offset),
  91. + gimple_assign_rhs1 (offset_def2), tmp);
  92. + }
  93. + else
  94. + return false;
  95. + }
  96. + else
  97. + return false;
  98. + }
  99. +
  100. + /* Replace the pointer addition with array indexing. */
  101. + index = force_gimple_operand_gsi (use_stmt_gsi, index, true, NULL_TREE,
  102. + true, GSI_SAME_STMT);
  103. + if (TREE_CODE (TREE_OPERAND (def_rhs, 0)) == ARRAY_REF)
  104. + {
  105. + new_rhs = unshare_expr (def_rhs);
  106. + TREE_OPERAND (TREE_OPERAND (new_rhs, 0), 1) = index;
  107. + }
  108. + else
  109. + {
  110. + new_rhs = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (TREE_TYPE (def_rhs))),
  111. + unshare_expr (TREE_OPERAND (def_rhs, 0)),
  112. + index, integer_zero_node, NULL_TREE);
  113. + new_rhs = build_fold_addr_expr (new_rhs);
  114. + if (!useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (use_stmt)),
  115. + TREE_TYPE (new_rhs)))
  116. + {
  117. + new_rhs = force_gimple_operand_gsi (use_stmt_gsi, new_rhs, true,
  118. + NULL_TREE, true, GSI_SAME_STMT);
  119. + new_rhs = fold_convert (TREE_TYPE (gimple_assign_lhs (use_stmt)),
  120. + new_rhs);
  121. + }
  122. + }
  123. + gimple_assign_set_rhs_from_tree (use_stmt_gsi, new_rhs);
  124. + fold_stmt (use_stmt_gsi);
  125. + tidy_after_forward_propagate_addr (gsi_stmt (*use_stmt_gsi));
  126. + return true;
  127. + }
  128. +
  129. +
  130. +
  131. /* NAME is a SSA_NAME representing DEF_RHS which is of the form
  132. ADDR_EXPR <whatever>.
  133. @@ -977,6 +1101,19 @@
  134. tidy_after_forward_propagate_addr (use_stmt);
  135. return true;
  136. }
  137. + /* Try to optimize &x[0] p+ OFFSET where OFFSET is defined by
  138. + converting a multiplication of an index by the size of the
  139. + array elements, then the result is converted into the proper
  140. + type for the arithmetic. */
  141. + if (TREE_CODE (rhs2) == SSA_NAME
  142. + && (TREE_CODE (array_ref) != ARRAY_REF
  143. + || integer_zerop (TREE_OPERAND (array_ref, 1)))
  144. + && useless_type_conversion_p (TREE_TYPE (name), TREE_TYPE (def_rhs))
  145. + /* Avoid problems with IVopts creating PLUS_EXPRs with a
  146. + different type than their operands. */
  147. + && useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
  148. + return forward_propagate_addr_into_variable_array_index (rhs2, def_rhs,
  149. + use_stmt_gsi);
  150. return false;
  151. }