jdk

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

25
#include "precompiled.hpp"
26
#include "opto/intrinsicnode.hpp"
27
#include "opto/addnode.hpp"
28
#include "opto/mulnode.hpp"
29
#include "opto/memnode.hpp"
30
#include "opto/phaseX.hpp"
31
#include "utilities/population_count.hpp"
32
#include "utilities/count_leading_zeros.hpp"
33
#include "utilities/globalDefinitions.hpp"
34

35
//=============================================================================
36
// Do not match memory edge.
37
uint StrIntrinsicNode::match_edge(uint idx) const {
38
  return idx == 2 || idx == 3;
39
}
40

41
//------------------------------Ideal------------------------------------------
42
// Return a node which is more "ideal" than the current node.  Strip out
43
// control copies
44
Node* StrIntrinsicNode::Ideal(PhaseGVN* phase, bool can_reshape) {
45
  if (remove_dead_region(phase, can_reshape)) return this;
46
  // Don't bother trying to transform a dead node
47
  if (in(0) && in(0)->is_top())  return nullptr;
48

49
  if (can_reshape) {
50
    Node* mem = phase->transform(in(MemNode::Memory));
51
    // If transformed to a MergeMem, get the desired slice
52
    uint alias_idx = phase->C->get_alias_index(adr_type());
53
    mem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(alias_idx) : mem;
54
    if (mem != in(MemNode::Memory)) {
55
      set_req_X(MemNode::Memory, mem, phase);
56
      return this;
57
    }
58
  }
59
  return nullptr;
60
}
61

62
//------------------------------Value------------------------------------------
63
const Type* StrIntrinsicNode::Value(PhaseGVN* phase) const {
64
  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
65
  return bottom_type();
66
}
67

68
uint StrIntrinsicNode::size_of() const { return sizeof(*this); }
69

70
//=============================================================================
71
//------------------------------Ideal------------------------------------------
72
// Return a node which is more "ideal" than the current node.  Strip out
73
// control copies
74
Node* StrCompressedCopyNode::Ideal(PhaseGVN* phase, bool can_reshape) {
75
  return remove_dead_region(phase, can_reshape) ? this : nullptr;
76
}
77

78
//=============================================================================
79
//------------------------------Ideal------------------------------------------
80
// Return a node which is more "ideal" than the current node.  Strip out
81
// control copies
82
Node* StrInflatedCopyNode::Ideal(PhaseGVN* phase, bool can_reshape) {
83
  return remove_dead_region(phase, can_reshape) ? this : nullptr;
84
}
85

86
uint VectorizedHashCodeNode::match_edge(uint idx) const {
87
  // Do not match memory edge.
88
  return idx >= 2 && idx <=  5; // VectorizedHashCodeNode (Binary ary1 cnt1) (Binary result bt)
89
}
90

91
Node* VectorizedHashCodeNode::Ideal(PhaseGVN* phase, bool can_reshape) {
92
  return remove_dead_region(phase, can_reshape) ? this : nullptr;
93
}
94

95
const Type* VectorizedHashCodeNode::Value(PhaseGVN* phase) const {
96
  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
97
  return bottom_type();
98
}
99

100

101
//=============================================================================
102
//------------------------------match_edge-------------------------------------
103
// Do not match memory edge
104
uint EncodeISOArrayNode::match_edge(uint idx) const {
105
  return idx == 2 || idx == 3; // EncodeISOArray src (Binary dst len)
106
}
107

108
//------------------------------Ideal------------------------------------------
109
// Return a node which is more "ideal" than the current node.  Strip out
110
// control copies
111
Node* EncodeISOArrayNode::Ideal(PhaseGVN* phase, bool can_reshape) {
112
  return remove_dead_region(phase, can_reshape) ? this : nullptr;
113
}
114

115
//------------------------------Value------------------------------------------
116
const Type* EncodeISOArrayNode::Value(PhaseGVN* phase) const {
117
  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
118
  return bottom_type();
119
}
120

121
//------------------------------CopySign-----------------------------------------
122
CopySignDNode* CopySignDNode::make(PhaseGVN& gvn, Node* in1, Node* in2) {
123
  return new CopySignDNode(in1, in2, gvn.makecon(TypeD::ZERO));
124
}
125

126
//------------------------------Signum-------------------------------------------
127
SignumDNode* SignumDNode::make(PhaseGVN& gvn, Node* in) {
128
  return new SignumDNode(in, gvn.makecon(TypeD::ZERO), gvn.makecon(TypeD::ONE));
129
}
130

131
SignumFNode* SignumFNode::make(PhaseGVN& gvn, Node* in) {
132
  return new SignumFNode(in, gvn.makecon(TypeF::ZERO), gvn.makecon(TypeF::ONE));
133
}
134

135
Node* CompressBitsNode::Ideal(PhaseGVN* phase, bool can_reshape) {
136
  Node* src = in(1);
137
  Node* mask = in(2);
138
  if (bottom_type()->isa_int()) {
139
    if (mask->Opcode() == Op_LShiftI && phase->type(mask->in(1))->is_int()->is_con()) {
140
      // compress(x, 1 << n) == (x >> n & 1)
141
      if (phase->type(mask->in(1))->higher_equal(TypeInt::ONE)) {
142
        Node* rshift = phase->transform(new RShiftINode(in(1), mask->in(2)));
143
        return new AndINode(rshift, phase->makecon(TypeInt::ONE));
144
      // compress(x, -1 << n) == x >>> n
145
      } else if (phase->type(mask->in(1))->higher_equal(TypeInt::MINUS_1)) {
146
        return new URShiftINode(in(1), mask->in(2));
147
      }
148
    }
149
    // compress(expand(x, m), m) == x & compress(m, m)
150
    if (src->Opcode() == Op_ExpandBits &&
151
        src->in(2) == mask) {
152
      Node* compr = phase->transform(new CompressBitsNode(mask, mask, TypeInt::INT));
153
      return new AndINode(compr, src->in(1));
154
    }
155
  } else {
156
    assert(bottom_type()->isa_long(), "");
157
    if (mask->Opcode() == Op_LShiftL && phase->type(mask->in(1))->is_long()->is_con()) {
158
      // compress(x, 1 << n) == (x >> n & 1)
159
      if (phase->type(mask->in(1))->higher_equal(TypeLong::ONE)) {
160
        Node* rshift = phase->transform(new RShiftLNode(in(1), mask->in(2)));
161
        return new AndLNode(rshift, phase->makecon(TypeLong::ONE));
162
      // compress(x, -1 << n) == x >>> n
163
      } else if (phase->type(mask->in(1))->higher_equal(TypeLong::MINUS_1)) {
164
        return new URShiftLNode(in(1), mask->in(2));
165
      }
166
    }
167
    // compress(expand(x, m), m) == x & compress(m, m)
168
    if (src->Opcode() == Op_ExpandBits &&
169
        src->in(2) == mask) {
170
      Node* compr = phase->transform(new CompressBitsNode(mask, mask, TypeLong::LONG));
171
      return new AndLNode(compr, src->in(1));
172
    }
173
  }
174
  return nullptr;
175
}
176

177
static Node* compress_expand_identity(PhaseGVN* phase, Node* n) {
178
  BasicType bt = n->bottom_type()->basic_type();
179
  // compress(x, 0) == 0, expand(x, 0) == 0
180
  if(phase->type(n->in(2))->higher_equal(TypeInteger::zero(bt))) return n->in(2);
181
  // compress(x, -1) == x, expand(x, -1) == x
182
  if(phase->type(n->in(2))->higher_equal(TypeInteger::minus_1(bt))) return n->in(1);
183
  // expand(-1, x) == x
184
  if(n->Opcode() == Op_ExpandBits &&
185
     phase->type(n->in(1))->higher_equal(TypeInteger::minus_1(bt))) return n->in(2);
186
  return n;
187
}
188

189
Node* CompressBitsNode::Identity(PhaseGVN* phase) {
190
  return compress_expand_identity(phase, this);
191
}
192

193
Node* ExpandBitsNode::Ideal(PhaseGVN* phase, bool can_reshape) {
194
  Node* src = in(1);
195
  Node* mask = in(2);
196
  if (bottom_type()->isa_int()) {
197
    if (mask->Opcode() == Op_LShiftI && phase->type(mask->in(1))->is_int()->is_con()) {
198
      // expand(x, 1 << n) == (x & 1) << n
199
      if (phase->type(mask->in(1))->higher_equal(TypeInt::ONE)) {
200
        Node* andnode = phase->transform(new AndINode(in(1), phase->makecon(TypeInt::ONE)));
201
        return new LShiftINode(andnode, mask->in(2));
202
      // expand(x, -1 << n) == x << n
203
      } else if (phase->type(mask->in(1))->higher_equal(TypeInt::MINUS_1)) {
204
        return new LShiftINode(in(1), mask->in(2));
205
      }
206
    }
207
    // expand(compress(x, m), m) == x & m
208
    if (src->Opcode() == Op_CompressBits &&
209
        src->in(2) == mask) {
210
      return new AndINode(src->in(1), mask);
211
    }
212
  } else {
213
    assert(bottom_type()->isa_long(), "");
214
    if (mask->Opcode() == Op_LShiftL && phase->type(mask->in(1))->is_long()->is_con()) {
215
      // expand(x, 1 << n) == (x & 1) << n
216
      if (phase->type(mask->in(1))->higher_equal(TypeLong::ONE)) {
217
        Node* andnode = phase->transform(new AndLNode(in(1), phase->makecon(TypeLong::ONE)));
218
        return new LShiftLNode(andnode, mask->in(2));
219
      // expand(x, -1 << n) == x << n
220
      } else if (phase->type(mask->in(1))->higher_equal(TypeLong::MINUS_1)) {
221
        return new LShiftLNode(in(1), mask->in(2));
222
      }
223
    }
224
    // expand(compress(x, m), m) == x & m
225
    if (src->Opcode() == Op_CompressBits &&
226
        src->in(2) == mask) {
227
      return new AndLNode(src->in(1), mask);
228
    }
229
  }
230
  return nullptr;
231
}
232

233
Node* ExpandBitsNode::Identity(PhaseGVN* phase) {
234
  return compress_expand_identity(phase, this);
235
}
236

237
static const Type* bitshuffle_value(const TypeInteger* src_type, const TypeInteger* mask_type, int opc, BasicType bt) {
238

239
  jlong hi = bt == T_INT ? max_jint : max_jlong;
240
  jlong lo = bt == T_INT ? min_jint : min_jlong;
241

242
  if(mask_type->is_con() && mask_type->get_con_as_long(bt) != -1L) {
243
    jlong maskcon = mask_type->get_con_as_long(bt);
244
    int bitcount = population_count(static_cast<julong>(bt == T_INT ? maskcon & 0xFFFFFFFFL : maskcon));
245
    if (opc == Op_CompressBits) {
246
      // Bit compression selects the source bits corresponding to true mask bits
247
      // and lays them out contiguously at destination bit positions starting from
248
      // LSB, remaining higher order bits are set to zero.
249
      // Thus, it will always generate a +ve value i.e. sign bit set to 0 if
250
      // any bit of constant mask value is zero.
251
      lo = 0L;
252
      hi = (1UL << bitcount) - 1;
253
    } else {
254
      assert(opc == Op_ExpandBits, "");
255
      // Expansion sequentially reads source bits starting from LSB
256
      // and places them over destination at bit positions corresponding
257
      // set mask bit. Thus bit expansion for non-negative mask value
258
      // will always generate a +ve value.
259
      hi = maskcon >= 0L ? maskcon : maskcon ^ lo;
260
      lo = maskcon >= 0L ? 0L : lo;
261
    }
262
  }
263

264
  if (!mask_type->is_con()) {
265
    int mask_max_bw;
266
    int max_bw = bt == T_INT ? 32 : 64;
267
    // Case 1) Mask value range includes -1.
268
    if ((mask_type->lo_as_long() < 0L && mask_type->hi_as_long() >= -1L)) {
269
      mask_max_bw = max_bw;
270
    // Case 2) Mask value range is less than -1.
271
    } else if (mask_type->hi_as_long() < -1L) {
272
      mask_max_bw = max_bw - 1;
273
    } else {
274
    // Case 3) Mask value range only includes +ve values.
275
      assert(mask_type->lo_as_long() >= 0, "");
276
      jlong clz = count_leading_zeros(mask_type->hi_as_long());
277
      clz = bt == T_INT ? clz - 32 : clz;
278
      mask_max_bw = max_bw - clz;
279
    }
280
    if ( opc == Op_CompressBits) {
281
      lo = mask_max_bw == max_bw ? lo : 0L;
282
      // Compress operation is inherently an unsigned operation and
283
      // result value range is primarily dependent on true count
284
      // of participating mask value.
285
      hi = mask_max_bw < max_bw ? (1L << mask_max_bw) - 1 : src_type->hi_as_long();
286
    } else {
287
      assert(opc == Op_ExpandBits, "");
288
      jlong max_mask = mask_type->hi_as_long();
289
      // Since mask here a range and not a constant value, hence being
290
      // conservative in determining the value range of result.
291
      lo = mask_type->lo_as_long() >= 0L ? 0L : lo;
292
      hi = mask_type->lo_as_long() >= 0L ? max_mask : hi;
293
    }
294
  }
295

296
  return bt == T_INT ? static_cast<const Type*>(TypeInt::make(lo, hi, Type::WidenMax)) :
297
                       static_cast<const Type*>(TypeLong::make(lo, hi, Type::WidenMax));
298
}
299

300
jlong CompressBitsNode::compress_bits(jlong src, jlong mask, int bit_count) {
301
  jlong res = 0;
302
  for (int i = 0, j = 0; i < bit_count; i++) {
303
    if(mask & 0x1) {
304
      res |= (src & 0x1) << j++;
305
    }
306
    src >>= 1;
307
    mask >>= 1;
308
  }
309
  return res;
310
}
311

312
const Type* CompressBitsNode::Value(PhaseGVN* phase) const {
313
  const Type* t1 = phase->type(in(1));
314
  const Type* t2 = phase->type(in(2));
315
  if (t1 == Type::TOP || t2 == Type::TOP) {
316
    return Type::TOP;
317
  }
318

319
  BasicType bt = bottom_type()->basic_type();
320
  const TypeInteger* src_type = t1->is_integer(bt);
321
  const TypeInteger* mask_type = t2->is_integer(bt);
322
  int w = bt == T_INT ? 32 : 64;
323

324
  // Constant fold if both src and mask are constants.
325
  if (src_type->is_con() && mask_type->is_con()) {
326
    jlong src = src_type->get_con_as_long(bt);
327
    jlong mask = mask_type->get_con_as_long(bt);
328
    jlong res = compress_bits(src, mask, w);
329
    return bt == T_INT ? static_cast<const Type*>(TypeInt::make(res)) :
330
                         static_cast<const Type*>(TypeLong::make(res));
331
  }
332

333
  return bitshuffle_value(src_type, mask_type, Op_CompressBits, bt);
334
}
335

336
jlong ExpandBitsNode::expand_bits(jlong src, jlong mask, int bit_count) {
337
  jlong res = 0;
338
  for (int i = 0; i < bit_count; i++) {
339
    if(mask & 0x1) {
340
      res |= (src & 0x1) << i;
341
      src >>= 1;
342
    }
343
    mask >>= 1;
344
  }
345
  return res;
346
}
347

348
const Type* ExpandBitsNode::Value(PhaseGVN* phase) const {
349
  const Type* t1 = phase->type(in(1));
350
  const Type* t2 = phase->type(in(2));
351
  if (t1 == Type::TOP || t2 == Type::TOP) {
352
    return Type::TOP;
353
  }
354

355
  BasicType bt = bottom_type()->basic_type();
356
  const TypeInteger* src_type = t1->is_integer(bt);
357
  const TypeInteger* mask_type = t2->is_integer(bt);
358
  int w = bt == T_INT ? 32 : 64;
359

360
  // Constant fold if both src and mask are constants.
361
  if (src_type->is_con() && mask_type->is_con()) {
362
     jlong src = src_type->get_con_as_long(bt);
363
     jlong mask = mask_type->get_con_as_long(bt);
364
     jlong res = expand_bits(src, mask, w);
365
     return bt == T_INT ? static_cast<const Type*>(TypeInt::make(res)) :
366
                          static_cast<const Type*>(TypeLong::make(res));
367
  }
368

369
  return bitshuffle_value(src_type, mask_type, Op_ExpandBits, bt);
370
}
371

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.