1 | /* A class for building vector tree constants. |
---|---|

2 | Copyright (C) 2017 Free Software Foundation, Inc. |

3 | |

4 | This file is part of GCC. |

5 | |

6 | GCC is free software; you can redistribute it and/or modify it under |

7 | the terms of the GNU General Public License as published by the Free |

8 | Software Foundation; either version 3, or (at your option) any later |

9 | version. |

10 | |

11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |

12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |

13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |

14 | for more details. |

15 | |

16 | You should have received a copy of the GNU General Public License |

17 | along with GCC; see the file COPYING3. If not see |

18 | <http://www.gnu.org/licenses/>. */ |

19 | |

20 | #include "config.h" |

21 | #include "system.h" |

22 | #include "coretypes.h" |

23 | #include "tree.h" |

24 | #include "fold-const.h" |

25 | #include "tree-vector-builder.h" |

26 | |

27 | /* Try to start building a new vector of type TYPE that holds the result of |

28 | a unary operation on VECTOR_CST T. ALLOW_STEPPED_P is true if the |

29 | operation can handle stepped encodings directly, without having to |

30 | expand the full sequence. |

31 | |

32 | Return true if the operation is possible, which it always is when |

33 | ALLOW_STEPPED_P is true. Leave the builder unchanged otherwise. */ |

34 | |

35 | bool |

36 | tree_vector_builder::new_unary_operation (tree type, tree t, |

37 | bool allow_stepped_p) |

38 | { |

39 | unsigned int full_nelts = TYPE_VECTOR_SUBPARTS (type); |

40 | gcc_assert (full_nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t))); |

41 | unsigned int npatterns = VECTOR_CST_NPATTERNS (t); |

42 | unsigned int nelts_per_pattern = VECTOR_CST_NELTS_PER_PATTERN (t); |

43 | if (!allow_stepped_p && nelts_per_pattern > 2) |

44 | { |

45 | npatterns = full_nelts; |

46 | nelts_per_pattern = 1; |

47 | } |

48 | new_vector (type, npatterns, nelts_per_pattern); |

49 | return true; |

50 | } |

51 | |

52 | /* Try to start building a new vector of type TYPE that holds the result of |

53 | a binary operation on VECTOR_CSTs T1 and T2. ALLOW_STEPPED_P is true if |

54 | the operation can handle stepped encodings directly, without having to |

55 | expand the full sequence. |

56 | |

57 | Return true if the operation is possible. Leave the builder unchanged |

58 | otherwise. */ |

59 | |

60 | bool |

61 | tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2, |

62 | bool allow_stepped_p) |

63 | { |

64 | unsigned int full_nelts = TYPE_VECTOR_SUBPARTS (type); |

65 | gcc_assert (full_nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1)) |

66 | && full_nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))); |

67 | /* Conceptually we split the patterns in T1 and T2 until we have |

68 | an equal number for both. Each split pattern requires the same |

69 | number of elements per pattern as the original. E.g. splitting: |

70 | |

71 | { 1, 2, 3, ... } |

72 | |

73 | into two gives: |

74 | |

75 | { 1, 3, 5, ... } |

76 | { 2, 4, 6, ... } |

77 | |

78 | while splitting: |

79 | |

80 | { 1, 0, ... } |

81 | |

82 | into two gives: |

83 | |

84 | { 1, 0, ... } |

85 | { 0, 0, ... }. */ |

86 | unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1), |

87 | VECTOR_CST_NPATTERNS (t2)); |

88 | unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1), |

89 | VECTOR_CST_NELTS_PER_PATTERN (t2)); |

90 | if (!allow_stepped_p && nelts_per_pattern > 2) |

91 | { |

92 | npatterns = full_nelts; |

93 | nelts_per_pattern = 1; |

94 | } |

95 | new_vector (type, npatterns, nelts_per_pattern); |

96 | return true; |

97 | } |

98 | |

99 | /* Return the number of elements that the caller needs to operate on in |

100 | order to handle a binary operation on VECTOR_CSTs T1 and T2. This static |

101 | function is used instead of new_binary_operation if the result of the |

102 | operation is not a VECTOR_CST. */ |

103 | |

104 | unsigned int |

105 | tree_vector_builder::binary_encoded_nelts (tree t1, tree t2) |

106 | { |

107 | unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1)); |

108 | gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))); |

109 | /* See new_binary_operation for details. */ |

110 | unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1), |

111 | VECTOR_CST_NPATTERNS (t2)); |

112 | unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1), |

113 | VECTOR_CST_NELTS_PER_PATTERN (t2)); |

114 | return MIN (npatterns * nelts_per_pattern, nelts); |

115 | } |

116 | |

117 | /* Return a vector element with the value BASE + FACTOR * STEP. */ |

118 | |

119 | tree |

120 | tree_vector_builder::apply_step (tree base, unsigned int factor, |

121 | const wide_int &step) const |

122 | { |

123 | return wide_int_to_tree (TREE_TYPE (base), |

124 | wi::to_wide (base) + factor * step); |

125 | } |

126 | |

127 | /* Return a VECTOR_CST for the current constant. */ |

128 | |

129 | tree |

130 | tree_vector_builder::build () |

131 | { |

132 | finalize (); |

133 | gcc_assert (pow2p_hwi (npatterns ())); |

134 | tree v = make_vector (exact_log2 (npatterns ()), nelts_per_pattern ()); |

135 | TREE_TYPE (v) = m_type; |

136 | memcpy (VECTOR_CST_ENCODED_ELTS (v), address (), |

137 | encoded_nelts () * sizeof (tree)); |

138 | return v; |

139 | } |

140 |