File: AirEmitShuffle.h

package info (click to toggle)
webkit2gtk 2.48.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 429,764 kB
  • sloc: cpp: 3,697,587; javascript: 194,444; ansic: 169,997; python: 46,499; asm: 19,295; ruby: 18,528; perl: 16,602; xml: 4,650; yacc: 2,360; sh: 2,098; java: 1,993; lex: 1,327; pascal: 366; makefile: 298
file content (138 lines) | stat: -rw-r--r-- 5,535 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#pragma once

#if ENABLE(B3_JIT)

#include "AirArg.h"
#include "AirInst.h"
#include <wtf/Vector.h>

namespace JSC { namespace B3 {

class Value;

namespace Air {

class Code;

inline Opcode moveFor(Bank bank, Width width)
{
    switch (width) {
    case Width32:
        return bank == GP ? Move32 : MoveFloat;
    case Width64:
        return bank == GP ? Move : MoveDouble;
    case Width128:
        ASSERT(bank == FP);
        return MoveVector;
    default:
        RELEASE_ASSERT_NOT_REACHED();
        return Oops;
    }
}

class ShufflePair {
public:
    ShufflePair()
    {
    }
    
    ShufflePair(const Arg& src, const Arg& dst, Width width)
        : m_src(src)
        , m_dst(dst)
        , m_width(width)
    {
    }

    const Arg& src() const { return m_src; }
    const Arg& dst() const { return m_dst; }

    // The width determines the kind of move we do. You can only choose Width32 or Width64 right now.
    // For GP, it picks between Move32 and Move. For FP, it picks between MoveFloat and MoveDouble.
    Width width() const { return m_width; }
    
    Bank bank() const;

    // Creates an instruction sequence for the move represented by this shuffle pair.
    // You need to pass Code because we may need to create a tmp.
    Vector<Inst, 2> insts(Code&, Value* origin) const;

    void dump(PrintStream&) const;
    
private:
    Arg m_src;
    Arg m_dst;
    Width m_width { Width8 };
};

// Create a Shuffle instruction.
Inst createShuffle(Value* origin, const Vector<ShufflePair>&);

// Perform a shuffle of a given type. The scratch argument is mandatory. You should pass it as
// follows: If you know that you have scratch registers or temporaries available - that is, they're
// registers that are not mentioned in the shuffle, have the same type as the shuffle, and are not
// live at the shuffle - then you can pass them. If you don't have scratch registers available or if
// you don't feel like looking for them, you can pass memory locations. It's always safe to pass a
// pair of memory locations, and replacing either memory location with a register can be viewed as an
// optimization. It's a pretty important optimization. Some more notes:
//
// - We define scratch registers as things that are not live before the shuffle and are not one of
//   the destinations of the shuffle. Not being live before the shuffle also means that they cannot
//   be used for any of the sources of the shuffle.
//
// - A second scratch location is only needed when you have shuffle pairs where memory is used both
//   as source and destination.
//
// - You're guaranteed not to need any scratch locations if there is a Swap instruction available for
//   the type and you don't have any memory locations that are both the source and the destination of
//   some pairs. GP supports Swap on x86 while FP never supports Swap.
//
// - Passing memory locations as scratch if are running emitShuffle() before register allocation is
//   silly, since that will cause emitShuffle() to pick some specific registers when it does need
//   scratch. One easy way to avoid that predicament is to ensure that you call emitShuffle() after
//   register allocation. For this reason we could add a Shuffle instruction so that we can defer
//   shufflings until after regalloc.
//
// - Shuffles with memory=>memory pairs are not very well tuned. You should avoid them if you want
//   performance. If you need to do them, then making sure that you reserve a temporary is one way to
//   get acceptable performance.
//
// NOTE: Use this method (and its friend below) to emit shuffles after register allocation. Before
// register allocation it is much better to simply use the Shuffle instruction.
Vector<Inst> emitShuffle(
    Code& code, Vector<ShufflePair>, std::array<Arg, 2> scratch, Bank, Value* origin);

// Perform a shuffle that involves any number of types. Pass scratch registers or memory locations
// for each type according to the rules above.
Vector<Inst> emitShuffle(
    Code& code, const Vector<ShufflePair>&,
    const std::array<Arg, 2>& gpScratch, const std::array<Arg, 2>& fpScratch,
    Value* origin);

} } } // namespace JSC::B3::Air

#endif // ENABLE(B3_JIT)