25    if (v8_flags.trace_wasm_revectorize) { \ 
   27      PrintF(__VA_ARGS__);                 \ 
 
   33#define SIMPLE_SIMD_OP(V)                   \ 
   34  V(F64x2Add, F64x4Add)                     \ 
   35  V(F32x4Add, F32x8Add)                     \ 
   36  V(I64x2Add, I64x4Add)                     \ 
   37  V(I32x4Add, I32x8Add)                     \ 
   38  V(I16x8Add, I16x16Add)                    \ 
   39  V(I8x16Add, I8x32Add)                     \ 
   40  V(F64x2Sub, F64x4Sub)                     \ 
   41  V(F32x4Sub, F32x8Sub)                     \ 
   42  V(I64x2Sub, I64x4Sub)                     \ 
   43  V(I32x4Sub, I32x8Sub)                     \ 
   44  V(I16x8Sub, I16x16Sub)                    \ 
   45  V(I8x16Sub, I8x32Sub)                     \ 
   46  V(F64x2Mul, F64x4Mul)                     \ 
   47  V(F32x4Mul, F32x8Mul)                     \ 
   48  V(I64x2Mul, I64x4Mul)                     \ 
   49  V(I32x4Mul, I32x8Mul)                     \ 
   50  V(I16x8Mul, I16x16Mul)                    \ 
   51  V(F64x2Div, F64x4Div)                     \ 
   52  V(F32x4Div, F32x8Div)                     \ 
   53  V(I16x8AddSatS, I16x16AddSatS)            \ 
   54  V(I16x8SubSatS, I16x16SubSatS)            \ 
   55  V(I16x8AddSatU, I16x16AddSatU)            \ 
   56  V(I16x8SubSatU, I16x16SubSatU)            \ 
   57  V(I8x16AddSatS, I8x32AddSatS)             \ 
   58  V(I8x16SubSatS, I8x32SubSatS)             \ 
   59  V(I8x16AddSatU, I8x32AddSatU)             \ 
   60  V(I8x16SubSatU, I8x32SubSatU)             \ 
   65  V(I16x8Eq, I16x16Eq)                      \ 
   69  V(I64x2GtS, I64x4GtS)                     \ 
   70  V(I32x4GtS, I32x8GtS)                     \ 
   71  V(I16x8GtS, I16x16GtS)                    \ 
   72  V(I8x16GtS, I8x32GtS)                     \ 
   77  V(I32x4MinS, I32x8MinS)                   \ 
   78  V(I16x8MinS, I16x16MinS)                  \ 
   79  V(I8x16MinS, I8x32MinS)                   \ 
   80  V(I32x4MinU, I32x8MinU)                   \ 
   81  V(I16x8MinU, I16x16MinU)                  \ 
   82  V(I8x16MinU, I8x32MinU)                   \ 
   83  V(I32x4MaxS, I32x8MaxS)                   \ 
   84  V(I16x8MaxS, I16x16MaxS)                  \ 
   85  V(I8x16MaxS, I8x32MaxS)                   \ 
   86  V(I32x4MaxU, I32x8MaxU)                   \ 
   87  V(I16x8MaxU, I16x16MaxU)                  \ 
   88  V(I8x16MaxU, I8x32MaxU)                   \ 
   89  V(F32x4Abs, F32x8Abs)                     \ 
   90  V(I32x4Abs, I32x8Abs)                     \ 
   91  V(I16x8Abs, I16x16Abs)                    \ 
   92  V(I8x16Abs, I8x32Abs)                     \ 
   93  V(F32x4Neg, F32x8Neg)                     \ 
   94  V(I32x4Neg, I32x8Neg)                     \ 
   95  V(I16x8Neg, I16x16Neg)                    \ 
   96  V(I8x16Neg, I8x32Neg)                     \ 
   97  V(F64x2Sqrt, F64x4Sqrt)                   \ 
   98  V(F32x4Sqrt, F32x8Sqrt)                   \ 
   99  V(F64x2Min, F64x4Min)                     \ 
  100  V(F32x4Min, F32x8Min)                     \ 
  101  V(F64x2Max, F64x4Max)                     \ 
  102  V(F32x4Max, F32x8Max)                     \ 
  103  V(I64x2Ne, I64x4Ne)                       \ 
  104  V(I32x4Ne, I32x8Ne)                       \ 
  105  V(I16x8Ne, I16x16Ne)                      \ 
  106  V(I8x16Ne, I8x32Ne)                       \ 
  107  V(I32x4GtU, I32x8GtU)                     \ 
  108  V(I16x8GtU, I16x16GtU)                    \ 
  109  V(I8x16GtU, I8x32GtU)                     \ 
  110  V(I64x2GeS, I64x4GeS)                     \ 
  111  V(I32x4GeS, I32x8GeS)                     \ 
  112  V(I16x8GeS, I16x16GeS)                    \ 
  113  V(I8x16GeS, I8x32GeS)                     \ 
  114  V(I32x4GeU, I32x8GeU)                     \ 
  115  V(I16x8GeU, I16x16GeU)                    \ 
  116  V(I8x16GeU, I8x32GeU)                     \ 
  117  V(F32x4Pmin, F32x8Pmin)                   \ 
  118  V(F32x4Pmax, F32x8Pmax)                   \ 
  119  V(F64x2Pmin, F64x4Pmin)                   \ 
  120  V(F64x2Pmax, F64x4Pmax)                   \ 
  121  V(F32x4SConvertI32x4, F32x8SConvertI32x8) \ 
  122  V(F32x4UConvertI32x4, F32x8UConvertI32x8) \ 
  123  V(I32x4UConvertF32x4, I32x8UConvertF32x8) \ 
  124  V(I32x4SConvertF32x4, I32x8SConvertF32x8) \ 
  125  V(S128And, S256And)                       \ 
  127  V(S128Xor, S256Xor)                       \ 
  128  V(S128Not, S256Not)                       \ 
  129  V(S128Select, S256Select)                 \ 
  130  V(S128AndNot, S256AndNot) 
 
  132#define SIMD_SHIFT_OP(V)   \ 
  133  V(I64x2Shl, I64x4Shl)    \ 
  134  V(I32x4Shl, I32x8Shl)    \ 
  135  V(I16x8Shl, I16x16Shl)   \ 
  136  V(I32x4ShrS, I32x8ShrS)  \ 
  137  V(I16x8ShrS, I16x16ShrS) \ 
  138  V(I64x2ShrU, I64x4ShrU)  \ 
  139  V(I32x4ShrU, I32x8ShrU)  \ 
  140  V(I16x8ShrU, I16x16ShrU) 
 
  142#define SIMD_SIGN_EXTENSION_CONVERT_OP(V)                               \ 
  143  V(I64x2SConvertI32x4Low, I64x2SConvertI32x4High, I64x4SConvertI32x4)  \ 
  144  V(I64x2UConvertI32x4Low, I64x2UConvertI32x4High, I64x4UConvertI32x4)  \ 
  145  V(I32x4SConvertI16x8Low, I32x4SConvertI16x8High, I32x8SConvertI16x8)  \ 
  146  V(I32x4UConvertI16x8Low, I32x4UConvertI16x8High, I32x8UConvertI16x8)  \ 
  147  V(I16x8SConvertI8x16Low, I16x8SConvertI8x16High, I16x16SConvertI8x16) \ 
  148  V(I16x8UConvertI8x16Low, I16x8UConvertI8x16High, I16x16UConvertI8x16) 
 
  150#define SIMD_SPLAT_OP(V)     \ 
  151  V(I8x16Splat, I8x32Splat)  \ 
  152  V(I16x8Splat, I16x16Splat) \ 
  153  V(I32x4Splat, I32x8Splat)  \ 
  154  V(I64x2Splat, I64x4Splat) 
 
  158bool IsSupportedLoad(
const Node* node) {
 
  159  if (node->opcode() == IrOpcode::kProtectedLoad ||
 
  160      node->opcode() == IrOpcode::kLoad ||
 
  161      node->opcode() == IrOpcode::kLoadTransform) {
 
  168bool IsSupportedLoad(
const ZoneVector<Node*>& node_group) {
 
  169  for (
auto node : node_group) {
 
  170    if (!IsSupportedLoad(node)) 
return false;
 
  176int64_t GetConstantValue(
const Node* node) {
 
  178  if (node->opcode() == IrOpcode::kInt64Constant) {
 
  184int64_t GetMemoryOffsetValue(
const Node* node) {
 
  185  DCHECK(IsSupportedLoad(node) || node->opcode() == IrOpcode::kStore ||
 
  186         node->opcode() == IrOpcode::kProtectedStore);
 
  188  Node* 
offset = node->InputAt(0);
 
  189  if (
offset->opcode() == IrOpcode::kLoadFromObject ||
 
  190      offset->opcode() == IrOpcode::kLoad) {
 
  194  int64_t offset_value = -1;
 
  195  if (
offset->opcode() == IrOpcode::kInt64Add) {
 
  197      offset_value = GetConstantValue(
offset->InputAt(0));
 
  199      offset_value = GetConstantValue(
offset->InputAt(1));
 
  209Node* GetNodeAddress(
const Node* node) {
 
  210  Node* address = node->InputAt(1);
 
  212  if (address->opcode() == IrOpcode::kChangeUint32ToUint64) {
 
  213    address = address->InputAt(0);
 
  218bool IsContinuousAccess(
const ZoneVector<Node*>& node_group) {
 
  220  int64_t previous_offset = GetMemoryOffsetValue(node_group[0]);
 
  221  for (
size_t i = 1; 
i < node_group.
size(); ++
i) {
 
  222    int64_t current_offset = GetMemoryOffsetValue(node_group[
i]);
 
  223    int64_t diff = current_offset - previous_offset;
 
  224    if (diff == 8 && node_group[0]->opcode() == IrOpcode::kLoadTransform) {
 
  225      LoadTransformParameters params =
 
  229        TRACE(
"Non-continuous access!\n");
 
  232      TRACE(
"Continuous access with load extend offset!\n");
 
  234      TRACE(
"Non-continuous access!\n");
 
  237    previous_offset = current_offset;
 
  243bool AllConstant(
const ZoneVector<Node*>& node_group) {
 
  244  for (Node* node : node_group) {
 
  253bool AllSameAddress(
const ZoneVector<Node*>& nodes) {
 
  254  Node* address = GetNodeAddress(nodes[0]);
 
  255  for (
size_t i = 1; 
i < nodes.
size(); 
i++) {
 
  256    if (GetNodeAddress(nodes[
i]) != address) {
 
  257      TRACE(
"Diff address #%d,#%d!\n", address->id(),
 
  258            GetNodeAddress(nodes[
i])->
id());
 
  268bool IsSplat(
const T& node_group) {
 
  269  for (
typename T::size_type 
i = 1; 
i < node_group.size(); ++
i) {
 
  270    if (node_group[
i] != node_group[0]) {
 
  280V8_INLINE static bool OperatorCanBePacked(
const Operator* lhs,
 
  281                                          const Operator* rhs) {
 
  282  return lhs->opcode() == rhs->opcode() &&
 
  283         lhs->properties() == rhs->properties();
 
  287bool AllPackableOperator(
const ZoneVector<Node*>& node_group) {
 
  288  auto op = node_group[0]->op();
 
  290    if (!OperatorCanBePacked(node_group[
i]->op(), op)) {
 
  297bool ShiftBySameScalar(
const ZoneVector<Node*>& node_group) {
 
  298  auto node0 = node_group[0];
 
  302    if (node_group[
i]->InputAt(1) != node0->InputAt(1)) {
 
  310#define CASE(op_low, op_high, not_used) \ 
  311  case IrOpcode::k##op_low:             \ 
  312  case IrOpcode::k##op_high: 
  323bool MaybePackSignExtensionOp(
const ZoneVector<Node*>& node_group) {
 
  324#define CHECK_SIGN_EXTENSION_CASE(op_low, op_high, not_used)      \ 
  325  case IrOpcode::k##op_low: {                                     \ 
  326    if (node_group[1]->opcode() == IrOpcode::k##op_high &&        \ 
  327        node_group[0]->InputAt(0) == node_group[1]->InputAt(0)) { \ 
  332  switch (node_group[0]->opcode()) {
 
  338#undef CHECK_SIGN_EXTENSION_CASE 
  342class EffectChainIterator {
 
  344  explicit EffectChainIterator(Node* node) : 
node_(node), 
prev_(nullptr) {}
 
  348    node_ = EffectInputOf(node_);
 
  357  Node* Next() { 
return EffectInputOf(node_); }
 
  359  void Set(Node* node) {
 
  364  Node* operator*() { 
return node_; }
 
  367  Node* EffectInputOf(Node* node) {
 
  368    DCHECK(IsSupportedLoad(node));
 
  369    return node->InputAt(2);
 
  376void InsertAfter(EffectChainIterator& dest, EffectChainIterator& src) {
 
  377  Node* dest_next = dest.Next();
 
  387  return GetMemoryOffsetValue(lhs) < GetMemoryOffsetValue(rhs);
 
 
  397          nodes_[0]->op()->mnemonic());
 
 
  408  if (!NodeProperties::IsSimd128Operation(node_group[0]) &&
 
  409      (op != IrOpcode::kStore) && (op != IrOpcode::kProtectedStore) &&
 
  410      (op != IrOpcode::kLoad) && (op != IrOpcode::kProtectedLoad) &&
 
  411      (op != IrOpcode::kPhi) && (op != IrOpcode::kLoopExitValue) &&
 
  412      (op != IrOpcode::kExtractF128)) {
 
  417  if (AllConstant(node_group)) {
 
  418    TRACE(
"%s(#%d, #%d) are constantant, not supported yet!\n",
 
  419          node_group[0]->op()->mnemonic(), node_group[0]->
id(),
 
  420          node_group[1]->
id());
 
  423  if (IsSignExtensionOperation(op)) {
 
  424    if (MaybePackSignExtensionOp(node_group)) {
 
  427      TRACE(
"%s(#%d, #%d) are not (low, high) sign extension pair\n",
 
  428            node_group[0]->op()->mnemonic(), node_group[0]->
id(),
 
  429            node_group[1]->
id());
 
  433  if (!AllPackableOperator(node_group)) {
 
  435        "%s(#%d, #%d) have different op, and are not sign extension operator\n",
 
  436        node_group[0]->op()->mnemonic(), node_group[0]->
id(),
 
  437        node_group[1]->
id());
 
 
  444  TRACE(
"PackNode %s(#%d:, #%d)\n", node_group[0]->op()->mnemonic(),
 
  445        node_group[0]->
id(), node_group[1]->
id());
 
  447  for (
Node* node : node_group) {
 
 
  454                                        int start_index, 
int count,
 
  457  for (
int i = start_index; 
i < start_index + 
count; ++
i) {
 
  460    for (
size_t j = 0; j < node_group.
size(); j++) {
 
  461      Node* node = node_group[j];
 
 
  484  TRACE(
"Stack Push (%d %s, %d %s)\n", node_group[0]->
id(),
 
  485        node_group[0]->op()->mnemonic(), node_group[1]->
id(),
 
  486        node_group[1]->op()->mnemonic());
 
  487  for (
auto node : node_group) {
 
  490  stack_.push({node_group});
 
 
  496  TRACE(
"Stack Pop (%d %s, %d %s)\n", node_group[0]->
id(),
 
  497        node_group[0]->op()->mnemonic(), node_group[1]->
id(),
 
  498        node_group[1]->op()->mnemonic());
 
  499  for (
auto node : node_group) {
 
 
  510  for (
auto node : node_group) {
 
  511    if (
OnStack(node)) 
return true;
 
 
  533  for (
Node* load : loads) {
 
  534    if (visited.find(load) != visited.end()) 
continue;
 
  535    visited.insert(load);
 
  537    EffectChainIterator dest(load);
 
  538    EffectChainIterator it(dest.Next());
 
  540      if (std::find(loads.
begin(), loads.
end(), *it) != loads.
end()) {
 
  542        if (dest.Next() != *it) {
 
  543          Node* prev = it.Prev();
 
  544          InsertAfter(dest, it);
 
 
  555  DCHECK(IsSupportedLoad(node_group));
 
  557  TRACE(
"Enter IsSideEffectFreeLoad (%d %s, %d %s)\n", node_group[0]->
id(),
 
  558        node_group[0]->op()->mnemonic(), node_group[1]->
id(),
 
  559        node_group[1]->op()->mnemonic());
 
  563  if (node_group[0] != node_group[1] &&
 
  568  std::stack<Node*> to_visit;
 
  569  std::unordered_set<Node*> visited;
 
  571  for (
size_t i = 0, e = node_group.
size(); 
i < e; 
i++) {
 
  572    Node* load = node_group[
i];
 
  575      if (std::find(node_group.
begin(), node_group.
end(), input) ==
 
  577        to_visit.push(input);
 
  585  while (!to_visit.empty()) {
 
  586    Node* input = to_visit.top();
 
  588    TRACE(
"IsSideEffectFreeLoad visit (%d %s)\n", input->id(),
 
  589          input->op()->mnemonic());
 
  590    if (visited.find(input) == visited.end()) {
 
  591      visited.insert(input);
 
  594        TRACE(
"Has internal dependency because (%d %s) on stack\n", input->id(),
 
  595              input->op()->mnemonic());
 
  604          to_visit.push(input->InputAt(
i));
 
 
  613  TRACE(
"Enter %s\n", __func__);
 
 
  623  TRACE(
"Enter %s\n", __func__);
 
  626  Node* node0 = node_group[0];
 
  627  Node* node1 = node_group[1];
 
  630    TRACE(
"Failed due to max recursion depth!\n");
 
  636      TRACE(
"Failed due to (%d %s, %d %s) on stack!\n", node0->
id(),
 
  637            node0->
op()->mnemonic(), node1->
id(), node1->
op()->mnemonic());
 
  647  DCHECK(AllConstant(node_group) || AllPackableOperator(node_group) ||
 
  648         MaybePackSignExtensionOp(node_group));
 
  651  for (
Node* node : node_group) {
 
  653      if (!p->IsSame(node_group)) {
 
  655        TRACE(
"Failed due to partial overlap at #%d,%s!\n", node->id(),
 
  656              node->op()->mnemonic());
 
  661      TRACE(
"Perfect diamond merge at #%d,%s\n", node->id(),
 
  662            node->op()->mnemonic());
 
  667  if (node0->
opcode() == IrOpcode::kS128Zero) {
 
  672  if (node0->
opcode() == IrOpcode::kS128Const) {
 
  677  if (node0->
opcode() == IrOpcode::kExtractF128) {
 
  679    TRACE(
"Extract leaf node from #%d,%s!\n", source->id(),
 
  680          source->op()->mnemonic());
 
  687      TRACE(
"Added a pair of Extract.\n");
 
  692    TRACE(
"Failed due to ExtractF128!\n");
 
  696  if (IsSupportedLoad(node0)) {
 
  697    TRACE(
"Load leaf node\n");
 
  698    if (!AllSameAddress(node_group)) {
 
  699      TRACE(
"Failed due to different load addr!\n");
 
  705      if (node0->
opcode() == IrOpcode::kProtectedLoad &&
 
  713        TRACE(
"Failed due to dependency check\n");
 
  720      std::partial_sort_copy(node_group.
begin(), node_group.
end(),
 
  721                             sorted_node_group.
begin(), sorted_node_group.
end(),
 
  723      if (!IsContinuousAccess(sorted_node_group)) {
 
  724        TRACE(
"Failed due to non-continuous load!\n");
 
  728    } 
else if (node0->
opcode() == IrOpcode::kLoadTransform) {
 
  731        TRACE(
"LoadTransform failed due to unsupported type #%d!\n",
 
  738      TRACE(
"Failed due to unsupported splat!\n");
 
  748  int value_in_count = node0->
op()->ValueInputCount();
 
  750#define CASE(op128, op256) case IrOpcode::k##op128: 
  751#define SIGN_EXTENSION_CASE(op_low, not_used1, not_used2) \ 
  752  case IrOpcode::k##op_low: 
  753  switch (node0->
opcode()) {
 
  754    case IrOpcode::kPhi: {
 
  755      TRACE(
"Added a vector of PHI nodes.\n");
 
  765    case IrOpcode::kLoopExitValue: {
 
  775    case IrOpcode::kI8x16Shuffle: {
 
  782                 IrOpcode::kProtectedLoad) ||
 
  785                 IrOpcode::kProtectedLoad)) {
 
  789        TRACE(
"Failed to match splat\n");
 
  800      TRACE(
"Added a vector of %s.\n", node0->
op()->mnemonic());
 
  807      if (ShiftBySameScalar(node_group)) {
 
  808        TRACE(
"Added a vector of %s.\n", node0->
op()->mnemonic());
 
  814      TRACE(
"Failed due to shift with different scalar!\n");
 
  818      TRACE(
"add a vector of sign extension op and stop building tree\n");
 
  824      TRACE(
"Added a vector of %s.\n", node0->
op()->mnemonic());
 
  826        TRACE(
"Failed due to different splat input");
 
  836    case IrOpcode::kStore:
 
  837    case IrOpcode::kProtectedStore: {
 
  838      TRACE(
"Added a vector of stores.\n");
 
  839      if (!AllSameAddress(node_group)) {
 
  840        TRACE(
"Failed due to different store addr!\n");
 
  848      TRACE(
"Default branch #%d:%s\n", node0->
id(), node0->
op()->mnemonic());
 
  852#undef SIGN_EXTENSION_CASE 
 
  862  TRACE(
"%s, Packed node:\n", info);
 
  863  if (!
v8_flags.trace_wasm_revectorize) {
 
 
  870template <
typename FunctionType>
 
  872  std::unordered_set<PackNode const*> visited;
 
  875    PackNode const* pnode = entry.second;
 
  876    if (!pnode || visited.find(pnode) != visited.end()) {
 
  879    visited.insert(pnode);
 
 
  892      group_of_stores_(zone),
 
  894      support_simd256_(false) {
 
 
  902  TRACE(
"Enter %s\n", __func__);
 
  904  int save = 0, cost = 0;
 
  912    if (op == IrOpcode::kLoopExitValue || op == IrOpcode::kExtractF128) {
 
  920    for (
size_t i = 0; 
i < nodes.
size(); 
i++) {
 
  921      if (
i > 0 && nodes[
i] == nodes[0]) 
continue;
 
  923      for (
auto edge : nodes[
i]->use_edges()) {
 
  925        Node* useNode = edge.from();
 
  927            useNode->
opcode() != IrOpcode::kLoopExitValue) {
 
  928          TRACE(
"External use edge: (%d:%s) -> (%d:%s)\n", useNode->
id(),
 
  929                useNode->
op()->mnemonic(), nodes[
i]->id(),
 
  930                nodes[
i]->op()->mnemonic());
 
  940  TRACE(
"Save: %d, cost: %d\n", save, cost);
 
 
  948  DCHECK(nodes[0] == nodes[1] ||
 
  953  for (
size_t i = 0; 
i < nodes.
size(); 
i++) {
 
  954    Node* node128 = nodes[
i];
 
  956    if (effect == pnode) 
continue;
 
  960      input = node128->
InputAt(index);
 
 
  966                                     PackNode* pnode, 
int effect_index) {
 
  969  inputs[0] = node->InputAt(0);
 
  970  inputs[1] = node->InputAt(1);
 
  974  inputs[effect_index + 1] = node->InputAt(effect_index + 1);
 
 
  978  TRACE(
"Enter %s with PackNode\n", __func__);
 
  983    TRACE(
"Diamond merged for #%d:%s\n", node0->
id(), node0->
op()->mnemonic());
 
  988  TRACE(
"Vectorize #%d:%s, input count: %d\n", node0->
id(),
 
  989        node0->
op()->mnemonic(), input_count);
 
  993  Node* source = 
nullptr;
 
  996  for (
int i = 0; 
i < input_count; 
i++) inputs[
i] = dead;
 
  999    case IrOpcode::kPhi: {
 
 1007    case IrOpcode::kLoopExitValue: {
 
 1015#define SIMPLE_CASE(from, to)           \ 
 1016  case IrOpcode::k##from:               \ 
 1017    new_op = mcgraph_->machine()->to(); \ 
 1021#undef SIMPLE_SIMD_OP 
 1023#define SHIFT_CASE(from, to)                   \ 
 1024  case IrOpcode::k##from: {                    \ 
 1025    DCHECK(ShiftBySameScalar(pnode->Nodes())); \ 
 1026    new_op = mcgraph_->machine()->to();        \ 
 1027    inputs[1] = node0->InputAt(1);             \ 
 1034#define SIGN_EXTENSION_CONVERT_CASE(from, not_used, to)          \ 
 1035  case IrOpcode::k##from: {                                      \ 
 1036    DCHECK_EQ(node0->InputAt(0), pnode->Nodes()[1]->InputAt(0)); \ 
 1037    new_op = mcgraph_->machine()->to();                          \ 
 1038    inputs[0] = node0->InputAt(0);                               \ 
 1042#undef SIGN_EXTENSION_CONVERT_CASE 
 1043#undef SIMD_SIGN_EXTENSION_CONVERT_OP 
 1045#define SPLAT_CASE(from, to)            \ 
 1046  case IrOpcode::k##from:               \ 
 1047    new_op = mcgraph_->machine()->to(); \ 
 1048    inputs[0] = node0->InputAt(0);      \ 
 1053    case IrOpcode::kI8x16Shuffle: {
 
 1076        DCHECK_EQ(source->opcode(), IrOpcode::kProtectedLoad);
 
 1085          inputs[0] = source->InputAt(0);
 
 1088        inputs[1] = source->InputAt(1);
 
 1089        inputs[2] = source->InputAt(2);
 
 1090        inputs[3] = source->InputAt(3);
 
 1095        uint8_t new_shuffle[32];
 
 1100          for (
int i = 0; 
i < 16; ++
i) {
 
 1101            new_shuffle[
i] = shuffle0[
i] % 16;
 
 1102            new_shuffle[
i + 16] = 16 + shuffle1[
i] % 16;
 
 1105          for (
int i = 0; 
i < 16; ++
i) {
 
 1106            if (shuffle0[
i] < 16) {
 
 1107              new_shuffle[
i] = shuffle0[
i];
 
 1109              new_shuffle[
i] = 16 + shuffle0[
i];
 
 1112            if (shuffle1[
i] < 16) {
 
 1113              new_shuffle[
i + 16] = 16 + shuffle1[
i];
 
 1115              new_shuffle[
i + 16] = 32 + shuffle1[
i];
 
 1124    case IrOpcode::kS128Zero: {
 
 1128    case IrOpcode::kS128Const: {
 
 1133        value[
i] = value0[
i];
 
 1134        value[
i + 16] = value1[
i];
 
 1139    case IrOpcode::kProtectedLoad: {
 
 1146    case IrOpcode::kLoad: {
 
 1153    case IrOpcode::kProtectedStore: {
 
 1161    case IrOpcode::kStore: {
 
 1171    case IrOpcode::kLoadTransform: {
 
 1176      switch (params.transformation) {
 
 1217    case IrOpcode::kExtractF128: {
 
 1227  if (new_op != 
nullptr) {
 
 1232    for (
int i = 0; 
i < input_count; 
i++) {
 
 1233      if (inputs[
i] == dead) {
 
 1239    for (
size_t i = 0; 
i < nodes.
size(); 
i++) {
 
 1240      if (
i > 0 && nodes[
i] == nodes[
i - 1]) 
continue;
 
 1241      Node* input_128 = 
nullptr;
 
 1242      for (
auto edge : nodes[
i]->use_edges()) {
 
 1243        Node* useNode = edge.from();
 
 1247            TRACE(
"Replace Value Edge from %d:%s, to %d:%s\n", useNode->
id(),
 
 1248                  useNode->
op()->mnemonic(), edge.to()->id(),
 
 1249                  edge.to()->op()->mnemonic());
 
 1252              TRACE(
"Create ExtractF128(%lu) node from #%d\n", 
i,
 
 1255                  mcgraph()->machine()->ExtractF128(
static_cast<int32_t
>(
i)),
 
 1258            edge.UpdateTo(input_128);
 
 1260            TRACE(
"Replace Effect Edge from %d:%s, to %d:%s\n", useNode->
id(),
 
 1261                  useNode->
op()->mnemonic(), edge.to()->id(),
 
 1262                  edge.to()->op()->mnemonic());
 
 1264            edge.UpdateTo(new_node);
 
 1268      if (nodes[
i]->uses().empty()) nodes[
i]->
Kill();
 
 1272    if (op == IrOpcode::kI8x16Shuffle && 
IsSplat(nodes)) {
 
 1275      TRACE(
"Replace Effect Edge from %d:%s, to %d:%s\n", source->id(),
 
 1276            source->op()->mnemonic(), new_node->
id(),
 
 1277            new_node->
op()->mnemonic());
 
 1281      TRACE(
"Remove Value Input of %d:%s\n", node0->
id(),
 
 1282            node0->
op()->mnemonic());
 
 
 1302  bool success = 
false;
 
 1304    TRACE(
"TryRevectorize %s\n", function);
 
 1308      if (store_chains != 
nullptr) {
 
 1311          TRACE(
"Successful revectorize %s\n", function);
 
 1316    TRACE(
"Finish revectorize %s\n", function);
 
 
 1324    std::vector<Node*> effect_uses;
 
 1325    bool hasExternalValueUse = 
false;
 
 1326    for (
auto edge : src->use_edges()) {
 
 1327      Node* use = edge.from();
 
 1330          TRACE(
"Source node has external value dependence %d:%s\n",
 
 1331                edge.from()->id(), edge.from()->op()->mnemonic());
 
 1332          hasExternalValueUse = 
true;
 
 1335          effect_uses.push_back(use);
 
 1340    if (!hasExternalValueUse) {
 
 1343      for (
auto use : effect_uses) {
 
 1344        TRACE(
"Replace Effect Edge for source node from %d:%s, to %d:%s\n",
 
 1345              use->id(), use->op()->mnemonic(), effect->id(),
 
 1346              effect->op()->mnemonic());
 
 
 1361    if ((GetMemoryOffsetValue(node) % 
kSimd128Size) != 0) {
 
 1364    Node* address = GetNodeAddress(node);
 
 1371      store_nodes = first_level_iter->second;
 
 1373    auto second_level_iter = store_nodes->find(address);
 
 1374    if (second_level_iter == store_nodes->end()) {
 
 1378    second_level_iter->second.insert(node);
 
 
 1384  TRACE(
"Enter %s\n", __func__);
 
 1385  bool changed = 
false;
 
 1386  for (
auto chain_iter = store_chains->cbegin();
 
 1387       chain_iter != store_chains->cend(); ++chain_iter) {
 
 1388    if (chain_iter->second.size() >= 2 && chain_iter->second.size() % 2 == 0) {
 
 1390                                    chain_iter->second.end(), 
zone_);
 
 1391      for (
auto it = store_chain.
begin(); it < store_chain.
end(); it = it + 2) {
 
 
 1407  TRACE(
"Enter %s, root@ (#%d,#%d)\n", __func__, Stores[0]->
id(),
 
 1409  if (!IsContinuousAccess(Stores)) {
 
 1415    TRACE(
"Build tree failed!\n");
 
 
 1441  if (!
v8_flags.trace_wasm_revectorize) {
 
 1444  TRACE(
"Enter %s\n", __func__);
 
 1445  for (
auto it = store_chains->cbegin(); it != store_chains->cend(); ++it) {
 
 1446    if (it->second.size() > 0) {
 
 1447      TRACE(
"address = #%d:%s \n", it->first->id(),
 
 1448            it->first->op()->mnemonic());
 
 1450      for (
auto node : it->second) {
 
 1451        TRACE(
"#%d:%s, ", node->id(), node->op()->mnemonic());
 
 
static Isolate * TryGetCurrent()
void resize(size_t new_size)
static constexpr MachineType Simd256()
constexpr MachineRepresentation representation() const
void push_back(const T &value)
const Operator * Phi(MachineRepresentation representation, int value_input_count)
const Operator * LoopExitValue(MachineRepresentation rep)
Node * Int64Constant(int64_t value)
CommonOperatorBuilder * common() const
MachineOperatorBuilder * machine() const
const Operator * ProtectedLoad(LoadRepresentation rep)
const Operator * Load(LoadRepresentation rep)
const Operator * ProtectedStore(MachineRepresentation rep)
const Operator * Int64Add()
const Operator * Store(StoreRepresentation rep)
virtual Observation OnNodeCreated(const Node *node)
static void ReplaceEffectInput(Node *node, Node *effect, int index=0)
static Node * GetEffectInput(Node *node, int index=0)
static bool IsValueEdge(Edge edge)
static Node * GetValueInput(Node *node, int index)
static bool IsEffectEdge(Edge edge)
static void ReplaceValueInput(Node *node, Node *value, int index)
static int FirstControlIndex(Node *node)
static bool IsConstant(Node *node)
static bool IsPhi(Node *node)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
const Operator * op() const
void ReplaceInput(int index, Node *new_to)
Node * InputAt(int index) const
PackNode * GetOperand(size_t index)
void SetRevectorizedNode(Node *node)
void SetOperand(size_t index, PackNode *pnode)
ZoneVector< Node * > nodes_
const ZoneVector< Node * > & Nodes() const
Node * revectorized_node_
Node * RevectorizedNode() const
PackNode * GetPackNode(Node *node) const
void PrintStores(ZoneMap< Node *, StoreNodeSet > *store_chains)
MachineGraph * mcgraph() const
Revectorizer(Zone *zone, TFGraph *graph, MachineGraph *mcgraph, SourcePositionTable *source_positions)
std::unordered_set< Node * > sources_
MachineGraph *const mcgraph_
SourcePositionTable * source_positions_
bool ReduceStoreChains(ZoneMap< Node *, StoreNodeSet > *store_chains)
ZoneMap< Node *, ZoneMap< Node *, StoreNodeSet > * > group_of_stores_
void SetEffectInput(PackNode *pnode, int index, Node *&nput)
bool ReduceStoreChain(const ZoneVector< Node * > &Stores)
compiler::NodeObserver * node_observer_for_test_
bool TryRevectorize(const char *name)
Node * VectorizeTree(PackNode *pnode)
void SetMemoryOpInputs(base::SmallVector< Node *, 2 > &inputs, PackNode *pnode, int index)
ZoneSet< Node * > on_stack_
static constexpr size_t RecursionMaxDepth
void Print(const char *info)
bool IsSideEffectFreeLoad(const ZoneVector< Node * > &node_group)
Node * GetEarlySchedulePosition(Node *node)
PackNode * BuildTree(const ZoneVector< Node * > &roots)
PackNode * NewPackNodeAndRecurs(const ZoneVector< Node * > &node_group, int start_index, int count, unsigned depth)
PackNode * GetPackNode(Node *node)
PackNode * NewPackNode(const ZoneVector< Node * > &node_group)
PackNode * BuildTreeRec(const ZoneVector< Node * > &node_group, unsigned depth)
void TryReduceLoadChain(const ZoneVector< Node * > &loads)
bool CanBePacked(const ZoneVector< Node * > &node_group)
bool SameBasicBlock(Node *node0, Node *node1)
ZoneStack< ZoneVector< Node * > > stack_
void PushStack(const ZoneVector< Node * > &node_group)
ZoneUnorderedMap< Node *, PackNode * > node_to_packnode_
void ForEach(FunctionType callback)
bool AllOnStack(const ZoneVector< Node * > &node_group)
MachineRepresentation representation() const
WriteBarrierKind write_barrier_kind() const
ZoneVector< Node * > const & GetSimdStoreNodes()
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
static bool TryMatchSplat(const uint8_t *shuffle, int *index)
SourcePositionTable * source_positions
bool(* FunctionType)(const Operation &op, Zone *zone)
bool IsSplat(const T &node_group)
V8_EXPORT_PRIVATE LoadTransformParameters const & LoadTransformParametersOf(Operator const *) V8_WARN_UNUSED_RESULT
V8_EXPORT_PRIVATE S128ImmediateParameter const & S128ImmediateParameterOf(Operator const *op) V8_WARN_UNUSED_RESULT
StoreRepresentation const & StoreRepresentationOf(Operator const *op)
LoadRepresentation LoadRepresentationOf(Operator const *op)
T const & OpParameter(const Operator *op)
@ kProtectedByTrapHandler
MachineRepresentation LoopExitValueRepresentationOf(const Operator *const op)
MachineRepresentation PhiRepresentationOf(const Operator *const op)
ZoneSet< Node *, MemoryOffsetComparer > StoreNodeSet
constexpr int kSimd128Size
V8_EXPORT_PRIVATE FlagValues v8_flags
#define SIGN_EXTENSION_CONVERT_CASE(from, not_used, to)
#define SIMD_SIGN_EXTENSION_CONVERT_OP(V)
#define SIGN_EXTENSION_CASE(op_low, not_used1, not_used2)
#define SHIFT_CASE(from, to)
#define SPLAT_CASE(from, to)
#define SIMPLE_SIMD_OP(V)
#define CHECK_SIGN_EXTENSION_CASE(op_low, op_high, not_used)
#define SIMPLE_CASE(from, to)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
bool operator()(const Node *lhs, const Node *rhs) const