Bug 1486857 - Don't box result of IonCompareIC; r=mgaudet
authorJohannes Schulte <j_schulte@outlook.com>
Wed, 19 Sep 2018 18:55:25 +0200
changeset 495053 63b06faf2f9e34510dd5661bb9ac20211d56ceac
parent 495052 61875633b2c215ccba313122257c6521ddb65617
child 495054 d58d7c5153c3d08a2364c3af6699b0d15188e054
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1486857
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1486857 - Don't box result of IonCompareIC; r=mgaudet
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/IonCacheIRCompiler.cpp
js/src/jit/IonIC.cpp
js/src/jit/IonIC.h
js/src/jit/Lowering.cpp
js/src/jit/MIR.h
js/src/jit/shared/LIR-shared.h
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -3398,21 +3398,21 @@ CacheIRCompiler::emitComparePointerResul
                             : allocator.useRegister(masm, reader.objOperandId());
     JSOp op = reader.jsop();
 
     AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
     Label ifTrue, done;
     masm.branchPtr(JSOpToCondition(op, /* signed = */true), left, right, &ifTrue);
 
-    masm.moveValue(BooleanValue(false), output.valueReg());
+    EmitStoreBoolean(masm, false, output);
     masm.jump(&done);
 
     masm.bind(&ifTrue);
-    masm.moveValue(BooleanValue(true), output.valueReg());
+    EmitStoreBoolean(masm, true, output);
     masm.bind(&done);
     return true;
 }
 
 
 bool
 CacheIRCompiler::emitCompareObjectResult()
 {
@@ -3431,21 +3431,21 @@ CacheIRCompiler::emitCompareInt32Result(
     AutoOutputRegister output(*this);
     Register left = allocator.useRegister(masm, reader.int32OperandId());
     Register right = allocator.useRegister(masm, reader.int32OperandId());
     JSOp op = reader.jsop();
 
     Label ifTrue, done;
     masm.branch32(JSOpToCondition(op, /* signed = */true), left, right, &ifTrue);
 
-    masm.moveValue(BooleanValue(false), output.valueReg());
+    EmitStoreBoolean(masm, false, output);
     masm.jump(&done);
 
     masm.bind(&ifTrue);
-    masm.moveValue(BooleanValue(true), output.valueReg());
+    EmitStoreBoolean(masm, true, output);
     masm.bind(&done);
     return true;
 }
 
 bool
 CacheIRCompiler::emitCompareDoubleResult()
 {
     AutoOutputRegister output(*this);
@@ -3456,21 +3456,21 @@ CacheIRCompiler::emitCompareDoubleResult
     }
 
     allocator.ensureDoubleRegister(masm, reader.valOperandId(), FloatReg0);
     allocator.ensureDoubleRegister(masm, reader.valOperandId(), FloatReg1);
     JSOp op = reader.jsop();
 
     Label done, ifTrue;
     masm.branchDouble(JSOpToDoubleCondition(op), FloatReg0, FloatReg1, &ifTrue);
-    masm.moveValue(BooleanValue(false), output.valueReg());
+    EmitStoreBoolean(masm, false, output);
     masm.jump(&done);
 
     masm.bind(&ifTrue);
-    masm.moveValue(BooleanValue(true), output.valueReg());
+    EmitStoreBoolean(masm, true, output);
     masm.bind(&done);
     return true;
 }
 
 bool
 CacheIRCompiler::emitCompareObjectUndefinedNullResult()
 {
     AutoOutputRegister output(*this);
@@ -3480,26 +3480,26 @@ CacheIRCompiler::emitCompareObjectUndefi
 
     FailurePath* failure;
     if (!addFailurePath(&failure)) {
         return false;
     }
 
     if (op == JSOP_STRICTEQ || op == JSOP_STRICTNE) {
         // obj !== undefined/null for all objects.
-        masm.moveValue(BooleanValue(op == JSOP_STRICTNE), output.valueReg());
+        EmitStoreBoolean(masm, op == JSOP_STRICTNE, output);
     } else {
         MOZ_ASSERT(op == JSOP_EQ || op == JSOP_NE);
         AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
         Label done, emulatesUndefined;
         masm.branchIfObjectEmulatesUndefined(obj, scratch, failure->label(), &emulatesUndefined);
-        masm.moveValue(BooleanValue(op == JSOP_NE), output.valueReg());
+        EmitStoreBoolean(masm, op == JSOP_NE, output);
         masm.jump(&done);
         masm.bind(&emulatesUndefined);
-        masm.moveValue(BooleanValue(op == JSOP_EQ), output.valueReg());
+        EmitStoreBoolean(masm, op == JSOP_EQ, output);
         masm.bind(&done);
     }
     return true;
 }
 
 bool
 CacheIRCompiler::emitCallPrintString()
 {
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -189,18 +189,22 @@ typedef bool (*IonUnaryArithICFn)(JSCont
 static const VMFunction IonUnaryArithICInfo =
     FunctionInfo<IonUnaryArithICFn>(IonUnaryArithIC::update, "IonUnaryArithIC::update");
 
 typedef bool (*IonBinaryArithICFn)(JSContext* cx, HandleScript outerScript, IonBinaryArithIC* stub,
                                     HandleValue lhs, HandleValue rhs, MutableHandleValue res);
 static const VMFunction IonBinaryArithICInfo =
     FunctionInfo<IonBinaryArithICFn>(IonBinaryArithIC::update, "IonBinaryArithIC::update");
 
-typedef bool (*IonCompareICFn)(JSContext* cx, HandleScript outerScript, IonCompareIC* stub,
-                                    HandleValue lhs, HandleValue rhs, MutableHandleValue res);
+typedef bool (*IonCompareICFn)(JSContext* cx,
+                               HandleScript outerScript,
+                               IonCompareIC* stub,
+                               HandleValue lhs,
+                               HandleValue rhs,
+                               bool* res);
 static const VMFunction IonCompareICInfo =
     FunctionInfo<IonCompareICFn>(IonCompareIC::update, "IonCompareIC::update");
 
 void
 CodeGenerator::visitOutOfLineICFallback(OutOfLineICFallback* ool)
 {
     LInstruction* lir = ool->lir();
     size_t cacheIndex = ool->cacheIndex();
@@ -414,18 +418,18 @@ CodeGenerator::visitOutOfLineICFallback(
         saveLive(lir);
 
         pushArg(compareIC->rhs());
         pushArg(compareIC->lhs());
         icInfo_[cacheInfoIndex].icOffsetForPush = pushArgWithPatch(ImmWord(-1));
         pushArg(ImmGCPtr(gen->info().script()));
         callVM(IonCompareICInfo, lir);
 
-        StoreValueTo(compareIC->output()).generate(this);
-        restoreLiveIgnore(lir, StoreValueTo(compareIC->output()).clobbered());
+        StoreRegisterTo(compareIC->output()).generate(this);
+        restoreLiveIgnore(lir, StoreRegisterTo(compareIC->output()).clobbered());
 
         masm.jump(ool->rejoin());
         return;
       }
       case CacheKind::Call:
       case CacheKind::TypeOf:
       case CacheKind::ToBool:
       case CacheKind::GetIntrinsic:
@@ -2925,50 +2929,66 @@ CodeGenerator::visitStringReplace(LStrin
     if (lir->mir()->isFlatReplacement()) {
         callVM(StringFlatReplaceInfo, lir);
     } else {
         callVM(StringReplaceInfo, lir);
     }
 }
 
 void
-CodeGenerator::visitBinaryCache(LBinaryCache* lir)
+CodeGenerator::visitBinaryValueCache(LBinaryValueCache* lir)
 {
     LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
-    TypedOrValueRegister lhs = TypedOrValueRegister(ToValue(lir, LBinaryCache::LhsInput));
-    TypedOrValueRegister rhs = TypedOrValueRegister(ToValue(lir, LBinaryCache::RhsInput));
+    TypedOrValueRegister lhs = TypedOrValueRegister(ToValue(lir, LBinaryValueCache::LhsInput));
+    TypedOrValueRegister rhs = TypedOrValueRegister(ToValue(lir, LBinaryValueCache::RhsInput));
     ValueOperand output = ToOutValue(lir);
 
     JSOp jsop = JSOp(*lir->mirRaw()->toInstruction()->resumePoint()->pc());
 
     switch (jsop) {
       case JSOP_ADD:
       case JSOP_SUB:
       case JSOP_MUL:
       case JSOP_DIV:
       case JSOP_MOD:
       case JSOP_POW: {
         IonBinaryArithIC ic(liveRegs, lhs, rhs, output);
         addIC(lir, allocateIC(ic));
         return;
       }
+      default:
+        MOZ_CRASH("Unsupported jsop in MBinaryValueCache");
+    }
+}
+
+void
+CodeGenerator::visitBinaryBoolCache(LBinaryBoolCache* lir)
+{
+    LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
+    TypedOrValueRegister lhs = TypedOrValueRegister(ToValue(lir, LBinaryBoolCache::LhsInput));
+    TypedOrValueRegister rhs = TypedOrValueRegister(ToValue(lir, LBinaryBoolCache::RhsInput));
+    Register output = ToRegister(lir->output());
+
+    JSOp jsop = JSOp(*lir->mirRaw()->toInstruction()->resumePoint()->pc());
+
+    switch (jsop) {
       case JSOP_LT:
       case JSOP_LE:
       case JSOP_GT:
       case JSOP_GE:
       case JSOP_EQ:
       case JSOP_NE:
       case JSOP_STRICTEQ:
       case JSOP_STRICTNE: {
         IonCompareIC ic(liveRegs, lhs, rhs, output);
         addIC(lir, allocateIC(ic));
         return;
       }
       default:
-        MOZ_CRASH("Unsupported jsop in MBinaryCache");
+        MOZ_CRASH("Unsupported jsop in MBinaryBoolCache");
     }
 }
 
 void
 CodeGenerator::visitUnaryCache(LUnaryCache* lir)
 {
     LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
     TypedOrValueRegister input = TypedOrValueRegister(ToValue(lir, LUnaryCache::Input));
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -3710,17 +3710,17 @@ IonBuilder::arithTryBinaryStub(bool* emi
         MOZ_ASSERT_IF(op != JSOP_MUL, !left);
         stub = MUnaryCache::New(alloc(), right);
         break;
       case JSOP_ADD:
       case JSOP_SUB:
       case JSOP_MUL:
       case JSOP_DIV:
       case JSOP_MOD:
-        stub = MBinaryCache::New(alloc(), left, right);
+        stub = MBinaryCache::New(alloc(), left, right, MIRType::Value);
         break;
       default:
         MOZ_CRASH("unsupported arith");
     }
 
     current->add(stub);
     current->push(stub);
 
@@ -6465,25 +6465,21 @@ IonBuilder::compareTryBinaryStub(bool* e
     if (JitOptions.disableCacheIR) {
         return Ok();
     }
 
     if (JSOp(*pc) == JSOP_CASE || IsCallPC(pc)) {
         return Ok();
     }
 
-    MBinaryCache* stub = MBinaryCache::New(alloc(), left, right);
+    MBinaryCache* stub = MBinaryCache::New(alloc(), left, right, MIRType::Boolean);
     current->add(stub);
     current->push(stub);
     MOZ_TRY(resumeAfter(stub));
 
-    MUnbox* unbox = MUnbox::New(alloc(), current->pop(), MIRType::Boolean, MUnbox::Infallible);
-    current->add(unbox);
-    current->push(unbox);
-
     trackOptimizationSuccess();
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newArrayTryTemplateObject(bool* emitted, JSObject* templateObject, uint32_t length)
 {
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -541,22 +541,22 @@ IonCacheIRCompiler::init()
 
         MOZ_ASSERT(numInputs == 2);
         allocator.initInputLocation(0, ic->lhs());
         allocator.initInputLocation(1, ic->rhs());
         break;
       }
       case CacheKind::Compare: {
         IonCompareIC *ic = ic_->asCompareIC();
-        ValueOperand output = ic->output();
+        Register output = ic->output();
 
         available.add(output);
 
         liveRegs_.emplace(ic->liveRegs());
-        outputUnchecked_.emplace(TypedOrValueRegister(output));
+        outputUnchecked_.emplace(TypedOrValueRegister(MIRType::Boolean, AnyRegister(output)));
 
         MOZ_ASSERT(numInputs == 2);
         allocator.initInputLocation(0, ic->lhs());
         allocator.initInputLocation(1, ic->rhs());
         break;
       }
       case CacheKind::Call:
       case CacheKind::TypeOf:
@@ -1336,41 +1336,38 @@ IonCacheIRCompiler::emitCompareStringRes
 {
     AutoSaveLiveRegisters save(*this);
     AutoOutputRegister output(*this);
 
     Register left = allocator.useRegister(masm, reader.stringOperandId());
     Register right = allocator.useRegister(masm, reader.stringOperandId());
     JSOp op = reader.jsop();
 
-    AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
-
     allocator.discardStack(masm);
 
     Label slow, done;
-    masm.compareStrings(op, left, right, scratch, &slow);
+    MOZ_ASSERT(!output.hasValue());
+    masm.compareStrings(op, left, right, output.typedReg().gpr(), &slow);
 
     masm.jump(&done);
     masm.bind(&slow);
 
     prepareVMCall(masm, save);
     masm.Push(right);
     masm.Push(left);
 
     if (!callVM(masm, (op == JSOP_EQ || op == JSOP_STRICTEQ) ?
                             StringsEqualInfo :
                             StringsNotEqualInfo))
     {
         return false;
     }
 
-    masm.storeCallBoolResult(scratch);
+    masm.storeCallBoolResult(output.typedReg().gpr());
     masm.bind(&done);
-
-    masm.tagValue(JSVAL_TYPE_BOOLEAN, scratch, output.valueReg());
     return true;
 }
 
 static bool
 GroupHasPropertyTypes(ObjectGroup* group, jsid* id, Value* v)
 {
     AutoUnsafeCallWithABI unsafe;
     if (group->unknownPropertiesDontCheckGeneration()) {
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -57,17 +57,17 @@ IonIC::scratchRegisterForEntryJump()
         return asGetIteratorIC()->temp1();
       case CacheKind::InstanceOf:
         return asInstanceOfIC()->output();
       case CacheKind::UnaryArith:
         return asUnaryArithIC()->output().scratchReg();
       case CacheKind::BinaryArith:
         return asBinaryArithIC()->output().scratchReg();
       case CacheKind::Compare:
-        return asCompareIC()->output().scratchReg();
+        return asCompareIC()->output();
       case CacheKind::Call:
       case CacheKind::TypeOf:
       case CacheKind::ToBool:
       case CacheKind::GetIntrinsic:
       case CacheKind::NewObject:
         MOZ_CRASH("Unsupported IC");
     }
 
@@ -684,18 +684,22 @@ IonBinaryArithIC::update(JSContext* cx, 
                 ic->state().trackNotAttached();
             }
         }
     }
     return true;
 }
 
 /* static */ bool
-IonCompareIC::update(JSContext* cx, HandleScript outerScript, IonCompareIC* ic,
-                                    HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+IonCompareIC::update(JSContext* cx,
+                     HandleScript outerScript,
+                     IonCompareIC* ic,
+                     HandleValue lhs,
+                     HandleValue rhs,
+                     bool* res)
 {
     IonScript* ionScript = outerScript->ionScript();
     RootedScript script(cx, ic->script());
     jsbytecode* pc = ic->pc();
     JSOp op = JSOp(*pc);
 
     // Case operations in a CONDSWITCH are performing strict equality.
     if (op == JSOP_CASE) {
@@ -703,65 +707,62 @@ IonCompareIC::update(JSContext* cx, Hand
     }
 
     // Don't pass lhs/rhs directly, we need the original values when
     // generating stubs.
     RootedValue lhsCopy(cx, lhs);
     RootedValue rhsCopy(cx, rhs);
 
     // Perform the compare operation.
-    bool out;
     switch (op) {
       case JSOP_LT:
-        if (!LessThan(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!LessThan(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       case JSOP_LE:
-        if (!LessThanOrEqual(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!LessThanOrEqual(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       case JSOP_GT:
-        if (!GreaterThan(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!GreaterThan(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       case JSOP_GE:
-        if (!GreaterThanOrEqual(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!GreaterThanOrEqual(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       case JSOP_EQ:
-        if (!LooselyEqual<true>(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!LooselyEqual<true>(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       case JSOP_NE:
-        if (!LooselyEqual<false>(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!LooselyEqual<false>(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       case JSOP_STRICTEQ:
-        if (!StrictlyEqual<true>(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!StrictlyEqual<true>(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       case JSOP_STRICTNE:
-        if (!StrictlyEqual<false>(cx, &lhsCopy, &rhsCopy, &out)) {
+        if (!StrictlyEqual<false>(cx, &lhsCopy, &rhsCopy, res)) {
             return false;
         }
         break;
       default:
         MOZ_ASSERT_UNREACHABLE("Unhandled ion compare op");
         return false;
     }
 
-    res.setBoolean(out);
-
     if (ic->state().maybeTransition()) {
         ic->discardStubs(cx->zone());
     }
 
     if (ic->state().canAttachStub()) {
         bool attached = false;
         CompareIRGenerator gen(cx, script, pc, ic->state().mode(),
                                op, lhs, rhs);
--- a/js/src/jit/IonIC.h
+++ b/js/src/jit/IonIC.h
@@ -491,35 +491,41 @@ class IonInstanceOfIC : public IonIC
 };
 
 class IonCompareIC : public IonIC
 {
     LiveRegisterSet liveRegs_;
 
     TypedOrValueRegister lhs_;
     TypedOrValueRegister rhs_;
-    ValueOperand output_;
+    Register output_;
 
-    public:
-
-    IonCompareIC(LiveRegisterSet liveRegs, TypedOrValueRegister lhs, TypedOrValueRegister rhs,  ValueOperand output)
+  public:
+    IonCompareIC(LiveRegisterSet liveRegs,
+                 TypedOrValueRegister lhs,
+                 TypedOrValueRegister rhs,
+                 Register output)
       : IonIC(CacheKind::Compare),
         liveRegs_(liveRegs),
         lhs_(lhs),
         rhs_(rhs),
         output_(output)
     { }
 
     LiveRegisterSet liveRegs() const { return liveRegs_; }
     TypedOrValueRegister lhs() const { return lhs_; }
     TypedOrValueRegister rhs() const { return rhs_; }
-    ValueOperand output() const { return output_; }
+    Register output() const { return output_; }
 
-    static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonCompareIC* stub,
-                                    HandleValue lhs, HandleValue rhs, MutableHandleValue res);
+    static MOZ_MUST_USE bool update(JSContext* cx,
+                                    HandleScript outerScript,
+                                    IonCompareIC* stub,
+                                    HandleValue lhs,
+                                    HandleValue rhs,
+                                    bool* res);
 };
 
 class IonUnaryArithIC : public IonIC
 {
     LiveRegisterSet liveRegs_;
 
     TypedOrValueRegister input_;
     ValueOperand output_;
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2549,24 +2549,34 @@ LIRGenerator::visitStringReplace(MString
 }
 
 void
 LIRGenerator::visitBinaryCache(MBinaryCache* ins)
 {
     MDefinition* lhs = ins->getOperand(0);
     MDefinition* rhs = ins->getOperand(1);
 
-    MOZ_ASSERT(ins->type() == MIRType::Value);
-    MOZ_ASSERT(ins->type() == MIRType::Value);
-
-    LBinaryCache* lir = new(alloc()) LBinaryCache(useBox(lhs),
-                                                  useBox(rhs),
-                                                  tempFixed(FloatReg0),
-                                                  tempFixed(FloatReg1));
-    defineBox(lir, ins);
+    MOZ_ASSERT(ins->type() == MIRType::Value || ins->type() == MIRType::Boolean);
+    LInstruction* lir;
+    if (ins->type() == MIRType::Value) {
+        LBinaryValueCache* valueLir = new (alloc()) LBinaryValueCache(useBox(lhs),
+                                                                      useBox(rhs),
+                                                                      tempFixed(FloatReg0),
+                                                                      tempFixed(FloatReg1));
+        defineBox(valueLir, ins);
+        lir = valueLir;
+    } else {
+        MOZ_ASSERT(ins->type() == MIRType::Boolean);
+        LBinaryBoolCache* boolLir = new (alloc()) LBinaryBoolCache(useBox(lhs),
+                                                                   useBox(rhs),
+                                                                   tempFixed(FloatReg0),
+                                                                   tempFixed(FloatReg1));
+        define(boolLir, ins);
+        lir = boolLir;
+    }
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitUnaryCache(MUnaryCache* ins)
 {
     MDefinition* input = ins->getOperand(0);
     MOZ_ASSERT(ins->type() == MIRType::Value);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7193,20 +7193,20 @@ class MOsrReturnValue
     }
 };
 
 class MBinaryCache
   : public MBinaryInstruction,
     public MixPolicy<BoxPolicy<0>, BoxPolicy<1> >::Data
 {
   protected:
-    explicit MBinaryCache(MDefinition* left, MDefinition* right)
+    explicit MBinaryCache(MDefinition* left, MDefinition* right, MIRType resType)
       : MBinaryInstruction(classOpcode, left, right)
     {
-        setResultType(MIRType::Value);
+        setResultType(resType);
     }
 
   public:
     INSTRUCTION_HEADER(BinaryCache)
     TRIVIAL_NEW_WRAPPERS
 };
 
 class MUnaryCache
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -4794,26 +4794,54 @@ class LStringReplace: public LCallInstru
     const LAllocation* pattern() {
         return getOperand(1);
     }
     const LAllocation* replacement() {
         return getOperand(2);
     }
 };
 
-class LBinaryCache : public LInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 2>
-{
-  public:
-    LIR_HEADER(BinaryCache)
+class LBinaryValueCache : public LInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 2>
+{
+  public:
+    LIR_HEADER(BinaryValueCache)
 
     // Takes two temps: these are intendend to be FloatReg0 and FloatReg1
     // To allow the actual cache code to safely clobber those values without
     // save and restore.
-    LBinaryCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs,
-                 const LDefinition& temp0, const LDefinition& temp1)
+    LBinaryValueCache(const LBoxAllocation& lhs,
+                      const LBoxAllocation& rhs,
+                      const LDefinition& temp0,
+                      const LDefinition& temp1)
+      : LInstructionHelper(classOpcode)
+    {
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
+        setTemp(0, temp0);
+        setTemp(1, temp1);
+    }
+
+    const MBinaryCache* mir() const { return mir_->toBinaryCache(); }
+
+    static const size_t LhsInput = 0;
+    static const size_t RhsInput = BOX_PIECES;
+};
+
+class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES, 2>
+{
+  public:
+    LIR_HEADER(BinaryBoolCache)
+
+    // Takes two temps: these are intendend to be FloatReg0 and FloatReg1
+    // To allow the actual cache code to safely clobber those values without
+    // save and restore.
+    LBinaryBoolCache(const LBoxAllocation& lhs,
+                     const LBoxAllocation& rhs,
+                     const LDefinition& temp0,
+                     const LDefinition& temp1)
       : LInstructionHelper(classOpcode)
     {
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }