CommonOperatorBuilder common(graph->zone());
Node* zero = graph->NewNode(common.Int32Constant(0));
Node* one = graph->NewNode(common.Int32Constant(1));
- MachineOperatorBuilder machine;
+ MachineOperatorBuilder machine(graph->zone());
BasicBlockVector* blocks = schedule->rpo_order();
size_t block_number = 0;
for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks;
#include "src/base/lazy-instance.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
+#include "src/v8.h"
+#include "src/zone-inl.h"
namespace v8 {
namespace internal {
LAZY_INSTANCE_INITIALIZER;
-MachineOperatorBuilder::MachineOperatorBuilder(MachineType word, Flags flags)
- : cache_(kCache.Get()), word_(word), flags_(flags) {
+MachineOperatorBuilder::MachineOperatorBuilder(Zone* zone, MachineType word,
+ Flags flags)
+ : zone_(zone), cache_(kCache.Get()), word_(word), flags_(flags) {
DCHECK(word == kRepWord32 || word == kRepWord64);
}
default:
break;
}
- UNREACHABLE();
- return NULL;
+ // Uncached.
+ return new (zone_) Operator1<LoadRepresentation>( // --
+ IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite, "Load", 2, 1, 1,
+ 1, 1, 0, rep);
}
default:
break;
}
- UNREACHABLE();
- return NULL;
+ // Uncached.
+ return new (zone_) Operator1<StoreRepresentation>( // --
+ IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow, "Store", 3, 1,
+ 1, 0, 1, 0, rep);
}
} // namespace compiler
} // namespace internal
};
typedef base::Flags<Flag, unsigned> Flags;
- explicit MachineOperatorBuilder(MachineType word = kMachPtr,
+ explicit MachineOperatorBuilder(Zone* zone, MachineType word = kMachPtr,
Flags supportedOperators = kNoFlags);
const Operator* Word32And();
#undef PSEUDO_OP_LIST
private:
+ Zone* zone_;
const MachineOperatorGlobalCache& cache_;
const MachineType word_;
const Flags flags_;
graph_(new (graph_zone()) Graph(graph_zone())),
source_positions_(new SourcePositionTable(graph())),
machine_(new (graph_zone()) MachineOperatorBuilder(
- kMachPtr, InstructionSelector::SupportedMachineOperatorFlags())),
+ graph_zone(), kMachPtr,
+ InstructionSelector::SupportedMachineOperatorFlags())),
common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())),
javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())),
jsgraph_(new (graph_zone())
MachineOperatorBuilder::Flags flags)
: GraphBuilder(graph),
schedule_(new (zone()) Schedule(zone())),
- machine_(word, flags),
+ machine_(zone(), word, flags),
common_(zone()),
machine_sig_(machine_sig),
call_descriptor_(
VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else if ((in & kTypeMask) == kTypeUint32 ||
- (in & kTypeMask) == kTypeInt32 ||
- in_upper->Is(Type::Unsigned32()) ||
+ in_upper->Is(Type::Unsigned32())) {
+ // Just change representation if necessary.
+ VisitUnop(node, kTypeUint32 | kRepWord32, kTypeInt32 | kRepWord32);
+ if (lower()) DeferReplacement(node, node->InputAt(0));
+ } else if ((in & kTypeMask) == kTypeInt32 ||
(in & kRepMask) == kRepWord32) {
// Just change representation if necessary.
VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32);
VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else if ((in & kTypeMask) == kTypeUint32 ||
- (in & kTypeMask) == kTypeInt32 ||
- in_upper->Is(Type::Signed32()) ||
- (in & kRepMask) == kRepWord32) {
+ in_upper->Is(Type::Unsigned32())) {
// Just change representation if necessary.
VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32);
if (lower()) DeferReplacement(node, node->InputAt(0));
+ } else if ((in & kTypeMask) == kTypeInt32 ||
+ (in & kRepMask) == kRepWord32) {
+ // Just change representation if necessary.
+ VisitUnop(node, kTypeInt32 | kRepWord32, kTypeUint32 | kRepWord32);
+ if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
// Require the input in float64 format and perform truncation.
// TODO(turbofan): avoid a truncation with a smi check.
lhs = Rangify(lhs, t);
rhs = Rangify(rhs, t);
if (lhs->IsRange() && rhs->IsRange()) {
- // TODO(titzer): fix me.
- // return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t);
+ return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t);
}
return Type::OrderedNumber();
}
explicit GraphAndBuilders(Zone* zone)
: main_graph_(new (zone) Graph(zone)),
main_common_(zone),
+ main_machine_(zone),
main_simplified_(zone) {}
protected:
info(static_cast<HydrogenCodeStub*>(NULL), main_isolate()),
linkage(zone(), &info),
common(zone()),
+ machine(zone()),
code(NULL) {}
~InstructionTester() { delete code; }
main_common_(zone),
main_javascript_(zone),
main_typer_(&main_graph_, MaybeHandle<Context>()),
- main_machine_() {}
+ main_machine_(zone) {}
Graph main_graph_;
CommonOperatorBuilder main_common_;
JSOperatorBuilder main_javascript_;
: DirectGraphBuilder(new (main_zone()) Graph(main_zone())),
common_(main_zone()),
javascript_(main_zone()),
- machine_(),
+ machine_(main_zone()),
simplified_(main_zone()),
jsgraph_(graph(), common(), &javascript_, &machine_),
info_(main_isolate(), main_zone()) {}
binop(NULL),
unop(NULL),
javascript(main_zone()),
+ machine(main_zone()),
simplified(main_zone()),
common(main_zone()),
graph(main_zone()),
: isolate(main_isolate()),
binop(NULL),
unop(NULL),
+ machine(main_zone()),
common(main_zone()),
graph(main_zone()),
javascript(main_zone()),
Schedule schedule(scope.main_zone());
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
- MachineOperatorBuilder machine;
+ // TODO(titzer): use test operators.
+ MachineOperatorBuilder machine(scope.main_zone());
Node* start = graph.NewNode(common.Start(0));
graph.SetStart(start);
// found in the LICENSE file.
#include "src/v8.h"
-#include "test/cctest/cctest.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/js-operator.h"
-#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
+#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/verifier.h"
+#include "test/cctest/cctest.h"
using namespace v8::internal;
using namespace v8::internal::compiler;
+Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, 0, 1,
+ 0, 0);
+
// TODO(titzer): pull RPO tests out to their own file.
static void CheckRPONumbers(BasicBlockVector* order, size_t expected,
bool loops_allowed) {
Graph graph(scope.main_zone());
CommonOperatorBuilder common_builder(scope.main_zone());
JSOperatorBuilder js_builder(scope.main_zone());
- MachineOperatorBuilder machine_builder;
const Operator* op;
Handle<HeapObject> object =
Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
USE(n20);
n20->ReplaceInput(0, n9);
- op = machine_builder.Int32Add();
+ op = &kIntAdd;
Node* n19 = graph.NewNode(op, nil, nil);
USE(n19);
op = common_builder.Phi(kMachAnyTagged, 2);
HandleAndZoneScope scope;
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
- MachineOperatorBuilder machine;
Node* start = graph.NewNode(common.Start(2));
graph.SetStart(start);
Node* p1 = graph.NewNode(common.Parameter(1), start);
Node* d1 = CreateDiamond(&graph, &common, p0);
Node* d2 = CreateDiamond(&graph, &common, p1);
- Node* add = graph.NewNode(machine.Int32Add(), d1, d2);
+ Node* add = graph.NewNode(&kIntAdd, d1, d2);
Node* ret = graph.NewNode(common.Return(), add, start, start);
Node* end = graph.NewNode(common.End(), ret, start);
HandleAndZoneScope scope;
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
- MachineOperatorBuilder machine;
Node* start = graph.NewNode(common.Start(2));
graph.SetStart(start);
Node* p1 = graph.NewNode(common.Parameter(1), start);
Node* d1 = CreateDiamond(&graph, &common, p0);
Node* d2 = CreateDiamond(&graph, &common, p1);
- Node* add = graph.NewNode(machine.Int32Add(), d1, d2);
+ Node* add = graph.NewNode(&kIntAdd, d1, d2);
Node* d3 = CreateDiamond(&graph, &common, add);
Node* ret = graph.NewNode(common.Return(), d3, start, start);
Node* end = graph.NewNode(common.End(), ret, start);
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
SimplifiedOperatorBuilder simplified(scope.main_zone());
- MachineOperatorBuilder machine;
Node* start = graph.NewNode(common.Start(2));
graph.SetStart(start);
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
SimplifiedOperatorBuilder simplified(scope.main_zone());
- MachineOperatorBuilder machine;
Node* start = graph.NewNode(common.Start(2));
graph.SetStart(start);
Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop);
// TODO(mstarzinger): Make scheduler deal with non-empty loops here.
- // Node* add = graph.NewNode(machine.IntAdd(), ind, fv);
+ // Node* add = graph.NewNode(&kIntAdd, ind, fv);
Node* br1 = graph.NewNode(common.Branch(), ind, loop);
Node* t1 = graph.NewNode(common.IfTrue(), br1);
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
SimplifiedOperatorBuilder simplified(scope.main_zone());
- MachineOperatorBuilder machine;
Node* start = graph.NewNode(common.Start(2));
graph.SetStart(start);
Node* c = graph.NewNode(common.Int32Constant(7));
Node* loop = graph.NewNode(common.Loop(2), start, start);
Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop);
- Node* add = graph.NewNode(machine.IntAdd(), ind, c);
+ Node* add = graph.NewNode(&kIntAdd, ind, c);
Node* br = graph.NewNode(common.Branch(), add, loop);
Node* t = graph.NewNode(common.IfTrue(), br);
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
SimplifiedOperatorBuilder simplified(scope.main_zone());
- MachineOperatorBuilder machine;
Node* start = graph.NewNode(common.Start(2));
graph.SetStart(start);
Node* m1 = graph.NewNode(common.Merge(2), t1, f1);
Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind, m1);
- Node* add = graph.NewNode(machine.IntAdd(), ind, phi1);
+ Node* add = graph.NewNode(&kIntAdd, ind, phi1);
Node* br = graph.NewNode(common.Branch(), add, loop);
Node* t = graph.NewNode(common.IfTrue(), br);
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
SimplifiedOperatorBuilder simplified(scope.main_zone());
- MachineOperatorBuilder machine;
Node* start = graph.NewNode(common.Start(2));
graph.SetStart(start);
}
}
+ Node* ExampleWithTypeAndRep(Type* type, MachineType mach_type) {
+ FieldAccess access = {kUntaggedBase, 0, Handle<Name>::null(), type,
+ mach_type};
+ // TODO(titzer): using loads here just to force the representation is ugly.
+ Node* node = graph()->NewNode(simplified()->LoadField(access),
+ jsgraph.IntPtrConstant(0), graph()->start(),
+ graph()->start());
+ NodeProperties::SetBounds(node, Bounds(type));
+ return node;
+ }
+
Node* Use(Node* node, MachineType type) {
if (type & kTypeInt32) {
return graph()->NewNode(machine()->Int32LessThan(), node,
} else if (type & kRepWord64) {
return graph()->NewNode(machine()->Int64LessThan(), node,
Int64Constant(1));
+ } else if (type & kRepWord32) {
+ return graph()->NewNode(machine()->Word32Equal(), node,
+ jsgraph.Int32Constant(1));
} else {
return graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), node,
jsgraph.TrueConstant());
TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) {
// NumberToInt32(x: kRepFloat64) used as kMachInt32
TestingGraph t(Type::Number());
- Node* p0 = t.ExampleWithOutput(kMachFloat64);
- // TODO(titzer): run the typer here, or attach machine type to param.
- NodeProperties::SetBounds(p0, Bounds(Type::Number()));
+ Node* p0 = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64);
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0);
Node* use = t.Use(trunc, kMachInt32);
t.Return(use);
}
-TEST(LowerNumberToInt32_to_ChangeFloat64ToTagged) {
- // TODO(titzer): NumberToInt32(x: kRepFloat64 | kTypeInt32) used as kRepTagged
-}
-
-
-TEST(LowerNumberToInt32_to_ChangeFloat64ToInt32) {
- // TODO(titzer): NumberToInt32(x: kRepFloat64 | kTypeInt32) used as kRepWord32
- // | kTypeInt32
-}
-
-
TEST(LowerNumberToUint32_to_nop) {
// NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepTagged
TestingGraph t(Type::Unsigned32());
}
-TEST(LowerNumberToUint32_to_ChangeFloat64ToTagged) {
- // TODO(titzer): NumberToUint32(x: kRepFloat64 | kTypeUint32) used as
- // kRepTagged
+TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) {
+ // NumberToUint32(x: kRepFloat64) used as kRepWord32
+ TestingGraph t(Type::Unsigned32());
+ Node* input = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64);
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input);
+ Node* use = t.Use(trunc, kRepWord32);
+ t.Return(use);
+ t.Lower();
+ CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0));
}
-TEST(LowerNumberToUint32_to_ChangeFloat64ToUint32) {
- // TODO(titzer): NumberToUint32(x: kRepFloat64 | kTypeUint32) used as
- // kRepWord32
+TEST(LowerNumberToUI32_of_Float64_used_as_word32) {
+ // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as
+ // kType(Int,Uint)32 | kRepWord32
+ Type* types[] = {Type::Signed32(), Type::Unsigned32()};
+ MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone};
+
+ for (int i = 0; i < 2; i++) {
+ for (int u = 0; u < 3; u++) {
+ TestingGraph t(types[i]);
+ Node* input = t.ExampleWithTypeAndRep(
+ types[i], static_cast<MachineType>(kRepFloat64 | mach[i]));
+ const Operator* op = i == 0 ? t.simplified()->NumberToInt32()
+ : t.simplified()->NumberToUint32();
+ Node* trunc = t.graph()->NewNode(op, input);
+ Node* use = t.Use(trunc, static_cast<MachineType>(kRepWord32 | mach[u]));
+ t.Return(use);
+ t.Lower();
+ IrOpcode::Value opcode = i == 0 ? IrOpcode::kChangeFloat64ToInt32
+ : IrOpcode::kChangeFloat64ToUint32;
+ CheckChangeOf(opcode, input, use->InputAt(0));
+ }
+ }
}
-TEST(LowerNumberToUint32_to_TruncateFloat64ToUint32) {
- // TODO(titzer): NumberToUint32(x: kRepFloat64) used as kRepWord32
+TEST(LowerNumberToUI32_of_Float64_used_as_tagged) {
+ // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as
+ // kType(Int,Uint)32 | kRepTagged
+ Type* types[] = {Type::Signed32(), Type::Unsigned32(), Type::Any()};
+ MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone};
+
+ for (int i = 0; i < 2; i++) {
+ for (int u = 0; u < 3; u++) {
+ TestingGraph t(types[i]);
+ Node* input = t.ExampleWithTypeAndRep(
+ types[i], static_cast<MachineType>(kRepFloat64 | mach[i]));
+ const Operator* op = i == 0 ? t.simplified()->NumberToInt32()
+ : t.simplified()->NumberToUint32();
+ Node* trunc = t.graph()->NewNode(op, input);
+ // TODO(titzer): we use the store here to force the representation.
+ FieldAccess access = {kTaggedBase, 0, Handle<Name>(), types[u],
+ static_cast<MachineType>(mach[u] | kRepTagged)};
+ Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
+ trunc, t.start, t.start);
+ t.Effect(store);
+ t.Lower();
+ CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, input, store->InputAt(2));
+ }
+ }
}
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function g1(i) {
+ var x = i * 1;
+ return (x >>> 0) % 1000000000000;
+}
+
+function g2(i) {
+ var x = i * 1;
+ return ((x >>> 0) % 1000000000000) | 0;
+}
+
+function test1() {
+ assertEquals(2294967296, g1(-2000000000));
+ assertEquals(2294967295, g1(-2000000001));
+ assertEquals(2294967290, g1(-2000000006));
+
+ assertEquals(2147483651, g1(-2147483645));
+ assertEquals(2147483650, g1(-2147483646));
+ assertEquals(2147483649, g1(-2147483647));
+ assertEquals(2147483648, g1(-2147483648));
+ assertEquals(2147483647, g1(-2147483649));
+
+ assertEquals(3000000000, g1(3000000000));
+ assertEquals(3000000001, g1(3000000001));
+ assertEquals(3000000002, g1(3000000002));
+
+ assertEquals(4000000000, g1(4000000000));
+ assertEquals(4000400001, g1(4000400001));
+ assertEquals(4000400002, g1(4000400002));
+
+ assertEquals(3, g1(4294967299));
+ assertEquals(2, g1(4294967298));
+ assertEquals(1, g1(4294967297));
+ assertEquals(0, g1(4294967296));
+ assertEquals(4294967295, g1(4294967295));
+ assertEquals(4294967294, g1(4294967294));
+ assertEquals(4294967293, g1(4294967293));
+ assertEquals(4294967292, g1(4294967292));
+}
+
+%NeverOptimizeFunction(test1);
+test1();
+
+function test2() {
+ assertEquals(-2000000000, g2(-2000000000));
+ assertEquals(-2000000001, g2(-2000000001));
+ assertEquals(-2000000006, g2(-2000000006));
+
+ assertEquals(-2147483645, g2(-2147483645));
+ assertEquals(-2147483646, g2(-2147483646));
+ assertEquals(-2147483647, g2(-2147483647));
+ assertEquals(-2147483648, g2(-2147483648));
+ assertEquals(2147483647, g2(-2147483649));
+
+ assertEquals(-1294967296, g2(3000000000));
+ assertEquals(-1294967295, g2(3000000001));
+ assertEquals(-1294967294, g2(3000000002));
+
+ assertEquals(-294967296, g2(4000000000));
+ assertEquals(-294567295, g2(4000400001));
+ assertEquals(-294567294, g2(4000400002));
+
+ assertEquals(3, g2(4294967299));
+ assertEquals(2, g2(4294967298));
+ assertEquals(1, g2(4294967297));
+ assertEquals(0, g2(4294967296));
+ assertEquals(-1, g2(4294967295));
+ assertEquals(-2, g2(4294967294));
+ assertEquals(-3, g2(4294967293));
+ assertEquals(-4, g2(4294967292));
+}
+
+%NeverOptimizeFunction(test2);
+test2();
}
Reduction Reduce(Node* node) {
- MachineOperatorBuilder machine(WordRepresentation());
+ MachineOperatorBuilder machine(zone(), WordRepresentation());
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(graph(), common(), &javascript, &machine);
CompilationInfo info(isolate(), zone());
protected:
Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::Flag::kNoFlags) {
- MachineOperatorBuilder machine(kMachPtr, flags);
+ MachineOperatorBuilder machine(zone(), kMachPtr, flags);
JSGraph jsgraph(graph(), common(), javascript(), &machine);
JSBuiltinReducer reducer(&jsgraph);
return reducer.Reduce(node);
protected:
Reduction Reduce(Node* node) {
- MachineOperatorBuilder machine;
+ MachineOperatorBuilder machine(zone());
JSGraph jsgraph(graph(), common(), javascript(), &machine);
JSTypedLowering reducer(&jsgraph);
return reducer.Reduce(node);
class MachineOperatorReducerTest : public TypedGraphTest {
public:
explicit MachineOperatorReducerTest(int num_parameters = 2)
- : TypedGraphTest(num_parameters) {}
+ : TypedGraphTest(num_parameters), machine_(zone()) {}
protected:
Reduction Reduce(Node* node) {
class NodeMatcherTest : public GraphTest {
public:
- NodeMatcherTest() {}
+ NodeMatcherTest() : machine_(zone()) {}
virtual ~NodeMatcherTest() {}
MachineOperatorBuilder* machine() { return &machine_; }
protected:
Reduction Reduce(Node* node) {
- MachineOperatorBuilder machine;
+ MachineOperatorBuilder machine(zone());
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(graph(), common(), &javascript, &machine);
SimplifiedOperatorReducer reducer(&jsgraph);