Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1 | // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file |
| 4 | |
| 5 | #include "test/unittests/compiler/instruction-selector-unittest.h" |
| 6 | |
| 7 | namespace v8 { |
| 8 | namespace internal { |
| 9 | namespace compiler { |
| 10 | |
| 11 | namespace { |
| 12 | |
| 13 | template <typename T> |
| 14 | struct MachInst { |
| 15 | T constructor; |
| 16 | const char* constructor_name; |
| 17 | ArchOpcode arch_opcode; |
| 18 | MachineType machine_type; |
| 19 | }; |
| 20 | |
| 21 | template <typename T> |
| 22 | std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) { |
| 23 | return os << mi.constructor_name; |
| 24 | } |
| 25 | |
| 26 | typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; |
| 27 | typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; |
| 28 | |
| 29 | // To avoid duplicated code IntCmp helper structure |
| 30 | // is created. It contains MachInst2 with two nodes and expected_size |
| 31 | // because different cmp instructions have different size. |
| 32 | struct IntCmp { |
| 33 | MachInst2 mi; |
| 34 | uint32_t expected_size; |
| 35 | }; |
| 36 | |
| 37 | struct FPCmp { |
| 38 | MachInst2 mi; |
| 39 | FlagsCondition cond; |
| 40 | }; |
| 41 | |
| 42 | const FPCmp kFPCmpInstructions[] = { |
| 43 | {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMipsCmpD, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 44 | MachineType::Float64()}, |
| 45 | kEqual}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 46 | {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsCmpD, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 47 | MachineType::Float64()}, |
| 48 | kUnsignedLessThan}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 49 | {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 50 | kMipsCmpD, MachineType::Float64()}, |
| 51 | kUnsignedLessThanOrEqual}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 52 | {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", kMipsCmpD, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 53 | MachineType::Float64()}, |
| 54 | kUnsignedLessThan}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 55 | {{&RawMachineAssembler::Float64GreaterThanOrEqual, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 56 | "Float64GreaterThanOrEqual", kMipsCmpD, MachineType::Float64()}, |
| 57 | kUnsignedLessThanOrEqual}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 58 | |
| 59 | struct Conversion { |
| 60 | // The machine_type field in MachInst1 represents the destination type. |
| 61 | MachInst1 mi; |
| 62 | MachineType src_machine_type; |
| 63 | }; |
| 64 | |
| 65 | |
| 66 | // ---------------------------------------------------------------------------- |
| 67 | // Logical instructions. |
| 68 | // ---------------------------------------------------------------------------- |
| 69 | |
| 70 | |
| 71 | const MachInst2 kLogicalInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 72 | {&RawMachineAssembler::WordAnd, "WordAnd", kMipsAnd, MachineType::Int16()}, |
| 73 | {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, MachineType::Int16()}, |
| 74 | {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, MachineType::Int16()}, |
| 75 | {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd, |
| 76 | MachineType::Int32()}, |
| 77 | {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, MachineType::Int32()}, |
| 78 | {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor, |
| 79 | MachineType::Int32()}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 80 | |
| 81 | |
| 82 | // ---------------------------------------------------------------------------- |
| 83 | // Shift instructions. |
| 84 | // ---------------------------------------------------------------------------- |
| 85 | |
| 86 | |
| 87 | const MachInst2 kShiftInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 88 | {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, MachineType::Int16()}, |
| 89 | {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, MachineType::Int16()}, |
| 90 | {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, MachineType::Int16()}, |
| 91 | {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, MachineType::Int16()}, |
| 92 | {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl, |
| 93 | MachineType::Int32()}, |
| 94 | {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr, |
| 95 | MachineType::Int32()}, |
| 96 | {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar, |
| 97 | MachineType::Int32()}, |
| 98 | {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor, |
| 99 | MachineType::Int32()}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 100 | |
| 101 | |
| 102 | // ---------------------------------------------------------------------------- |
| 103 | // MUL/DIV instructions. |
| 104 | // ---------------------------------------------------------------------------- |
| 105 | |
| 106 | |
| 107 | const MachInst2 kMulDivInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 108 | {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul, |
| 109 | MachineType::Int32()}, |
| 110 | {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv, |
| 111 | MachineType::Int32()}, |
| 112 | {&RawMachineAssembler::Uint32Div, "Uint32Div", kMipsDivU, |
| 113 | MachineType::Uint32()}, |
| 114 | {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsMulD, |
| 115 | MachineType::Float64()}, |
| 116 | {&RawMachineAssembler::Float64Div, "Float64Div", kMipsDivD, |
| 117 | MachineType::Float64()}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 118 | |
| 119 | |
| 120 | // ---------------------------------------------------------------------------- |
| 121 | // MOD instructions. |
| 122 | // ---------------------------------------------------------------------------- |
| 123 | |
| 124 | |
| 125 | const MachInst2 kModInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 126 | {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod, |
| 127 | MachineType::Int32()}, |
| 128 | {&RawMachineAssembler::Uint32Mod, "Int32UMod", kMipsModU, |
| 129 | MachineType::Int32()}, |
| 130 | {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsModD, |
| 131 | MachineType::Float64()}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 132 | |
| 133 | |
| 134 | // ---------------------------------------------------------------------------- |
| 135 | // Arithmetic FPU instructions. |
| 136 | // ---------------------------------------------------------------------------- |
| 137 | |
| 138 | |
| 139 | const MachInst2 kFPArithInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 140 | {&RawMachineAssembler::Float64Add, "Float64Add", kMipsAddD, |
| 141 | MachineType::Float64()}, |
| 142 | {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsSubD, |
| 143 | MachineType::Float64()}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 144 | |
| 145 | |
| 146 | // ---------------------------------------------------------------------------- |
| 147 | // IntArithTest instructions, two nodes. |
| 148 | // ---------------------------------------------------------------------------- |
| 149 | |
| 150 | |
| 151 | const MachInst2 kAddSubInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 152 | {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd, |
| 153 | MachineType::Int32()}, |
| 154 | {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub, |
| 155 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 156 | {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 157 | kMipsAddOvf, MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 158 | {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 159 | kMipsSubOvf, MachineType::Int32()}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 160 | |
| 161 | |
| 162 | // ---------------------------------------------------------------------------- |
| 163 | // IntArithTest instructions, one node. |
| 164 | // ---------------------------------------------------------------------------- |
| 165 | |
| 166 | |
| 167 | const MachInst1 kAddSubOneInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 168 | {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub, |
| 169 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 170 | // TODO(dusmil): check this ... |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 171 | // {&RawMachineAssembler::WordEqual , "WordEqual" , kMipsTst, |
| 172 | // MachineType::Int32()} |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 173 | }; |
| 174 | |
| 175 | |
| 176 | // ---------------------------------------------------------------------------- |
| 177 | // Arithmetic compare instructions. |
| 178 | // ---------------------------------------------------------------------------- |
| 179 | |
| 180 | |
| 181 | const IntCmp kCmpInstructions[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 182 | {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp, |
| 183 | MachineType::Int16()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 184 | 1U}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 185 | {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp, |
| 186 | MachineType::Int16()}, |
| 187 | 1U}, |
| 188 | {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp, |
| 189 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 190 | 1U}, |
| 191 | {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 192 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 193 | 1U}, |
| 194 | {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 195 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 196 | 1U}, |
| 197 | {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 198 | kMipsCmp, MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 199 | 1U}, |
| 200 | {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 201 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 202 | 1U}, |
| 203 | {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 204 | kMipsCmp, MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 205 | 1U}, |
| 206 | {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 207 | MachineType::Uint32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 208 | 1U}, |
| 209 | {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 210 | kMipsCmp, MachineType::Uint32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 211 | 1U}}; |
| 212 | |
| 213 | |
| 214 | // ---------------------------------------------------------------------------- |
| 215 | // Conversion instructions. |
| 216 | // ---------------------------------------------------------------------------- |
| 217 | |
| 218 | const Conversion kConversionInstructions[] = { |
| 219 | // Conversion instructions are related to machine_operator.h: |
| 220 | // FPU conversions: |
| 221 | // Convert representation of integers between float64 and int32/uint32. |
| 222 | // The precise rounding mode and handling of out of range inputs are *not* |
| 223 | // defined for these operators, since they are intended only for use with |
| 224 | // integers. |
| 225 | // mips instruction: cvt_d_w |
| 226 | {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 227 | kMipsCvtDW, MachineType::Float64()}, |
| 228 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 229 | |
| 230 | // mips instruction: cvt_d_uw |
| 231 | {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 232 | kMipsCvtDUw, MachineType::Float64()}, |
| 233 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 234 | |
| 235 | // mips instruction: trunc_w_d |
| 236 | {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 237 | kMipsTruncWD, MachineType::Float64()}, |
| 238 | MachineType::Int32()}, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 239 | |
| 240 | // mips instruction: trunc_uw_d |
| 241 | {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32", |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 242 | kMipsTruncUwD, MachineType::Float64()}, |
| 243 | MachineType::Int32()}}; |
| 244 | |
| 245 | const Conversion kFloat64RoundInstructions[] = { |
| 246 | {{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMipsCeilWD, |
| 247 | MachineType::Int32()}, |
| 248 | MachineType::Float64()}, |
| 249 | {{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown", kMipsFloorWD, |
| 250 | MachineType::Int32()}, |
| 251 | MachineType::Float64()}, |
| 252 | {{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven", |
| 253 | kMipsRoundWD, MachineType::Int32()}, |
| 254 | MachineType::Float64()}, |
| 255 | {{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate", |
| 256 | kMipsTruncWD, MachineType::Int32()}, |
| 257 | MachineType::Float64()}}; |
| 258 | |
| 259 | const Conversion kFloat32RoundInstructions[] = { |
| 260 | {{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMipsCeilWS, |
| 261 | MachineType::Int32()}, |
| 262 | MachineType::Float32()}, |
| 263 | {{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown", kMipsFloorWS, |
| 264 | MachineType::Int32()}, |
| 265 | MachineType::Float32()}, |
| 266 | {{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven", |
| 267 | kMipsRoundWS, MachineType::Int32()}, |
| 268 | MachineType::Float32()}, |
| 269 | {{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate", |
| 270 | kMipsTruncWS, MachineType::Int32()}, |
| 271 | MachineType::Float32()}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 272 | |
| 273 | } // namespace |
| 274 | |
| 275 | |
| 276 | typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest; |
| 277 | |
| 278 | |
| 279 | TEST_P(InstructionSelectorFPCmpTest, Parameter) { |
| 280 | const FPCmp cmp = GetParam(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 281 | StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type, |
| 282 | cmp.mi.machine_type); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 283 | m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 284 | Stream s = m.Build(); |
| 285 | ASSERT_EQ(1U, s.size()); |
| 286 | EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); |
| 287 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 288 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 289 | EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 290 | EXPECT_EQ(cmp.cond, s[0]->flags_condition()); |
| 291 | } |
| 292 | |
| 293 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, |
| 294 | ::testing::ValuesIn(kFPCmpInstructions)); |
| 295 | |
| 296 | |
| 297 | // ---------------------------------------------------------------------------- |
| 298 | // Arithmetic compare instructions integers. |
| 299 | // ---------------------------------------------------------------------------- |
| 300 | |
| 301 | |
| 302 | typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest; |
| 303 | |
| 304 | |
| 305 | TEST_P(InstructionSelectorCmpTest, Parameter) { |
| 306 | const IntCmp cmp = GetParam(); |
| 307 | const MachineType type = cmp.mi.machine_type; |
| 308 | StreamBuilder m(this, type, type, type); |
| 309 | m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 310 | Stream s = m.Build(); |
| 311 | ASSERT_EQ(cmp.expected_size, s.size()); |
| 312 | EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); |
| 313 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 314 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 315 | } |
| 316 | |
| 317 | |
| 318 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest, |
| 319 | ::testing::ValuesIn(kCmpInstructions)); |
| 320 | |
| 321 | |
| 322 | // ---------------------------------------------------------------------------- |
| 323 | // Shift instructions. |
| 324 | // ---------------------------------------------------------------------------- |
| 325 | |
| 326 | |
| 327 | typedef InstructionSelectorTestWithParam<MachInst2> |
| 328 | InstructionSelectorShiftTest; |
| 329 | |
| 330 | |
| 331 | TEST_P(InstructionSelectorShiftTest, Immediate) { |
| 332 | const MachInst2 dpi = GetParam(); |
| 333 | const MachineType type = dpi.machine_type; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 334 | TRACED_FORRANGE(int32_t, imm, 0, |
| 335 | ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 336 | StreamBuilder m(this, type, type); |
| 337 | m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); |
| 338 | Stream s = m.Build(); |
| 339 | ASSERT_EQ(1U, s.size()); |
| 340 | EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 341 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 342 | EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
| 343 | EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 344 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | |
| 349 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, |
| 350 | ::testing::ValuesIn(kShiftInstructions)); |
| 351 | |
| 352 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 353 | TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) { |
| 354 | // The available shift operand range is `0 <= imm < 32`, but we also test |
| 355 | // that immediates outside this range are handled properly (modulo-32). |
| 356 | TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 357 | int32_t lsb = shift & 0x1f; |
| 358 | TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 359 | uint32_t jnk = rng()->NextInt(); |
| 360 | jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; |
| 361 | uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; |
| 362 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 363 | m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)), |
| 364 | m.Int32Constant(shift))); |
| 365 | Stream s = m.Build(); |
| 366 | ASSERT_EQ(1U, s.size()); |
| 367 | EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); |
| 368 | ASSERT_EQ(3U, s[0]->InputCount()); |
| 369 | EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 370 | EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 371 | } |
| 372 | } |
| 373 | TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 374 | int32_t lsb = shift & 0x1f; |
| 375 | TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 376 | uint32_t jnk = rng()->NextInt(); |
| 377 | jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; |
| 378 | uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; |
| 379 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 380 | m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)), |
| 381 | m.Int32Constant(shift))); |
| 382 | Stream s = m.Build(); |
| 383 | ASSERT_EQ(1U, s.size()); |
| 384 | EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); |
| 385 | ASSERT_EQ(3U, s[0]->InputCount()); |
| 386 | EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 387 | EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 388 | } |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | |
| 393 | TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) { |
| 394 | TRACED_FORRANGE(int32_t, shift, 0, 30) { |
| 395 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 396 | Node* const p0 = m.Parameter(0); |
| 397 | Node* const r = |
| 398 | m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)), |
| 399 | m.Int32Constant(shift + 1)); |
| 400 | m.Return(r); |
| 401 | Stream s = m.Build(); |
| 402 | ASSERT_EQ(1U, s.size()); |
| 403 | EXPECT_EQ(kMipsShl, s[0]->arch_opcode()); |
| 404 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 405 | EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 406 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 407 | EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 412 | // ---------------------------------------------------------------------------- |
| 413 | // Logical instructions. |
| 414 | // ---------------------------------------------------------------------------- |
| 415 | |
| 416 | |
| 417 | typedef InstructionSelectorTestWithParam<MachInst2> |
| 418 | InstructionSelectorLogicalTest; |
| 419 | |
| 420 | |
| 421 | TEST_P(InstructionSelectorLogicalTest, Parameter) { |
| 422 | const MachInst2 dpi = GetParam(); |
| 423 | const MachineType type = dpi.machine_type; |
| 424 | StreamBuilder m(this, type, type, type); |
| 425 | m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 426 | Stream s = m.Build(); |
| 427 | ASSERT_EQ(1U, s.size()); |
| 428 | EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 429 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 430 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 431 | } |
| 432 | |
| 433 | |
| 434 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, |
| 435 | ::testing::ValuesIn(kLogicalInstructions)); |
| 436 | |
| 437 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 438 | TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) { |
| 439 | { |
| 440 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 441 | m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1))); |
| 442 | Stream s = m.Build(); |
| 443 | ASSERT_EQ(1U, s.size()); |
| 444 | EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); |
| 445 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 446 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 447 | } |
| 448 | { |
| 449 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 450 | m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0))); |
| 451 | Stream s = m.Build(); |
| 452 | ASSERT_EQ(1U, s.size()); |
| 453 | EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); |
| 454 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 455 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 456 | } |
| 457 | } |
| 458 | |
| 459 | |
| 460 | TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) { |
| 461 | { |
| 462 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 463 | m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)), |
| 464 | m.Int32Constant(-1))); |
| 465 | Stream s = m.Build(); |
| 466 | ASSERT_EQ(1U, s.size()); |
| 467 | EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); |
| 468 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 469 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 470 | } |
| 471 | { |
| 472 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 473 | m.Return(m.Word32Xor(m.Int32Constant(-1), |
| 474 | m.Word32Or(m.Parameter(0), m.Parameter(0)))); |
| 475 | Stream s = m.Build(); |
| 476 | ASSERT_EQ(1U, s.size()); |
| 477 | EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); |
| 478 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 479 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | |
| 484 | TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) { |
| 485 | // The available shift operand range is `0 <= imm < 32`, but we also test |
| 486 | // that immediates outside this range are handled properly (modulo-32). |
| 487 | TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 488 | int32_t lsb = shift & 0x1f; |
| 489 | TRACED_FORRANGE(int32_t, width, 1, 31) { |
| 490 | uint32_t msk = (1 << width) - 1; |
| 491 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 492 | m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)), |
| 493 | m.Int32Constant(msk))); |
| 494 | Stream s = m.Build(); |
| 495 | ASSERT_EQ(1U, s.size()); |
| 496 | EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); |
| 497 | ASSERT_EQ(3U, s[0]->InputCount()); |
| 498 | EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 499 | int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width; |
| 500 | EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2))); |
| 501 | } |
| 502 | } |
| 503 | TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 504 | int32_t lsb = shift & 0x1f; |
| 505 | TRACED_FORRANGE(int32_t, width, 1, 31) { |
| 506 | uint32_t msk = (1 << width) - 1; |
| 507 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 508 | m.Return( |
| 509 | m.Word32And(m.Int32Constant(msk), |
| 510 | m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)))); |
| 511 | Stream s = m.Build(); |
| 512 | ASSERT_EQ(1U, s.size()); |
| 513 | EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); |
| 514 | ASSERT_EQ(3U, s[0]->InputCount()); |
| 515 | EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 516 | int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width; |
| 517 | EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2))); |
| 518 | } |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | |
| 523 | TEST_F(InstructionSelectorTest, Word32AndToClearBits) { |
| 524 | TRACED_FORRANGE(int32_t, shift, 1, 31) { |
| 525 | int32_t mask = ~((1 << shift) - 1); |
| 526 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 527 | m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(mask))); |
| 528 | Stream s = m.Build(); |
| 529 | ASSERT_EQ(1U, s.size()); |
| 530 | EXPECT_EQ(kMipsIns, s[0]->arch_opcode()); |
| 531 | ASSERT_EQ(3U, s[0]->InputCount()); |
| 532 | EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); |
| 533 | EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2))); |
| 534 | } |
| 535 | TRACED_FORRANGE(int32_t, shift, 1, 31) { |
| 536 | int32_t mask = ~((1 << shift) - 1); |
| 537 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 538 | m.Return(m.Word32And(m.Int32Constant(mask), m.Parameter(0))); |
| 539 | Stream s = m.Build(); |
| 540 | ASSERT_EQ(1U, s.size()); |
| 541 | EXPECT_EQ(kMipsIns, s[0]->arch_opcode()); |
| 542 | ASSERT_EQ(3U, s[0]->InputCount()); |
| 543 | EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); |
| 544 | EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2))); |
| 545 | } |
| 546 | } |
| 547 | |
| 548 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 549 | // ---------------------------------------------------------------------------- |
| 550 | // MUL/DIV instructions. |
| 551 | // ---------------------------------------------------------------------------- |
| 552 | |
| 553 | |
| 554 | typedef InstructionSelectorTestWithParam<MachInst2> |
| 555 | InstructionSelectorMulDivTest; |
| 556 | |
| 557 | |
| 558 | TEST_P(InstructionSelectorMulDivTest, Parameter) { |
| 559 | const MachInst2 dpi = GetParam(); |
| 560 | const MachineType type = dpi.machine_type; |
| 561 | StreamBuilder m(this, type, type, type); |
| 562 | m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 563 | Stream s = m.Build(); |
| 564 | ASSERT_EQ(1U, s.size()); |
| 565 | EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 566 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 567 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 568 | } |
| 569 | |
| 570 | |
| 571 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, |
| 572 | ::testing::ValuesIn(kMulDivInstructions)); |
| 573 | |
| 574 | |
| 575 | // ---------------------------------------------------------------------------- |
| 576 | // MOD instructions. |
| 577 | // ---------------------------------------------------------------------------- |
| 578 | |
| 579 | |
| 580 | typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest; |
| 581 | |
| 582 | |
| 583 | TEST_P(InstructionSelectorModTest, Parameter) { |
| 584 | const MachInst2 dpi = GetParam(); |
| 585 | const MachineType type = dpi.machine_type; |
| 586 | StreamBuilder m(this, type, type, type); |
| 587 | m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 588 | Stream s = m.Build(); |
| 589 | ASSERT_EQ(1U, s.size()); |
| 590 | EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 591 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 592 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 593 | } |
| 594 | |
| 595 | |
| 596 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest, |
| 597 | ::testing::ValuesIn(kModInstructions)); |
| 598 | |
| 599 | |
| 600 | // ---------------------------------------------------------------------------- |
| 601 | // Floating point instructions. |
| 602 | // ---------------------------------------------------------------------------- |
| 603 | |
| 604 | |
| 605 | typedef InstructionSelectorTestWithParam<MachInst2> |
| 606 | InstructionSelectorFPArithTest; |
| 607 | |
| 608 | |
| 609 | TEST_P(InstructionSelectorFPArithTest, Parameter) { |
| 610 | const MachInst2 fpa = GetParam(); |
| 611 | StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type); |
| 612 | m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1))); |
| 613 | Stream s = m.Build(); |
| 614 | ASSERT_EQ(1U, s.size()); |
| 615 | EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode()); |
| 616 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 617 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 618 | } |
| 619 | |
| 620 | |
| 621 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest, |
| 622 | ::testing::ValuesIn(kFPArithInstructions)); |
| 623 | |
| 624 | |
| 625 | // ---------------------------------------------------------------------------- |
| 626 | // Integer arithmetic. |
| 627 | // ---------------------------------------------------------------------------- |
| 628 | |
| 629 | |
| 630 | typedef InstructionSelectorTestWithParam<MachInst2> |
| 631 | InstructionSelectorIntArithTwoTest; |
| 632 | |
| 633 | |
| 634 | TEST_P(InstructionSelectorIntArithTwoTest, Parameter) { |
| 635 | const MachInst2 intpa = GetParam(); |
| 636 | StreamBuilder m(this, intpa.machine_type, intpa.machine_type, |
| 637 | intpa.machine_type); |
| 638 | m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1))); |
| 639 | Stream s = m.Build(); |
| 640 | ASSERT_EQ(1U, s.size()); |
| 641 | EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); |
| 642 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 643 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 644 | } |
| 645 | |
| 646 | |
| 647 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 648 | InstructionSelectorIntArithTwoTest, |
| 649 | ::testing::ValuesIn(kAddSubInstructions)); |
| 650 | |
| 651 | |
| 652 | // ---------------------------------------------------------------------------- |
| 653 | // One node. |
| 654 | // ---------------------------------------------------------------------------- |
| 655 | |
| 656 | |
| 657 | typedef InstructionSelectorTestWithParam<MachInst1> |
| 658 | InstructionSelectorIntArithOneTest; |
| 659 | |
| 660 | |
| 661 | TEST_P(InstructionSelectorIntArithOneTest, Parameter) { |
| 662 | const MachInst1 intpa = GetParam(); |
| 663 | StreamBuilder m(this, intpa.machine_type, intpa.machine_type, |
| 664 | intpa.machine_type); |
| 665 | m.Return((m.*intpa.constructor)(m.Parameter(0))); |
| 666 | Stream s = m.Build(); |
| 667 | ASSERT_EQ(1U, s.size()); |
| 668 | EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); |
| 669 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 670 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 671 | } |
| 672 | |
| 673 | |
| 674 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 675 | InstructionSelectorIntArithOneTest, |
| 676 | ::testing::ValuesIn(kAddSubOneInstructions)); |
| 677 | |
| 678 | |
| 679 | // ---------------------------------------------------------------------------- |
| 680 | // Conversions. |
| 681 | // ---------------------------------------------------------------------------- |
| 682 | |
| 683 | |
| 684 | typedef InstructionSelectorTestWithParam<Conversion> |
| 685 | InstructionSelectorConversionTest; |
| 686 | |
| 687 | |
| 688 | TEST_P(InstructionSelectorConversionTest, Parameter) { |
| 689 | const Conversion conv = GetParam(); |
| 690 | StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); |
| 691 | m.Return((m.*conv.mi.constructor)(m.Parameter(0))); |
| 692 | Stream s = m.Build(); |
| 693 | ASSERT_EQ(1U, s.size()); |
| 694 | EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); |
| 695 | EXPECT_EQ(1U, s[0]->InputCount()); |
| 696 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 697 | } |
| 698 | |
| 699 | |
| 700 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 701 | InstructionSelectorConversionTest, |
| 702 | ::testing::ValuesIn(kConversionInstructions)); |
| 703 | |
| 704 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 705 | typedef InstructionSelectorTestWithParam<Conversion> |
| 706 | CombineChangeFloat64ToInt32WithRoundFloat64; |
| 707 | |
| 708 | TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) { |
| 709 | { |
| 710 | const Conversion conv = GetParam(); |
| 711 | StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); |
| 712 | m.Return(m.ChangeFloat64ToInt32((m.*conv.mi.constructor)(m.Parameter(0)))); |
| 713 | Stream s = m.Build(); |
| 714 | ASSERT_EQ(1U, s.size()); |
| 715 | EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); |
| 716 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 717 | ASSERT_EQ(1U, s[0]->InputCount()); |
| 718 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 723 | CombineChangeFloat64ToInt32WithRoundFloat64, |
| 724 | ::testing::ValuesIn(kFloat64RoundInstructions)); |
| 725 | |
| 726 | |
| 727 | typedef InstructionSelectorTestWithParam<Conversion> |
| 728 | CombineChangeFloat32ToInt32WithRoundFloat32; |
| 729 | |
| 730 | TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) { |
| 731 | { |
| 732 | const Conversion conv = GetParam(); |
| 733 | StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); |
| 734 | m.Return(m.ChangeFloat64ToInt32( |
| 735 | m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0))))); |
| 736 | Stream s = m.Build(); |
| 737 | ASSERT_EQ(1U, s.size()); |
| 738 | EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); |
| 739 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 740 | ASSERT_EQ(1U, s[0]->InputCount()); |
| 741 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 742 | } |
| 743 | } |
| 744 | |
| 745 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 746 | CombineChangeFloat32ToInt32WithRoundFloat32, |
| 747 | ::testing::ValuesIn(kFloat32RoundInstructions)); |
| 748 | |
| 749 | |
| 750 | TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) { |
| 751 | { |
| 752 | StreamBuilder m(this, MachineType::Int32(), MachineType::Float32()); |
| 753 | m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0)))); |
| 754 | Stream s = m.Build(); |
| 755 | ASSERT_EQ(1U, s.size()); |
| 756 | EXPECT_EQ(kMipsTruncWS, s[0]->arch_opcode()); |
| 757 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 758 | ASSERT_EQ(1U, s[0]->InputCount()); |
| 759 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 760 | } |
| 761 | } |
| 762 | |
| 763 | |
| 764 | TEST_F(InstructionSelectorTest, |
| 765 | TruncateFloat64ToFloat32OfChangeInt32ToFloat64) { |
| 766 | { |
| 767 | StreamBuilder m(this, MachineType::Float32(), MachineType::Int32()); |
| 768 | m.Return( |
| 769 | m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0)))); |
| 770 | Stream s = m.Build(); |
| 771 | ASSERT_EQ(1U, s.size()); |
| 772 | EXPECT_EQ(kMipsCvtSW, s[0]->arch_opcode()); |
| 773 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 774 | ASSERT_EQ(1U, s[0]->InputCount()); |
| 775 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 776 | } |
| 777 | } |
| 778 | |
| 779 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 780 | // ---------------------------------------------------------------------------- |
| 781 | // Loads and stores. |
| 782 | // ---------------------------------------------------------------------------- |
| 783 | |
| 784 | namespace { |
| 785 | |
| 786 | struct MemoryAccess { |
| 787 | MachineType type; |
| 788 | ArchOpcode load_opcode; |
| 789 | ArchOpcode store_opcode; |
| 790 | }; |
| 791 | |
| 792 | |
| 793 | static const MemoryAccess kMemoryAccesses[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 794 | {MachineType::Int8(), kMipsLb, kMipsSb}, |
| 795 | {MachineType::Uint8(), kMipsLbu, kMipsSb}, |
| 796 | {MachineType::Int16(), kMipsLh, kMipsSh}, |
| 797 | {MachineType::Uint16(), kMipsLhu, kMipsSh}, |
| 798 | {MachineType::Int32(), kMipsLw, kMipsSw}, |
| 799 | {MachineType::Float32(), kMipsLwc1, kMipsSwc1}, |
| 800 | {MachineType::Float64(), kMipsLdc1, kMipsSdc1}}; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 801 | |
| 802 | |
| 803 | struct MemoryAccessImm { |
| 804 | MachineType type; |
| 805 | ArchOpcode load_opcode; |
| 806 | ArchOpcode store_opcode; |
| 807 | bool (InstructionSelectorTest::Stream::*val_predicate)( |
| 808 | const InstructionOperand*) const; |
| 809 | const int32_t immediates[40]; |
| 810 | }; |
| 811 | |
| 812 | |
| 813 | std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) { |
| 814 | return os << acc.type; |
| 815 | } |
| 816 | |
| 817 | |
| 818 | struct MemoryAccessImm1 { |
| 819 | MachineType type; |
| 820 | ArchOpcode load_opcode; |
| 821 | ArchOpcode store_opcode; |
| 822 | bool (InstructionSelectorTest::Stream::*val_predicate)( |
| 823 | const InstructionOperand*) const; |
| 824 | const int32_t immediates[5]; |
| 825 | }; |
| 826 | |
| 827 | |
| 828 | std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) { |
| 829 | return os << acc.type; |
| 830 | } |
| 831 | |
| 832 | |
| 833 | // ---------------------------------------------------------------------------- |
| 834 | // Loads and stores immediate values. |
| 835 | // ---------------------------------------------------------------------------- |
| 836 | |
| 837 | |
| 838 | const MemoryAccessImm kMemoryAccessesImm[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 839 | {MachineType::Int8(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 840 | kMipsLb, |
| 841 | kMipsSb, |
| 842 | &InstructionSelectorTest::Stream::IsInteger, |
| 843 | {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| 844 | -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| 845 | 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 846 | {MachineType::Uint8(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 847 | kMipsLbu, |
| 848 | kMipsSb, |
| 849 | &InstructionSelectorTest::Stream::IsInteger, |
| 850 | {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| 851 | -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| 852 | 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 853 | {MachineType::Int16(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 854 | kMipsLh, |
| 855 | kMipsSh, |
| 856 | &InstructionSelectorTest::Stream::IsInteger, |
| 857 | {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| 858 | -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| 859 | 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 860 | {MachineType::Uint16(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 861 | kMipsLhu, |
| 862 | kMipsSh, |
| 863 | &InstructionSelectorTest::Stream::IsInteger, |
| 864 | {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| 865 | -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| 866 | 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 867 | {MachineType::Int32(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 868 | kMipsLw, |
| 869 | kMipsSw, |
| 870 | &InstructionSelectorTest::Stream::IsInteger, |
| 871 | {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| 872 | -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| 873 | 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 874 | {MachineType::Float32(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 875 | kMipsLwc1, |
| 876 | kMipsSwc1, |
| 877 | &InstructionSelectorTest::Stream::IsDouble, |
| 878 | {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| 879 | -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| 880 | 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 881 | {MachineType::Float64(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 882 | kMipsLdc1, |
| 883 | kMipsSdc1, |
| 884 | &InstructionSelectorTest::Stream::IsDouble, |
| 885 | {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| 886 | -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| 887 | 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}}; |
| 888 | |
| 889 | |
| 890 | const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 891 | {MachineType::Int8(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 892 | kMipsLb, |
| 893 | kMipsSb, |
| 894 | &InstructionSelectorTest::Stream::IsInteger, |
| 895 | {-65000, -55000, 32777, 55000, 65000}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 896 | {MachineType::Int8(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 897 | kMipsLbu, |
| 898 | kMipsSb, |
| 899 | &InstructionSelectorTest::Stream::IsInteger, |
| 900 | {-65000, -55000, 32777, 55000, 65000}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 901 | {MachineType::Int16(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 902 | kMipsLh, |
| 903 | kMipsSh, |
| 904 | &InstructionSelectorTest::Stream::IsInteger, |
| 905 | {-65000, -55000, 32777, 55000, 65000}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 906 | {MachineType::Int16(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 907 | kMipsLhu, |
| 908 | kMipsSh, |
| 909 | &InstructionSelectorTest::Stream::IsInteger, |
| 910 | {-65000, -55000, 32777, 55000, 65000}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 911 | {MachineType::Int32(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 912 | kMipsLw, |
| 913 | kMipsSw, |
| 914 | &InstructionSelectorTest::Stream::IsInteger, |
| 915 | {-65000, -55000, 32777, 55000, 65000}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 916 | {MachineType::Float32(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 917 | kMipsLwc1, |
| 918 | kMipsSwc1, |
| 919 | &InstructionSelectorTest::Stream::IsDouble, |
| 920 | {-65000, -55000, 32777, 55000, 65000}}, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 921 | {MachineType::Float64(), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 922 | kMipsLdc1, |
| 923 | kMipsSdc1, |
| 924 | &InstructionSelectorTest::Stream::IsDouble, |
| 925 | {-65000, -55000, 32777, 55000, 65000}}}; |
| 926 | |
| 927 | } // namespace |
| 928 | |
| 929 | |
| 930 | typedef InstructionSelectorTestWithParam<MemoryAccess> |
| 931 | InstructionSelectorMemoryAccessTest; |
| 932 | |
| 933 | |
| 934 | TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { |
| 935 | const MemoryAccess memacc = GetParam(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 936 | StreamBuilder m(this, memacc.type, MachineType::Pointer(), |
| 937 | MachineType::Int32()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 938 | m.Return(m.Load(memacc.type, m.Parameter(0))); |
| 939 | Stream s = m.Build(); |
| 940 | ASSERT_EQ(1U, s.size()); |
| 941 | EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| 942 | EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| 943 | } |
| 944 | |
| 945 | |
| 946 | TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { |
| 947 | const MemoryAccess memacc = GetParam(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 948 | StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), |
| 949 | MachineType::Int32(), memacc.type); |
| 950 | m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1), |
| 951 | kNoWriteBarrier); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 952 | m.Return(m.Int32Constant(0)); |
| 953 | Stream s = m.Build(); |
| 954 | ASSERT_EQ(1U, s.size()); |
| 955 | EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| 956 | EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| 957 | } |
| 958 | |
| 959 | |
| 960 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 961 | InstructionSelectorMemoryAccessTest, |
| 962 | ::testing::ValuesIn(kMemoryAccesses)); |
| 963 | |
| 964 | |
| 965 | // ---------------------------------------------------------------------------- |
| 966 | // Load immediate. |
| 967 | // ---------------------------------------------------------------------------- |
| 968 | |
| 969 | |
| 970 | typedef InstructionSelectorTestWithParam<MemoryAccessImm> |
| 971 | InstructionSelectorMemoryAccessImmTest; |
| 972 | |
| 973 | |
| 974 | TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) { |
| 975 | const MemoryAccessImm memacc = GetParam(); |
| 976 | TRACED_FOREACH(int32_t, index, memacc.immediates) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 977 | StreamBuilder m(this, memacc.type, MachineType::Pointer()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 978 | m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); |
| 979 | Stream s = m.Build(); |
| 980 | ASSERT_EQ(1U, s.size()); |
| 981 | EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| 982 | EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| 983 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 984 | ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 985 | EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
| 986 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 987 | EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); |
| 988 | } |
| 989 | } |
| 990 | |
| 991 | |
| 992 | // ---------------------------------------------------------------------------- |
| 993 | // Store immediate. |
| 994 | // ---------------------------------------------------------------------------- |
| 995 | |
| 996 | |
| 997 | TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) { |
| 998 | const MemoryAccessImm memacc = GetParam(); |
| 999 | TRACED_FOREACH(int32_t, index, memacc.immediates) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1000 | StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), |
| 1001 | memacc.type); |
| 1002 | m.Store(memacc.type.representation(), m.Parameter(0), |
| 1003 | m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1004 | m.Return(m.Int32Constant(0)); |
| 1005 | Stream s = m.Build(); |
| 1006 | ASSERT_EQ(1U, s.size()); |
| 1007 | EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| 1008 | EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| 1009 | ASSERT_EQ(3U, s[0]->InputCount()); |
| 1010 | ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1011 | EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
| 1012 | EXPECT_EQ(0U, s[0]->OutputCount()); |
| 1013 | } |
| 1014 | } |
| 1015 | |
| 1016 | |
| 1017 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 1018 | InstructionSelectorMemoryAccessImmTest, |
| 1019 | ::testing::ValuesIn(kMemoryAccessesImm)); |
| 1020 | |
| 1021 | |
| 1022 | // ---------------------------------------------------------------------------- |
| 1023 | // Load/store offsets more than 16 bits. |
| 1024 | // ---------------------------------------------------------------------------- |
| 1025 | |
| 1026 | |
| 1027 | typedef InstructionSelectorTestWithParam<MemoryAccessImm1> |
| 1028 | InstructionSelectorMemoryAccessImmMoreThan16bitTest; |
| 1029 | |
| 1030 | |
| 1031 | TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, |
| 1032 | LoadWithImmediateIndex) { |
| 1033 | const MemoryAccessImm1 memacc = GetParam(); |
| 1034 | TRACED_FOREACH(int32_t, index, memacc.immediates) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1035 | StreamBuilder m(this, memacc.type, MachineType::Pointer()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1036 | m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); |
| 1037 | Stream s = m.Build(); |
| 1038 | ASSERT_EQ(2U, s.size()); |
| 1039 | // kMipsAdd is expected opcode. |
| 1040 | // size more than 16 bits wide. |
| 1041 | EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); |
| 1042 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 1043 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 1044 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1045 | } |
| 1046 | } |
| 1047 | |
| 1048 | |
| 1049 | TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, |
| 1050 | StoreWithImmediateIndex) { |
| 1051 | const MemoryAccessImm1 memacc = GetParam(); |
| 1052 | TRACED_FOREACH(int32_t, index, memacc.immediates) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1053 | StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), |
| 1054 | memacc.type); |
| 1055 | m.Store(memacc.type.representation(), m.Parameter(0), |
| 1056 | m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1057 | m.Return(m.Int32Constant(0)); |
| 1058 | Stream s = m.Build(); |
| 1059 | ASSERT_EQ(2U, s.size()); |
| 1060 | // kMipsAdd is expected opcode |
| 1061 | // size more than 16 bits wide |
| 1062 | EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); |
| 1063 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 1064 | EXPECT_EQ(2U, s[0]->InputCount()); |
| 1065 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1066 | } |
| 1067 | } |
| 1068 | |
| 1069 | |
| 1070 | INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 1071 | InstructionSelectorMemoryAccessImmMoreThan16bitTest, |
| 1072 | ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit)); |
| 1073 | |
| 1074 | |
| 1075 | // ---------------------------------------------------------------------------- |
| 1076 | // kMipsTst testing. |
| 1077 | // ---------------------------------------------------------------------------- |
| 1078 | |
| 1079 | |
| 1080 | TEST_F(InstructionSelectorTest, Word32EqualWithZero) { |
| 1081 | { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1082 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1083 | m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); |
| 1084 | Stream s = m.Build(); |
| 1085 | ASSERT_EQ(1U, s.size()); |
| 1086 | EXPECT_EQ(kMipsCmp, s[0]->arch_opcode()); |
| 1087 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 1088 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 1089 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1090 | EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1091 | EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1092 | } |
| 1093 | { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1094 | StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1095 | m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); |
| 1096 | Stream s = m.Build(); |
| 1097 | ASSERT_EQ(1U, s.size()); |
| 1098 | EXPECT_EQ(kMipsCmp, s[0]->arch_opcode()); |
| 1099 | EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 1100 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 1101 | EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1102 | EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1103 | EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1104 | } |
| 1105 | } |
| 1106 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1107 | |
| 1108 | TEST_F(InstructionSelectorTest, Word32Clz) { |
| 1109 | StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32()); |
| 1110 | Node* const p0 = m.Parameter(0); |
| 1111 | Node* const n = m.Word32Clz(p0); |
| 1112 | m.Return(n); |
| 1113 | Stream s = m.Build(); |
| 1114 | ASSERT_EQ(1U, s.size()); |
| 1115 | EXPECT_EQ(kMipsClz, s[0]->arch_opcode()); |
| 1116 | ASSERT_EQ(1U, s[0]->InputCount()); |
| 1117 | EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 1118 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1119 | EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 1120 | } |
| 1121 | |
| 1122 | |
| 1123 | TEST_F(InstructionSelectorTest, Float32Abs) { |
| 1124 | StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); |
| 1125 | Node* const p0 = m.Parameter(0); |
| 1126 | Node* const n = m.Float32Abs(p0); |
| 1127 | m.Return(n); |
| 1128 | Stream s = m.Build(); |
| 1129 | ASSERT_EQ(1U, s.size()); |
| 1130 | EXPECT_EQ(kMipsAbsS, s[0]->arch_opcode()); |
| 1131 | ASSERT_EQ(1U, s[0]->InputCount()); |
| 1132 | EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 1133 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1134 | EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 1135 | } |
| 1136 | |
| 1137 | |
| 1138 | TEST_F(InstructionSelectorTest, Float64Abs) { |
| 1139 | StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); |
| 1140 | Node* const p0 = m.Parameter(0); |
| 1141 | Node* const n = m.Float64Abs(p0); |
| 1142 | m.Return(n); |
| 1143 | Stream s = m.Build(); |
| 1144 | ASSERT_EQ(1U, s.size()); |
| 1145 | EXPECT_EQ(kMipsAbsD, s[0]->arch_opcode()); |
| 1146 | ASSERT_EQ(1U, s[0]->InputCount()); |
| 1147 | EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 1148 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1149 | EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 1150 | } |
| 1151 | |
| 1152 | |
| 1153 | TEST_F(InstructionSelectorTest, Float32Max) { |
| 1154 | StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), |
| 1155 | MachineType::Float32()); |
| 1156 | Node* const p0 = m.Parameter(0); |
| 1157 | Node* const p1 = m.Parameter(1); |
| 1158 | Node* const n = m.Float32Max(p0, p1); |
| 1159 | m.Return(n); |
| 1160 | Stream s = m.Build(); |
| 1161 | // Float32Max is `(b < a) ? a : b`. |
| 1162 | ASSERT_EQ(1U, s.size()); |
| 1163 | EXPECT_EQ(kMipsFloat32Max, s[0]->arch_opcode()); |
| 1164 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 1165 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1166 | EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 1167 | } |
| 1168 | |
| 1169 | |
| 1170 | TEST_F(InstructionSelectorTest, Float32Min) { |
| 1171 | StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), |
| 1172 | MachineType::Float32()); |
| 1173 | Node* const p0 = m.Parameter(0); |
| 1174 | Node* const p1 = m.Parameter(1); |
| 1175 | Node* const n = m.Float32Min(p0, p1); |
| 1176 | m.Return(n); |
| 1177 | Stream s = m.Build(); |
| 1178 | // Float32Min is `(a < b) ? a : b`. |
| 1179 | ASSERT_EQ(1U, s.size()); |
| 1180 | EXPECT_EQ(kMipsFloat32Min, s[0]->arch_opcode()); |
| 1181 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 1182 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1183 | EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 1184 | } |
| 1185 | |
| 1186 | |
| 1187 | TEST_F(InstructionSelectorTest, Float64Max) { |
| 1188 | StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), |
| 1189 | MachineType::Float64()); |
| 1190 | Node* const p0 = m.Parameter(0); |
| 1191 | Node* const p1 = m.Parameter(1); |
| 1192 | Node* const n = m.Float64Max(p0, p1); |
| 1193 | m.Return(n); |
| 1194 | Stream s = m.Build(); |
| 1195 | // Float64Max is `(b < a) ? a : b`. |
| 1196 | ASSERT_EQ(1U, s.size()); |
| 1197 | EXPECT_EQ(kMipsFloat64Max, s[0]->arch_opcode()); |
| 1198 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 1199 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1200 | EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 1201 | } |
| 1202 | |
| 1203 | |
| 1204 | TEST_F(InstructionSelectorTest, Float64Min) { |
| 1205 | StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), |
| 1206 | MachineType::Float64()); |
| 1207 | Node* const p0 = m.Parameter(0); |
| 1208 | Node* const p1 = m.Parameter(1); |
| 1209 | Node* const n = m.Float64Min(p0, p1); |
| 1210 | m.Return(n); |
| 1211 | Stream s = m.Build(); |
| 1212 | // Float64Min is `(a < b) ? a : b`. |
| 1213 | ASSERT_EQ(1U, s.size()); |
| 1214 | EXPECT_EQ(kMipsFloat64Min, s[0]->arch_opcode()); |
| 1215 | ASSERT_EQ(2U, s[0]->InputCount()); |
| 1216 | ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1217 | EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 1218 | } |
| 1219 | |
| 1220 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1221 | } // namespace compiler |
| 1222 | } // namespace internal |
| 1223 | } // namespace v8 |