- a/Source/JavaScriptCore/ChangeLog +77 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2015-12-10  Benjamin Poulain  <bpoulain@apple.com>
2
3
        [JSC] Add a Modulo operator to B3, and a chill variant
4
        https://bugs.webkit.org/show_bug.cgi?id=152110
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        It is basically refactoring the Div and ChillDiv
9
        code to be used by both opcodes.
10
11
        * b3/B3Common.h:
12
        (JSC::B3::chillDiv):
13
        (JSC::B3::chillMod):
14
        * b3/B3Const32Value.cpp:
15
        (JSC::B3::Const32Value::modConstant):
16
        * b3/B3Const32Value.h:
17
        * b3/B3Const64Value.cpp:
18
        (JSC::B3::Const64Value::modConstant):
19
        * b3/B3Const64Value.h:
20
        * b3/B3ConstDoubleValue.cpp:
21
        (JSC::B3::ConstDoubleValue::modConstant):
22
        * b3/B3ConstDoubleValue.h:
23
        * b3/B3LowerMacros.cpp:
24
        * b3/B3LowerToAir.cpp:
25
        (JSC::B3::Air::LowerToAir::lower):
26
        (JSC::B3::Air::LowerToAir::lowerX86Div):
27
        * b3/B3Opcode.cpp:
28
        (WTF::printInternal):
29
        * b3/B3Opcode.h:
30
        * b3/B3ReduceStrength.cpp:
31
        * b3/B3Validate.cpp:
32
        * b3/B3Value.cpp:
33
        (JSC::B3::Value::modConstant):
34
        (JSC::B3::Value::effects):
35
        (JSC::B3::Value::key):
36
        (JSC::B3::Value::typeFor):
37
        * b3/B3Value.h:
38
        * b3/testb3.cpp:
39
        (JSC::B3::testModArgDouble):
40
        (JSC::B3::testModArgsDouble):
41
        (JSC::B3::testModArgImmDouble):
42
        (JSC::B3::testModImmArgDouble):
43
        (JSC::B3::testModImmsDouble):
44
        (JSC::B3::testModArgFloat):
45
        (JSC::B3::testModArgsFloat):
46
        (JSC::B3::testModArgImmFloat):
47
        (JSC::B3::testModImmArgFloat):
48
        (JSC::B3::testModImmsFloat):
49
        (JSC::B3::testModArg):
50
        (JSC::B3::testModArgs):
51
        (JSC::B3::testModImms):
52
        (JSC::B3::testModArg32):
53
        (JSC::B3::testModArgs32):
54
        (JSC::B3::testModImms32):
55
        (JSC::B3::testChillModArg):
56
        (JSC::B3::testChillModArgs):
57
        (JSC::B3::testChillModImms):
58
        (JSC::B3::testChillModArg32):
59
        (JSC::B3::testChillModArgs32):
60
        (JSC::B3::testChillModImms32):
61
        (JSC::B3::run):
62
        * ftl/FTLB3Output.h:
63
        (JSC::FTL::Output::mod):
64
        (JSC::FTL::Output::chillMod):
65
        (JSC::FTL::Output::doubleMod):
66
        (JSC::FTL::Output::rem): Deleted.
67
        (JSC::FTL::Output::doubleRem): Deleted.
68
        * ftl/FTLLowerDFGToLLVM.cpp:
69
        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMod):
70
        * ftl/FTLOutput.cpp:
71
        (JSC::FTL::Output::chillMod):
72
        * ftl/FTLOutput.h:
73
        (JSC::FTL::Output::mod):
74
        (JSC::FTL::Output::doubleMod):
75
        (JSC::FTL::Output::rem): Deleted.
76
        (JSC::FTL::Output::doubleRem): Deleted.
77
1
2015-12-09  Saam barati  <sbarati@apple.com>
78
2015-12-09  Saam barati  <sbarati@apple.com>
2
79
3
        Update generators' features.json to indicate that we have a spec compliant implementation
80
        Update generators' features.json to indicate that we have a spec compliant implementation
- a/Source/JavaScriptCore/b3/B3Common.h -10 / +12 lines
Lines 94-115 inline bool isRepresentableAs(double value) a/Source/JavaScriptCore/b3/B3Common.h_sec1
94
    return isRepresentableAsImpl<ResultType, double, int64_t>(value);
94
    return isRepresentableAsImpl<ResultType, double, int64_t>(value);
95
}
95
}
96
96
97
inline int32_t chillDiv(int32_t num, int32_t den)
97
template<typename IntType>
98
static IntType chillDiv(IntType numerator, IntType denominator)
98
{
99
{
99
    if (!den)
100
    if (!denominator)
100
        return 0;
101
        return 0;
101
    if (den == -1 && num == std::numeric_limits<int32_t>::min())
102
    if (denominator == -1 && numerator == std::numeric_limits<IntType>::min())
102
        return num;
103
        return std::numeric_limits<IntType>::min();
103
    return num / den;
104
    return numerator / denominator;
104
}
105
}
105
106
106
inline int64_t chillDiv(int64_t num, int64_t den)
107
template<typename IntType>
108
static IntType chillMod(IntType numerator, IntType denominator)
107
{
109
{
108
    if (!den)
110
    if (!denominator)
109
        return 0;
111
        return 0;
110
    if (den == -1 && num == std::numeric_limits<int64_t>::min())
112
    if (denominator == -1 && numerator == std::numeric_limits<IntType>::min())
111
        return num;
113
        return 0;
112
    return num / den;
114
    return numerator % denominator;
113
}
115
}
114
116
115
} } // namespace JSC::B3
117
} } // namespace JSC::B3
- a/Source/JavaScriptCore/b3/B3Const32Value.cpp +7 lines
Lines 112-117 Value* Const32Value::divConstant(Procedure& proc, const Value* other) const a/Source/JavaScriptCore/b3/B3Const32Value.cpp_sec1
112
    return proc.add<Const32Value>(origin(), chillDiv(m_value, other->asInt32()));
112
    return proc.add<Const32Value>(origin(), chillDiv(m_value, other->asInt32()));
113
}
113
}
114
114
115
Value* Const32Value::modConstant(Procedure& proc, const Value* other) const
116
{
117
    if (!other->hasInt32())
118
        return nullptr;
119
    return proc.add<Const32Value>(origin(), chillMod(m_value, other->asInt32()));
120
}
121
115
Value* Const32Value::bitAndConstant(Procedure& proc, const Value* other) const
122
Value* Const32Value::bitAndConstant(Procedure& proc, const Value* other) const
116
{
123
{
117
    if (!other->hasInt32())
124
    if (!other->hasInt32())
- a/Source/JavaScriptCore/b3/B3Const32Value.h +1 lines
Lines 50-55 public: a/Source/JavaScriptCore/b3/B3Const32Value.h_sec1
50
    Value* checkMulConstant(Procedure&, const Value* other) const override;
50
    Value* checkMulConstant(Procedure&, const Value* other) const override;
51
    Value* checkNegConstant(Procedure&) const override;
51
    Value* checkNegConstant(Procedure&) const override;
52
    Value* divConstant(Procedure&, const Value* other) const override;
52
    Value* divConstant(Procedure&, const Value* other) const override;
53
    Value* modConstant(Procedure&, const Value* other) const override;
53
    Value* bitAndConstant(Procedure&, const Value* other) const override;
54
    Value* bitAndConstant(Procedure&, const Value* other) const override;
54
    Value* bitOrConstant(Procedure&, const Value* other) const override;
55
    Value* bitOrConstant(Procedure&, const Value* other) const override;
55
    Value* bitXorConstant(Procedure&, const Value* other) const override;
56
    Value* bitXorConstant(Procedure&, const Value* other) const override;
- a/Source/JavaScriptCore/b3/B3Const64Value.cpp +7 lines
Lines 112-117 Value* Const64Value::divConstant(Procedure& proc, const Value* other) const a/Source/JavaScriptCore/b3/B3Const64Value.cpp_sec1
112
    return proc.add<Const64Value>(origin(), chillDiv(m_value, other->asInt64()));
112
    return proc.add<Const64Value>(origin(), chillDiv(m_value, other->asInt64()));
113
}
113
}
114
114
115
Value* Const64Value::modConstant(Procedure& proc, const Value* other) const
116
{
117
    if (!other->hasInt64())
118
        return nullptr;
119
    return proc.add<Const64Value>(origin(), chillMod(m_value, other->asInt64()));
120
}
121
115
Value* Const64Value::bitAndConstant(Procedure& proc, const Value* other) const
122
Value* Const64Value::bitAndConstant(Procedure& proc, const Value* other) const
116
{
123
{
117
    if (!other->hasInt64())
124
    if (!other->hasInt64())
- a/Source/JavaScriptCore/b3/B3Const64Value.h +1 lines
Lines 50-55 public: a/Source/JavaScriptCore/b3/B3Const64Value.h_sec1
50
    Value* checkMulConstant(Procedure&, const Value* other) const override;
50
    Value* checkMulConstant(Procedure&, const Value* other) const override;
51
    Value* checkNegConstant(Procedure&) const override;
51
    Value* checkNegConstant(Procedure&) const override;
52
    Value* divConstant(Procedure&, const Value* other) const override;
52
    Value* divConstant(Procedure&, const Value* other) const override;
53
    Value* modConstant(Procedure&, const Value* other) const override;
53
    Value* bitAndConstant(Procedure&, const Value* other) const override;
54
    Value* bitAndConstant(Procedure&, const Value* other) const override;
54
    Value* bitOrConstant(Procedure&, const Value* other) const override;
55
    Value* bitOrConstant(Procedure&, const Value* other) const override;
55
    Value* bitXorConstant(Procedure&, const Value* other) const override;
56
    Value* bitXorConstant(Procedure&, const Value* other) const override;
- a/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp +7 lines
Lines 91-96 Value* ConstDoubleValue::divConstant(Procedure& proc, const Value* other) const a/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp_sec1
91
    return proc.add<ConstDoubleValue>(origin(), m_value / other->asDouble());
91
    return proc.add<ConstDoubleValue>(origin(), m_value / other->asDouble());
92
}
92
}
93
93
94
Value* ConstDoubleValue::modConstant(Procedure& proc, const Value* other) const
95
{
96
    if (!other->hasDouble())
97
        return nullptr;
98
    return proc.add<ConstDoubleValue>(origin(), fmod(m_value, other->asDouble()));
99
}
100
94
TriState ConstDoubleValue::equalConstant(const Value* other) const
101
TriState ConstDoubleValue::equalConstant(const Value* other) const
95
{
102
{
96
    if (!other->hasDouble())
103
    if (!other->hasDouble())
- a/Source/JavaScriptCore/b3/B3ConstDoubleValue.h +1 lines
Lines 45-50 public: a/Source/JavaScriptCore/b3/B3ConstDoubleValue.h_sec1
45
    Value* addConstant(Procedure&, const Value* other) const override;
45
    Value* addConstant(Procedure&, const Value* other) const override;
46
    Value* subConstant(Procedure&, const Value* other) const override;
46
    Value* subConstant(Procedure&, const Value* other) const override;
47
    Value* divConstant(Procedure&, const Value* other) const override;
47
    Value* divConstant(Procedure&, const Value* other) const override;
48
    Value* modConstant(Procedure&, const Value* other) const override;
48
    Value* mulConstant(Procedure&, const Value* other) const override;
49
    Value* mulConstant(Procedure&, const Value* other) const override;
49
    Value* bitwiseCastConstant(Procedure&) const override;
50
    Value* bitwiseCastConstant(Procedure&) const override;
50
    Value* doubleToFloatConstant(Procedure&) const override;
51
    Value* doubleToFloatConstant(Procedure&) const override;
- a/Source/JavaScriptCore/b3/B3LowerMacros.cpp -97 / +133 lines
Lines 30-35 a/Source/JavaScriptCore/b3/B3LowerMacros.cpp_sec1
30
30
31
#include "B3BasicBlockInlines.h"
31
#include "B3BasicBlockInlines.h"
32
#include "B3BlockInsertionSet.h"
32
#include "B3BlockInsertionSet.h"
33
#include "B3CCallValue.h"
34
#include "B3ConstPtrValue.h"
33
#include "B3ControlValue.h"
35
#include "B3ControlValue.h"
34
#include "B3InsertionSetInlines.h"
36
#include "B3InsertionSetInlines.h"
35
#include "B3PhaseScope.h"
37
#include "B3PhaseScope.h"
Lines 37-42 a/Source/JavaScriptCore/b3/B3LowerMacros.cpp_sec2
37
#include "B3SwitchValue.h"
39
#include "B3SwitchValue.h"
38
#include "B3UpsilonValue.h"
40
#include "B3UpsilonValue.h"
39
#include "B3ValueInlines.h"
41
#include "B3ValueInlines.h"
42
#include <cmath>
40
43
41
namespace JSC { namespace B3 {
44
namespace JSC { namespace B3 {
42
45
Lines 72-176 private: a/Source/JavaScriptCore/b3/B3LowerMacros.cpp_sec3
72
            m_value = m_block->at(m_index);
75
            m_value = m_block->at(m_index);
73
            m_origin = m_value->origin();
76
            m_origin = m_value->origin();
74
            switch (m_value->opcode()) {
77
            switch (m_value->opcode()) {
75
            case ChillDiv: {
78
            case Mod: {
76
                // ARM supports this instruction natively.
79
                if (m_value->type() == Double) {
77
                if (isARM64())
80
                    Value* functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, fmod);
78
                    break;
81
                    Value* result = m_insertionSet.insert<CCallValue>(m_index, Double, m_origin,
79
82
                        Effects::none(),
80
                m_changed = true;
83
                        functionAddress,
81
84
                        m_value->child(0),
82
                // We implement "res = ChillDiv(num, den)" as follows:
85
                        m_value->child(1));
83
                //
86
                    m_value->replaceWithIdentity(result);
84
                //     if (den + 1 <=_unsigned 1) {
87
                } else if (m_value->type() == Float) {
85
                //         if (!den) {
88
                    Value* numeratorAsDouble = m_insertionSet.insert<Value>(m_index, FloatToDouble, m_origin, m_value->child(0));
86
                //             res = 0;
89
                    Value* denominatorAsDouble = m_insertionSet.insert<Value>(m_index, FloatToDouble, m_origin, m_value->child(1));
87
                //             goto done;
90
                    Value* functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, fmod);
88
                //         }
91
                    Value* doubleMod = m_insertionSet.insert<CCallValue>(m_index, Double, m_origin,
89
                //         if (num == -2147483648) {
92
                        Effects::none(),
90
                //             res = num;
93
                        functionAddress,
91
                //             goto done;
94
                        numeratorAsDouble,
92
                //         }
95
                        denominatorAsDouble);
93
                //     }
96
                    Value* result = m_insertionSet.insert<Value>(m_index, DoubleToFloat, m_origin, doubleMod);
94
                //     res = num / dev;
97
                    m_value->replaceWithIdentity(result);
95
                // done:
96
97
                Value* num = m_value->child(0);
98
                Value* den = m_value->child(1);
99
100
                Value* one =
101
                    m_insertionSet.insertIntConstant(m_index, m_value, 1);
102
                Value* isDenOK = m_insertionSet.insert<Value>(
103
                    m_index, Above, m_origin,
104
                    m_insertionSet.insert<Value>(m_index, Add, m_origin, den, one),
105
                    one);
106
107
                BasicBlock* before =
108
                    m_blockInsertionSet.splitForward(m_block, m_index, &m_insertionSet);
109
110
                BasicBlock* normalDivCase = m_blockInsertionSet.insertBefore(m_block);
111
                BasicBlock* shadyDenCase = m_blockInsertionSet.insertBefore(m_block);
112
                BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
113
                BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block);
114
                BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block);
115
116
                before->replaceLastWithNew<ControlValue>(
117
                    m_proc, Branch, m_origin, isDenOK,
118
                    FrequentedBlock(normalDivCase, FrequencyClass::Normal),
119
                    FrequentedBlock(shadyDenCase, FrequencyClass::Rare));
120
121
                UpsilonValue* normalResult = normalDivCase->appendNew<UpsilonValue>(
122
                    m_proc, m_origin,
123
                    normalDivCase->appendNew<Value>(m_proc, Div, m_origin, num, den));
124
                normalDivCase->appendNew<ControlValue>(
125
                    m_proc, Jump, m_origin, FrequentedBlock(m_block));
126
127
                shadyDenCase->appendNew<ControlValue>(
128
                    m_proc, Branch, m_origin, den,
129
                    FrequentedBlock(neg1DenCase, FrequencyClass::Normal),
130
                    FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
131
132
                UpsilonValue* zeroResult = zeroDenCase->appendNew<UpsilonValue>(
133
                    m_proc, m_origin,
134
                    zeroDenCase->appendIntConstant(m_proc, m_value, 0));
135
                zeroDenCase->appendNew<ControlValue>(
136
                    m_proc, Jump, m_origin, FrequentedBlock(m_block));
137
138
                int64_t badNumeratorConst;
139
                switch (m_value->type()) {
140
                case Int32:
141
                    badNumeratorConst = std::numeric_limits<int32_t>::min();
142
                    break;
143
                case Int64:
144
                    badNumeratorConst = std::numeric_limits<int64_t>::min();
145
                    break;
146
                default:
147
                    ASSERT_NOT_REACHED();
148
                    badNumeratorConst = 0;
149
                }
98
                }
99
                break;
100
            }
101
            case ChillDiv: {
102
                makeDivisionChill(Div);
103
                break;
104
            }
150
105
151
                Value* badNumerator =
106
            case ChillMod: {
152
                    neg1DenCase->appendIntConstant(m_proc, m_value, badNumeratorConst);
107
                makeDivisionChill(Mod);
153
154
                neg1DenCase->appendNew<ControlValue>(
155
                    m_proc, Branch, m_origin,
156
                    neg1DenCase->appendNew<Value>(
157
                        m_proc, Equal, m_origin, num, badNumerator),
158
                    FrequentedBlock(intMinCase, FrequencyClass::Rare),
159
                    FrequentedBlock(normalDivCase, FrequencyClass::Normal));
160
161
                UpsilonValue* intMinResult = intMinCase->appendNew<UpsilonValue>(
162
                    m_proc, m_origin, badNumerator);
163
                intMinCase->appendNew<ControlValue>(
164
                    m_proc, Jump, m_origin, FrequentedBlock(m_block));
165
166
                Value* phi = m_insertionSet.insert<Value>(
167
                    m_index, Phi, m_value->type(), m_origin);
168
                normalResult->setPhi(phi);
169
                zeroResult->setPhi(phi);
170
                intMinResult->setPhi(phi);
171
172
                m_value->replaceWithIdentity(phi);
173
                before->updatePredecessorsAfter();
174
                break;
108
                break;
175
            }
109
            }
176
110
Lines 199-204 private: a/Source/JavaScriptCore/b3/B3LowerMacros.cpp_sec4
199
        m_insertionSet.execute(m_block);
133
        m_insertionSet.execute(m_block);
200
    }
134
    }
201
135
136
    void makeDivisionChill(Opcode nonChillOpcode)
137
    {
138
        ASSERT(nonChillOpcode == Div || nonChillOpcode == Mod);
139
140
        // ARM supports this instruction natively.
141
        if (isARM64())
142
            return;
143
144
        // We implement "res = ChillDiv/ChillMod(num, den)" as follows:
145
        //
146
        //     if (den + 1 <=_unsigned 1) {
147
        //         if (!den) {
148
        //             res = 0;
149
        //             goto done;
150
        //         }
151
        //         if (num == -2147483648) {
152
        //             res = isDiv ? num : 0;
153
        //             goto done;
154
        //         }
155
        //     }
156
        //     res = num (/ or %) dev;
157
        // done:
158
        m_changed = true;
159
160
        Value* num = m_value->child(0);
161
        Value* den = m_value->child(1);
162
163
        Value* one = m_insertionSet.insertIntConstant(m_index, m_value, 1);
164
        Value* isDenOK = m_insertionSet.insert<Value>(
165
            m_index, Above, m_origin,
166
            m_insertionSet.insert<Value>(m_index, Add, m_origin, den, one),
167
            one);
168
169
        BasicBlock* before = m_blockInsertionSet.splitForward(m_block, m_index, &m_insertionSet);
170
171
        BasicBlock* normalDivCase = m_blockInsertionSet.insertBefore(m_block);
172
        BasicBlock* shadyDenCase = m_blockInsertionSet.insertBefore(m_block);
173
        BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
174
        BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block);
175
        BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block);
176
177
        before->replaceLastWithNew<ControlValue>(
178
            m_proc, Branch, m_origin, isDenOK,
179
            FrequentedBlock(normalDivCase, FrequencyClass::Normal),
180
            FrequentedBlock(shadyDenCase, FrequencyClass::Rare));
181
182
        UpsilonValue* normalResult = normalDivCase->appendNew<UpsilonValue>(
183
            m_proc, m_origin,
184
            normalDivCase->appendNew<Value>(m_proc, nonChillOpcode, m_origin, num, den));
185
        normalDivCase->appendNew<ControlValue>(
186
            m_proc, Jump, m_origin, FrequentedBlock(m_block));
187
188
        shadyDenCase->appendNew<ControlValue>(
189
            m_proc, Branch, m_origin, den,
190
            FrequentedBlock(neg1DenCase, FrequencyClass::Normal),
191
            FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
192
193
        UpsilonValue* zeroResult = zeroDenCase->appendNew<UpsilonValue>(
194
            m_proc, m_origin,
195
            zeroDenCase->appendIntConstant(m_proc, m_value, 0));
196
        zeroDenCase->appendNew<ControlValue>(
197
            m_proc, Jump, m_origin, FrequentedBlock(m_block));
198
199
        int64_t badNumeratorConst = 0;
200
        switch (m_value->type()) {
201
        case Int32:
202
            badNumeratorConst = std::numeric_limits<int32_t>::min();
203
            break;
204
        case Int64:
205
            badNumeratorConst = std::numeric_limits<int64_t>::min();
206
            break;
207
        default:
208
            ASSERT_NOT_REACHED();
209
            badNumeratorConst = 0;
210
        }
211
212
        Value* badNumerator =
213
            neg1DenCase->appendIntConstant(m_proc, m_value, badNumeratorConst);
214
215
        neg1DenCase->appendNew<ControlValue>(
216
            m_proc, Branch, m_origin,
217
            neg1DenCase->appendNew<Value>(
218
                m_proc, Equal, m_origin, num, badNumerator),
219
            FrequentedBlock(intMinCase, FrequencyClass::Rare),
220
            FrequentedBlock(normalDivCase, FrequencyClass::Normal));
221
222
        Value* intMinResult = nonChillOpcode == Div ? badNumerator : intMinCase->appendIntConstant(m_proc, m_value, 0);
223
        UpsilonValue* intMinResultUpsilon = intMinCase->appendNew<UpsilonValue>(
224
            m_proc, m_origin, intMinResult);
225
        intMinCase->appendNew<ControlValue>(
226
            m_proc, Jump, m_origin, FrequentedBlock(m_block));
227
228
        Value* phi = m_insertionSet.insert<Value>(
229
            m_index, Phi, m_value->type(), m_origin);
230
        normalResult->setPhi(phi);
231
        zeroResult->setPhi(phi);
232
        intMinResultUpsilon->setPhi(phi);
233
234
        m_value->replaceWithIdentity(phi);
235
        before->updatePredecessorsAfter();
236
    }
237
202
    void recursivelyBuildSwitch(
238
    void recursivelyBuildSwitch(
203
        const Vector<SwitchCase>& cases, unsigned start, bool hardStart, unsigned end,
239
        const Vector<SwitchCase>& cases, unsigned start, bool hardStart, unsigned end,
204
        BasicBlock* before)
240
        BasicBlock* before)
- a/Source/JavaScriptCore/b3/B3LowerToAir.cpp -23 / +34 lines
Lines 1441-1469 private: a/Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec1
1441
1441
1442
        case Div: {
1442
        case Div: {
1443
            if (isInt(m_value->type())) {
1443
            if (isInt(m_value->type())) {
1444
                Tmp eax = Tmp(X86Registers::eax);
1444
                lowerX86Div();
1445
                Tmp edx = Tmp(X86Registers::edx);
1445
                append(Move, Tmp(X86Registers::eax), tmp(m_value));
1446
1447
                Air::Opcode convertToDoubleWord;
1448
                Air::Opcode div;
1449
                switch (m_value->type()) {
1450
                case Int32:
1451
                    convertToDoubleWord = X86ConvertToDoubleWord32;
1452
                    div = X86Div32;
1453
                    break;
1454
                case Int64:
1455
                    convertToDoubleWord = X86ConvertToQuadWord64;
1456
                    div = X86Div64;
1457
                    break;
1458
                default:
1459
                    RELEASE_ASSERT_NOT_REACHED();
1460
                    return;
1461
                }
1462
                
1463
                append(Move, tmp(m_value->child(0)), eax);
1464
                append(convertToDoubleWord, eax, edx);
1465
                append(div, eax, edx, tmp(m_value->child(1)));
1466
                append(Move, eax, tmp(m_value));
1467
                return;
1446
                return;
1468
            }
1447
            }
1469
            ASSERT(isFloat(m_value->type()));
1448
            ASSERT(isFloat(m_value->type()));
Lines 1472-1477 private: a/Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec2
1472
            return;
1451
            return;
1473
        }
1452
        }
1474
1453
1454
        case Mod: {
1455
            lowerX86Div();
1456
            append(Move, Tmp(X86Registers::edx), tmp(m_value));
1457
            return;
1458
        }
1459
1475
        case BitAnd: {
1460
        case BitAnd: {
1476
            appendBinOp<And32, And64, Commutative>(
1461
            appendBinOp<And32, And64, Commutative>(
1477
                m_value->child(0), m_value->child(1));
1462
                m_value->child(0), m_value->child(1));
Lines 1977-1982 private: a/Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec3
1977
        dataLog("FATAL: could not lower ", deepDump(m_value), "\n");
1962
        dataLog("FATAL: could not lower ", deepDump(m_value), "\n");
1978
        RELEASE_ASSERT_NOT_REACHED();
1963
        RELEASE_ASSERT_NOT_REACHED();
1979
    }
1964
    }
1965
1966
    void lowerX86Div()
1967
    {
1968
        Tmp eax = Tmp(X86Registers::eax);
1969
        Tmp edx = Tmp(X86Registers::edx);
1970
1971
        Air::Opcode convertToDoubleWord;
1972
        Air::Opcode div;
1973
        switch (m_value->type()) {
1974
        case Int32:
1975
            convertToDoubleWord = X86ConvertToDoubleWord32;
1976
            div = X86Div32;
1977
            break;
1978
        case Int64:
1979
            convertToDoubleWord = X86ConvertToQuadWord64;
1980
            div = X86Div64;
1981
            break;
1982
        default:
1983
            RELEASE_ASSERT_NOT_REACHED();
1984
            return;
1985
        }
1986
        
1987
        append(Move, tmp(m_value->child(0)), eax);
1988
        append(convertToDoubleWord, eax, edx);
1989
        append(div, eax, edx, tmp(m_value->child(1)));
1990
    }
1980
    
1991
    
1981
    IndexSet<Value> m_locked; // These are values that will have no Tmp in Air.
1992
    IndexSet<Value> m_locked; // These are values that will have no Tmp in Air.
1982
    IndexMap<Value, Tmp> m_valueToTmp; // These are values that must have a Tmp in Air. We say that a Value* with a non-null Tmp is "pinned".
1993
    IndexMap<Value, Tmp> m_valueToTmp; // These are values that must have a Tmp in Air. We say that a Value* with a non-null Tmp is "pinned".
- a/Source/JavaScriptCore/b3/B3Opcode.cpp -2 / +5 lines
Lines 116-126 void printInternal(PrintStream& out, Opcode opcode) a/Source/JavaScriptCore/b3/B3Opcode.cpp_sec1
116
    case Div:
116
    case Div:
117
        out.print("Div");
117
        out.print("Div");
118
        return;
118
        return;
119
    case Mod:
120
        out.print("Mod");
121
        return;
119
    case ChillDiv:
122
    case ChillDiv:
120
        out.print("ChillDiv");
123
        out.print("ChillDiv");
121
        return;
124
        return;
122
    case Mod:
125
    case ChillMod:
123
        out.print("Mod");
126
        out.print("ChillMod");
124
        return;
127
        return;
125
    case BitAnd:
128
    case BitAnd:
126
        out.print("BitAnd");
129
        out.print("BitAnd");
- a/Source/JavaScriptCore/b3/B3Opcode.h -1 / +2 lines
Lines 71-80 enum Opcode : int16_t { a/Source/JavaScriptCore/b3/B3Opcode.h_sec1
71
    Sub,
71
    Sub,
72
    Mul,
72
    Mul,
73
    Div, // All bets are off as to what will happen when you execute this for -2^31/-1 and x/0.
73
    Div, // All bets are off as to what will happen when you execute this for -2^31/-1 and x/0.
74
    Mod, // All bets are off as to what will happen when you execute this for -2^31%-1 and x%0.
74
75
75
    // Integer math.
76
    // Integer math.
76
    ChillDiv, // doesn't trap ever, behaves like JS (x/y)|0.
77
    ChillDiv, // doesn't trap ever, behaves like JS (x/y)|0.
77
    Mod,
78
    ChillMod, // doesn't trap ever, behaves like JS (x%y)|0.
78
    BitAnd,
79
    BitAnd,
79
    BitOr,
80
    BitOr,
80
    BitXor,
81
    BitXor,
- a/Source/JavaScriptCore/b3/B3ReduceStrength.cpp -1 / +18 lines
Lines 291-296 private: a/Source/JavaScriptCore/b3/B3ReduceStrength.cpp_sec1
291
            replaceWithNewValue(m_value->child(0)->divConstant(m_proc, m_value->child(1)));
291
            replaceWithNewValue(m_value->child(0)->divConstant(m_proc, m_value->child(1)));
292
            break;
292
            break;
293
293
294
        case Mod:
295
        case ChillMod:
296
            replaceWithNewValue(m_value->child(0)->modConstant(m_proc, m_value->child(1)));
297
            break;
298
294
        case BitAnd:
299
        case BitAnd:
295
            handleCommutativity();
300
            handleCommutativity();
296
301
Lines 658-664 private: a/Source/JavaScriptCore/b3/B3ReduceStrength.cpp_sec2
658
            }
663
            }
659
664
660
            // Turn this: Load(constant1, offset = constant2)
665
            // Turn this: Load(constant1, offset = constant2)
661
            // Into this: Laod(constant1 + constant2)
666
            // Into this: Load(constant1 + constant2)
662
            //
667
            //
663
            // This is a fun canonicalization. It purely regresses naively generated code. We rely
668
            // This is a fun canonicalization. It purely regresses naively generated code. We rely
664
            // on constant materialization to be smart enough to materialize this constant the smart
669
            // on constant materialization to be smart enough to materialize this constant the smart
Lines 677-682 private: a/Source/JavaScriptCore/b3/B3ReduceStrength.cpp_sec3
677
            break;
682
            break;
678
        }
683
        }
679
684
685
        case CCall:
686
            // Turn this: Call(fmod, constant1, constant2)
687
            // Into this: fcall-constant(constant1, constant2)
688
            if (m_value->type() == Double
689
                && m_value->numChildren() == 3
690
                && m_value->child(0)->isIntPtr(reinterpret_cast<intptr_t>(fmod))
691
                && m_value->child(1)->type() == Double
692
                && m_value->child(2)->type() == Double) {
693
                replaceWithNewValue(m_value->child(1)->modConstant(m_proc, m_value->child(2)));
694
            }
695
            break;
696
680
        case Equal:
697
        case Equal:
681
            handleCommutativity();
698
            handleCommutativity();
682
699
- a/Source/JavaScriptCore/b3/B3Validate.cpp -1 / +2 lines
Lines 153-165 public: a/Source/JavaScriptCore/b3/B3Validate.cpp_sec1
153
            case Sub:
153
            case Sub:
154
            case Mul:
154
            case Mul:
155
            case Div:
155
            case Div:
156
            case Mod:
156
                VALIDATE(value->numChildren() == 2, ("At ", *value));
157
                VALIDATE(value->numChildren() == 2, ("At ", *value));
157
                VALIDATE(value->type() == value->child(0)->type(), ("At ", *value));
158
                VALIDATE(value->type() == value->child(0)->type(), ("At ", *value));
158
                VALIDATE(value->type() == value->child(1)->type(), ("At ", *value));
159
                VALIDATE(value->type() == value->child(1)->type(), ("At ", *value));
159
                VALIDATE(value->type() != Void, ("At ", *value));
160
                VALIDATE(value->type() != Void, ("At ", *value));
160
                break;
161
                break;
161
            case ChillDiv:
162
            case ChillDiv:
162
            case Mod:
163
            case ChillMod:
163
            case BitAnd:
164
            case BitAnd:
164
            case BitOr:
165
            case BitOr:
165
            case BitXor:
166
            case BitXor:
- a/Source/JavaScriptCore/b3/B3Value.cpp -4 / +12 lines
Lines 164-169 Value* Value::divConstant(Procedure&, const Value*) const a/Source/JavaScriptCore/b3/B3Value.cpp_sec1
164
    return nullptr;
164
    return nullptr;
165
}
165
}
166
166
167
Value* Value::modConstant(Procedure&, const Value*) const
168
{
169
    return nullptr;
170
}
171
167
Value* Value::bitAndConstant(Procedure&, const Value*) const
172
Value* Value::bitAndConstant(Procedure&, const Value*) const
168
{
173
{
169
    return nullptr;
174
    return nullptr;
Lines 337-343 Effects Value::effects() const a/Source/JavaScriptCore/b3/B3Value.cpp_sec2
337
    case Sub:
342
    case Sub:
338
    case Mul:
343
    case Mul:
339
    case ChillDiv:
344
    case ChillDiv:
340
    case Mod:
345
    case ChillMod:
341
    case BitAnd:
346
    case BitAnd:
342
    case BitOr:
347
    case BitOr:
343
    case BitXor:
348
    case BitXor:
Lines 369-374 Effects Value::effects() const a/Source/JavaScriptCore/b3/B3Value.cpp_sec3
369
    case Select:
374
    case Select:
370
        break;
375
        break;
371
    case Div:
376
    case Div:
377
    case Mod:
372
        result.controlDependent = true;
378
        result.controlDependent = true;
373
        break;
379
        break;
374
    case Load8Z:
380
    case Load8Z:
Lines 436-443 ValueKey Value::key() const a/Source/JavaScriptCore/b3/B3Value.cpp_sec4
436
    case Add:
442
    case Add:
437
    case Sub:
443
    case Sub:
438
    case Mul:
444
    case Mul:
439
    case ChillDiv:
445
    case Div:
440
    case Mod:
446
    case Mod:
447
    case ChillDiv:
448
    case ChillMod:
441
    case BitAnd:
449
    case BitAnd:
442
    case BitOr:
450
    case BitOr:
443
    case BitXor:
451
    case BitXor:
Lines 452-458 ValueKey Value::key() const a/Source/JavaScriptCore/b3/B3Value.cpp_sec5
452
    case Below:
460
    case Below:
453
    case AboveEqual:
461
    case AboveEqual:
454
    case BelowEqual:
462
    case BelowEqual:
455
    case Div:
456
    case CheckAdd:
463
    case CheckAdd:
457
    case CheckSub:
464
    case CheckSub:
458
    case CheckMul:
465
    case CheckMul:
Lines 514-521 Type Value::typeFor(Opcode opcode, Value* firstChild, Value* secondChild) a/Source/JavaScriptCore/b3/B3Value.cpp_sec6
514
    case Sub:
521
    case Sub:
515
    case Mul:
522
    case Mul:
516
    case Div:
523
    case Div:
517
    case ChillDiv:
518
    case Mod:
524
    case Mod:
525
    case ChillDiv:
526
    case ChillMod:
519
    case BitAnd:
527
    case BitAnd:
520
    case BitOr:
528
    case BitOr:
521
    case BitXor:
529
    case BitXor:
- a/Source/JavaScriptCore/b3/B3Value.h +1 lines
Lines 121-126 public: a/Source/JavaScriptCore/b3/B3Value.h_sec1
121
    virtual Value* checkMulConstant(Procedure&, const Value* other) const;
121
    virtual Value* checkMulConstant(Procedure&, const Value* other) const;
122
    virtual Value* checkNegConstant(Procedure&) const;
122
    virtual Value* checkNegConstant(Procedure&) const;
123
    virtual Value* divConstant(Procedure&, const Value* other) const; // This chooses ChillDiv semantics for integers.
123
    virtual Value* divConstant(Procedure&, const Value* other) const; // This chooses ChillDiv semantics for integers.
124
    virtual Value* modConstant(Procedure&, const Value* other) const; // This chooses ChillMod semantics for integers.
124
    virtual Value* bitAndConstant(Procedure&, const Value* other) const;
125
    virtual Value* bitAndConstant(Procedure&, const Value* other) const;
125
    virtual Value* bitOrConstant(Procedure&, const Value* other) const;
126
    virtual Value* bitOrConstant(Procedure&, const Value* other) const;
126
    virtual Value* bitXorConstant(Procedure&, const Value* other) const;
127
    virtual Value* bitXorConstant(Procedure&, const Value* other) const;
- a/Source/JavaScriptCore/b3/testb3.cpp +347 lines
Lines 1027-1032 void testDivImmsFloat(float a, float b) a/Source/JavaScriptCore/b3/testb3.cpp_sec1
1027
    CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a / b)));
1027
    CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a / b)));
1028
}
1028
}
1029
1029
1030
void testModArgDouble(double a)
1031
{
1032
    Procedure proc;
1033
    BasicBlock* root = proc.addBlock();
1034
    Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1035
    root->appendNew<ControlValue>(
1036
        proc, Return, Origin(),
1037
        root->appendNew<Value>(proc, Mod, Origin(), value, value));
1038
1039
    CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, a)));
1040
}
1041
1042
void testModArgsDouble(double a, double b)
1043
{
1044
    Procedure proc;
1045
    BasicBlock* root = proc.addBlock();
1046
    Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1047
    Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1048
    root->appendNew<ControlValue>(
1049
        proc, Return, Origin(),
1050
        root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1051
1052
    CHECK(isIdentical(compileAndRun<double>(proc, a, b), fmod(a, b)));
1053
}
1054
1055
void testModArgImmDouble(double a, double b)
1056
{
1057
    Procedure proc;
1058
    BasicBlock* root = proc.addBlock();
1059
    Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1060
    Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1061
    root->appendNew<ControlValue>(
1062
        proc, Return, Origin(),
1063
        root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1064
1065
    CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, b)));
1066
}
1067
1068
void testModImmArgDouble(double a, double b)
1069
{
1070
    Procedure proc;
1071
    BasicBlock* root = proc.addBlock();
1072
    Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1073
    Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1074
    root->appendNew<ControlValue>(
1075
        proc, Return, Origin(),
1076
        root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1077
1078
    CHECK(isIdentical(compileAndRun<double>(proc, b), fmod(a, b)));
1079
}
1080
1081
void testModImmsDouble(double a, double b)
1082
{
1083
    Procedure proc;
1084
    BasicBlock* root = proc.addBlock();
1085
    Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1086
    Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1087
    root->appendNew<ControlValue>(
1088
        proc, Return, Origin(),
1089
        root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1090
1091
    CHECK(isIdentical(compileAndRun<double>(proc), fmod(a, b)));
1092
}
1093
1094
void testModArgFloat(float a)
1095
{
1096
    Procedure proc;
1097
    BasicBlock* root = proc.addBlock();
1098
    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1099
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1100
    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1101
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, floatValue);
1102
    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1103
    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1104
1105
1106
    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, a)))));
1107
}
1108
1109
void testModArgsFloat(float a, float b)
1110
{
1111
    Procedure proc;
1112
    BasicBlock* root = proc.addBlock();
1113
    Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1114
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1115
    Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1116
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1117
    Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1118
    Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1119
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue1, floatValue2);
1120
    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1121
    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1122
1123
    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1124
}
1125
1126
void testModArgImmFloat(float a, float b)
1127
{
1128
    Procedure proc;
1129
    BasicBlock* root = proc.addBlock();
1130
    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1131
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1132
    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1133
    Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1134
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, constValue);
1135
    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1136
    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1137
1138
    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1139
}
1140
1141
void testModImmArgFloat(float a, float b)
1142
{
1143
    Procedure proc;
1144
    BasicBlock* root = proc.addBlock();
1145
    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1146
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1147
    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1148
    Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1149
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue, floatValue);
1150
    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1151
    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1152
1153
    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1154
}
1155
1156
void testModImmsFloat(float a, float b)
1157
{
1158
    Procedure proc;
1159
    BasicBlock* root = proc.addBlock();
1160
    Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1161
    Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1162
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue1, constValue2);
1163
    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1164
    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1165
1166
    CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1167
}
1168
1030
void testDivArgFloatWithUselessDoubleConversion(float a)
1169
void testDivArgFloatWithUselessDoubleConversion(float a)
1031
{
1170
{
1032
    Procedure proc;
1171
    Procedure proc;
Lines 6300-6305 void testChillDiv64(int64_t num, int64_t den, int64_t res) a/Source/JavaScriptCore/b3/testb3.cpp_sec2
6300
    }
6439
    }
6301
}
6440
}
6302
6441
6442
void testModArg(int64_t value)
6443
{
6444
    if (!value)
6445
        return;
6446
6447
    Procedure proc;
6448
    BasicBlock* root = proc.addBlock();
6449
6450
    Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6451
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument);
6452
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6453
6454
    CHECK(!compileAndRun<int64_t>(proc, value));
6455
}
6456
6457
void testModArgs(int64_t numerator, int64_t denominator)
6458
{
6459
    if (!denominator)
6460
        return;
6461
    if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1)
6462
        return;
6463
6464
    Procedure proc;
6465
    BasicBlock* root = proc.addBlock();
6466
6467
    Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6468
    Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6469
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
6470
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6471
6472
    CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator);
6473
}
6474
6475
void testModImms(int64_t numerator, int64_t denominator)
6476
{
6477
    if (!denominator)
6478
        return;
6479
    if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1)
6480
        return;
6481
6482
    Procedure proc;
6483
    BasicBlock* root = proc.addBlock();
6484
6485
    Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator);
6486
    Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator);
6487
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
6488
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6489
6490
    CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator);
6491
}
6492
6493
void testModArg32(int32_t value)
6494
{
6495
    if (!value)
6496
        return;
6497
6498
    Procedure proc;
6499
    BasicBlock* root = proc.addBlock();
6500
6501
    Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
6502
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6503
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument);
6504
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6505
6506
    CHECK(!compileAndRun<int32_t>(proc, value));
6507
}
6508
6509
void testModArgs32(int32_t numerator, int32_t denominator)
6510
{
6511
    if (!denominator)
6512
        return;
6513
    if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1)
6514
        return;
6515
6516
    Procedure proc;
6517
    BasicBlock* root = proc.addBlock();
6518
6519
    Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
6520
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6521
    Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
6522
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
6523
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
6524
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6525
6526
    CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator);
6527
}
6528
6529
void testModImms32(int32_t numerator, int32_t denominator)
6530
{
6531
    if (!denominator)
6532
        return;
6533
    if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1)
6534
        return;
6535
6536
    Procedure proc;
6537
    BasicBlock* root = proc.addBlock();
6538
6539
    Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator);
6540
    Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator);
6541
    Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
6542
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6543
6544
    CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator);
6545
}
6546
6547
void testChillModArg(int64_t value)
6548
{
6549
    Procedure proc;
6550
    BasicBlock* root = proc.addBlock();
6551
6552
    Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6553
    Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument, argument);
6554
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6555
6556
    CHECK(!compileAndRun<int64_t>(proc, value));
6557
}
6558
6559
void testChillModArgs(int64_t numerator, int64_t denominator)
6560
{
6561
    Procedure proc;
6562
    BasicBlock* root = proc.addBlock();
6563
6564
    Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6565
    Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6566
    Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2);
6567
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6568
6569
    CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
6570
}
6571
6572
void testChillModImms(int64_t numerator, int64_t denominator)
6573
{
6574
    Procedure proc;
6575
    BasicBlock* root = proc.addBlock();
6576
6577
    Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator);
6578
    Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator);
6579
    Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2);
6580
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6581
6582
    CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
6583
}
6584
6585
void testChillModArg32(int32_t value)
6586
{
6587
    Procedure proc;
6588
    BasicBlock* root = proc.addBlock();
6589
6590
    Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
6591
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6592
    Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument, argument);
6593
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6594
6595
    CHECK(!compileAndRun<int32_t>(proc, value));
6596
}
6597
6598
void testChillModArgs32(int32_t numerator, int32_t denominator)
6599
{
6600
    Procedure proc;
6601
    BasicBlock* root = proc.addBlock();
6602
6603
    Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
6604
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6605
    Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
6606
        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
6607
    Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2);
6608
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6609
6610
    CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
6611
}
6612
6613
void testChillModImms32(int32_t numerator, int32_t denominator)
6614
{
6615
    Procedure proc;
6616
    BasicBlock* root = proc.addBlock();
6617
6618
    Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator);
6619
    Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator);
6620
    Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2);
6621
    root->appendNew<ControlValue>(proc, Return, Origin(), result);
6622
6623
    CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
6624
}
6625
6303
void testSwitch(unsigned degree, unsigned gap = 1)
6626
void testSwitch(unsigned degree, unsigned gap = 1)
6304
{
6627
{
6305
    Procedure proc;
6628
    Procedure proc;
Lines 7059-7064 void run(const char* filter) a/Source/JavaScriptCore/b3/testb3.cpp_sec3
7059
    RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
7382
    RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
7060
    RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
7383
    RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
7061
7384
7385
    RUN_UNARY(testModArgDouble, floatingPointOperands<double>());
7386
    RUN_BINARY(testModArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
7387
    RUN_BINARY(testModArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
7388
    RUN_BINARY(testModImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
7389
    RUN_BINARY(testModImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
7390
    RUN_UNARY(testModArgFloat, floatingPointOperands<float>());
7391
    RUN_BINARY(testModArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
7392
    RUN_BINARY(testModArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
7393
    RUN_BINARY(testModImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
7394
    RUN_BINARY(testModImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
7395
7062
    RUN(testSubArg(24));
7396
    RUN(testSubArg(24));
7063
    RUN(testSubArgs(1, 1));
7397
    RUN(testSubArgs(1, 1));
7064
    RUN(testSubArgs(1, 2));
7398
    RUN(testSubArgs(1, 2));
Lines 7633-7638 void run(const char* filter) a/Source/JavaScriptCore/b3/testb3.cpp_sec4
7633
    RUN(testChillDivTwice(4, 0, 6, 2, 3));
7967
    RUN(testChillDivTwice(4, 0, 6, 2, 3));
7634
    RUN(testChillDivTwice(4, 2, 6, 0, 2));
7968
    RUN(testChillDivTwice(4, 2, 6, 0, 2));
7635
7969
7970
    RUN_UNARY(testModArg, int64Operands());
7971
    RUN_BINARY(testModArgs, int64Operands(), int64Operands());
7972
    RUN_BINARY(testModImms, int64Operands(), int64Operands());
7973
    RUN_UNARY(testModArg32, int32Operands());
7974
    RUN_BINARY(testModArgs32, int32Operands(), int32Operands());
7975
    RUN_BINARY(testModImms32, int32Operands(), int32Operands());
7976
    RUN_UNARY(testChillModArg, int64Operands());
7977
    RUN_BINARY(testChillModArgs, int64Operands(), int64Operands());
7978
    RUN_BINARY(testChillModImms, int64Operands(), int64Operands());
7979
    RUN_UNARY(testChillModArg32, int32Operands());
7980
    RUN_BINARY(testChillModArgs32, int32Operands(), int32Operands());
7981
    RUN_BINARY(testChillModImms32, int32Operands(), int32Operands());
7982
7636
    RUN(testSwitch(0, 1));
7983
    RUN(testSwitch(0, 1));
7637
    RUN(testSwitch(1, 1));
7984
    RUN(testSwitch(1, 1));
7638
    RUN(testSwitch(2, 1));
7985
    RUN(testSwitch(2, 1));
- a/Source/JavaScriptCore/ftl/FTLB3Output.h -2 / +3 lines
Lines 128-134 public: a/Source/JavaScriptCore/ftl/FTLB3Output.h_sec1
128
    LValue mul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
128
    LValue mul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
129
    LValue div(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
129
    LValue div(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
130
    LValue chillDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ChillDiv, origin(), left, right); }
130
    LValue chillDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ChillDiv, origin(), left, right); }
131
    LValue rem(LValue left, LValue right) { CRASH(); }
131
    LValue mod(LValue left, LValue right) { m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right); }
132
    LValue chillMod(LValue left, LValue right) { m_block->appendNew<B3::Value>(m_proc, B3::ChillMod, origin(), left, right); }
132
    LValue neg(LValue value)
133
    LValue neg(LValue value)
133
    {
134
    {
134
        LValue zero = m_block->appendIntConstant(m_proc, origin(), value->type(), 0);
135
        LValue zero = m_block->appendIntConstant(m_proc, origin(), value->type(), 0);
Lines 139-145 public: a/Source/JavaScriptCore/ftl/FTLB3Output.h_sec2
139
    LValue doubleSub(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right); }
140
    LValue doubleSub(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right); }
140
    LValue doubleMul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
141
    LValue doubleMul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
141
    LValue doubleDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
142
    LValue doubleDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
142
    LValue doubleRem(LValue left, LValue right) { return callWithoutSideEffects(B3::Double, fmod, left, right); }
143
    LValue doubleMod(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right); }
143
    LValue doubleNeg(LValue value)
144
    LValue doubleNeg(LValue value)
144
    {
145
    {
145
        return sub(doubleZero, value);
146
        return sub(doubleZero, value);
- a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -63 / +27 lines
Lines 2023-2111 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
2023
        case Int32Use: {
2023
        case Int32Use: {
2024
            LValue numerator = lowInt32(m_node->child1());
2024
            LValue numerator = lowInt32(m_node->child1());
2025
            LValue denominator = lowInt32(m_node->child2());
2025
            LValue denominator = lowInt32(m_node->child2());
2026
            
2026
2027
            LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
2027
            LValue remainder;
2028
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
2029
            LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithMod done"));
2030
            
2031
            Vector<ValueFromBlock, 3> results;
2032
            
2033
            LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
2034
            
2035
            m_out.branch(
2036
                m_out.above(adjustedDenominator, m_out.int32One),
2037
                usually(continuation), rarely(unsafeDenominator));
2038
            
2039
            LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
2040
            
2041
            LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
2042
            
2043
            // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
2044
            // separate case for that. But it probably doesn't matter so much.
2045
            if (shouldCheckOverflow(m_node->arithMode())) {
2028
            if (shouldCheckOverflow(m_node->arithMode())) {
2029
                LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
2030
                LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
2031
2032
                LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
2033
                m_out.branch(
2034
                    m_out.above(adjustedDenominator, m_out.int32One),
2035
                    usually(continuation), rarely(unsafeDenominator));
2036
2037
                LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
2038
                LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
2046
                LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
2039
                LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
2047
                speculate(Overflow, noValue(), 0, cond);
2040
                speculate(Overflow, noValue(), 0, cond);
2048
                m_out.jump(continuation);
2041
                m_out.jump(continuation);
2049
            } else {
2042
2050
                // This is the case where we convert the result to an int after we're done. So,
2043
                m_out.appendTo(continuation, lastNext);
2051
                // if the denominator is zero, then the result should be result should be zero.
2044
                LValue result = m_out.mod(numerator, denominator);
2052
                // If the denominator is not zero (i.e. it's -1 because we're guarded by the
2045
                remainder = result;
2053
                // check above) and the numerator is -2^31 then the result should be -2^31.
2046
            } else
2054
                
2047
                remainder = m_out.chillMod(numerator, denominator);
2055
                LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, ("ArithMod modulo by zero"));
2048
2056
                LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, ("ArithMod not modulo by zero"));
2057
                LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithMod -2^31/-1"));
2058
                
2059
                m_out.branch(
2060
                    m_out.isZero32(denominator), rarely(modByZero), usually(notModByZero));
2061
                
2062
                m_out.appendTo(modByZero, notModByZero);
2063
                results.append(m_out.anchor(m_out.int32Zero));
2064
                m_out.jump(done);
2065
                
2066
                m_out.appendTo(notModByZero, neg2ToThe31ByNeg1);
2067
                m_out.branch(
2068
                    m_out.equal(numerator, neg2ToThe31),
2069
                    rarely(neg2ToThe31ByNeg1), usually(continuation));
2070
                
2071
                m_out.appendTo(neg2ToThe31ByNeg1, continuation);
2072
                results.append(m_out.anchor(m_out.int32Zero));
2073
                m_out.jump(done);
2074
            }
2075
            
2076
            m_out.appendTo(continuation, done);
2077
            
2078
            LValue remainder = m_out.rem(numerator, denominator);
2079
            
2080
            if (shouldCheckNegativeZero(m_node->arithMode())) {
2049
            if (shouldCheckNegativeZero(m_node->arithMode())) {
2081
                LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator"));
2050
                LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator"));
2082
                LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
2051
                LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
2083
                
2052
2084
                m_out.branch(
2053
                m_out.branch(
2085
                    m_out.lessThan(numerator, m_out.int32Zero),
2054
                    m_out.lessThan(numerator, m_out.int32Zero),
2086
                    unsure(negativeNumerator), unsure(numeratorContinuation));
2055
                    unsure(negativeNumerator), unsure(numeratorContinuation));
2087
                
2056
2088
                LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
2057
                LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
2089
                
2058
2090
                speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
2059
                speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
2091
                
2060
2092
                m_out.jump(numeratorContinuation);
2061
                m_out.jump(numeratorContinuation);
2093
                
2062
2094
                m_out.appendTo(numeratorContinuation, innerLastNext);
2063
                m_out.appendTo(numeratorContinuation, innerLastNext);
2095
            }
2064
            }
2096
            
2065
2097
            results.append(m_out.anchor(remainder));
2066
            setInt32(remainder);
2098
            m_out.jump(done);
2099
            
2100
            m_out.appendTo(done, lastNext);
2101
            
2102
            setInt32(m_out.phi(m_out.int32, results));
2103
            break;
2067
            break;
2104
        }
2068
        }
2105
            
2069
            
2106
        case DoubleRepUse: {
2070
        case DoubleRepUse: {
2107
            setDouble(
2071
            setDouble(
2108
                m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
2072
                m_out.doubleMod(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
2109
            break;
2073
            break;
2110
        }
2074
        }
2111
            
2075
            
- a/Source/JavaScriptCore/ftl/FTLOutput.cpp +41 lines
Lines 116-121 LValue Output::chillDiv(LValue numerator, LValue denominator) a/Source/JavaScriptCore/ftl/FTLOutput.cpp_sec1
116
    return phi(int32, results);
116
    return phi(int32, results);
117
}
117
}
118
118
119
LValue Output::chillMod(LValue numerator, LValue denominator)
120
{
121
    LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(*this, ("ChillMod unsafe denominator"));
122
    LBasicBlock continuation = FTL_NEW_BLOCK(*this, ("ChillMod continuation"));
123
    LBasicBlock done = FTL_NEW_BLOCK(*this, ("ChillMod done"));
124
    LBasicBlock divByZero = FTL_NEW_BLOCK(*this, ("ChillMod divide by zero"));
125
    LBasicBlock notDivByZero = FTL_NEW_BLOCK(*this, ("ChillMod not divide by zero"));
126
    LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(*this, ("ChillMod -2^31/-1"));
127
128
    LValue adjustedDenominator = add(denominator, int32One);
129
    branch(
130
        above(adjustedDenominator, int32One),
131
        usually(continuation), rarely(unsafeDenominator));
132
133
    Vector<ValueFromBlock, 3> results;
134
    LBasicBlock lastNext = appendTo(unsafeDenominator, continuation);
135
136
    LValue neg2ToThe31 = constInt32(-2147483647-1);
137
    branch(isZero32(denominator), rarely(divByZero), usually(notDivByZero));
138
139
    appendTo(divByZero, notDivByZero);
140
    results.append(anchor(int32Zero));
141
    jump(done);
142
143
    appendTo(notDivByZero, neg2ToThe31ByNeg1);
144
    branch(equal(numerator, neg2ToThe31),
145
        rarely(neg2ToThe31ByNeg1), usually(continuation));
146
147
    appendTo(neg2ToThe31ByNeg1, continuation);
148
    results.append(anchor(int32Zero));
149
    jump(done);
150
151
    appendTo(continuation, done);
152
    LValue result = mod(numerator, denominator);
153
    results.append(anchor(result));
154
    jump(done);
155
156
    appendTo(done, lastNext);
157
    return phi(int32, results);
158
}
159
119
LValue Output::sensibleDoubleToInt(LValue value)
160
LValue Output::sensibleDoubleToInt(LValue value)
120
{
161
{
121
    RELEASE_ASSERT(isX86());
162
    RELEASE_ASSERT(isX86());
- a/Source/JavaScriptCore/ftl/FTLOutput.h -2 / +3 lines
Lines 126-139 public: a/Source/JavaScriptCore/ftl/FTLOutput.h_sec1
126
    LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
126
    LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
127
    LValue div(LValue left, LValue right) { return buildDiv(m_builder, left, right); }
127
    LValue div(LValue left, LValue right) { return buildDiv(m_builder, left, right); }
128
    LValue chillDiv(LValue left, LValue right);
128
    LValue chillDiv(LValue left, LValue right);
129
    LValue rem(LValue left, LValue right) { return buildRem(m_builder, left, right); }
129
    LValue mod(LValue left, LValue right) { return buildRem(m_builder, left, right); }
130
    LValue chillMod(LValue left, LValue right);
130
    LValue neg(LValue value) { return buildNeg(m_builder, value); }
131
    LValue neg(LValue value) { return buildNeg(m_builder, value); }
131
132
132
    LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
133
    LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
133
    LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
134
    LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
134
    LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
135
    LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
135
    LValue doubleDiv(LValue left, LValue right) { return buildFDiv(m_builder, left, right); }
136
    LValue doubleDiv(LValue left, LValue right) { return buildFDiv(m_builder, left, right); }
136
    LValue doubleRem(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
137
    LValue doubleMod(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
137
    LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
138
    LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
138
139
139
    LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }
140
    LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }

Return to Bug 152110