From 8750eadec178c3877bf116b5b7078ed1576c37e8 Mon Sep 17 00:00:00 2001 From: bsimmers Date: Mon, 24 Nov 2014 16:27:20 -0800 Subject: [PATCH] Raise psllq and psrlq to absdbl, support in llvm Summary: We were only using these two instructions to clear the sign bit of a double to take its absolute value. Use the llvm intrinsic in the llvm backend. Reviewed By: @jasone Differential Revision: D1702068 --- hphp/doc/ir.specification | 3 +-- hphp/runtime/vm/jit/code-gen-x64.cpp | 5 +---- hphp/runtime/vm/jit/vasm-llvm.cpp | 11 ++++++++++- hphp/runtime/vm/jit/vasm-x64.cpp | 19 +++++++++++++++++++ hphp/runtime/vm/jit/vasm-x64.h | 2 ++ 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/hphp/doc/ir.specification b/hphp/doc/ir.specification index 94165b0b439..53afd41e79f 100644 --- a/hphp/doc/ir.specification +++ b/hphp/doc/ir.specification @@ -451,8 +451,7 @@ exceptions depending on how coercion is implemented. Undefined behavior occurs if Mod is given a divisor of zero, or if the divisor is -1 and the dividend is the minimum representable integer. - AbsDbl computes the absolute value of a double-precision value by clearing - the sign bit. + AbsDbl computes the absolute value of a double-precision value. DivDbl will branch to block B when S1 is zero (signed or unsigned). When the result of the division is a real valued number DivDbl conforms to IEEE 754. diff --git a/hphp/runtime/vm/jit/code-gen-x64.cpp b/hphp/runtime/vm/jit/code-gen-x64.cpp index d15f41d06d5..9c0eedc3348 100644 --- a/hphp/runtime/vm/jit/code-gen-x64.cpp +++ b/hphp/runtime/vm/jit/code-gen-x64.cpp @@ -925,10 +925,7 @@ void CodeGenerator::cgAbsDbl(IRInstruction* inst) { auto src = srcLoc(inst, 0).reg(); auto dst = dstLoc(inst, 0).reg(); auto& v = vmain(); - // clear the high bit - auto tmp = v.makeReg(); - v << psllq{1, src, tmp}; - v << psrlq{1, tmp, dst}; + v << absdbl{src, dst}; } Vreg CodeGenerator::emitAddInt(Vout& v, IRInstruction* inst) { diff --git a/hphp/runtime/vm/jit/vasm-llvm.cpp b/hphp/runtime/vm/jit/vasm-llvm.cpp index 5b608d26325..b3865fa2297 100644 --- a/hphp/runtime/vm/jit/vasm-llvm.cpp +++ b/hphp/runtime/vm/jit/vasm-llvm.cpp @@ -936,7 +936,8 @@ O(xorq) \ O(xorqi) \ O(landingpad) \ O(ldretaddr) \ -O(retctrl) +O(retctrl) \ +O(absdbl) #define O(name) case Vinstr::name: emit(inst.name##_); break; SUPPORTED_OPS #undef O @@ -964,6 +965,8 @@ O(retctrl) case Vinstr::pushm: case Vinstr::pop: case Vinstr::popm: + case Vinstr::psllq: + case Vinstr::psrlq: always_assert_flog(false, "Banned opcode in B{}: {}", size_t(label), show(m_unit, inst)); @@ -1724,6 +1727,12 @@ void LLVMEmitter::emit(const retctrl& inst) { m_irb.CreateRetVoid(); } +void LLVMEmitter::emit(const absdbl& inst) { + auto abs = llvm::Intrinsic::getDeclaration(m_module.get(), + llvm::Intrinsic::fabs); + defineValue(inst.d, m_irb.CreateCall(abs, value(inst.s))); +} + void LLVMEmitter::emit(const roundsd& inst) { auto roundID = [&]{ switch (inst.dir) { diff --git a/hphp/runtime/vm/jit/vasm-x64.cpp b/hphp/runtime/vm/jit/vasm-x64.cpp index f731bbac6e7..9482356573b 100644 --- a/hphp/runtime/vm/jit/vasm-x64.cpp +++ b/hphp/runtime/vm/jit/vasm-x64.cpp @@ -931,6 +931,21 @@ static void lowerShift(Vunit& unit, Vlabel b, size_t iInst) { vector_splice(unit.blocks[b].code, iInst, 1, unit.blocks[scratch].code); } +static void lowerAbsdbl(Vunit& unit, Vlabel b, size_t iInst) { + auto const& inst = unit.blocks[b].code[iInst]; + auto const& absdbl = inst.absdbl_; + auto scratch = unit.makeScratchBlock(); + SCOPE_EXIT { unit.freeScratchBlock(scratch); }; + Vout v(unit, scratch, inst.origin); + + // clear the high bit + auto tmp = v.makeReg(); + v << psllq{1, absdbl.s, tmp}; + v << psrlq{1, tmp, absdbl.d}; + + vector_splice(unit.blocks[b].code, iInst, 1, unit.blocks[scratch].code); +} + static void lowerVcall(Vunit& unit, Vlabel b, size_t iInst) { auto& blocks = unit.blocks; auto& inst = blocks[b].code[iInst]; @@ -1086,6 +1101,10 @@ static void lowerForX64(Vunit& unit, const Abi& abi) { lowerShift(unit, Vlabel{ib}, ii); break; + case Vinstr::absdbl: + lowerAbsdbl(unit, Vlabel{ib}, ii); + break; + case Vinstr::defvmsp: inst = copy{rVmSp, inst.defvmsp_.d}; break; diff --git a/hphp/runtime/vm/jit/vasm-x64.h b/hphp/runtime/vm/jit/vasm-x64.h index 62a691e8404..248814681dd 100644 --- a/hphp/runtime/vm/jit/vasm-x64.h +++ b/hphp/runtime/vm/jit/vasm-x64.h @@ -408,6 +408,7 @@ inline Vptr Vr::operator+(size_t d) const { O(shl, Inone, U(s0) U(s1), D(d) D(sf))\ O(ldretaddr, Inone, U(s), D(d))\ O(retctrl, Inone, U(s), Dn)\ + O(absdbl, Inone, U(s), D(d))\ /* arm instructions */\ O(asrv, Inone, U(sl) U(sr), D(d))\ O(brk, I(code), Un, Dn)\ @@ -558,6 +559,7 @@ struct copyargs { Vtuple s, d; }; struct debugtrap {}; struct ldretaddr { Vptr s; Vreg d; }; struct retctrl { Vreg s; }; +struct absdbl { Vreg s, d; }; // No-op, used for marking the end of a block that is intentionally going to // fall-through. Only for use with Vauto. -- 2.11.4.GIT