OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
9 #include "src/s390/frames-s390.h" | 9 #include "src/s390/frames-s390.h" |
10 | 10 |
11 namespace v8 { | 11 namespace v8 { |
12 namespace internal { | 12 namespace internal { |
13 namespace compiler { | 13 namespace compiler { |
14 | 14 |
15 enum class OperandMode : uint32_t { | 15 enum class OperandMode : uint32_t { |
16 kNone = 0u, | 16 kNone = 0u, |
17 // Immediate mode | 17 // Immediate mode |
18 kShift32Imm = 1u << 0, | 18 kShift32Imm = 1u << 0, |
19 kShift64Imm = 1u << 1, | 19 kShift64Imm = 1u << 1, |
20 kInt32Imm = 1u << 2, | 20 kInt32Imm = 1u << 2, |
21 kInt32Imm_Negate = 1u << 3, | 21 kInt32Imm_Negate = 1u << 3, |
22 kUint32Imm = 1u << 4, | 22 kUint32Imm = 1u << 4, |
23 kInt20Imm = 1u << 5, | 23 kInt20Imm = 1u << 5, |
| 24 kUint12Imm = 1u << 6, |
24 // Instr format | 25 // Instr format |
25 kAllowRRR = 1u << 7, | 26 kAllowRRR = 1u << 7, |
26 kAllowRM = 1u << 8, | 27 kAllowRM = 1u << 8, |
27 kAllowRI = 1u << 9, | 28 kAllowRI = 1u << 9, |
28 kAllowRRI = 1u << 10, | 29 kAllowRRI = 1u << 10, |
29 kAllowRRM = 1u << 11, | 30 kAllowRRM = 1u << 11, |
30 // Useful combination | 31 // Useful combination |
31 kAllowImmediate = kAllowRI | kAllowRRI, | 32 kAllowImmediate = kAllowRI | kAllowRRI, |
32 kAllowMemoryOperand = kAllowRM | kAllowRRM, | 33 kAllowMemoryOperand = kAllowRM | kAllowRRM, |
33 kAllowDistinctOps = kAllowRRR | kAllowRRI | kAllowRRM, | 34 kAllowDistinctOps = kAllowRRR | kAllowRRI | kAllowRRM, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 explicit S390OperandGenerator(InstructionSelector* selector) | 77 explicit S390OperandGenerator(InstructionSelector* selector) |
77 : OperandGenerator(selector) {} | 78 : OperandGenerator(selector) {} |
78 | 79 |
79 InstructionOperand UseOperand(Node* node, OperandModes mode) { | 80 InstructionOperand UseOperand(Node* node, OperandModes mode) { |
80 if (CanBeImmediate(node, mode)) { | 81 if (CanBeImmediate(node, mode)) { |
81 return UseImmediate(node); | 82 return UseImmediate(node); |
82 } | 83 } |
83 return UseRegister(node); | 84 return UseRegister(node); |
84 } | 85 } |
85 | 86 |
| 87 InstructionOperand UseAnyExceptImmediate(Node* node) { |
| 88 if (NodeProperties::IsConstant(node)) |
| 89 return UseRegister(node); |
| 90 else |
| 91 return Use(node); |
| 92 } |
| 93 |
86 int64_t GetImmediate(Node* node) { | 94 int64_t GetImmediate(Node* node) { |
87 if (node->opcode() == IrOpcode::kInt32Constant) | 95 if (node->opcode() == IrOpcode::kInt32Constant) |
88 return OpParameter<int32_t>(node); | 96 return OpParameter<int32_t>(node); |
89 else if (node->opcode() == IrOpcode::kInt64Constant) | 97 else if (node->opcode() == IrOpcode::kInt64Constant) |
90 return OpParameter<int64_t>(node); | 98 return OpParameter<int64_t>(node); |
91 else | 99 else |
92 UNIMPLEMENTED(); | 100 UNIMPLEMENTED(); |
93 return 0L; | 101 return 0L; |
94 } | 102 } |
95 | 103 |
(...skipping 14 matching lines...) Expand all Loading... |
110 else if (mode & OperandMode::kShift64Imm) | 118 else if (mode & OperandMode::kShift64Imm) |
111 return 0 <= value && value < 64; | 119 return 0 <= value && value < 64; |
112 else if (mode & OperandMode::kInt32Imm) | 120 else if (mode & OperandMode::kInt32Imm) |
113 return is_int32(value); | 121 return is_int32(value); |
114 else if (mode & OperandMode::kInt32Imm_Negate) | 122 else if (mode & OperandMode::kInt32Imm_Negate) |
115 return is_int32(-value); | 123 return is_int32(-value); |
116 else if (mode & OperandMode::kUint32Imm) | 124 else if (mode & OperandMode::kUint32Imm) |
117 return is_uint32(value); | 125 return is_uint32(value); |
118 else if (mode & OperandMode::kInt20Imm) | 126 else if (mode & OperandMode::kInt20Imm) |
119 return is_int20(value); | 127 return is_int20(value); |
| 128 else if (mode & OperandMode::kUint12Imm) |
| 129 return is_uint12(value); |
120 else | 130 else |
121 return false; | 131 return false; |
122 } | 132 } |
123 | 133 |
| 134 bool CanBeMemoryOperand(InstructionCode opcode, Node* user, Node* input, |
| 135 int effect_level) { |
| 136 if (input->opcode() != IrOpcode::kLoad || |
| 137 !selector()->CanCover(user, input)) { |
| 138 return false; |
| 139 } |
| 140 |
| 141 if (effect_level != selector()->GetEffectLevel(input)) { |
| 142 return false; |
| 143 } |
| 144 |
| 145 MachineRepresentation rep = |
| 146 LoadRepresentationOf(input->op()).representation(); |
| 147 switch (opcode) { |
| 148 case kS390_Cmp64: |
| 149 case kS390_LoadAndTestWord64: |
| 150 return rep == MachineRepresentation::kWord64 || IsAnyTagged(rep); |
| 151 case kS390_LoadAndTestWord32: |
| 152 case kS390_Cmp32: |
| 153 return rep == MachineRepresentation::kWord32; |
| 154 default: |
| 155 break; |
| 156 } |
| 157 return false; |
| 158 } |
| 159 |
124 AddressingMode GenerateMemoryOperandInputs(Node* index, Node* base, | 160 AddressingMode GenerateMemoryOperandInputs(Node* index, Node* base, |
125 Node* displacement, | 161 Node* displacement, |
126 DisplacementMode displacement_mode, | 162 DisplacementMode displacement_mode, |
127 InstructionOperand inputs[], | 163 InstructionOperand inputs[], |
128 size_t* input_count) { | 164 size_t* input_count) { |
129 AddressingMode mode = kMode_MRI; | 165 AddressingMode mode = kMode_MRI; |
130 if (base != nullptr) { | 166 if (base != nullptr) { |
131 inputs[(*input_count)++] = UseRegister(base); | 167 inputs[(*input_count)++] = UseRegister(base); |
132 if (index != nullptr) { | 168 if (index != nullptr) { |
133 inputs[(*input_count)++] = UseRegister(index); | 169 inputs[(*input_count)++] = UseRegister(index); |
(...skipping 23 matching lines...) Expand all Loading... |
157 ? UseNegatedImmediate(displacement) | 193 ? UseNegatedImmediate(displacement) |
158 : UseImmediate(displacement); | 194 : UseImmediate(displacement); |
159 mode = kMode_MRI; | 195 mode = kMode_MRI; |
160 } else { | 196 } else { |
161 mode = kMode_MR; | 197 mode = kMode_MR; |
162 } | 198 } |
163 } | 199 } |
164 return mode; | 200 return mode; |
165 } | 201 } |
166 | 202 |
167 AddressingMode GetEffectiveAddressMemoryOperand(Node* operand, | 203 AddressingMode GetEffectiveAddressMemoryOperand( |
168 InstructionOperand inputs[], | 204 Node* operand, InstructionOperand inputs[], size_t* input_count, |
169 size_t* input_count) { | 205 OperandModes immediate_mode = OperandMode::kInt20Imm) { |
170 #if V8_TARGET_ARCH_S390X | 206 #if V8_TARGET_ARCH_S390X |
171 BaseWithIndexAndDisplacement64Matcher m(operand, | 207 BaseWithIndexAndDisplacement64Matcher m(operand, |
172 AddressOption::kAllowInputSwap); | 208 AddressOption::kAllowInputSwap); |
173 #else | 209 #else |
174 BaseWithIndexAndDisplacement32Matcher m(operand, | 210 BaseWithIndexAndDisplacement32Matcher m(operand, |
175 AddressOption::kAllowInputSwap); | 211 AddressOption::kAllowInputSwap); |
176 #endif | 212 #endif |
177 DCHECK(m.matches()); | 213 DCHECK(m.matches()); |
178 if ((m.displacement() == nullptr || | 214 if ((m.displacement() == nullptr || |
179 CanBeImmediate(m.displacement(), OperandMode::kInt20Imm))) { | 215 CanBeImmediate(m.displacement(), immediate_mode))) { |
180 DCHECK(m.scale() == 0); | 216 DCHECK(m.scale() == 0); |
181 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), | 217 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), |
182 m.displacement_mode(), inputs, | 218 m.displacement_mode(), inputs, |
183 input_count); | 219 input_count); |
184 } else { | 220 } else { |
185 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); | 221 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
186 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); | 222 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
187 return kMode_MRR; | 223 return kMode_MRR; |
188 } | 224 } |
189 } | 225 } |
190 | 226 |
191 bool CanBeBetterLeftOperand(Node* node) const { | 227 bool CanBeBetterLeftOperand(Node* node) const { |
192 return !selector()->IsLive(node); | 228 return !selector()->IsLive(node); |
193 } | 229 } |
194 | 230 |
195 MachineRepresentation GetRepresentation(Node* node) { | 231 MachineRepresentation GetRepresentation(Node* node) { |
196 return sequence()->GetRepresentation(selector()->GetVirtualRegister(node)); | 232 return sequence()->GetRepresentation(selector()->GetVirtualRegister(node)); |
197 } | 233 } |
198 | 234 |
199 bool Is64BitOperand(Node* node) { | 235 bool Is64BitOperand(Node* node) { |
200 return MachineRepresentation::kWord64 == GetRepresentation(node); | 236 return MachineRepresentation::kWord64 == GetRepresentation(node); |
201 } | 237 } |
202 }; | 238 }; |
203 | 239 |
204 namespace { | 240 namespace { |
205 | 241 |
| 242 bool S390OpcodeOnlySupport12BitDisp(ArchOpcode opcode) { |
| 243 switch (opcode) { |
| 244 case kS390_CmpFloat: |
| 245 case kS390_CmpDouble: |
| 246 return true; |
| 247 default: |
| 248 return false; |
| 249 } |
| 250 } |
| 251 |
| 252 bool S390OpcodeOnlySupport12BitDisp(InstructionCode op) { |
| 253 ArchOpcode opcode = ArchOpcodeField::decode(op); |
| 254 return S390OpcodeOnlySupport12BitDisp(opcode); |
| 255 } |
| 256 |
| 257 #define OpcodeImmMode(op) \ |
| 258 (S390OpcodeOnlySupport12BitDisp(op) ? OperandMode::kUint12Imm \ |
| 259 : OperandMode::kInt20Imm) |
| 260 |
206 ArchOpcode SelectLoadOpcode(Node* node) { | 261 ArchOpcode SelectLoadOpcode(Node* node) { |
207 NodeMatcher m(node); | 262 NodeMatcher m(node); |
208 DCHECK(m.IsLoad()); | 263 DCHECK(m.IsLoad()); |
209 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | 264 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
210 ArchOpcode opcode = kArchNop; | 265 ArchOpcode opcode = kArchNop; |
211 switch (load_rep.representation()) { | 266 switch (load_rep.representation()) { |
212 case MachineRepresentation::kFloat32: | 267 case MachineRepresentation::kFloat32: |
213 opcode = kS390_LoadFloat32; | 268 opcode = kS390_LoadFloat32; |
214 break; | 269 break; |
215 case MachineRepresentation::kFloat64: | 270 case MachineRepresentation::kFloat64: |
(...skipping 1518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1734 cont->frame_state()); | 1789 cont->frame_state()); |
1735 } else if (cont->IsSet()) { | 1790 } else if (cont->IsSet()) { |
1736 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1791 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1737 } else { | 1792 } else { |
1738 DCHECK(cont->IsTrap()); | 1793 DCHECK(cont->IsTrap()); |
1739 selector->Emit(opcode, g.NoOutput(), left, right, | 1794 selector->Emit(opcode, g.NoOutput(), left, right, |
1740 g.UseImmediate(cont->trap_id())); | 1795 g.UseImmediate(cont->trap_id())); |
1741 } | 1796 } |
1742 } | 1797 } |
1743 | 1798 |
| 1799 void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
| 1800 Node* value, InstructionCode opcode, |
| 1801 FlagsContinuation* cont); |
| 1802 |
| 1803 void VisitLoadAndTest(InstructionSelector* selector, InstructionCode opcode, |
| 1804 Node* node, Node* value, FlagsContinuation* cont, |
| 1805 bool discard_output = false); |
| 1806 |
1744 // Shared routine for multiple word compare operations. | 1807 // Shared routine for multiple word compare operations. |
1745 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1808 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1746 InstructionCode opcode, FlagsContinuation* cont, | 1809 InstructionCode opcode, FlagsContinuation* cont, |
1747 bool commutative, OperandModes immediate_mode) { | 1810 OperandModes immediate_mode) { |
1748 S390OperandGenerator g(selector); | 1811 S390OperandGenerator g(selector); |
1749 Node* left = node->InputAt(0); | 1812 Node* left = node->InputAt(0); |
1750 Node* right = node->InputAt(1); | 1813 Node* right = node->InputAt(1); |
1751 | 1814 |
1752 // Match immediates on left or right side of comparison. | 1815 DCHECK(IrOpcode::IsComparisonOpcode(node->opcode()) || |
1753 if (g.CanBeImmediate(right, immediate_mode)) { | 1816 node->opcode() == IrOpcode::kInt32Sub || |
1754 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), | 1817 node->opcode() == IrOpcode::kInt64Sub); |
1755 cont); | 1818 |
1756 } else if (g.CanBeImmediate(left, immediate_mode)) { | 1819 InstructionOperand inputs[8]; |
1757 if (!commutative) cont->Commute(); | 1820 InstructionOperand outputs[1]; |
1758 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), | 1821 size_t input_count = 0; |
1759 cont); | 1822 size_t output_count = 0; |
| 1823 |
| 1824 // If one of the two inputs is an immediate, make sure it's on the right, or |
| 1825 // if one of the two inputs is a memory operand, make sure it's on the left. |
| 1826 int effect_level = selector->GetEffectLevel(node); |
| 1827 if (cont->IsBranch()) { |
| 1828 effect_level = selector->GetEffectLevel( |
| 1829 cont->true_block()->PredecessorAt(0)->control_input()); |
| 1830 } |
| 1831 |
| 1832 if ((!g.CanBeImmediate(right, immediate_mode) && |
| 1833 g.CanBeImmediate(left, immediate_mode)) || |
| 1834 (!g.CanBeMemoryOperand(opcode, node, right, effect_level) && |
| 1835 g.CanBeMemoryOperand(opcode, node, left, effect_level))) { |
| 1836 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1837 std::swap(left, right); |
| 1838 } |
| 1839 |
| 1840 // check if compare with 0 |
| 1841 if (g.CanBeImmediate(right, immediate_mode) && g.GetImmediate(right) == 0) { |
| 1842 DCHECK(opcode == kS390_Cmp32 || opcode == kS390_Cmp64); |
| 1843 ArchOpcode load_and_test = (opcode == kS390_Cmp32) |
| 1844 ? kS390_LoadAndTestWord32 |
| 1845 : kS390_LoadAndTestWord64; |
| 1846 return VisitLoadAndTest(selector, load_and_test, node, left, cont, true); |
| 1847 } |
| 1848 |
| 1849 inputs[input_count++] = g.UseRegister(left); |
| 1850 if (g.CanBeMemoryOperand(opcode, node, right, effect_level)) { |
| 1851 // generate memory operand |
| 1852 AddressingMode addressing_mode = g.GetEffectiveAddressMemoryOperand( |
| 1853 right, inputs, &input_count, OpcodeImmMode(opcode)); |
| 1854 opcode |= AddressingModeField::encode(addressing_mode); |
| 1855 } else if (g.CanBeImmediate(right, immediate_mode)) { |
| 1856 inputs[input_count++] = g.UseImmediate(right); |
1760 } else { | 1857 } else { |
1761 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 1858 inputs[input_count++] = g.UseAnyExceptImmediate(right); |
1762 cont); | 1859 } |
| 1860 |
| 1861 opcode = cont->Encode(opcode); |
| 1862 if (cont->IsBranch()) { |
| 1863 inputs[input_count++] = g.Label(cont->true_block()); |
| 1864 inputs[input_count++] = g.Label(cont->false_block()); |
| 1865 } else if (cont->IsSet()) { |
| 1866 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 1867 } else if (cont->IsTrap()) { |
| 1868 inputs[input_count++] = g.UseImmediate(cont->trap_id()); |
| 1869 } else { |
| 1870 DCHECK(cont->IsDeoptimize()); |
| 1871 // nothing to do |
| 1872 } |
| 1873 |
| 1874 DCHECK(input_count <= 8 && output_count <= 1); |
| 1875 if (cont->IsDeoptimize()) { |
| 1876 selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs, |
| 1877 cont->reason(), cont->frame_state()); |
| 1878 } else { |
| 1879 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
1763 } | 1880 } |
1764 } | 1881 } |
1765 | 1882 |
1766 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 1883 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
1767 FlagsContinuation* cont) { | 1884 FlagsContinuation* cont) { |
1768 OperandModes mode = | 1885 OperandModes mode = |
1769 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); | 1886 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); |
1770 VisitWordCompare(selector, node, kS390_Cmp32, cont, false, mode); | 1887 VisitWordCompare(selector, node, kS390_Cmp32, cont, mode); |
1771 } | 1888 } |
1772 | 1889 |
1773 #if V8_TARGET_ARCH_S390X | 1890 #if V8_TARGET_ARCH_S390X |
1774 void VisitWord64Compare(InstructionSelector* selector, Node* node, | 1891 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
1775 FlagsContinuation* cont) { | 1892 FlagsContinuation* cont) { |
1776 OperandModes mode = | 1893 OperandModes mode = |
1777 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); | 1894 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); |
1778 VisitWordCompare(selector, node, kS390_Cmp64, cont, false, mode); | 1895 VisitWordCompare(selector, node, kS390_Cmp64, cont, mode); |
1779 } | 1896 } |
1780 #endif | 1897 #endif |
1781 | 1898 |
1782 // Shared routine for multiple float32 compare operations. | 1899 // Shared routine for multiple float32 compare operations. |
1783 void VisitFloat32Compare(InstructionSelector* selector, Node* node, | 1900 void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
1784 FlagsContinuation* cont) { | 1901 FlagsContinuation* cont) { |
1785 S390OperandGenerator g(selector); | 1902 VisitWordCompare(selector, node, kS390_CmpFloat, cont, OperandMode::kNone); |
1786 Node* left = node->InputAt(0); | |
1787 Node* right = node->InputAt(1); | |
1788 VisitCompare(selector, kS390_CmpFloat, g.UseRegister(left), | |
1789 g.UseRegister(right), cont); | |
1790 } | 1903 } |
1791 | 1904 |
1792 // Shared routine for multiple float64 compare operations. | 1905 // Shared routine for multiple float64 compare operations. |
1793 void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1906 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
1794 FlagsContinuation* cont) { | 1907 FlagsContinuation* cont) { |
| 1908 VisitWordCompare(selector, node, kS390_CmpDouble, cont, OperandMode::kNone); |
| 1909 } |
| 1910 |
| 1911 void VisitTestUnderMask(InstructionSelector* selector, Node* node, |
| 1912 FlagsContinuation* cont) { |
| 1913 DCHECK(node->opcode() == IrOpcode::kWord32And || |
| 1914 node->opcode() == IrOpcode::kWord64And); |
| 1915 ArchOpcode opcode = |
| 1916 (node->opcode() == IrOpcode::kWord32And) ? kS390_Tst32 : kS390_Tst64; |
1795 S390OperandGenerator g(selector); | 1917 S390OperandGenerator g(selector); |
1796 Node* left = node->InputAt(0); | 1918 Node* left = node->InputAt(0); |
1797 Node* right = node->InputAt(1); | 1919 Node* right = node->InputAt(1); |
1798 VisitCompare(selector, kS390_CmpDouble, g.UseRegister(left), | 1920 if (!g.CanBeImmediate(right, OperandMode::kUint32Imm) && |
1799 g.UseRegister(right), cont); | 1921 g.CanBeImmediate(left, OperandMode::kUint32Imm)) { |
| 1922 std::swap(left, right); |
| 1923 } |
| 1924 VisitCompare(selector, opcode, g.UseRegister(left), |
| 1925 g.UseOperand(right, OperandMode::kUint32Imm), cont); |
| 1926 } |
| 1927 |
| 1928 void VisitLoadAndTest(InstructionSelector* selector, InstructionCode opcode, |
| 1929 Node* node, Node* value, FlagsContinuation* cont, |
| 1930 bool discard_output) { |
| 1931 static_assert(kS390_LoadAndTestFloat64 - kS390_LoadAndTestWord32 == 3, |
| 1932 "LoadAndTest Opcode shouldn't contain other opcodes."); |
| 1933 |
| 1934 // TODO(john.yan): Add support for Float32/Float64. |
| 1935 DCHECK(opcode >= kS390_LoadAndTestWord32 || |
| 1936 opcode <= kS390_LoadAndTestWord64); |
| 1937 |
| 1938 S390OperandGenerator g(selector); |
| 1939 InstructionOperand inputs[8]; |
| 1940 InstructionOperand outputs[2]; |
| 1941 size_t input_count = 0; |
| 1942 size_t output_count = 0; |
| 1943 bool use_value = false; |
| 1944 |
| 1945 int effect_level = selector->GetEffectLevel(node); |
| 1946 if (cont->IsBranch()) { |
| 1947 effect_level = selector->GetEffectLevel( |
| 1948 cont->true_block()->PredecessorAt(0)->control_input()); |
| 1949 } |
| 1950 |
| 1951 if (g.CanBeMemoryOperand(opcode, node, value, effect_level)) { |
| 1952 // generate memory operand |
| 1953 AddressingMode addressing_mode = |
| 1954 g.GetEffectiveAddressMemoryOperand(value, inputs, &input_count); |
| 1955 opcode |= AddressingModeField::encode(addressing_mode); |
| 1956 } else { |
| 1957 inputs[input_count++] = g.UseAnyExceptImmediate(value); |
| 1958 use_value = true; |
| 1959 } |
| 1960 |
| 1961 if (!discard_output && !use_value) { |
| 1962 outputs[output_count++] = g.DefineAsRegister(value); |
| 1963 } |
| 1964 |
| 1965 opcode = cont->Encode(opcode); |
| 1966 if (cont->IsBranch()) { |
| 1967 inputs[input_count++] = g.Label(cont->true_block()); |
| 1968 inputs[input_count++] = g.Label(cont->false_block()); |
| 1969 } else if (cont->IsSet()) { |
| 1970 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 1971 } else if (cont->IsTrap()) { |
| 1972 inputs[input_count++] = g.UseImmediate(cont->trap_id()); |
| 1973 } else { |
| 1974 DCHECK(cont->IsDeoptimize()); |
| 1975 // nothing to do |
| 1976 } |
| 1977 |
| 1978 DCHECK(input_count <= 8 && output_count <= 2); |
| 1979 opcode = cont->Encode(opcode); |
| 1980 if (cont->IsDeoptimize()) { |
| 1981 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 1982 cont->reason(), cont->frame_state()); |
| 1983 } else { |
| 1984 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 1985 } |
1800 } | 1986 } |
1801 | 1987 |
1802 // Shared routine for word comparisons against zero. | 1988 // Shared routine for word comparisons against zero. |
1803 void VisitWordCompareZero(InstructionSelector* selector, Node* user, | 1989 void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
1804 Node* value, InstructionCode opcode, | 1990 Node* value, InstructionCode opcode, |
1805 FlagsContinuation* cont) { | 1991 FlagsContinuation* cont) { |
1806 // Try to combine with comparisons against 0 by simply inverting the branch. | 1992 // Try to combine with comparisons against 0 by simply inverting the branch. |
1807 while (value->opcode() == IrOpcode::kWord32Equal && | 1993 while (value->opcode() == IrOpcode::kWord32Equal && |
1808 selector->CanCover(user, value)) { | 1994 selector->CanCover(user, value)) { |
1809 Int32BinopMatcher m(value); | 1995 Int32BinopMatcher m(value); |
1810 if (!m.right().Is(0)) break; | 1996 if (!m.right().Is(0)) break; |
1811 | 1997 |
1812 user = value; | 1998 user = value; |
1813 value = m.left().node(); | 1999 value = m.left().node(); |
1814 cont->Negate(); | 2000 cont->Negate(); |
1815 } | 2001 } |
1816 | 2002 |
| 2003 FlagsCondition fc = cont->condition(); |
1817 if (selector->CanCover(user, value)) { | 2004 if (selector->CanCover(user, value)) { |
1818 switch (value->opcode()) { | 2005 switch (value->opcode()) { |
1819 case IrOpcode::kWord32Equal: { | 2006 case IrOpcode::kWord32Equal: { |
1820 cont->OverwriteAndNegateIfEqual(kEqual); | 2007 cont->OverwriteAndNegateIfEqual(kEqual); |
1821 Int32BinopMatcher m(value); | 2008 Int32BinopMatcher m(value); |
1822 if (m.right().Is(0)) { | 2009 if (m.right().Is(0)) { |
1823 // Try to combine the branch with a comparison. | 2010 // Try to combine the branch with a comparison. |
1824 Node* const user = m.node(); | 2011 Node* const user = m.node(); |
1825 Node* const value = m.left().node(); | 2012 Node* const value = m.left().node(); |
1826 if (selector->CanCover(user, value)) { | 2013 if (selector->CanCover(user, value)) { |
1827 switch (value->opcode()) { | 2014 switch (value->opcode()) { |
1828 case IrOpcode::kInt32Sub: | 2015 case IrOpcode::kInt32Sub: |
1829 return VisitWord32Compare(selector, value, cont); | 2016 return VisitWord32Compare(selector, value, cont); |
1830 case IrOpcode::kWord32And: | 2017 case IrOpcode::kWord32And: |
1831 return VisitWordCompare(selector, value, kS390_Tst64, cont, | 2018 return VisitTestUnderMask(selector, value, cont); |
1832 true, OperandMode::kUint32Imm); | |
1833 default: | 2019 default: |
1834 break; | 2020 break; |
1835 } | 2021 } |
1836 } | 2022 } |
1837 } | 2023 } |
1838 return VisitWord32Compare(selector, value, cont); | 2024 return VisitWord32Compare(selector, value, cont); |
1839 } | 2025 } |
1840 case IrOpcode::kInt32LessThan: | 2026 case IrOpcode::kInt32LessThan: |
1841 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 2027 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
1842 return VisitWord32Compare(selector, value, cont); | 2028 return VisitWord32Compare(selector, value, cont); |
(...skipping 12 matching lines...) Expand all Loading... |
1855 Int64BinopMatcher m(value); | 2041 Int64BinopMatcher m(value); |
1856 if (m.right().Is(0)) { | 2042 if (m.right().Is(0)) { |
1857 // Try to combine the branch with a comparison. | 2043 // Try to combine the branch with a comparison. |
1858 Node* const user = m.node(); | 2044 Node* const user = m.node(); |
1859 Node* const value = m.left().node(); | 2045 Node* const value = m.left().node(); |
1860 if (selector->CanCover(user, value)) { | 2046 if (selector->CanCover(user, value)) { |
1861 switch (value->opcode()) { | 2047 switch (value->opcode()) { |
1862 case IrOpcode::kInt64Sub: | 2048 case IrOpcode::kInt64Sub: |
1863 return VisitWord64Compare(selector, value, cont); | 2049 return VisitWord64Compare(selector, value, cont); |
1864 case IrOpcode::kWord64And: | 2050 case IrOpcode::kWord64And: |
1865 return VisitWordCompare(selector, value, kS390_Tst64, cont, | 2051 return VisitTestUnderMask(selector, value, cont); |
1866 true, OperandMode::kUint32Imm); | |
1867 default: | 2052 default: |
1868 break; | 2053 break; |
1869 } | 2054 } |
1870 } | 2055 } |
1871 } | 2056 } |
1872 return VisitWord64Compare(selector, value, cont); | 2057 return VisitWord64Compare(selector, value, cont); |
1873 } | 2058 } |
1874 case IrOpcode::kInt64LessThan: | 2059 case IrOpcode::kInt64LessThan: |
1875 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 2060 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
1876 return VisitWord64Compare(selector, value, cont); | 2061 return VisitWord64Compare(selector, value, cont); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1940 selector, node, kS390_Sub64, OperandMode::kInt32Imm_Negate, | 2125 selector, node, kS390_Sub64, OperandMode::kInt32Imm_Negate, |
1941 cont); | 2126 cont); |
1942 #endif | 2127 #endif |
1943 default: | 2128 default: |
1944 break; | 2129 break; |
1945 } | 2130 } |
1946 } | 2131 } |
1947 } | 2132 } |
1948 break; | 2133 break; |
1949 case IrOpcode::kInt32Sub: | 2134 case IrOpcode::kInt32Sub: |
1950 return VisitWord32Compare(selector, value, cont); | 2135 if (fc == kNotEqual || fc == kEqual) |
| 2136 return VisitWord32Compare(selector, value, cont); |
| 2137 break; |
1951 case IrOpcode::kWord32And: | 2138 case IrOpcode::kWord32And: |
1952 return VisitWordCompare(selector, value, kS390_Tst32, cont, true, | 2139 return VisitTestUnderMask(selector, value, cont); |
1953 OperandMode::kUint32Imm); | 2140 case IrOpcode::kLoad: { |
1954 // TODO(mbrandy): Handle? | 2141 LoadRepresentation load_rep = LoadRepresentationOf(value->op()); |
1955 // case IrOpcode::kInt32Add: | 2142 switch (load_rep.representation()) { |
1956 // case IrOpcode::kWord32Or: | 2143 case MachineRepresentation::kWord32: |
1957 // case IrOpcode::kWord32Xor: | 2144 if (opcode == kS390_LoadAndTestWord32) { |
1958 // case IrOpcode::kWord32Sar: | 2145 return VisitLoadAndTest(selector, opcode, user, value, cont); |
1959 // case IrOpcode::kWord32Shl: | 2146 } |
1960 // case IrOpcode::kWord32Shr: | 2147 default: |
1961 // case IrOpcode::kWord32Ror: | 2148 break; |
| 2149 } |
| 2150 break; |
| 2151 } |
| 2152 case IrOpcode::kInt32Add: |
| 2153 // can't handle overflow case. |
| 2154 break; |
| 2155 case IrOpcode::kWord32Or: |
| 2156 return VisitBin32op(selector, value, kS390_Or32, OrOperandMode, cont); |
| 2157 case IrOpcode::kWord32Xor: |
| 2158 return VisitBin32op(selector, value, kS390_Xor32, XorOperandMode, cont); |
| 2159 case IrOpcode::kWord32Sar: |
| 2160 case IrOpcode::kWord32Shl: |
| 2161 case IrOpcode::kWord32Shr: |
| 2162 case IrOpcode::kWord32Ror: |
| 2163 // doesn't generate cc, so ignore. |
| 2164 break; |
1962 #if V8_TARGET_ARCH_S390X | 2165 #if V8_TARGET_ARCH_S390X |
1963 case IrOpcode::kInt64Sub: | 2166 case IrOpcode::kInt64Sub: |
1964 return VisitWord64Compare(selector, value, cont); | 2167 if (fc == kNotEqual || fc == kEqual) |
| 2168 return VisitWord64Compare(selector, value, cont); |
| 2169 break; |
1965 case IrOpcode::kWord64And: | 2170 case IrOpcode::kWord64And: |
1966 return VisitWordCompare(selector, value, kS390_Tst64, cont, true, | 2171 return VisitTestUnderMask(selector, value, cont); |
1967 OperandMode::kUint32Imm); | 2172 case IrOpcode::kInt64Add: |
1968 // TODO(mbrandy): Handle? | 2173 // can't handle overflow case. |
1969 // case IrOpcode::kInt64Add: | 2174 break; |
1970 // case IrOpcode::kWord64Or: | 2175 case IrOpcode::kWord64Or: |
1971 // case IrOpcode::kWord64Xor: | 2176 // TODO(john.yan): need to handle |
1972 // case IrOpcode::kWord64Sar: | 2177 break; |
1973 // case IrOpcode::kWord64Shl: | 2178 case IrOpcode::kWord64Xor: |
1974 // case IrOpcode::kWord64Shr: | 2179 // TODO(john.yan): need to handle |
1975 // case IrOpcode::kWord64Ror: | 2180 break; |
| 2181 case IrOpcode::kWord64Sar: |
| 2182 case IrOpcode::kWord64Shl: |
| 2183 case IrOpcode::kWord64Shr: |
| 2184 case IrOpcode::kWord64Ror: |
| 2185 // doesn't generate cc, so ignore |
| 2186 break; |
1976 #endif | 2187 #endif |
1977 default: | 2188 default: |
1978 break; | 2189 break; |
1979 } | 2190 } |
1980 } | 2191 } |
1981 | 2192 |
1982 // Branch could not be combined with a compare, emit compare against 0. | 2193 // Branch could not be combined with a compare, emit LoadAndTest |
1983 S390OperandGenerator g(selector); | 2194 VisitLoadAndTest(selector, opcode, user, value, cont, true); |
1984 VisitCompare(selector, opcode, g.UseRegister(value), g.TempImmediate(0), | |
1985 cont); | |
1986 } | 2195 } |
1987 | 2196 |
1988 void VisitWord32CompareZero(InstructionSelector* selector, Node* user, | 2197 void VisitWord32CompareZero(InstructionSelector* selector, Node* user, |
1989 Node* value, FlagsContinuation* cont) { | 2198 Node* value, FlagsContinuation* cont) { |
1990 VisitWordCompareZero(selector, user, value, kS390_Cmp32, cont); | 2199 VisitWordCompareZero(selector, user, value, kS390_LoadAndTestWord32, cont); |
1991 } | 2200 } |
1992 | 2201 |
1993 #if V8_TARGET_ARCH_S390X | 2202 #if V8_TARGET_ARCH_S390X |
1994 void VisitWord64CompareZero(InstructionSelector* selector, Node* user, | 2203 void VisitWord64CompareZero(InstructionSelector* selector, Node* user, |
1995 Node* value, FlagsContinuation* cont) { | 2204 Node* value, FlagsContinuation* cont) { |
1996 VisitWordCompareZero(selector, user, value, kS390_Cmp64, cont); | 2205 VisitWordCompareZero(selector, user, value, kS390_LoadAndTestWord64, cont); |
1997 } | 2206 } |
1998 #endif | 2207 #endif |
1999 | 2208 |
2000 } // namespace | 2209 } // namespace |
2001 | 2210 |
2002 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 2211 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
2003 BasicBlock* fbranch) { | 2212 BasicBlock* fbranch) { |
2004 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 2213 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
2005 VisitWord32CompareZero(this, branch, branch->InputAt(0), &cont); | 2214 VisitWord32CompareZero(this, branch, branch->InputAt(0), &cont); |
2006 } | 2215 } |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2317 // static | 2526 // static |
2318 MachineOperatorBuilder::AlignmentRequirements | 2527 MachineOperatorBuilder::AlignmentRequirements |
2319 InstructionSelector::AlignmentRequirements() { | 2528 InstructionSelector::AlignmentRequirements() { |
2320 return MachineOperatorBuilder::AlignmentRequirements:: | 2529 return MachineOperatorBuilder::AlignmentRequirements:: |
2321 FullUnalignedAccessSupport(); | 2530 FullUnalignedAccessSupport(); |
2322 } | 2531 } |
2323 | 2532 |
2324 } // namespace compiler | 2533 } // namespace compiler |
2325 } // namespace internal | 2534 } // namespace internal |
2326 } // namespace v8 | 2535 } // namespace v8 |
OLD | NEW |