Skip to content

Commit

Permalink
xplat: use xmm for float args
Browse files Browse the repository at this point in the history
Previously xplat LowerCall args were limited to REG_INT_ARG... Adding XMM* support and a test case to make sure we don't break.

This PR also improves n-body xplat perf 3x.

Disabling couple of additional wasm tests on xplat with a note.
  • Loading branch information
obastemur committed Mar 22, 2017
1 parent f7e94b3 commit 08a8e9a
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 41 deletions.
115 changes: 75 additions & 40 deletions lib/Backend/amd64/LowererMDArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ LowererMDArch::LoadHeapArguments(IR::Instr *instrArgs)
// s2 = actual argument count (without counting "this")
instr = this->lowererMD->LoadInputParamCount(instrArgs, -1);
IR::Opnd * opndInputParamCount = instr->GetDst();

this->LoadHelperArgument(instrArgs, opndInputParamCount);

// s1 = current function
Expand Down Expand Up @@ -466,6 +466,40 @@ LowererMDArch::LoadNewScObjFirstArg(IR::Instr * instr, IR::Opnd * dst, ushort ex
return argInstr;
}

inline static RegNum GetRegFromArgPosition(const bool isFloatArg, const uint16 argPosition)
{
RegNum reg = RegNOREG;

if (!isFloatArg && argPosition <= IntArgRegsCount)
{
switch (argPosition)
{
#define REG_INT_ARG(Index, Name) \
case ((Index) + 1): \
reg = Reg ## Name; \
break;
#include "RegList.h"
default:
Assume(UNREACHED);
}
}
else if (isFloatArg && argPosition <= XmmArgRegsCount)
{
switch (argPosition)
{
#define REG_XMM_ARG(Index, Name) \
case ((Index) + 1): \
reg = Reg ## Name; \
break;
#include "RegList.h"
default:
Assume(UNREACHED);
}
}

return reg;
}

int32
LowererMDArch::LowerCallArgs(IR::Instr *callInstr, ushort callFlags, Js::ArgSlot extraParams, IR::IntConstOpnd **callInfoOpndRef /* = nullptr */)
{
Expand All @@ -479,6 +513,10 @@ LowererMDArch::LowerCallArgs(IR::Instr *callInstr, ushort callFlags, Js::ArgSlot
IR::Instr * argInstr = callInstr;
IR::Instr * cfgInsertLoc = callInstr->GetPrevRealInstr();
IR::Opnd *src2 = argInstr->UnlinkSrc2();
#ifndef _WIN32
this->xplatCallArgs.StartRecording();
#endif

while (src2->IsSymOpnd())
{
IR::SymOpnd * argLinkOpnd = src2->AsSymOpnd();
Expand Down Expand Up @@ -523,7 +561,9 @@ LowererMDArch::LowerCallArgs(IR::Instr *callInstr, ushort callFlags, Js::ArgSlot
callInstr->InsertBefore(argInstr);
argCount++;
}

#ifndef _WIN32
this->xplatCallArgs.StopRecording();
#endif

IR::RegOpnd * argLinkOpnd = src2->AsRegOpnd();
StackSym * argLinkSym = argLinkOpnd->m_sym->AsStackSym();
Expand Down Expand Up @@ -957,23 +997,39 @@ LowererMDArch::LowerCall(IR::Instr * callInstr, uint32 argCount)
// Manually home args
if (shouldHomeParams)
{
static const RegNum s_argRegs[IntArgRegsCount] = {
#define REG_INT_ARG(Index, Name) Reg ## Name,
#include "RegList.h"
};

const int callArgCount = this->helperCallArgsCount + static_cast<int>(argCount);
const int argRegs = min(callArgCount, static_cast<int>(IntArgRegsCount));
for (int i = argRegs - 1; i >= 0; i--)
const int xpTopPos = this->xplatCallArgs.GetTopPosition();

int floatCount = this->xplatCallArgs.floatCount;
int argRes = min(callArgCount, static_cast<int>(XmmArgRegsCount));
int intCount = max(0, min(argRes - floatCount, static_cast<int>(IntArgRegsCount)));
int argRegs = intCount + floatCount;

for (int i = argRegs > xpTopPos ? argRegs : xpTopPos; i > 0 && argRegs > 0; i--, argRegs--)
{
StackSym * sym = this->m_func->m_symTable->GetArgSlotSym(static_cast<uint16>(i + 1));
StackSym * sym = this->m_func->m_symTable->GetArgSlotSym(static_cast<uint16>(i));

IRType type = TyMachReg;
bool isFloatArg = false;
if (i <= xpTopPos)
{
type = this->xplatCallArgs.args[i];
isFloatArg = this->xplatCallArgs.IsFloat(i);
}

RegNum reg = GetRegFromArgPosition(isFloatArg, i);

IR::RegOpnd *regOpnd = IR::RegOpnd::New(nullptr, reg, type, this->m_func);
regOpnd->m_isCallArg = true;

Lowerer::InsertMove(
IR::SymOpnd::New(sym, TyMachReg, this->m_func),
IR::RegOpnd::New(nullptr, s_argRegs[i], TyMachReg, this->m_func),
IR::SymOpnd::New(sym, type, this->m_func),
regOpnd,
callInstr, false);
}
}
#endif
this->xplatCallArgs.Reset();
#endif // !_WIN32

//
// load the address into a register because we cannot directly access 64 bit constants
Expand Down Expand Up @@ -1036,35 +1092,14 @@ LowererMDArch::GetArgSlotOpnd(uint16 index, StackSym * argSym, bool isHelper /*=

IRType type = argSym ? argSym->GetType() : TyMachReg;
const bool isFloatArg = IRType_IsFloat(type) || IRType_IsSimd128(type);
RegNum reg = RegNOREG;

if (!isFloatArg && argPosition <= IntArgRegsCount)
{
switch (argPosition)
{
#define REG_INT_ARG(Index, Name) \
case ((Index) + 1): \
reg = Reg ## Name; \
break;
#include "RegList.h"
default:
Assume(UNREACHED);
}
}
else if (isFloatArg && argPosition <= XmmArgRegsCount)
RegNum reg = GetRegFromArgPosition(isFloatArg, argPosition);
#ifndef _WIN32
if (reg != RegNOREG && this->xplatCallArgs.IsRecording())
{
switch (argPosition)
{
#define REG_XMM_ARG(Index, Name) \
case ((Index) + 1): \
reg = Reg ## Name; \
break;
#include "RegList.h"
default:
Assume(UNREACHED);
}
this->xplatCallArgs.Add(isFloatArg, argPosition);
}

#endif

if (reg != RegNOREG)
{
IR::RegOpnd *regOpnd = IR::RegOpnd::New(argSym, reg, type, m_func);
Expand Down
56 changes: 55 additions & 1 deletion lib/Backend/amd64/LowererMDArch.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,61 @@ class LowererMDArch
int helperCallArgsCount;
IR::Opnd * helperCallArgs[MaxArgumentsToHelper];


#ifndef _WIN32
class XPlatRegArgList
{
bool isRecording;
int lastPosition;
public:
XPlatRegArgList():isRecording(false) { Reset(); }
inline void Reset() { floatCount = 0; intCount = 0; lastPosition = 0;}

inline void StartRecording() { Assert(!isRecording); Reset(); isRecording = true; }

void StopRecording()
{
Assert(isRecording);
isRecording = false;
for (int i = lastPosition - GetArgsCount(); i >= 0; i--) args[i] = TyMachPtr;
}

inline bool IsRecording() { return isRecording; }

inline int GetArgsCount() { return intCount + floatCount; }

inline int GetTopPosition() { return lastPosition; }

inline bool IsFloat(uint16 position) { return args[position] == TyFloat64; }

inline void Add(bool isFloat, uint16 regPosition)
{
Assert(isRecording && regPosition != 0);

if (isFloat)
{
Assert(regPosition <= XmmArgRegsCount);
args[regPosition] = TyFloat64;
floatCount++;
}
else
{
Assert(regPosition <= IntArgRegsCount);
args[regPosition] = TyMachPtr;
intCount++;
}

if (regPosition > lastPosition)
{
lastPosition = regPosition;
}
}

IRType args [XmmArgRegsCount + 1];
int floatCount;
int intCount;
};
XPlatRegArgList xplatCallArgs;
#endif
public:

LowererMDArch(Func* function):
Expand Down
64 changes: 64 additions & 0 deletions test/AsmJs/argTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

function AsmModuleDouble() {
"use asm";

function test0(x) { x = +x; return +test0sub(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 0.5, 10.5); }
function test0sub(a,b,c,d,e,f,g,h,j,i,k) {
a = +a; b = +b;
c = +c; d = +d;
e = +e; f = +f;
g = +g; h = +h;
j = +j; i = +i;
k = +k; return +(a); }

function test1(x) { x = +x; return +test1sub(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 0.5, 10.5); }
function test1sub(a,b,c,d,e,f,g,h,j,i,k) {
a = +a; b = +b;
c = +c; d = +d;
e = +e; f = +f;
g = +g; h = +h;
j = +j; i = +i;
k = +k; return +(f); }

function test2(x) { x = +x; return +test2sub(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 0.5, 10.5); }
function test2sub(a,b,c,d,e,f,g,h,j,i,k) {
a = +a; b = +b;
c = +c; d = +d;
e = +e; f = +f;
g = +g; h = +h;
j = +j; i = +i;
k = +k; return +(g); }

function test3(x) { x = +x; return +test3sub(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 0.5, 10.5); }
function test3sub(a,b,c,d,e,f,g,h,j,i,k) {
a = +a; b = +b;
c = +c; d = +d;
e = +e; f = +f;
g = +g; h = +h;
j = +j; i = +i;
k = +k; return +(h); }

function test4(x) { x = +x; return +test4sub(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 0.5, 10.5); }
function test4sub(a,b,c,d,e,f,g,h,j,i,k) {
a = +a; b = +b;
c = +c; d = +d;
e = +e; f = +f;
g = +g; h = +h;
j = +j; i = +i;
k = +k; return +(k); }

return { test0: test0, test1: test1, test2: test2, test3: test3, test4: test4 };
}

var asmModuleDouble = AsmModuleDouble();
if (asmModuleDouble.test0(2, 3, 4) != 1.5) throw ('a - 1st arg. storage has failed.');
if (asmModuleDouble.test1(2, 3, 4) != 6.5) throw ('f - 6th arg. storage has failed.');
if (asmModuleDouble.test2(2, 3, 4) != 7.5) throw ('g - 7th arg. storage has failed.');
if (asmModuleDouble.test3(2, 3, 4) != 8.5) throw ('h - 8th arg. storage has failed.');
if (asmModuleDouble.test4(2, 3, 4) != 10.5) throw ('k - 11th arg. storage has failed.');

print("PASS")
6 changes: 6 additions & 0 deletions test/AsmJs/rlexe.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<regress-exe>
<test>
<default>
<files>argTest.js</files>
<compile-flags>-maic:0</compile-flags>
</default>
</test>
<test>
<default>
<files>ArrayView.js</files>
Expand Down
3 changes: 3 additions & 0 deletions test/WasmSpec/rlexe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,8 @@
<files>spec.js</files>
<baseline>baselines/func.baseline</baseline>
<compile-flags>-wasm -args testsuite-bin/func.json -endargs</compile-flags>
<!-- xplat-todo: implement xmm.. with wasm related asm. -->
<tags>exclude_xplat</tags>
</default>
</test>
<test>
Expand Down Expand Up @@ -543,6 +545,7 @@
<files>spec.js</files>
<baseline>baselines/left-to-right.baseline</baseline>
<compile-flags>-wasm -args testsuite-bin/left-to-right.json -endargs</compile-flags>
<tags>exclude_xplat</tags>
</default>
</test>
<test>
Expand Down

0 comments on commit 08a8e9a

Please sign in to comment.