Index: src/compiler/simplified-lowering.cc |
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc |
index 5033c1919ec073acc57dda0b34a8c8b6f52169f4..3402607790e52ac593f8ca71f996fa13bd4681ff 100644 |
--- a/src/compiler/simplified-lowering.cc |
+++ b/src/compiler/simplified-lowering.cc |
@@ -56,6 +56,120 @@ enum Phase { |
}; |
+namespace { |
+ |
+// The {UseInfo} class is used to describe a use of an input of a node. |
+// |
+// This information is used in two different ways, based on the phase: |
+// |
+// 1. During propagation, the use info is used to inform the input node |
+// about what part of the input is used (we call this truncation) and what |
+// is the preferred representation. |
+// |
+// 2. During lowering, the use info is used to properly convert the input |
+// to the preferred representation. The preferred representation might be |
+// insufficient to do the conversion (e.g. word32->float64 conv), so we also |
+// need the signedness information to produce the correct value. |
+class UseInfo { |
+ public: |
+ // Constructors |
+ // ================================================================ |
+ |
+ // Uses truncating to the preferred representation. |
+ static UseInfo TruncatingWord32() { |
+ return UseInfo(kTypeInt32 | kTypeUint32 | kRepWord32); |
+ } |
+ static UseInfo TruncatingWord64() { |
+ return UseInfo(kTypeInt64 | kTypeUint64 | kRepWord64); |
+ } |
+ static UseInfo Bool() { return UseInfo(kMachBool); } |
+ static UseInfo Float32() { return UseInfo(kMachFloat32); } |
+ static UseInfo Float64() { return UseInfo(kMachFloat64); } |
+ static UseInfo PointerInt() { |
+ return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64(); |
+ } |
+ |
+ // Non-truncating uses. |
+ static UseInfo AnyTagged() { return UseInfo(kMachAnyTagged); } |
+ static UseInfo Any() { return UseInfo(kTypeAny); } |
+ |
+ // Ignored-value 'use'. |
+ static UseInfo None() { return UseInfo(kMachNone); } |
+ |
+ // Truncating to a representation that is smaller than the preferred |
+ // one. |
+ static UseInfo Float64TruncatingToWord32() { |
+ return UseInfo(kRepFloat64 | kTypeInt32 | kTypeUint32); |
+ } |
+ static UseInfo Word64TruncatingToWord32() { |
+ return UseInfo(kRepWord64 | kTypeInt32 | kTypeUint32); |
+ } |
+ static UseInfo AnyTruncatingToBool() { return UseInfo(kTypeBool); } |
+ |
+ UseInfo(MachineTypeUnion representation, MachineTypeUnion truncation) |
+ : type_(representation | truncation) { |
+ DCHECK(base::bits::CountPopulation32(representation & kRepMask) == 1); |
+ DCHECK((representation & kTypeMask) == 0); |
+ DCHECK((truncation & kRepMask) == 0); |
+ // TODO(jarin) Check/normalize truncation? |
+ } |
+ |
+ // Queries |
+ // ================================================================ |
+ MachineType GetRepresentation() const { |
+ return static_cast<MachineType>(type_ & kRepMask); |
+ } |
+ |
+ // This should only be used by the Enqueue method. |
+ MachineTypeUnion machine_type() const { return type_; } |
+ |
+ private: |
+ explicit UseInfo(MachineTypeUnion type) : type_(type) {} |
+ |
+ MachineTypeUnion type_; |
+}; |
+ |
+ |
+UseInfo UseInfoFromRepresentation(MachineTypeUnion rep) { |
+ DCHECK((rep & kTypeMask) == 0); |
+ if (rep & kRepTagged) return UseInfo::AnyTagged(); |
+ if (rep & kRepFloat64) { |
+ DCHECK((rep & kRepWord64) == 0); |
+ return UseInfo::Float64(); |
+ } |
+ if (rep & kRepFloat32) { |
+ if (rep == kRepFloat32) return UseInfo::Float32(); |
+ return UseInfo::AnyTagged(); |
+ } |
+ if (rep & kRepWord64) { |
+ return UseInfo::TruncatingWord64(); |
+ } |
+ if (rep & (kRepWord32 | kRepWord16 | kRepWord8)) { |
+ CHECK(!(rep & kRepBit)); |
+ return UseInfo::TruncatingWord32(); |
+ } |
+ DCHECK(rep & kRepBit); |
+ return UseInfo::Bool(); |
+} |
+ |
+ |
+UseInfo UseInfoFromMachineType(MachineType type) { |
+ return UseInfoFromRepresentation(RepresentationOf(type)); |
+} |
+ |
+ |
+UseInfo UseInfoForBasePointer(const FieldAccess& access) { |
+ return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); |
+} |
+ |
+ |
+UseInfo UseInfoForBasePointer(const ElementAccess& access) { |
+ return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); |
+} |
+ |
+} // namespace |
+ |
+ |
class RepresentationSelector { |
public: |
// Information for each node tracked during the fixpoint. |
@@ -131,7 +245,9 @@ class RepresentationSelector { |
// Enqueue {node} if the {use} contains new information for that node. |
// Add {node} to {nodes_} if this is the first time it's been visited. |
- void Enqueue(Node* node, MachineTypeUnion use = 0) { |
+ void Enqueue(Node* node, UseInfo use_info = UseInfo::None()) { |
+ MachineTypeUnion use = use_info.machine_type(); |
+ |
if (phase_ != PROPAGATE) return; |
NodeInfo* info = GetInfo(node); |
if (!info->visited) { |
@@ -163,10 +279,6 @@ class RepresentationSelector { |
bool lower() { return phase_ == LOWER; } |
- void Enqueue(Node* node, MachineType use) { |
- Enqueue(node, static_cast<MachineTypeUnion>(use)); |
- } |
- |
void SetOutput(Node* node, MachineTypeUnion output) { |
// Every node should have at most one output representation. Note that |
// phis can have 0, if they have not been used in a representation-inducing |
@@ -182,11 +294,11 @@ class RepresentationSelector { |
NodeProperties::GetType(node->InputAt(1))->Is(type); |
} |
- void ProcessTruncateWord32Input(Node* node, int index, MachineTypeUnion use) { |
+ void ProcessTruncateWord32Input(Node* node, int index) { |
Node* input = node->InputAt(index); |
if (phase_ == PROPAGATE) { |
// In the propagate phase, propagate the usage information backward. |
- Enqueue(input, use); |
+ Enqueue(input, UseInfo::TruncatingWord32()); |
} else { |
// In the change phase, insert a change before the use if necessary. |
MachineTypeUnion output = GetInfo(input)->output; |
@@ -197,8 +309,6 @@ class RepresentationSelector { |
input->op()->mnemonic()); |
TRACE(" from "); |
PrintInfo(output); |
- TRACE(" to "); |
- PrintInfo(use); |
TRACE("\n"); |
Node* n = changer_->GetTruncatedWord32For(input, output); |
node->ReplaceInput(index, n); |
@@ -206,28 +316,36 @@ class RepresentationSelector { |
} |
} |
- void ProcessInput(Node* node, int index, MachineTypeUnion use) { |
+ void EnqueueInputUse(Node* node, int index, UseInfo use) { |
+ Enqueue(node->InputAt(index), use); |
+ } |
+ |
+ void ConvertInput(Node* node, int index, UseInfo use) { |
Node* input = node->InputAt(index); |
+ // In the change phase, insert a change before the use if necessary. |
+ if (use.GetRepresentation() == kMachNone) |
+ return; // No input requirement on the use. |
+ MachineTypeUnion output = GetInfo(input)->output; |
+ if ((output & kRepMask) != use.GetRepresentation()) { |
+ // Output representation doesn't match usage. |
+ TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), |
+ index, input->id(), input->op()->mnemonic()); |
+ TRACE(" from "); |
+ PrintInfo(output); |
+ TRACE(" to "); |
+ PrintUseInfo(use); |
+ TRACE("\n"); |
+ Node* n = |
+ changer_->GetRepresentationFor(input, output, use.machine_type()); |
+ node->ReplaceInput(index, n); |
+ } |
+ } |
+ |
+ void ProcessInput(Node* node, int index, UseInfo use) { |
if (phase_ == PROPAGATE) { |
- // In the propagate phase, propagate the usage information backward. |
- Enqueue(input, use); |
+ EnqueueInputUse(node, index, use); |
} else { |
- // In the change phase, insert a change before the use if necessary. |
- if ((use & kRepMask) == 0) return; // No input requirement on the use. |
- MachineTypeUnion output = GetInfo(input)->output; |
- if ((output & kRepMask & use) == 0) { |
- // Output representation doesn't match usage. |
- TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), |
- node->op()->mnemonic(), index, input->id(), |
- input->op()->mnemonic()); |
- TRACE(" from "); |
- PrintInfo(output); |
- TRACE(" to "); |
- PrintInfo(use); |
- TRACE("\n"); |
- Node* n = changer_->GetRepresentationFor(input, output, use); |
- node->ReplaceInput(index, n); |
- } |
+ ConvertInput(node, index, use); |
} |
} |
@@ -253,7 +371,7 @@ class RepresentationSelector { |
OperatorProperties::GetContextInputCount(node->op()); |
// Visit value and context inputs as tagged. |
for (int i = 0; i < tagged_count; i++) { |
- ProcessInput(node, i, kMachAnyTagged); |
+ ProcessInput(node, i, UseInfo::AnyTagged()); |
} |
// Only enqueue other inputs (framestates, effects, control). |
for (int i = tagged_count; i < node->InputCount(); i++) { |
@@ -264,8 +382,8 @@ class RepresentationSelector { |
} |
// Helper for binops of the R x L -> O variety. |
- void VisitBinop(Node* node, MachineTypeUnion left_use, |
- MachineTypeUnion right_use, MachineTypeUnion output) { |
+ void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, |
+ MachineTypeUnion output) { |
DCHECK_EQ(2, node->op()->ValueInputCount()); |
ProcessInput(node, 0, left_use); |
ProcessInput(node, 1, right_use); |
@@ -276,14 +394,12 @@ class RepresentationSelector { |
} |
// Helper for binops of the I x I -> O variety. |
- void VisitBinop(Node* node, MachineTypeUnion input_use, |
- MachineTypeUnion output) { |
+ void VisitBinop(Node* node, UseInfo input_use, MachineTypeUnion output) { |
VisitBinop(node, input_use, input_use, output); |
} |
// Helper for unops of the I -> O variety. |
- void VisitUnop(Node* node, MachineTypeUnion input_use, |
- MachineTypeUnion output) { |
+ void VisitUnop(Node* node, UseInfo input_use, MachineTypeUnion output) { |
DCHECK_EQ(1, node->InputCount()); |
ProcessInput(node, 0, input_use); |
SetOutput(node, output); |
@@ -297,24 +413,38 @@ class RepresentationSelector { |
// Helpers for specific types of binops. |
void VisitFloat64Binop(Node* node) { |
- VisitBinop(node, kMachFloat64, kMachFloat64); |
+ VisitBinop(node, UseInfo::Float64(), kMachFloat64); |
+ } |
+ void VisitInt32Binop(Node* node) { |
+ VisitBinop(node, UseInfo::TruncatingWord32(), kMachInt32); |
} |
- void VisitInt32Binop(Node* node) { VisitBinop(node, kMachInt32, kMachInt32); } |
void VisitUint32Binop(Node* node) { |
- VisitBinop(node, kMachUint32, kMachUint32); |
+ VisitBinop(node, UseInfo::TruncatingWord32(), kMachUint32); |
+ } |
+ void VisitInt64Binop(Node* node) { |
+ VisitBinop(node, UseInfo::TruncatingWord64(), kMachInt64); |
} |
- void VisitInt64Binop(Node* node) { VisitBinop(node, kMachInt64, kMachInt64); } |
void VisitUint64Binop(Node* node) { |
- VisitBinop(node, kMachUint64, kMachUint64); |
+ VisitBinop(node, UseInfo::TruncatingWord64(), kMachUint64); |
+ } |
+ void VisitFloat64Cmp(Node* node) { |
+ VisitBinop(node, UseInfo::Float64(), kMachBool); |
+ } |
+ void VisitInt32Cmp(Node* node) { |
+ VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
+ } |
+ void VisitUint32Cmp(Node* node) { |
+ VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
+ } |
+ void VisitInt64Cmp(Node* node) { |
+ VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
+ } |
+ void VisitUint64Cmp(Node* node) { |
+ VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
} |
- void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); } |
- void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); } |
- void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); } |
- void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } |
- void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } |
// Infer representation for phi-like nodes. |
- MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { |
+ static MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { |
// Phis adapt to the output representation their uses demand. |
Type* upper = NodeProperties::GetType(node); |
if ((use & kRepMask) == kRepFloat32) { |
@@ -331,9 +461,8 @@ class RepresentationSelector { |
if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { |
// multiple uses, but we are within 32 bits range => pick kRepWord32. |
return kRepWord32; |
- } else if ((use & kTypeMask) == kTypeInt32 || |
- (use & kTypeMask) == kTypeUint32) { |
- // We only use 32 bits or we use the result consistently. |
+ } else if (!CanObserveNonWord32(use)) { |
+ // We only use 32 bits. |
return kRepWord32; |
} else { |
return kRepFloat64; |
@@ -353,7 +482,7 @@ class RepresentationSelector { |
// Helper for handling selects. |
void VisitSelect(Node* node, MachineTypeUnion use, |
SimplifiedLowering* lowering) { |
- ProcessInput(node, 0, kRepBit); |
+ ProcessInput(node, 0, UseInfo::Bool()); |
MachineType output = GetRepresentationForPhi(node, use); |
Type* upper = NodeProperties::GetType(node); |
@@ -369,17 +498,12 @@ class RepresentationSelector { |
NodeProperties::ChangeOp(node, |
lowering->common()->Select(type, p.hint())); |
} |
- |
- // Convert inputs to the output representation of this select. |
- ProcessInput(node, 1, output_type); |
- ProcessInput(node, 2, output_type); |
- } else { |
- // Propagate {use} of the select to value inputs. |
- MachineType use_type = |
- static_cast<MachineType>((use & kTypeMask) | output); |
- ProcessInput(node, 1, use_type); |
- ProcessInput(node, 2, use_type); |
} |
+ // Convert inputs to the output representation of this phi, pass the |
+ // use truncation along. |
+ UseInfo input_use(output, use & kTypeMask); |
+ ProcessInput(node, 1, input_use); |
+ ProcessInput(node, 2, input_use); |
} |
// Helper for handling phis. |
@@ -404,9 +528,9 @@ class RepresentationSelector { |
// Convert inputs to the output representation of this phi, pass the |
// use truncation along. |
- MachineType use_type = static_cast<MachineType>((use & kTypeMask) | output); |
+ UseInfo input_use(output, use & kTypeMask); |
for (int i = 0; i < node->InputCount(); i++) { |
- ProcessInput(node, i, i < values ? use_type : 0); |
+ ProcessInput(node, i, i < values ? input_use : UseInfo::None()); |
} |
} |
@@ -418,11 +542,11 @@ class RepresentationSelector { |
for (int i = 0; i < node->InputCount(); i++) { |
if (i == 0) { |
// The target of the call. |
- ProcessInput(node, i, 0); |
+ ProcessInput(node, i, UseInfo::None()); |
} else if ((i - 1) < params) { |
- ProcessInput(node, i, sig->GetParam(i - 1)); |
+ ProcessInput(node, i, UseInfoFromMachineType(sig->GetParam(i - 1))); |
} else { |
- ProcessInput(node, i, 0); |
+ ProcessInput(node, i, UseInfo::None()); |
} |
} |
@@ -436,7 +560,7 @@ class RepresentationSelector { |
void VisitStateValues(Node* node) { |
if (phase_ == PROPAGATE) { |
for (int i = 0; i < node->InputCount(); i++) { |
- Enqueue(node->InputAt(i), kTypeAny); |
+ Enqueue(node->InputAt(i), UseInfo::Any()); |
} |
} else { |
Zone* zone = jsgraph_->zone(); |
@@ -482,11 +606,11 @@ class RepresentationSelector { |
NodeProperties::GetType(node)->Is(Type::Unsigned32())); |
} |
- bool CanObserveNonWord32(MachineTypeUnion use) { |
+ static bool CanObserveNonWord32(MachineTypeUnion use) { |
return (use & kTypeMask & ~(kTypeInt32 | kTypeUint32)) != 0; |
} |
- bool CanObserveNaN(MachineTypeUnion use) { |
+ static bool CanObserveNaN(MachineTypeUnion use) { |
return (use & (kTypeNumber | kTypeAny)) != 0; |
} |
@@ -504,7 +628,7 @@ class RepresentationSelector { |
case IrOpcode::kParameter: { |
// TODO(titzer): use representation from linkage. |
Type* upper = NodeProperties::GetType(node); |
- ProcessInput(node, 0, 0); |
+ ProcessInput(node, 0, UseInfo::None()); |
SetOutput(node, kRepTagged | changer_->TypeFromUpperBound(upper)); |
return; |
} |
@@ -524,11 +648,11 @@ class RepresentationSelector { |
return VisitLeaf(node, kRepTagged); |
case IrOpcode::kBranch: |
- ProcessInput(node, 0, kRepBit); |
+ ProcessInput(node, 0, UseInfo::Bool()); |
Enqueue(NodeProperties::GetControlInput(node, 0)); |
break; |
case IrOpcode::kSwitch: |
- ProcessInput(node, 0, kRepWord32); |
+ ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
Enqueue(NodeProperties::GetControlInput(node, 0)); |
break; |
case IrOpcode::kSelect: |
@@ -569,7 +693,7 @@ class RepresentationSelector { |
} |
} else { |
// No input representation requirement; adapt during lowering. |
- ProcessInput(node, 0, kTypeBool); |
+ ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
SetOutput(node, kRepBit); |
} |
break; |
@@ -587,7 +711,7 @@ class RepresentationSelector { |
} |
} else { |
// No input representation requirement; adapt during lowering. |
- ProcessInput(node, 0, kTypeBool); |
+ ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
SetOutput(node, kMachInt32); |
} |
break; |
@@ -625,8 +749,8 @@ class RepresentationSelector { |
if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
} else if (CanLowerToWord32AdditiveBinop(node, use)) { |
// => signed Int32Add/Sub, truncating inputs |
- ProcessTruncateWord32Input(node, 0, kTypeInt32); |
- ProcessTruncateWord32Input(node, 1, kTypeInt32); |
+ ProcessTruncateWord32Input(node, 0); |
+ ProcessTruncateWord32Input(node, 1); |
SetOutput(node, kMachInt32); |
if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
} else { |
@@ -695,17 +819,20 @@ class RepresentationSelector { |
break; |
} |
case IrOpcode::kNumberShiftLeft: { |
- VisitBinop(node, kMachInt32, kMachUint32, kMachInt32); |
+ VisitBinop(node, UseInfo::TruncatingWord32(), |
+ UseInfo::TruncatingWord32(), kMachInt32); |
if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl()); |
break; |
} |
case IrOpcode::kNumberShiftRight: { |
- VisitBinop(node, kMachInt32, kMachUint32, kMachInt32); |
+ VisitBinop(node, UseInfo::TruncatingWord32(), |
+ UseInfo::TruncatingWord32(), kMachInt32); |
if (lower()) lowering->DoShift(node, lowering->machine()->Word32Sar()); |
break; |
} |
case IrOpcode::kNumberShiftRightLogical: { |
- VisitBinop(node, kMachUint32, kMachUint32, kMachUint32); |
+ VisitBinop(node, UseInfo::TruncatingWord32(), |
+ UseInfo::TruncatingWord32(), kMachUint32); |
if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shr()); |
break; |
} |
@@ -716,22 +843,24 @@ class RepresentationSelector { |
MachineTypeUnion in = GetInfo(input)->output; |
if (in_upper->Is(Type::Signed32())) { |
// If the input has type int32, pass through representation. |
- VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); |
+ VisitUnop(node, UseInfoFromRepresentation(use_rep), |
+ kTypeInt32 | use_rep); |
if (lower()) DeferReplacement(node, node->InputAt(0)); |
} else if ((in & kTypeMask) == kTypeUint32 || |
in_upper->Is(Type::Unsigned32())) { |
// Just change representation if necessary. |
- VisitUnop(node, kTypeUint32 | kRepWord32, kTypeInt32 | kRepWord32); |
+ VisitUnop(node, UseInfo::TruncatingWord32(), 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, UseInfo::TruncatingWord32(), kTypeInt32 | 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. |
- VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); |
+ VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
+ kTypeInt32 | kRepWord32); |
if (lower()) { |
NodeProperties::ChangeOp( |
node, lowering->machine()->TruncateFloat64ToInt32( |
@@ -747,22 +876,26 @@ class RepresentationSelector { |
MachineTypeUnion in = GetInfo(input)->output; |
if (in_upper->Is(Type::Unsigned32())) { |
// If the input has type uint32, pass through representation. |
- VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); |
+ VisitUnop(node, UseInfoFromRepresentation(use_rep), |
+ kTypeUint32 | use_rep); |
if (lower()) DeferReplacement(node, node->InputAt(0)); |
} else if ((in & kTypeMask) == kTypeInt32 || |
in_upper->Is(Type::Signed32())) { |
// Just change representation if necessary. |
- VisitUnop(node, kTypeInt32 | kRepWord32, kTypeUint32 | kRepWord32); |
+ VisitUnop(node, UseInfo::TruncatingWord32(), |
+ kTypeUint32 | kRepWord32); |
if (lower()) DeferReplacement(node, node->InputAt(0)); |
} else if ((in & kTypeMask) == kTypeUint32 || |
(in & kRepMask) == kRepWord32) { |
// Just change representation if necessary. |
- VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); |
+ VisitUnop(node, UseInfo::TruncatingWord32(), |
+ 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. |
- VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); |
+ VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
+ kTypeUint32 | kRepWord32); |
if (lower()) { |
NodeProperties::ChangeOp( |
node, lowering->machine()->TruncateFloat64ToInt32( |
@@ -772,7 +905,7 @@ class RepresentationSelector { |
break; |
} |
case IrOpcode::kNumberIsHoleNaN: { |
- VisitUnop(node, kMachFloat64, kMachBool); |
+ VisitUnop(node, UseInfo::Float64(), kMachBool); |
if (lower()) { |
// NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), |
// #HoleNaNLower32) |
@@ -787,7 +920,7 @@ class RepresentationSelector { |
break; |
} |
case IrOpcode::kPlainPrimitiveToNumber: { |
- VisitUnop(node, kMachAnyTagged, kTypeNumber | kRepTagged); |
+ VisitUnop(node, UseInfo::AnyTagged(), kTypeNumber | kRepTagged); |
if (lower()) { |
// PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context) |
Operator::Properties properties = node->op()->properties(); |
@@ -804,53 +937,53 @@ class RepresentationSelector { |
break; |
} |
case IrOpcode::kReferenceEqual: { |
- VisitBinop(node, kMachAnyTagged, kRepBit); |
+ VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
if (lower()) { |
NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
} |
break; |
} |
case IrOpcode::kStringEqual: { |
- VisitBinop(node, kMachAnyTagged, kRepBit); |
+ VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
if (lower()) lowering->DoStringEqual(node); |
break; |
} |
case IrOpcode::kStringLessThan: { |
- VisitBinop(node, kMachAnyTagged, kRepBit); |
+ VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
if (lower()) lowering->DoStringLessThan(node); |
break; |
} |
case IrOpcode::kStringLessThanOrEqual: { |
- VisitBinop(node, kMachAnyTagged, kRepBit); |
+ VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
if (lower()) lowering->DoStringLessThanOrEqual(node); |
break; |
} |
case IrOpcode::kAllocate: { |
- ProcessInput(node, 0, kMachAnyTagged); |
+ ProcessInput(node, 0, UseInfo::AnyTagged()); |
ProcessRemainingInputs(node, 1); |
SetOutput(node, kMachAnyTagged); |
break; |
} |
case IrOpcode::kLoadField: { |
FieldAccess access = FieldAccessOf(node->op()); |
- ProcessInput(node, 0, changer_->TypeForBasePointer(access)); |
+ ProcessInput(node, 0, UseInfoForBasePointer(access)); |
ProcessRemainingInputs(node, 1); |
SetOutput(node, access.machine_type); |
break; |
} |
case IrOpcode::kStoreField: { |
FieldAccess access = FieldAccessOf(node->op()); |
- ProcessInput(node, 0, changer_->TypeForBasePointer(access)); |
- ProcessInput(node, 1, access.machine_type); |
+ ProcessInput(node, 0, UseInfoForBasePointer(access)); |
+ ProcessInput(node, 1, UseInfoFromMachineType(access.machine_type)); |
ProcessRemainingInputs(node, 2); |
SetOutput(node, 0); |
break; |
} |
case IrOpcode::kLoadBuffer: { |
BufferAccess access = BufferAccessOf(node->op()); |
- ProcessInput(node, 0, kMachPtr); // buffer |
- ProcessInput(node, 1, kMachInt32); // offset |
- ProcessInput(node, 2, kMachInt32); // length |
+ ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
+ ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
+ ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
ProcessRemainingInputs(node, 3); |
// Tagged overrides everything if we have to do a typed array bounds |
// check, because we may need to return undefined then. |
@@ -874,10 +1007,11 @@ class RepresentationSelector { |
} |
case IrOpcode::kStoreBuffer: { |
BufferAccess access = BufferAccessOf(node->op()); |
- ProcessInput(node, 0, kMachPtr); // buffer |
- ProcessInput(node, 1, kMachInt32); // offset |
- ProcessInput(node, 2, kMachInt32); // length |
- ProcessInput(node, 3, access.machine_type()); // value |
+ ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
+ ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
+ ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
+ ProcessInput(node, 3, |
+ UseInfoFromMachineType(access.machine_type())); // value |
ProcessRemainingInputs(node, 4); |
SetOutput(node, 0); |
if (lower()) lowering->DoStoreBuffer(node); |
@@ -885,30 +1019,31 @@ class RepresentationSelector { |
} |
case IrOpcode::kLoadElement: { |
ElementAccess access = ElementAccessOf(node->op()); |
- ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base |
- ProcessInput(node, 1, kMachInt32); // index |
+ ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
+ ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
ProcessRemainingInputs(node, 2); |
SetOutput(node, access.machine_type); |
break; |
} |
case IrOpcode::kStoreElement: { |
ElementAccess access = ElementAccessOf(node->op()); |
- ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base |
- ProcessInput(node, 1, kMachInt32); // index |
- ProcessInput(node, 2, access.machine_type); // value |
+ ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
+ ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
+ ProcessInput(node, 2, |
+ UseInfoFromMachineType(access.machine_type)); // value |
ProcessRemainingInputs(node, 3); |
SetOutput(node, 0); |
break; |
} |
case IrOpcode::kObjectIsNumber: { |
- ProcessInput(node, 0, kMachAnyTagged); |
- SetOutput(node, kRepBit | kTypeBool); |
+ ProcessInput(node, 0, UseInfo::AnyTagged()); |
+ SetOutput(node, kMachBool); |
if (lower()) lowering->DoObjectIsNumber(node); |
break; |
} |
case IrOpcode::kObjectIsSmi: { |
- ProcessInput(node, 0, kMachAnyTagged); |
- SetOutput(node, kRepBit | kTypeBool); |
+ ProcessInput(node, 0, UseInfo::AnyTagged()); |
+ SetOutput(node, kMachBool); |
if (lower()) lowering->DoObjectIsSmi(node); |
break; |
} |
@@ -917,29 +1052,29 @@ class RepresentationSelector { |
// Machine-level operators. |
//------------------------------------------------------------------ |
case IrOpcode::kLoad: { |
- // TODO(titzer): machine loads/stores need to know BaseTaggedness!? |
- MachineTypeUnion tBase = kRepTagged | kMachPtr; |
+ // TODO(jarin) Eventually, we should get rid of all machine stores |
+ // from the high-level phases, then this becomes UNREACHABLE. |
LoadRepresentation rep = OpParameter<LoadRepresentation>(node); |
- ProcessInput(node, 0, tBase); // pointer or object |
- ProcessInput(node, 1, kMachIntPtr); // index |
+ ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
+ ProcessInput(node, 1, UseInfo::PointerInt()); // index |
ProcessRemainingInputs(node, 2); |
SetOutput(node, rep); |
break; |
} |
case IrOpcode::kStore: { |
- // TODO(titzer): machine loads/stores need to know BaseTaggedness!? |
- MachineTypeUnion tBase = kRepTagged | kMachPtr; |
+ // TODO(jarin) Eventually, we should get rid of all machine stores |
+ // from the high-level phases, then this becomes UNREACHABLE. |
StoreRepresentation rep = OpParameter<StoreRepresentation>(node); |
- ProcessInput(node, 0, tBase); // pointer or object |
- ProcessInput(node, 1, kMachIntPtr); // index |
- ProcessInput(node, 2, rep.machine_type()); |
+ ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
+ ProcessInput(node, 1, UseInfo::PointerInt()); // index |
+ ProcessInput(node, 2, UseInfoFromMachineType(rep.machine_type())); |
ProcessRemainingInputs(node, 3); |
SetOutput(node, 0); |
break; |
} |
case IrOpcode::kWord32Shr: |
// We output unsigned int32 for shift right because JavaScript. |
- return VisitBinop(node, kMachUint32, kMachUint32); |
+ return VisitBinop(node, UseInfo::TruncatingWord32(), kMachUint32); |
case IrOpcode::kWord32And: |
case IrOpcode::kWord32Or: |
case IrOpcode::kWord32Xor: |
@@ -948,12 +1083,13 @@ class RepresentationSelector { |
// We use signed int32 as the output type for these word32 operations, |
// though the machine bits are the same for either signed or unsigned, |
// because JavaScript considers the result from these operations signed. |
- return VisitBinop(node, kRepWord32, kRepWord32 | kTypeInt32); |
+ return VisitBinop(node, UseInfo::TruncatingWord32(), |
+ kRepWord32 | kTypeInt32); |
case IrOpcode::kWord32Equal: |
- return VisitBinop(node, kRepWord32, kRepBit); |
+ return VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
case IrOpcode::kWord32Clz: |
- return VisitUnop(node, kMachUint32, kMachUint32); |
+ return VisitUnop(node, UseInfo::TruncatingWord32(), kMachUint32); |
case IrOpcode::kInt32Add: |
case IrOpcode::kInt32Sub: |
@@ -997,41 +1133,38 @@ class RepresentationSelector { |
case IrOpcode::kWord64Shl: |
case IrOpcode::kWord64Shr: |
case IrOpcode::kWord64Sar: |
- return VisitBinop(node, kRepWord64, kRepWord64); |
+ return VisitBinop(node, UseInfo::TruncatingWord64(), kRepWord64); |
case IrOpcode::kWord64Equal: |
- return VisitBinop(node, kRepWord64, kRepBit); |
+ return VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
case IrOpcode::kChangeInt32ToInt64: |
- return VisitUnop(node, kTypeInt32 | kRepWord32, |
+ return VisitUnop(node, UseInfo::TruncatingWord32(), |
kTypeInt32 | kRepWord64); |
case IrOpcode::kChangeUint32ToUint64: |
- return VisitUnop(node, kTypeUint32 | kRepWord32, |
+ return VisitUnop(node, UseInfo::TruncatingWord32(), |
kTypeUint32 | kRepWord64); |
case IrOpcode::kTruncateFloat64ToFloat32: |
- return VisitUnop(node, kTypeNumber | kRepFloat64, |
- kTypeNumber | kRepFloat32); |
+ return VisitUnop(node, UseInfo::Float64(), kTypeNumber | kRepFloat32); |
case IrOpcode::kTruncateFloat64ToInt32: |
- return VisitUnop(node, kTypeNumber | kRepFloat64, |
- kTypeInt32 | kRepWord32); |
+ return VisitUnop(node, UseInfo::Float64(), kTypeInt32 | kRepWord32); |
case IrOpcode::kTruncateInt64ToInt32: |
// TODO(titzer): Is kTypeInt32 correct here? |
- return VisitUnop(node, kTypeInt32 | kRepWord64, |
+ return VisitUnop(node, UseInfo::Word64TruncatingToWord32(), |
kTypeInt32 | kRepWord32); |
case IrOpcode::kChangeFloat32ToFloat64: |
- return VisitUnop(node, kTypeNumber | kRepFloat32, |
- kTypeNumber | kRepFloat64); |
+ return VisitUnop(node, UseInfo::Float32(), kTypeNumber | kRepFloat64); |
case IrOpcode::kChangeInt32ToFloat64: |
- return VisitUnop(node, kTypeInt32 | kRepWord32, |
+ return VisitUnop(node, UseInfo::TruncatingWord32(), |
kTypeInt32 | kRepFloat64); |
case IrOpcode::kChangeUint32ToFloat64: |
- return VisitUnop(node, kTypeUint32 | kRepWord32, |
+ return VisitUnop(node, UseInfo::TruncatingWord32(), |
kTypeUint32 | kRepFloat64); |
case IrOpcode::kChangeFloat64ToInt32: |
- return VisitUnop(node, kTypeInt32 | kRepFloat64, |
+ return VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
kTypeInt32 | kRepWord32); |
case IrOpcode::kChangeFloat64ToUint32: |
- return VisitUnop(node, kTypeUint32 | kRepFloat64, |
+ return VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
kTypeUint32 | kRepWord32); |
case IrOpcode::kFloat64Add: |
@@ -1046,17 +1179,18 @@ class RepresentationSelector { |
case IrOpcode::kFloat64RoundDown: |
case IrOpcode::kFloat64RoundTruncate: |
case IrOpcode::kFloat64RoundTiesAway: |
- return VisitUnop(node, kMachFloat64, kMachFloat64); |
+ return VisitUnop(node, UseInfo::Float64(), kMachFloat64); |
case IrOpcode::kFloat64Equal: |
case IrOpcode::kFloat64LessThan: |
case IrOpcode::kFloat64LessThanOrEqual: |
return VisitFloat64Cmp(node); |
case IrOpcode::kFloat64ExtractLowWord32: |
case IrOpcode::kFloat64ExtractHighWord32: |
- return VisitUnop(node, kMachFloat64, kMachInt32); |
+ return VisitUnop(node, UseInfo::Float64(), kMachInt32); |
case IrOpcode::kFloat64InsertLowWord32: |
case IrOpcode::kFloat64InsertHighWord32: |
- return VisitBinop(node, kMachFloat64, kMachInt32, kMachFloat64); |
+ return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(), |
+ kMachFloat64); |
case IrOpcode::kLoadStackPointer: |
case IrOpcode::kLoadFramePointer: |
return VisitLeaf(node, kMachPtr); |
@@ -1103,6 +1237,13 @@ class RepresentationSelector { |
} |
} |
+ void PrintUseInfo(UseInfo info) { |
+ if (FLAG_trace_representation) { |
+ OFStream os(stdout); |
+ os << static_cast<MachineType>(info.machine_type()); |
+ } |
+ } |
+ |
private: |
JSGraph* jsgraph_; |
size_t const count_; // number of nodes in the graph |