summaryrefslogtreecommitdiff
path: root/src/jit/lowerarm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/lowerarm.cpp')
-rw-r--r--src/jit/lowerarm.cpp148
1 files changed, 123 insertions, 25 deletions
diff --git a/src/jit/lowerarm.cpp b/src/jit/lowerarm.cpp
index 5bf23c4199..9792b8a9c6 100644
--- a/src/jit/lowerarm.cpp
+++ b/src/jit/lowerarm.cpp
@@ -23,8 +23,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#ifndef LEGACY_BACKEND // This file is ONLY used for the RyuJIT backend that uses the linear scan register allocator
-// The ARM backend is not yet implemented, so the methods here are all NYI.
-// TODO-ARM-NYI: Lowering for ARM.
#ifdef _TARGET_ARM_
#include "jit.h"
@@ -33,6 +31,68 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include "lsra.h"
//------------------------------------------------------------------------
+// LowerStoreLoc: Lower a store of a lclVar
+//
+// Arguments:
+// storeLoc - the local store (GT_STORE_LCL_FLD or GT_STORE_LCL_VAR)
+//
+// Notes:
+// This involves:
+// - Widening operations of unsigneds.
+//
+void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc)
+{
+ // Try to widen the ops if they are going into a local var.
+ GenTree* op1 = storeLoc->gtGetOp1();
+ if ((storeLoc->gtOper == GT_STORE_LCL_VAR) && (op1->gtOper == GT_CNS_INT))
+ {
+ GenTreeIntCon* con = op1->AsIntCon();
+ ssize_t ival = con->gtIconVal;
+ unsigned varNum = storeLoc->gtLclNum;
+ LclVarDsc* varDsc = comp->lvaTable + varNum;
+
+ if (varDsc->lvIsSIMDType())
+ {
+ noway_assert(storeLoc->gtType != TYP_STRUCT);
+ }
+ unsigned size = genTypeSize(storeLoc);
+ // If we are storing a constant into a local variable
+ // we extend the size of the store here
+ if ((size < 4) && !varTypeIsStruct(varDsc))
+ {
+ if (!varTypeIsUnsigned(varDsc))
+ {
+ if (genTypeSize(storeLoc) == 1)
+ {
+ if ((ival & 0x7f) != ival)
+ {
+ ival = ival | 0xffffff00;
+ }
+ }
+ else
+ {
+ assert(genTypeSize(storeLoc) == 2);
+ if ((ival & 0x7fff) != ival)
+ {
+ ival = ival | 0xffff0000;
+ }
+ }
+ }
+
+ // A local stack slot is at least 4 bytes in size, regardless of
+ // what the local var is typed as, so auto-promote it here
+ // unless it is a field of a promoted struct
+ // TODO-ARM-CQ: if the field is promoted shouldn't we also be able to do this?
+ if (!varDsc->lvIsStructField)
+ {
+ storeLoc->gtType = TYP_INT;
+ con->SetIconValue(ival);
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------
// LowerCast: Lower GT_CAST(srcType, DstType) nodes.
//
// Arguments:
@@ -57,7 +117,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// Note that for the overflow conversions we still depend on helper calls and
// don't expect to see them here.
// i) GT_CAST(float/double, int type with overflow detection)
-
+//
void Lowering::LowerCast(GenTree* tree)
{
assert(tree->OperGet() == GT_CAST);
@@ -71,10 +131,8 @@ void Lowering::LowerCast(GenTree* tree)
var_types srcType = op1->TypeGet();
var_types tmpType = TYP_UNDEF;
- // TODO-ARM-Cleanup: Remove following NYI assertions.
if (varTypeIsFloating(srcType))
{
- NYI_ARM("Lowering for cast from float"); // Not tested yet.
noway_assert(!tree->gtOverflow());
}
@@ -104,36 +162,78 @@ void Lowering::LowerCast(GenTree* tree)
}
}
+//------------------------------------------------------------------------
+// LowerRotate: Lower GT_ROL and GT_ROL nodes.
+//
+// Arguments:
+// tree - the node to lower
+//
+// Return Value:
+// None.
+//
void Lowering::LowerRotate(GenTreePtr tree)
{
- NYI_ARM("ARM Lowering for ROL and ROR");
-}
+ if (tree->OperGet() == GT_ROL)
+ {
+ // There is no ROL instruction on ARM. Convert ROL into ROR.
+ GenTreePtr rotatedValue = tree->gtOp.gtOp1;
+ unsigned rotatedValueBitSize = genTypeSize(rotatedValue->gtType) * 8;
+ GenTreePtr rotateLeftIndexNode = tree->gtOp.gtOp2;
-void Lowering::TreeNodeInfoInit(GenTree* stmt)
-{
- NYI("ARM TreeNodInfoInit");
+ if (rotateLeftIndexNode->IsCnsIntOrI())
+ {
+ ssize_t rotateLeftIndex = rotateLeftIndexNode->gtIntCon.gtIconVal;
+ ssize_t rotateRightIndex = rotatedValueBitSize - rotateLeftIndex;
+ rotateLeftIndexNode->gtIntCon.gtIconVal = rotateRightIndex;
+ }
+ else
+ {
+ GenTreePtr tmp =
+ comp->gtNewOperNode(GT_NEG, genActualType(rotateLeftIndexNode->gtType), rotateLeftIndexNode);
+ BlockRange().InsertAfter(rotateLeftIndexNode, tmp);
+ tree->gtOp.gtOp2 = tmp;
+ }
+ tree->ChangeOper(GT_ROR);
+ }
}
-// returns true if the tree can use the read-modify-write memory instruction form
-bool Lowering::isRMWRegOper(GenTreePtr tree)
+//------------------------------------------------------------------------
+// LowerPutArgStk: Lower a GT_PUTARG_STK node
+//
+// Arguments:
+// argNode - a GT_PUTARG_STK node
+//
+// Return Value:
+// None.
+//
+// Notes:
+// There is currently no Lowering required for this on ARM.
+//
+void Lowering::LowerPutArgStk(GenTreePutArgStk* argNode, fgArgTabEntryPtr info)
{
- return false;
}
+//------------------------------------------------------------------------
+// IsCallTargetInRange: Can a call target address be encoded in-place?
+//
+// Return Value:
+// True if the addr fits into the range.
+//
bool Lowering::IsCallTargetInRange(void* addr)
{
return comp->codeGen->validImmForBL((ssize_t)addr);
}
-// return true if the immediate can be folded into an instruction, for example small enough and non-relocatable
+//------------------------------------------------------------------------
+// IsContainableImmed: Is an immediate encodable in-place?
+//
+// Return Value:
+// True if the immediate can be folded into an instruction,
+// for example small enough and non-relocatable.
bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode)
{
if (varTypeIsFloating(parentNode->TypeGet()))
{
- // TODO-ARM-Cleanup: not tested yet.
- NYI_ARM("ARM IsContainableImmed for floating point type");
-
- // We can contain a floating point 0.0 constant in a compare instruction
switch (parentNode->OperGet())
{
default:
@@ -146,7 +246,12 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode)
case GT_GE:
case GT_GT:
if (childNode->IsIntegralConst(0))
+ {
+ // TODO-ARM-Cleanup: not tested yet.
+ NYI_ARM("ARM IsContainableImmed for floating point type");
+ // We can contain a floating point 0.0 constant in a compare instruction
return true;
+ }
break;
}
}
@@ -185,13 +290,6 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode)
if (emitter::emitIns_valid_imm_for_alu(immVal))
return true;
break;
-
- case GT_STORE_LCL_VAR:
- // TODO-ARM-Cleanup: not tested yet
- NYI_ARM("ARM IsContainableImmed for GT_STORE_LCL_VAR");
- if (immVal == 0)
- return true;
- break;
}
}