Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: src/compiler/s390/instruction-selector-s390.cc

Issue 2696343002: s390: optimize for compares (Closed)
Patch Set: add todo Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/s390/instruction-scheduler-s390.cc ('k') | src/s390/assembler-s390.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/s390/instruction-scheduler-s390.cc ('k') | src/s390/assembler-s390.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698