From bb815f3ba96b2833fbc7dd8177db33b8f712334d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 Jul 2009 14:53:56 +1000 Subject: [PATCH] Bug 501232: remove LIR_2. r=edwsmith. --- js/src/nanojit/LIR.cpp | 85 ++++++++++++++++++++++++++++------ js/src/nanojit/LIR.h | 59 +++++++++++++++++++++-- js/src/nanojit/LIRopcode.tbl | 7 +-- js/src/nanojit/NativeARM.cpp | 10 ++-- js/src/nanojit/NativeSparc.cpp | 10 ++-- js/src/nanojit/Nativei386.cpp | 10 ++-- 6 files changed, 138 insertions(+), 43 deletions(-) diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index 176179921df..a3877d8dd8e 100644 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -282,6 +282,14 @@ namespace nanojit return ins; } + LInsp LirBufWriter::ins3(LOpcode op, LInsp o1, LInsp o2, LInsp o3) + { + LInsOp3* insOp3 = (LInsOp3*)_buf->makeRoom(sizeof(LInsOp3)); + LIns* ins = insOp3->getLIns(); + ins->initLInsOp3(op, o1, o2, o3); + return ins; + } + LInsp LirBufWriter::insLoad(LOpcode op, LInsp base, int32_t d) { LInsLd* insLd = (LInsLd*)_buf->makeRoom(sizeof(LInsLd)); @@ -417,7 +425,7 @@ namespace nanojit } iop = ((LInsp)i)->opcode(); } - while (iop==LIR_skip || iop==LIR_2); + while (LIR_skip == iop); _i = (LInsp)i; return cur; } @@ -453,6 +461,11 @@ namespace nanojit return LRK_Op2 == repKind[opcode()]; } + bool LIns::isLInsOp3() const { + NanoAssert(LRK_None != repKind[opcode()]); + return LRK_Op3 == repKind[opcode()]; + } + bool LIns::isLInsLd() const { NanoAssert(LRK_None != repKind[opcode()]); return LRK_Ld == repKind[opcode()]; @@ -664,16 +677,6 @@ namespace nanojit LIns* ExprFilter::ins2(LOpcode v, LIns* oprnd1, LIns* oprnd2) { NanoAssert(oprnd1 && oprnd2); - if (v == LIR_cmov || v == LIR_qcmov) { - if (oprnd2->oprnd1() == oprnd2->oprnd2()) { - // c ? a : a => a - return oprnd2->oprnd1(); - } - if (oprnd1->isconst()) { - // const ? x : y => return x or y depending on const - return oprnd1->imm32() ? oprnd2->oprnd1() : oprnd2->oprnd2(); - } - } if (oprnd1 == oprnd2) { switch (v) { @@ -907,6 +910,22 @@ namespace nanojit return out->ins2(v, oprnd1, oprnd2); } + LIns* ExprFilter::ins3(LOpcode v, LIns* oprnd1, LIns* oprnd2, LIns* oprnd3) + { + NanoAssert(oprnd1 && oprnd2 && oprnd3); + NanoAssert(v == LIR_cmov || v == LIR_qcmov); + if (oprnd2 == oprnd3) { + // c ? a : a => a + return oprnd2; + } + if (oprnd1->isconst()) { + // const ? x : y => return x or y depending on const + return oprnd1->imm32() ? oprnd2 : oprnd3; + } + + return out->ins3(v, oprnd1, oprnd2, oprnd3); + } + LIns* ExprFilter::insGuard(LOpcode v, LInsp c, LInsp x) { if (v == LIR_xt || v == LIR_xf) { @@ -993,7 +1012,7 @@ namespace nanojit } if (avmplus::AvmCore::use_cmov()) - return ins2((iftrue->isQuad() || iffalse->isQuad()) ? LIR_qcmov : LIR_cmov, cond, ins2(LIR_2, iftrue, iffalse)); + return ins3((iftrue->isQuad() || iffalse->isQuad()) ? LIR_qcmov : LIR_cmov, cond, iftrue, iffalse); LInsp ncond = ins1(LIR_neg, cond); // cond ? -1 : 0 return ins2(LIR_or, @@ -1191,7 +1210,9 @@ namespace nanojit return hashLoad(op, i->oprnd1(), i->disp()); default: - if (operandCount[op] == 2) + if (operandCount[op] == 3) + return hash3(op, i->oprnd1(), i->oprnd2(), i->oprnd3()); + else if (operandCount[op] == 2) return hash2(op, i->oprnd1(), i->oprnd2()); else return hash1(op, i->oprnd1()); @@ -1244,7 +1265,8 @@ namespace nanojit { const uint32_t count = operandCount[op]; if ((count >= 1 && a->oprnd1() != b->oprnd1()) || - (count >= 2 && a->oprnd2() != b->oprnd2())) + (count >= 2 && a->oprnd2() != b->oprnd2()) || + (count >= 3 && a->oprnd3() != b->oprnd3())) return false; return true; } @@ -1330,6 +1352,13 @@ namespace nanojit return _hashfinish(_hashptr(hash, b)); } + uint32_t LInsHashSet::hash3(LOpcode op, LInsp a, LInsp b, LInsp c) { + uint32_t hash = _hash8(0,uint8_t(op)); + hash = _hashptr(hash, a); + hash = _hashptr(hash, b); + return _hashfinish(_hashptr(hash, c)); + } + uint32_t LInsHashSet::hashLoad(LOpcode op, LInsp a, int32_t d) { uint32_t hash = _hash8(0,uint8_t(op)); hash = _hashptr(hash, a); @@ -1411,6 +1440,23 @@ namespace nanojit return k; } + LInsp LInsHashSet::find3(LOpcode op, LInsp a, LInsp b, LInsp c, uint32_t &i) + { + uint32_t cap = m_cap; + const LInsp *list = m_list; + const uint32_t bitmask = (cap - 1) & ~0x1; + uint32_t hash = hash3(op,a,b,c) & bitmask; + uint32_t n = 7 << 1; + LInsp k; + while ((k = list[hash]) != NULL && + (k->opcode() != op || k->oprnd1() != a || k->oprnd2() != b || k->oprnd3() != c)) + { + hash = (hash + (n += 2)) & bitmask; // quadratic probe + } + i = hash; + return k; + } + LInsp LInsHashSet::findLoad(LOpcode op, LInsp a, int32_t d, uint32_t &i) { uint32_t cap = m_cap; @@ -1931,6 +1977,17 @@ namespace nanojit return out->ins2(v,a,b); } + LIns* CseFilter::ins3(LOpcode v, LInsp a, LInsp b, LInsp c) + { + NanoAssert(isCseOpcode(v)); + NanoAssert(operandCount[v]==3); + uint32_t k; + LInsp found = exprs.find3(v, a, b, c, k); + if (found) + return found; + return exprs.add(out->ins3(v,a,b,c), k); + } + LIns* CseFilter::insLoad(LOpcode v, LInsp base, int32_t disp) { if (isCseOpcode(v)) { diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index e1ad0b26d75..5e44595ab15 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -278,6 +278,7 @@ namespace nanojit LRK_Op0, LRK_Op1, LRK_Op2, + LRK_Op3, LRK_Ld, LRK_Sti, LRK_Sk, @@ -332,6 +333,24 @@ namespace nanojit LIns* getLIns() { return (LIns*)&ins; }; }; + // 3-operand form. Used for conditional moves. + class LInsOp3 + { + private: + friend class LIns; + + LIns* oprnd_3; + + LIns* oprnd_2; + + LIns* oprnd_1; + + void* ins; + + public: + LIns* getLIns() { return (LIns*)&ins; }; + }; + // Used for all loads. class LInsLd { @@ -458,6 +477,7 @@ namespace nanojit LInsOp0* toLInsOp0() const { return (LInsOp0*)( uintptr_t(this+1) - sizeof(LInsOp0) ); } LInsOp1* toLInsOp1() const { return (LInsOp1*)( uintptr_t(this+1) - sizeof(LInsOp1) ); } LInsOp2* toLInsOp2() const { return (LInsOp2*)( uintptr_t(this+1) - sizeof(LInsOp2) ); } + LInsOp3* toLInsOp3() const { return (LInsOp3*)( uintptr_t(this+1) - sizeof(LInsOp3) ); } LInsLd* toLInsLd() const { return (LInsLd* )( uintptr_t(this+1) - sizeof(LInsLd ) ); } LInsSti* toLInsSti() const { return (LInsSti*)( uintptr_t(this+1) - sizeof(LInsSti) ); } LInsSk* toLInsSk() const { return (LInsSk* )( uintptr_t(this+1) - sizeof(LInsSk ) ); } @@ -477,6 +497,7 @@ namespace nanojit NanoStaticAssert(sizeof(LInsOp0) == 1*sizeof(void*)); NanoStaticAssert(sizeof(LInsOp1) == 2*sizeof(void*)); NanoStaticAssert(sizeof(LInsOp2) == 3*sizeof(void*)); + NanoStaticAssert(sizeof(LInsOp3) == 4*sizeof(void*)); NanoStaticAssert(sizeof(LInsLd) == 3*sizeof(void*)); NanoStaticAssert(sizeof(LInsSti) == 4*sizeof(void*)); NanoStaticAssert(sizeof(LInsSk) == 2*sizeof(void*)); @@ -489,18 +510,22 @@ namespace nanojit NanoStaticAssert(sizeof(LInsI64) == 3*sizeof(void*)); #endif - // oprnd_1 must be in the same position in LIns{Op1,Op2,Ld,Sti} + // oprnd_1 must be in the same position in LIns{Op1,Op2,Op3,Ld,Sti} // because oprnd1() is used for all of them. NanoStaticAssert( (offsetof(LInsOp1, ins) - offsetof(LInsOp1, oprnd_1)) == (offsetof(LInsOp2, ins) - offsetof(LInsOp2, oprnd_1)) ); NanoStaticAssert( (offsetof(LInsOp2, ins) - offsetof(LInsOp2, oprnd_1)) == + (offsetof(LInsOp3, ins) - offsetof(LInsOp3, oprnd_1)) ); + NanoStaticAssert( (offsetof(LInsOp3, ins) - offsetof(LInsOp3, oprnd_1)) == (offsetof(LInsLd, ins) - offsetof(LInsLd, oprnd_1)) ); NanoStaticAssert( (offsetof(LInsLd, ins) - offsetof(LInsLd, oprnd_1)) == (offsetof(LInsSti, ins) - offsetof(LInsSti, oprnd_1)) ); - // oprnd_2 must be in the same position in LIns{Op2,Sti} + // oprnd_2 must be in the same position in LIns{Op2,Op3,Sti} // because oprnd2() is used for both of them. NanoStaticAssert( (offsetof(LInsOp2, ins) - offsetof(LInsOp2, oprnd_2)) == + (offsetof(LInsOp3, ins) - offsetof(LInsOp3, oprnd_2)) ); + NanoStaticAssert( (offsetof(LInsOp3, ins) - offsetof(LInsOp3, oprnd_2)) == (offsetof(LInsSti, ins) - offsetof(LInsSti, oprnd_2)) ); } @@ -523,6 +548,14 @@ namespace nanojit toLInsOp2()->oprnd_2 = oprnd2; NanoAssert(isLInsOp2()); } + void initLInsOp3(LOpcode opcode, LIns* oprnd1, LIns* oprnd2, LIns* oprnd3) { + lastWord.clear(); + lastWord.opcode = opcode; + toLInsOp3()->oprnd_1 = oprnd1; + toLInsOp3()->oprnd_2 = oprnd2; + toLInsOp3()->oprnd_3 = oprnd3; + NanoAssert(isLInsOp3()); + } void initLInsLd(LOpcode opcode, LIns* val, int32_t d) { lastWord.clear(); lastWord.opcode = opcode; @@ -577,13 +610,17 @@ namespace nanojit } LIns* oprnd1() const { - NanoAssert(isLInsOp1() || isLInsOp2() || isLInsLd() || isLInsSti()); + NanoAssert(isLInsOp1() || isLInsOp2() || isLInsOp3() || isLInsLd() || isLInsSti()); return toLInsOp2()->oprnd_1; } LIns* oprnd2() const { - NanoAssert(isLInsOp2() || isLInsSti()); + NanoAssert(isLInsOp2() || isLInsOp3() || isLInsSti()); return toLInsOp2()->oprnd_2; } + LIns* oprnd3() const { + NanoAssert(isLInsOp3()); + return toLInsOp3()->oprnd_3; + } LIns* prevLIns() const { NanoAssert(isLInsSk()); @@ -639,6 +676,7 @@ namespace nanojit bool isLInsOp0() const; bool isLInsOp1() const; bool isLInsOp2() const; + bool isLInsOp3() const; bool isLInsSti() const; bool isLInsLd() const; bool isLInsSk() const; @@ -720,6 +758,9 @@ namespace nanojit virtual LInsp ins2(LOpcode v, LIns* a, LIns* b) { return out->ins2(v, a, b); } + virtual LInsp ins3(LOpcode v, LIns* a, LIns* b, LIns* c) { + return out->ins3(v, a, b, c); + } virtual LInsp insGuard(LOpcode v, LIns *c, LIns *x) { return out->insGuard(v, c, x); } @@ -917,7 +958,10 @@ namespace nanojit return isRetOpcode(v) ? add_flush(out->ins1(v, a)) : add(out->ins1(v, a)); } LIns* ins2(LOpcode v, LInsp a, LInsp b) { - return v == LIR_2 ? out->ins2(v,a,b) : add(out->ins2(v, a, b)); + return add(out->ins2(v, a, b)); + } + LIns* ins3(LOpcode v, LInsp a, LInsp b, LInsp c) { + return add(out->ins3(v, a, b, c)); } LIns* insCall(const CallInfo *call, LInsp args[]) { return add_flush(out->insCall(call, args)); @@ -950,6 +994,7 @@ namespace nanojit ExprFilter(LirWriter *out) : LirWriter(out) {} LIns* ins1(LOpcode v, LIns* a); LIns* ins2(LOpcode v, LIns* a, LIns* b); + LIns* ins3(LOpcode v, LIns* a, LIns* b, LIns* c); LIns* insGuard(LOpcode, LIns *cond, LIns *); LIns* insBranch(LOpcode, LIns *cond, LIns *target); }; @@ -979,6 +1024,7 @@ namespace nanojit LInsp find64(uint64_t a, uint32_t &i); LInsp find1(LOpcode v, LInsp a, uint32_t &i); LInsp find2(LOpcode v, LInsp a, LInsp b, uint32_t &i); + LInsp find3(LOpcode v, LInsp a, LInsp b, LInsp c, uint32_t &i); LInsp findLoad(LOpcode v, LInsp a, int32_t b, uint32_t &i); LInsp findcall(const CallInfo *call, uint32_t argc, LInsp args[], uint32_t &i); LInsp add(LInsp i, uint32_t k); @@ -989,6 +1035,7 @@ namespace nanojit static uint32_t FASTCALL hashimmq(uint64_t); static uint32_t FASTCALL hash1(LOpcode v, LInsp); static uint32_t FASTCALL hash2(LOpcode v, LInsp, LInsp); + static uint32_t FASTCALL hash3(LOpcode v, LInsp, LInsp, LInsp); static uint32_t FASTCALL hashLoad(LOpcode v, LInsp, int32_t); static uint32_t FASTCALL hashcall(const CallInfo *call, uint32_t argc, LInsp args[]); }; @@ -1003,6 +1050,7 @@ namespace nanojit LIns* ins0(LOpcode v); LIns* ins1(LOpcode v, LInsp); LIns* ins2(LOpcode v, LInsp, LInsp); + LIns* ins3(LOpcode v, LInsp, LInsp, LInsp); LIns* insLoad(LOpcode op, LInsp cond, int32_t d); LIns* insCall(const CallInfo *call, LInsp args[]); LIns* insGuard(LOpcode op, LInsp cond, LIns *x); @@ -1062,6 +1110,7 @@ namespace nanojit LInsp ins0(LOpcode op); LInsp ins1(LOpcode op, LInsp o1); LInsp ins2(LOpcode op, LInsp o1, LInsp o2); + LInsp ins3(LOpcode op, LInsp o1, LInsp o2, LInsp o3); LInsp insParam(int32_t i, int32_t kind); LInsp insImm(int32_t imm); LInsp insImmq(uint64_t imm); diff --git a/js/src/nanojit/LIRopcode.tbl b/js/src/nanojit/LIRopcode.tbl index a3a2e6eb0c8..17d5719e995 100644 --- a/js/src/nanojit/LIRopcode.tbl +++ b/js/src/nanojit/LIRopcode.tbl @@ -113,7 +113,7 @@ OPDEF(ji, 23,-1, None, 0) // indirect jump (currently not implemented) */ OPDEF(int, 24, 0, I, 0) // constant 32-bit integer -OPDEF(cmov, 25, 2, Op2, 0) // conditional move (op1=cond, op2=LIR_2(iftrue,iffalse)) +OPDEF(cmov, 25, 3, Op3, 0) // conditional move: cmov(cond,iftrue,iffalse) #if defined(NANOJIT_64BIT) OPDEF(callh, 26,-1, None, 0) // unused on 64-bit machines #else @@ -185,7 +185,8 @@ OPDEF(ugt, 61, 2, Op2, 0) // unsigned integer greater-than (0x3D OPDEF(ule, 62, 2, Op2, 0) // unsigned integer less-than-or-equal (0x3E 0011 1110) OPDEF(uge, 63, 2, Op2, 0) // unsigned integer greater-than-or-equal (0x3F 0011 1111) -OPDEF64(2, 0, 2, Op2, 0) // wraps a pair of refs, for LIR_cmov or LIR_qcmov +OPDEF64(__0b, 0,-1, None, 0) + OPDEF64(file, 1, 2, Op1, 0) // source filename for debug symbols OPDEF64(line, 2, 2, Op1, 0) // source line number for debug symbols OPDEF64(xbarrier,3, 1, Op2, 1) // memory barrier; doesn't exit, but flushes all values to the stack @@ -222,7 +223,7 @@ OPDEF64(__23b, 23,-1, None, 0) // this marker are subject to CSE. OPDEF64(quad, LIR_int, 0, I64, 0) // 64-bit (quad) constant value -OPDEF64(qcmov, LIR_cmov, 2, Op2, 0) // 64-bit conditional move +OPDEF64(qcmov, LIR_cmov, 3, Op3, 0) // 64-bit conditional move OPDEF64(__26b, 26,-1, None, 0) OPDEF64(__27b, 27,-1, None, 0) diff --git a/js/src/nanojit/NativeARM.cpp b/js/src/nanojit/NativeARM.cpp index 734811527f1..7ab418d8124 100644 --- a/js/src/nanojit/NativeARM.cpp +++ b/js/src/nanojit/NativeARM.cpp @@ -1862,14 +1862,10 @@ Assembler::asm_cmov(LInsp ins) { NanoAssert(ins->opcode() == LIR_cmov); LIns* condval = ins->oprnd1(); + LIns* iftrue = ins->oprnd2(); + LIns* iffalse = ins->oprnd3(); + NanoAssert(condval->isCmp()); - - LIns* values = ins->oprnd2(); - - NanoAssert(values->opcode() == LIR_2); - LIns* iftrue = values->oprnd1(); - LIns* iffalse = values->oprnd2(); - NanoAssert(!iftrue->isQuad() && !iffalse->isQuad()); const Register rr = prepResultReg(ins, GpRegs); diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index 9b36332fde0..e1deaf54e6d 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -764,14 +764,10 @@ namespace nanojit underrunProtect(4); LOpcode op = ins->opcode(); LIns* condval = ins->oprnd1(); + LIns* iftrue = ins->oprnd2(); + LIns* iffalse = ins->oprnd3(); + NanoAssert(condval->isCmp()); - - LIns* values = ins->oprnd2(); - - NanoAssert(values->opcode() == LIR_2); - LIns* iftrue = values->oprnd1(); - LIns* iffalse = values->oprnd2(); - NanoAssert(op == LIR_qcmov || (!iftrue->isQuad() && !iffalse->isQuad())); const Register rr = prepResultReg(ins, GpRegs); diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index c68c4113717..83dc71549d4 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -1059,14 +1059,10 @@ namespace nanojit { LOpcode op = ins->opcode(); LIns* condval = ins->oprnd1(); + LIns* iftrue = ins->oprnd2(); + LIns* iffalse = ins->oprnd3(); + NanoAssert(condval->isCmp()); - - LIns* values = ins->oprnd2(); - - NanoAssert(values->opcode() == LIR_2); - LIns* iftrue = values->oprnd1(); - LIns* iffalse = values->oprnd2(); - NanoAssert(op == LIR_qcmov || (!iftrue->isQuad() && !iffalse->isQuad())); const Register rr = prepResultReg(ins, GpRegs);