From 561ea23da961fde246d64442cb75088dbed13171 Mon Sep 17 00:00:00 2001 From: Owen Yamauchi Date: Wed, 9 Apr 2014 14:34:12 -0700 Subject: [PATCH] Factor out ARM reg saving, add SIMD support This fixes an apparent bug in my last diff and makes life much easier for my upcoming catch traces diff. In the case where there are odd number of both SIMD and GP regs to save, I could have saved space by packing both into the same 16-byte stack slot, but I didn't because we're going to need to support 16-byte SIMD registers soon. Reviewed By: @swtaarrs Differential Revision: D1268104 --- hphp/runtime/vm/jit/code-gen-arm.cpp | 103 ++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/hphp/runtime/vm/jit/code-gen-arm.cpp b/hphp/runtime/vm/jit/code-gen-arm.cpp index 934ba7f498e..7f4e75ba146 100644 --- a/hphp/runtime/vm/jit/code-gen-arm.cpp +++ b/hphp/runtime/vm/jit/code-gen-arm.cpp @@ -37,6 +37,73 @@ using namespace vixl; ////////////////////////////////////////////////////////////////////// +struct RegSaver { + explicit RegSaver(RegSet regs) + : m_gprs(CPURegister::kRegister, kXRegSize, 0) + , m_simds(CPURegister::kFPRegister, kDRegSize, 0) + , m_maybeOddGPR(folly::none) + , m_maybeOddSIMD(folly::none) { + regs.forEach([&] (PhysReg r) { + if (r.isGP()) { + m_gprs.Combine(r); + } else { + m_simds.Combine(r); + } + }); + + // The vixl helper requires you to pass it an even number of registers. If + // we have an odd number of regs to save, remove one from the list we pass, + // and save it ourselves. + if (m_gprs.Count() % 2 == 1) { + m_maybeOddGPR = m_gprs.PopHighestIndex(); + } + if (m_simds.Count() % 2 == 1) { + m_maybeOddSIMD = m_simds.PopHighestIndex(); + } + } + + void emitPushes(MacroAssembler& as) { + assert(m_gprs.Count() % 2 == 0); + assert(m_simds.Count() % 2 == 0); + as. PushCPURegList(m_gprs); + as. PushCPURegList(m_simds); + + if (m_maybeOddGPR.hasValue()) { + // We're only storing a single reg, but the stack pointer must always be + // 16-byte aligned. This instruction subtracts 16 from the stack pointer, + // then writes the value. + as. Str (m_maybeOddGPR.value(), MemOperand(sp, -16, PreIndex)); + } + if (m_maybeOddSIMD.hasValue()) { + as. Str (m_maybeOddSIMD.value(), MemOperand(sp, -16, PreIndex)); + } + } + + void emitPops(MacroAssembler& as) { + assert(m_gprs.Count() % 2 == 0); + assert(m_simds.Count() % 2 == 0); + + if (m_maybeOddSIMD.hasValue()) { + // Read the value, then add 16 to the stack pointer. + as. Ldr (m_maybeOddSIMD.value(), MemOperand(sp, 16, PostIndex)); + } + if (m_maybeOddGPR.hasValue()) { + // Read the value, then add 16 to the stack pointer. + as. Ldr (m_maybeOddGPR.value(), MemOperand(sp, 16, PostIndex)); + } + as. PopCPURegList(m_simds); + as. PopCPURegList(m_gprs); + } + + private: + CPURegList m_gprs; + CPURegList m_simds; + folly::Optional m_maybeOddGPR; + folly::Optional m_maybeOddSIMD; +}; + +////////////////////////////////////////////////////////////////////// + #define NOOP_OPCODE(name) void CodeGenerator::cg##name(IRInstruction*) {} NOOP_OPCODE(DefConst) @@ -1077,40 +1144,12 @@ void CodeGenerator::cgCallHelper(vixl::MacroAssembler& a, auto dstReg0 = dstInfo.reg0; DEBUG_ONLY auto dstReg1 = dstInfo.reg1; - if (debug) { - toSave.forEach([](PhysReg r) { assert(r.isGP()); }); - } - - toSave = toSave & kGPCallerSaved; + toSave = toSave & (kGPCallerSaved | kSIMDCallerSaved); assert((toSave & RegSet().add(dstReg0).add(dstReg1)).empty()); - // Use vixl's handy helper to push caller-save regs. It uses ldp/stp when - // possible. - CPURegList pushedRegs(vixl::CPURegister::kRegister, vixl::kXRegSize, 0); - toSave.forEach([&](PhysReg r) { pushedRegs.Combine(r); }); - - // The vixl helper requires you to pass it an even number of registers. If we - // have an odd number of regs to save, remove one from the list we pass, and - // save it ourselves. - folly::Optional maybeOddOne; - if (pushedRegs.Count() % 2 == 1) { - maybeOddOne = pushedRegs.PopHighestIndex(); - } - a. PushCPURegList(pushedRegs); - if (maybeOddOne) { - // We're only storing a single reg, but the stack pointer must always be - // 16-byte aligned. This instruction subtracts 16 from the stack pointer, - // then writes the value. - a. Str (maybeOddOne.value(), MemOperand(vixl::sp, -16, vixl::PreIndex)); - } - - SCOPE_EXIT { - if (maybeOddOne) { - // Read the value, then add 16 to the stack pointer. - a.Ldr (maybeOddOne.value(), MemOperand(vixl::sp, 16, vixl::PostIndex)); - } - a. PopCPURegList(pushedRegs); - }; + RegSaver saver{toSave}; + saver.emitPushes(a); + SCOPE_EXIT { saver.emitPops(a); }; for (size_t i = 0; i < args.numRegArgs(); i++) { args[i].setDstReg(PhysReg{argReg(i)}); -- 2.11.4.GIT