[ARM32/RyuJIT] Lowering: enable passing split struct less than 16 bytes
authorHyeongseok Oh <hseok82.oh@samsung.com>
Fri, 30 Jun 2017 01:02:43 +0000 (10:02 +0900)
committerHyeongseok Oh <hseok82.oh@samsung.com>
Fri, 30 Jun 2017 05:16:26 +0000 (14:16 +0900)
- Enable passing split struct (less than 16 bytes) in registers and on stack
morphing phase
Lowering phase
- Block at LSRA phase - add NYI_ARM
- Print split struct

src/jit/gentree.cpp
src/jit/lower.cpp
src/jit/lsraarmarch.cpp
src/jit/morph.cpp

index ace7e13..bf2a873 100644 (file)
@@ -11342,6 +11342,68 @@ void Compiler::gtGetLateArgMsg(
         {
             sprintf_s(bufp, bufLength, "this in %s%c", compRegVarName(argReg), 0);
         }
+#ifdef _TARGET_ARM_
+        else if (curArgTabEntry->isSplit)
+        {
+            regNumber firstReg = curArgTabEntry->regNum;
+            unsigned  argNum   = curArgTabEntry->argNum;
+            if (listCount == -1)
+            {
+                if (curArgTabEntry->numRegs == 1)
+                {
+                    sprintf_s(bufp, bufLength, "arg%d %s out+%02x%c", argNum, compRegVarName(firstReg),
+                              (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
+                }
+                else
+                {
+                    regNumber lastReg   = REG_STK;
+                    char      separator = (curArgTabEntry->numRegs == 2) ? ',' : '-';
+                    if (curArgTabEntry->isHfaRegArg)
+                    {
+                        unsigned lastRegNum = genMapFloatRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
+                        lastReg             = genMapFloatRegArgNumToRegNum(lastRegNum);
+                    }
+                    else
+                    {
+                        unsigned lastRegNum = genMapIntRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
+                        lastReg             = genMapIntRegArgNumToRegNum(lastRegNum);
+                    }
+                    sprintf_s(bufp, bufLength, "arg%d %s%c%s out+%02x%c", argNum, compRegVarName(firstReg), separator,
+                              compRegVarName(lastReg), (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
+                }
+            }
+            else
+            {
+                unsigned curArgNum = BAD_VAR_NUM;
+                bool     isFloat   = curArgTabEntry->isHfaRegArg;
+                if (isFloat)
+                {
+                    curArgNum = genMapFloatRegNumToRegArgNum(firstReg) + listCount;
+                }
+                else
+                {
+                    curArgNum = genMapIntRegNumToRegArgNum(firstReg) + listCount;
+                }
+
+                if (!isFloat && curArgNum < MAX_REG_ARG)
+                {
+                    regNumber curReg = genMapIntRegArgNumToRegNum(curArgNum);
+                    sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
+                }
+                else if (isFloat && curArgNum < MAX_FLOAT_REG_ARG)
+                {
+                    regNumber curReg = genMapFloatRegArgNumToRegNum(curArgNum);
+                    sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
+                }
+                else
+                {
+                    unsigned stackSlot = listCount - curArgTabEntry->numRegs;
+                    sprintf_s(bufp, bufLength, "arg%d m%d out+%s%c", argNum, listCount, stackSlot, 0);
+                }
+            }
+            return;
+        }
+#endif // _TARGET_ARM_
         else
         {
 #if FEATURE_MULTIREG_ARGS
index 0479b78..7b95b75 100644 (file)
@@ -831,26 +831,56 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP
     // Struct can be split into register(s) and stack on ARM
     if (info->isSplit)
     {
-        if (arg->OperGet() != GT_OBJ)
+        assert(arg->OperGet() == GT_OBJ || arg->OperGet() == GT_FIELD_LIST);
+        // TODO: Need to check correctness for FastTailCall
+        if (call->IsFastTailCall())
         {
-            NYI_ARM("Lowering: Oper for struct argument is not GT_OBJ");
+            NYI_ARM("lower: struct argument by fast tail call");
         }
 
         putArg = new (comp, GT_PUTARG_SPLIT)
             GenTreePutArgSplit(arg, info->slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(info->numSlots), info->numRegs,
                                info->isHfaRegArg, call->IsFastTailCall(), call);
 
-        // Set GC Pointer info
+        // If struct argument is morphed to GT_FIELD_LIST node(s),
+        // we can know GC info by type of each GT_FIELD_LIST node.
+        // So we skip setting GC Pointer info.
+        //
         GenTreePutArgSplit* argSplit = putArg->AsPutArgSplit();
-        BYTE*               gcLayout = new (comp, CMK_Codegen) BYTE[info->numSlots + info->numRegs];
-        unsigned            numRefs  = comp->info.compCompHnd->getClassGClayout(arg->gtObj.gtClass, gcLayout);
-        argSplit->setGcPointers(numRefs, gcLayout);
+        if (arg->OperGet() == GT_OBJ)
+        {
+            BYTE*       gcLayout = nullptr;
+            unsigned    numRefs  = 0;
+            GenTreeObj* argObj   = arg->AsObj();
+
+            if (argObj->IsGCInfoInitialized())
+            {
+                gcLayout = argObj->gtGcPtrs;
+                numRefs  = argObj->GetGcPtrCount();
+            }
+            else
+            {
+                // Set GC Pointer info
+                gcLayout = new (comp, CMK_Codegen) BYTE[info->numSlots + info->numRegs];
+                numRefs  = comp->info.compCompHnd->getClassGClayout(arg->gtObj.gtClass, gcLayout);
+                argSplit->setGcPointers(numRefs, gcLayout);
+            }
 
-        // Set type of registers
-        for (unsigned index = 0; index < info->numRegs; index++)
+            // Set type of registers
+            for (unsigned index = 0; index < info->numRegs; index++)
+            {
+                var_types regType          = comp->getJitGCType(gcLayout[index]);
+                argSplit->m_regType[index] = regType;
+            }
+        }
+        else
         {
-            var_types regType          = comp->getJitGCType(gcLayout[index]);
-            argSplit->m_regType[index] = regType;
+            GenTreeFieldList* fieldListPtr = arg->AsFieldList();
+            for (unsigned index = 0; index < info->numRegs; fieldListPtr = fieldListPtr->Rest(), index++)
+            {
+                var_types regType          = fieldListPtr->TypeGet();
+                argSplit->m_regType[index] = regType;
+            }
         }
     }
     else
index e361478..75dc6e3 100644 (file)
@@ -771,6 +771,11 @@ void Lowering::TreeNodeInfoInitPutArgSplit(GenTreePutArgSplit* argNode, TreeNode
     }
     argNode->gtLsraInfo.setDstCandidates(m_lsra, argMask);
 
+    if (putArgChild->OperGet() == GT_FIELD_LIST)
+    {
+        NYI_ARM("LSRA: Oper for split struct argument is GT_FIELD_LIST");
+    }
+
     assert(putArgChild->TypeGet() == TYP_STRUCT);
     assert(putArgChild->OperGet() == GT_OBJ);
     // We could use a ldr/str sequence so we need a internal register
index 588309d..ec169a5 100644 (file)
@@ -4769,18 +4769,13 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
     {
         if (fgEntryPtr->isHfaRegArg)
         {
-            // We cannot handle split struct morphed to GT_FIELD_LIST yet
+            // We cannot handle HFA split struct morphed to GT_FIELD_LIST yet
             NYI_ARM("Struct split between float registers and stack");
         }
         else if (fgEntryPtr->numSlots + fgEntryPtr->numRegs > 4)
         {
             return arg;
         }
-        else
-        {
-            // We cannot handle split struct morphed to GT_FIELD_LIST yet
-            NYI_ARM("Struct split between integer registers and stack");
-        }
     }
     else if (!fgEntryPtr->isHfaRegArg && fgEntryPtr->numSlots > 4)
     {