vectornode.cpp 12.5 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23
 */

24 25 26 27
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/connode.hpp"
#include "opto/vectornode.hpp"
D
duke 已提交
28 29 30 31

//------------------------------VectorNode--------------------------------------

// Return the vector operator for the specified scalar operation
32
// and vector length.  Also used to check if the code generator
D
duke 已提交
33
// supports the vector operation.
34
int VectorNode::opcode(int sopc, BasicType bt) {
D
duke 已提交
35 36 37 38 39
  switch (sopc) {
  case Op_AddI:
    switch (bt) {
    case T_BOOLEAN:
    case T_BYTE:      return Op_AddVB;
40
    case T_CHAR:
D
duke 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
    case T_SHORT:     return Op_AddVS;
    case T_INT:       return Op_AddVI;
    }
    ShouldNotReachHere();
  case Op_AddL:
    assert(bt == T_LONG, "must be");
    return Op_AddVL;
  case Op_AddF:
    assert(bt == T_FLOAT, "must be");
    return Op_AddVF;
  case Op_AddD:
    assert(bt == T_DOUBLE, "must be");
    return Op_AddVD;
  case Op_SubI:
    switch (bt) {
    case T_BOOLEAN:
    case T_BYTE:   return Op_SubVB;
58
    case T_CHAR:
D
duke 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71
    case T_SHORT:  return Op_SubVS;
    case T_INT:    return Op_SubVI;
    }
    ShouldNotReachHere();
  case Op_SubL:
    assert(bt == T_LONG, "must be");
    return Op_SubVL;
  case Op_SubF:
    assert(bt == T_FLOAT, "must be");
    return Op_SubVF;
  case Op_SubD:
    assert(bt == T_DOUBLE, "must be");
    return Op_SubVD;
72 73 74 75 76 77 78 79 80
  case Op_MulI:
    switch (bt) {
    case T_BOOLEAN:
    case T_BYTE:   return 0;   // Unimplemented
    case T_CHAR:
    case T_SHORT:  return Op_MulVS;
    case T_INT:    return Matcher::match_rule_supported(Op_MulVI) ? Op_MulVI : 0; // SSE4_1
    }
    ShouldNotReachHere();
D
duke 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
  case Op_MulF:
    assert(bt == T_FLOAT, "must be");
    return Op_MulVF;
  case Op_MulD:
    assert(bt == T_DOUBLE, "must be");
    return Op_MulVD;
  case Op_DivF:
    assert(bt == T_FLOAT, "must be");
    return Op_DivVF;
  case Op_DivD:
    assert(bt == T_DOUBLE, "must be");
    return Op_DivVD;
  case Op_LShiftI:
    switch (bt) {
    case T_BOOLEAN:
    case T_BYTE:   return Op_LShiftVB;
97
    case T_CHAR:
D
duke 已提交
98 99 100 101
    case T_SHORT:  return Op_LShiftVS;
    case T_INT:    return Op_LShiftVI;
    }
    ShouldNotReachHere();
102 103 104
  case Op_LShiftL:
    assert(bt == T_LONG, "must be");
    return Op_LShiftVL;
105
  case Op_RShiftI:
D
duke 已提交
106 107
    switch (bt) {
    case T_BOOLEAN:
108 109 110 111
    case T_BYTE:   return Op_RShiftVB;
    case T_CHAR:
    case T_SHORT:  return Op_RShiftVS;
    case T_INT:    return Op_RShiftVI;
D
duke 已提交
112 113
    }
    ShouldNotReachHere();
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
  case Op_RShiftL:
    assert(bt == T_LONG, "must be");
    return Op_RShiftVL;
  case Op_URShiftI:
    switch (bt) {
    case T_BOOLEAN:
    case T_BYTE:   return Op_URShiftVB;
    case T_CHAR:
    case T_SHORT:  return Op_URShiftVS;
    case T_INT:    return Op_URShiftVI;
    }
    ShouldNotReachHere();
  case Op_URShiftL:
    assert(bt == T_LONG, "must be");
    return Op_URShiftVL;
D
duke 已提交
129 130 131 132 133 134 135 136 137 138 139
  case Op_AndI:
  case Op_AndL:
    return Op_AndV;
  case Op_OrI:
  case Op_OrL:
    return Op_OrV;
  case Op_XorI:
  case Op_XorL:
    return Op_XorV;

  case Op_LoadB:
140
  case Op_LoadUB:
141
  case Op_LoadUS:
D
duke 已提交
142 143 144 145 146
  case Op_LoadS:
  case Op_LoadI:
  case Op_LoadL:
  case Op_LoadF:
  case Op_LoadD:
147
    return Op_LoadVector;
D
duke 已提交
148 149 150 151 152 153 154

  case Op_StoreB:
  case Op_StoreC:
  case Op_StoreI:
  case Op_StoreL:
  case Op_StoreF:
  case Op_StoreD:
155
    return Op_StoreVector;
D
duke 已提交
156 157 158 159
  }
  return 0; // Unimplemented
}

160 161 162 163
bool VectorNode::implemented(int opc, uint vlen, BasicType bt) {
  if (is_java_primitive(bt) &&
      (vlen > 1) && is_power_of_2(vlen) &&
      Matcher::vector_size_supported(bt, vlen)) {
164
    int vopc = VectorNode::opcode(opc, bt);
165
    return vopc > 0 && Matcher::has_match_rule(vopc);
D
duke 已提交
166
  }
167
  return false;
D
duke 已提交
168 169
}

170 171 172 173 174 175 176 177 178 179 180 181 182
bool VectorNode::is_shift(Node* n) {
  switch (n->Opcode()) {
  case Op_LShiftI:
  case Op_LShiftL:
  case Op_RShiftI:
  case Op_RShiftL:
  case Op_URShiftI:
  case Op_URShiftL:
    return true;
  }
  return false;
}

K
kvn 已提交
183
// Check if input is loop invariant vector.
184
bool VectorNode::is_invariant_vector(Node* n) {
K
kvn 已提交
185
  // Only Replicate vector nodes are loop invariant for now.
186 187 188 189 190 191 192 193 194 195 196 197
  switch (n->Opcode()) {
  case Op_ReplicateB:
  case Op_ReplicateS:
  case Op_ReplicateI:
  case Op_ReplicateL:
  case Op_ReplicateF:
  case Op_ReplicateD:
    return true;
  }
  return false;
}

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
// [Start, end) half-open range defining which operands are vectors
void VectorNode::vector_operands(Node* n, uint* start, uint* end) {
  switch (n->Opcode()) {
  case Op_LoadB:   case Op_LoadUB:
  case Op_LoadS:   case Op_LoadUS:
  case Op_LoadI:   case Op_LoadL:
  case Op_LoadF:   case Op_LoadD:
  case Op_LoadP:   case Op_LoadN:
    *start = 0;
    *end   = 0; // no vector operands
    break;
  case Op_StoreB:  case Op_StoreC:
  case Op_StoreI:  case Op_StoreL:
  case Op_StoreF:  case Op_StoreD:
  case Op_StoreP:  case Op_StoreN:
    *start = MemNode::ValueIn;
    *end   = MemNode::ValueIn + 1; // 1 vector operand
    break;
  case Op_LShiftI:  case Op_LShiftL:
  case Op_RShiftI:  case Op_RShiftL:
  case Op_URShiftI: case Op_URShiftL:
    *start = 1;
    *end   = 2; // 1 vector operand
    break;
  case Op_AddI: case Op_AddL: case Op_AddF: case Op_AddD:
  case Op_SubI: case Op_SubL: case Op_SubF: case Op_SubD:
  case Op_MulI: case Op_MulL: case Op_MulF: case Op_MulD:
  case Op_DivF: case Op_DivD:
  case Op_AndI: case Op_AndL:
  case Op_OrI:  case Op_OrL:
  case Op_XorI: case Op_XorL:
    *start = 1;
    *end   = 3; // 2 vector operands
    break;
  case Op_CMoveI:  case Op_CMoveL:  case Op_CMoveF:  case Op_CMoveD:
    *start = 2;
    *end   = n->req();
    break;
  default:
    *start = 1;
    *end   = n->req(); // default is all operands
  }
}

D
duke 已提交
242
// Return the vector version of a scalar operation node.
243 244
VectorNode* VectorNode::make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt) {
  const TypeVect* vt = TypeVect::make(bt, vlen);
245
  int vopc = VectorNode::opcode(opc, bt);
D
duke 已提交
246 247

  switch (vopc) {
248 249 250 251 252 253
  case Op_AddVB: return new (C) AddVBNode(n1, n2, vt);
  case Op_AddVS: return new (C) AddVSNode(n1, n2, vt);
  case Op_AddVI: return new (C) AddVINode(n1, n2, vt);
  case Op_AddVL: return new (C) AddVLNode(n1, n2, vt);
  case Op_AddVF: return new (C) AddVFNode(n1, n2, vt);
  case Op_AddVD: return new (C) AddVDNode(n1, n2, vt);
254

255 256 257 258 259 260
  case Op_SubVB: return new (C) SubVBNode(n1, n2, vt);
  case Op_SubVS: return new (C) SubVSNode(n1, n2, vt);
  case Op_SubVI: return new (C) SubVINode(n1, n2, vt);
  case Op_SubVL: return new (C) SubVLNode(n1, n2, vt);
  case Op_SubVF: return new (C) SubVFNode(n1, n2, vt);
  case Op_SubVD: return new (C) SubVDNode(n1, n2, vt);
261

262 263 264 265
  case Op_MulVS: return new (C) MulVSNode(n1, n2, vt);
  case Op_MulVI: return new (C) MulVINode(n1, n2, vt);
  case Op_MulVF: return new (C) MulVFNode(n1, n2, vt);
  case Op_MulVD: return new (C) MulVDNode(n1, n2, vt);
266

267 268
  case Op_DivVF: return new (C) DivVFNode(n1, n2, vt);
  case Op_DivVD: return new (C) DivVDNode(n1, n2, vt);
269

270 271 272 273
  case Op_LShiftVB: return new (C) LShiftVBNode(n1, n2, vt);
  case Op_LShiftVS: return new (C) LShiftVSNode(n1, n2, vt);
  case Op_LShiftVI: return new (C) LShiftVINode(n1, n2, vt);
  case Op_LShiftVL: return new (C) LShiftVLNode(n1, n2, vt);
274

275 276 277 278
  case Op_RShiftVB: return new (C) RShiftVBNode(n1, n2, vt);
  case Op_RShiftVS: return new (C) RShiftVSNode(n1, n2, vt);
  case Op_RShiftVI: return new (C) RShiftVINode(n1, n2, vt);
  case Op_RShiftVL: return new (C) RShiftVLNode(n1, n2, vt);
279

280 281 282 283
  case Op_URShiftVB: return new (C) URShiftVBNode(n1, n2, vt);
  case Op_URShiftVS: return new (C) URShiftVSNode(n1, n2, vt);
  case Op_URShiftVI: return new (C) URShiftVINode(n1, n2, vt);
  case Op_URShiftVL: return new (C) URShiftVLNode(n1, n2, vt);
284

285 286 287
  case Op_AndV: return new (C) AndVNode(n1, n2, vt);
  case Op_OrV:  return new (C) OrVNode (n1, n2, vt);
  case Op_XorV: return new (C) XorVNode(n1, n2, vt);
288 289 290
  }
  ShouldNotReachHere();
  return NULL;
D
duke 已提交
291

292
}
D
duke 已提交
293

294 295 296 297 298 299 300 301
// Scalar promotion
VectorNode* VectorNode::scalar2vector(Compile* C, Node* s, uint vlen, const Type* opd_t) {
  BasicType bt = opd_t->array_element_basic_type();
  const TypeVect* vt = opd_t->singleton() ? TypeVect::make(opd_t, vlen)
                                          : TypeVect::make(bt, vlen);
  switch (bt) {
  case T_BOOLEAN:
  case T_BYTE:
302
    return new (C) ReplicateBNode(s, vt);
303 304
  case T_CHAR:
  case T_SHORT:
305
    return new (C) ReplicateSNode(s, vt);
306
  case T_INT:
307
    return new (C) ReplicateINode(s, vt);
308
  case T_LONG:
309
    return new (C) ReplicateLNode(s, vt);
310
  case T_FLOAT:
311
    return new (C) ReplicateFNode(s, vt);
312
  case T_DOUBLE:
313
    return new (C) ReplicateDNode(s, vt);
D
duke 已提交
314 315 316 317 318
  }
  ShouldNotReachHere();
  return NULL;
}

319 320 321 322 323 324
// Return initial Pack node. Additional operands added with add_opd() calls.
PackNode* PackNode::make(Compile* C, Node* s, uint vlen, BasicType bt) {
  const TypeVect* vt = TypeVect::make(bt, vlen);
  switch (bt) {
  case T_BOOLEAN:
  case T_BYTE:
325
    return new (C) PackBNode(s, vt);
326 327
  case T_CHAR:
  case T_SHORT:
328
    return new (C) PackSNode(s, vt);
329
  case T_INT:
330
    return new (C) PackINode(s, vt);
331
  case T_LONG:
332
    return new (C) PackLNode(s, vt);
333
  case T_FLOAT:
334
    return new (C) PackFNode(s, vt);
335
  case T_DOUBLE:
336
    return new (C) PackDNode(s, vt);
337 338 339 340
  }
  ShouldNotReachHere();
  return NULL;
}
D
duke 已提交
341

342
// Create a binary tree form for Packs. [lo, hi) (half-open) range
343
PackNode* PackNode::binary_tree_pack(Compile* C, int lo, int hi) {
344 345 346 347
  int ct = hi - lo;
  assert(is_power_of_2(ct), "power of 2");
  if (ct == 2) {
    PackNode* pk = PackNode::make(C, in(lo), 2, vect_type()->element_basic_type());
348
    pk->add_opd(in(lo+1));
349
    return pk;
D
duke 已提交
350

351 352
  } else {
    int mid = lo + ct/2;
353 354
    PackNode* n1 = binary_tree_pack(C, lo,  mid);
    PackNode* n2 = binary_tree_pack(C, mid, hi );
D
duke 已提交
355

356 357
    BasicType bt = n1->vect_type()->element_basic_type();
    assert(bt == n2->vect_type()->element_basic_type(), "should be the same");
358 359 360
    switch (bt) {
    case T_BOOLEAN:
    case T_BYTE:
361
      return new (C) PackSNode(n1, n2, TypeVect::make(T_SHORT, 2));
362 363
    case T_CHAR:
    case T_SHORT:
364
      return new (C) PackINode(n1, n2, TypeVect::make(T_INT, 2));
365
    case T_INT:
366
      return new (C) PackLNode(n1, n2, TypeVect::make(T_LONG, 2));
367
    case T_LONG:
368
      return new (C) Pack2LNode(n1, n2, TypeVect::make(T_LONG, 2));
369
    case T_FLOAT:
370
      return new (C) PackDNode(n1, n2, TypeVect::make(T_DOUBLE, 2));
371
    case T_DOUBLE:
372
      return new (C) Pack2DNode(n1, n2, TypeVect::make(T_DOUBLE, 2));
373 374
    }
    ShouldNotReachHere();
D
duke 已提交
375
  }
376 377 378 379 380 381 382
  return NULL;
}

// Return the vector version of a scalar load node.
LoadVectorNode* LoadVectorNode::make(Compile* C, int opc, Node* ctl, Node* mem,
                                     Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) {
  const TypeVect* vt = TypeVect::make(bt, vlen);
383
  return new (C) LoadVectorNode(ctl, mem, adr, atyp, vt);
D
duke 已提交
384 385 386 387
  return NULL;
}

// Return the vector version of a scalar store node.
388
StoreVectorNode* StoreVectorNode::make(Compile* C, int opc, Node* ctl, Node* mem,
K
kvn 已提交
389
                                       Node* adr, const TypePtr* atyp, Node* val,
D
duke 已提交
390
                                       uint vlen) {
391
  return new (C) StoreVectorNode(ctl, mem, adr, atyp, val);
D
duke 已提交
392 393 394
}

// Extract a scalar element of vector.
395 396
Node* ExtractNode::make(Compile* C, Node* v, uint position, BasicType bt) {
  assert((int)position < Matcher::max_vector_size(bt), "pos in range");
D
duke 已提交
397 398 399
  ConINode* pos = ConINode::make(C, (int)position);
  switch (bt) {
  case T_BOOLEAN:
400
    return new (C) ExtractUBNode(v, pos);
D
duke 已提交
401
  case T_BYTE:
402
    return new (C) ExtractBNode(v, pos);
D
duke 已提交
403
  case T_CHAR:
404
    return new (C) ExtractCNode(v, pos);
D
duke 已提交
405
  case T_SHORT:
406
    return new (C) ExtractSNode(v, pos);
D
duke 已提交
407
  case T_INT:
408
    return new (C) ExtractINode(v, pos);
D
duke 已提交
409
  case T_LONG:
410
    return new (C) ExtractLNode(v, pos);
D
duke 已提交
411
  case T_FLOAT:
412
    return new (C) ExtractFNode(v, pos);
D
duke 已提交
413
  case T_DOUBLE:
414
    return new (C) ExtractDNode(v, pos);
D
duke 已提交
415 416 417 418
  }
  ShouldNotReachHere();
  return NULL;
}
419