vectornode.cpp 9.6 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, uint vlen, 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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
    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;
  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;
88
    case T_CHAR:
D
duke 已提交
89 90 91 92
    case T_SHORT:  return Op_LShiftVS;
    case T_INT:    return Op_LShiftVI;
    }
    ShouldNotReachHere();
93
  case Op_RShiftI:
D
duke 已提交
94 95
    switch (bt) {
    case T_BOOLEAN:
96 97 98 99
    case T_BYTE:   return Op_RShiftVB;
    case T_CHAR:
    case T_SHORT:  return Op_RShiftVS;
    case T_INT:    return Op_RShiftVI;
D
duke 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112
    }
    ShouldNotReachHere();
  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:
113
  case Op_LoadUB:
114
  case Op_LoadUS:
D
duke 已提交
115 116 117 118 119
  case Op_LoadS:
  case Op_LoadI:
  case Op_LoadL:
  case Op_LoadF:
  case Op_LoadD:
120
    return Op_LoadVector;
D
duke 已提交
121 122 123 124 125 126 127

  case Op_StoreB:
  case Op_StoreC:
  case Op_StoreI:
  case Op_StoreL:
  case Op_StoreF:
  case Op_StoreD:
128
    return Op_StoreVector;
D
duke 已提交
129 130 131 132
  }
  return 0; // Unimplemented
}

133 134 135 136 137 138
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)) {
    int vopc = VectorNode::opcode(opc, vlen, bt);
    return vopc > 0 && Matcher::has_match_rule(vopc);
D
duke 已提交
139
  }
140
  return false;
D
duke 已提交
141 142 143
}

// Return the vector version of a scalar operation node.
144 145 146
VectorNode* VectorNode::make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt) {
  const TypeVect* vt = TypeVect::make(bt, vlen);
  int vopc = VectorNode::opcode(opc, vlen, bt);
D
duke 已提交
147 148

  switch (vopc) {
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  case Op_AddVB: return new (C, 3) AddVBNode(n1, n2, vt);
  case Op_AddVS: return new (C, 3) AddVSNode(n1, n2, vt);
  case Op_AddVI: return new (C, 3) AddVINode(n1, n2, vt);
  case Op_AddVL: return new (C, 3) AddVLNode(n1, n2, vt);
  case Op_AddVF: return new (C, 3) AddVFNode(n1, n2, vt);
  case Op_AddVD: return new (C, 3) AddVDNode(n1, n2, vt);

  case Op_SubVB: return new (C, 3) SubVBNode(n1, n2, vt);
  case Op_SubVS: return new (C, 3) SubVSNode(n1, n2, vt);
  case Op_SubVI: return new (C, 3) SubVINode(n1, n2, vt);
  case Op_SubVL: return new (C, 3) SubVLNode(n1, n2, vt);
  case Op_SubVF: return new (C, 3) SubVFNode(n1, n2, vt);
  case Op_SubVD: return new (C, 3) SubVDNode(n1, n2, vt);

  case Op_MulVF: return new (C, 3) MulVFNode(n1, n2, vt);
  case Op_MulVD: return new (C, 3) MulVDNode(n1, n2, vt);

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

  case Op_LShiftVB: return new (C, 3) LShiftVBNode(n1, n2, vt);
  case Op_LShiftVS: return new (C, 3) LShiftVSNode(n1, n2, vt);
  case Op_LShiftVI: return new (C, 3) LShiftVINode(n1, n2, vt);

  case Op_RShiftVB: return new (C, 3) RShiftVBNode(n1, n2, vt);
  case Op_RShiftVS: return new (C, 3) RShiftVSNode(n1, n2, vt);
  case Op_RShiftVI: return new (C, 3) RShiftVINode(n1, n2, vt);

  case Op_AndV: return new (C, 3) AndVNode(n1, n2, vt);
  case Op_OrV:  return new (C, 3) OrVNode (n1, n2, vt);
  case Op_XorV: return new (C, 3) XorVNode(n1, n2, vt);
  }
  ShouldNotReachHere();
  return NULL;
D
duke 已提交
183

184
}
D
duke 已提交
185

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
// 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:
    return new (C, 2) ReplicateBNode(s, vt);
  case T_CHAR:
  case T_SHORT:
    return new (C, 2) ReplicateSNode(s, vt);
  case T_INT:
    return new (C, 2) ReplicateINode(s, vt);
  case T_LONG:
    return new (C, 2) ReplicateLNode(s, vt);
  case T_FLOAT:
    return new (C, 2) ReplicateFNode(s, vt);
  case T_DOUBLE:
    return new (C, 2) ReplicateDNode(s, vt);
D
duke 已提交
206 207 208 209 210
  }
  ShouldNotReachHere();
  return NULL;
}

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
// 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:
    return new (C, vlen+1) PackBNode(s, vt);
  case T_CHAR:
  case T_SHORT:
    return new (C, vlen+1) PackSNode(s, vt);
  case T_INT:
    return new (C, vlen+1) PackINode(s, vt);
  case T_LONG:
    return new (C, vlen+1) PackLNode(s, vt);
  case T_FLOAT:
    return new (C, vlen+1) PackFNode(s, vt);
  case T_DOUBLE:
    return new (C, vlen+1) PackDNode(s, vt);
  }
  ShouldNotReachHere();
  return NULL;
}
D
duke 已提交
233

234 235 236 237 238 239 240 241
// Create a binary tree form for Packs. [lo, hi) (half-open) range
Node* PackNode::binaryTreePack(Compile* C, int lo, int hi) {
  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());
    pk->add_opd(1, in(lo+1));
    return pk;
D
duke 已提交
242

243 244 245 246
  } else {
    int mid = lo + ct/2;
    Node* n1 = binaryTreePack(C, lo,  mid);
    Node* n2 = binaryTreePack(C, mid, hi );
D
duke 已提交
247

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
    BasicType bt = vect_type()->element_basic_type();
    switch (bt) {
    case T_BOOLEAN:
    case T_BYTE:
      return new (C, 3) PackSNode(n1, n2, TypeVect::make(T_SHORT, 2));
    case T_CHAR:
    case T_SHORT:
      return new (C, 3) PackINode(n1, n2, TypeVect::make(T_INT, 2));
    case T_INT:
      return new (C, 3) PackLNode(n1, n2, TypeVect::make(T_LONG, 2));
    case T_LONG:
      return new (C, 3) Pack2LNode(n1, n2, TypeVect::make(T_LONG, 2));
    case T_FLOAT:
      return new (C, 3) PackDNode(n1, n2, TypeVect::make(T_DOUBLE, 2));
    case T_DOUBLE:
      return new (C, 3) Pack2DNode(n1, n2, TypeVect::make(T_DOUBLE, 2));
    }
    ShouldNotReachHere();
D
duke 已提交
266
  }
267 268 269 270 271 272 273 274
  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);
  return new (C, 3) LoadVectorNode(ctl, mem, adr, atyp, vt);
D
duke 已提交
275 276 277 278
  return NULL;
}

// Return the vector version of a scalar store node.
279
StoreVectorNode* StoreVectorNode::make(Compile* C, int opc, Node* ctl, Node* mem,
K
kvn 已提交
280
                                       Node* adr, const TypePtr* atyp, Node* val,
D
duke 已提交
281
                                       uint vlen) {
282
  return new (C, 4) StoreVectorNode(ctl, mem, adr, atyp, val);
D
duke 已提交
283 284 285
}

// Extract a scalar element of vector.
286 287
Node* ExtractNode::make(Compile* C, Node* v, uint position, BasicType bt) {
  assert((int)position < Matcher::max_vector_size(bt), "pos in range");
D
duke 已提交
288 289 290
  ConINode* pos = ConINode::make(C, (int)position);
  switch (bt) {
  case T_BOOLEAN:
291
    return new (C, 3) ExtractUBNode(v, pos);
D
duke 已提交
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
  case T_BYTE:
    return new (C, 3) ExtractBNode(v, pos);
  case T_CHAR:
    return new (C, 3) ExtractCNode(v, pos);
  case T_SHORT:
    return new (C, 3) ExtractSNode(v, pos);
  case T_INT:
    return new (C, 3) ExtractINode(v, pos);
  case T_LONG:
    return new (C, 3) ExtractLNode(v, pos);
  case T_FLOAT:
    return new (C, 3) ExtractFNode(v, pos);
  case T_DOUBLE:
    return new (C, 3) ExtractDNode(v, pos);
  }
  ShouldNotReachHere();
  return NULL;
}
310