[arm64] Addressing modes for SIMD (#67490)
authorEgor Bogatov <egorbo@gmail.com>
Sun, 3 Apr 2022 19:16:00 +0000 (22:16 +0300)
committerGitHub <noreply@github.com>
Sun, 3 Apr 2022 19:16:00 +0000 (22:16 +0300)
src/coreclr/jit/hwintrinsiccodegenarm64.cpp
src/coreclr/jit/lower.cpp
src/coreclr/jit/lowerarmarch.cpp

index 48a3966..2bf4d7c 100644 (file)
@@ -367,7 +367,21 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
             switch (intrin.numOperands)
             {
                 case 1:
-                    GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt);
+                    if (intrin.op1->isContained())
+                    {
+                        assert(ins == INS_ld1);
+
+                        // Emit 'ldr target, [base, index]'
+                        GenTreeAddrMode* lea = intrin.op1->AsAddrMode();
+                        assert(lea->GetScale() == 1);
+                        assert(lea->Offset() == 0);
+                        GetEmitter()->emitIns_R_R_R(INS_ldr, emitSize, targetReg, lea->Base()->GetRegNum(),
+                                                    lea->Index()->GetRegNum());
+                    }
+                    else
+                    {
+                        GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt);
+                    }
                     break;
 
                 case 2:
index 4a68f81..5951452 100644 (file)
@@ -5304,6 +5304,12 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* par
     {
         return false;
     }
+
+    if (((scale | offset) > 0) && parent->OperIsHWIntrinsic())
+    {
+        // For now we only support unscaled indices for SIMD loads
+        return false;
+    }
 #endif
 
     if (scale == 0)
index 978f377..4bcaea7 100644 (file)
@@ -2070,6 +2070,18 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
                 unreached();
         }
     }
+    else if ((intrin.id == NI_AdvSimd_LoadVector128) || (intrin.id == NI_AdvSimd_LoadVector64))
+    {
+        assert(intrin.numOperands == 1);
+        assert(HWIntrinsicInfo::lookupCategory(intrin.id) == HW_Category_MemoryLoad);
+
+        GenTree* addr = node->Op(1);
+        if (TryCreateAddrMode(addr, true, node) && IsSafeToContainMem(node, addr))
+        {
+            assert(addr->OperIs(GT_LEA));
+            MakeSrcContained(node, addr);
+        }
+    }
 }
 #endif // FEATURE_HW_INTRINSICS