本文整理汇总了C++中lir::Use::Def方法的典型用法代码示例。如果您正苦于以下问题:C++ Use::Def方法的具体用法?C++ Use::Def怎么用?C++ Use::Def使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类lir::Use
的用法示例。
在下文中一共展示了Use::Def方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: RewriteAddress
void Rationalizer::RewriteAddress(LIR::Use& use)
{
assert(use.IsInitialized());
GenTreeUnOp* address = use.Def()->AsUnOp();
assert(address->OperGet() == GT_ADDR);
GenTree* location = address->gtGetOp1();
genTreeOps locationOp = location->OperGet();
if (location->IsLocal())
{
// We are changing the child from GT_LCL_VAR TO GT_LCL_VAR_ADDR.
// Therefore gtType of the child needs to be changed to a TYP_BYREF
#ifdef DEBUG
if (locationOp == GT_LCL_VAR)
{
JITDUMP("Rewriting GT_ADDR(GT_LCL_VAR) to GT_LCL_VAR_ADDR:\n");
}
else
{
assert(locationOp == GT_LCL_FLD);
JITDUMP("Rewriting GT_ADDR(GT_LCL_FLD) to GT_LCL_FLD_ADDR:\n");
}
#endif // DEBUG
location->SetOper(addrForm(locationOp));
location->gtType = TYP_BYREF;
copyFlags(location, address, GTF_ALL_EFFECT);
use.ReplaceWith(comp, location);
BlockRange().Remove(address);
}
else if (locationOp == GT_CLS_VAR)
{
location->SetOper(GT_CLS_VAR_ADDR);
location->gtType = TYP_BYREF;
copyFlags(location, address, GTF_ALL_EFFECT);
use.ReplaceWith(comp, location);
BlockRange().Remove(address);
JITDUMP("Rewriting GT_ADDR(GT_CLS_VAR) to GT_CLS_VAR_ADDR:\n");
}
else if (location->OperIsIndir())
{
use.ReplaceWith(comp, location->gtGetOp1());
BlockRange().Remove(location);
BlockRange().Remove(address);
JITDUMP("Rewriting GT_ADDR(GT_IND(X)) to X:\n");
}
DISPTREERANGE(BlockRange(), use.Def());
JITDUMP("\n");
}
示例2: RewriteAssignment
void Rationalizer::RewriteAssignment(LIR::Use& use)
{
assert(use.IsInitialized());
GenTreeOp* assignment = use.Def()->AsOp();
assert(assignment->OperGet() == GT_ASG);
GenTree* location = assignment->gtGetOp1();
GenTree* value = assignment->gtGetOp2();
genTreeOps locationOp = location->OperGet();
switch (locationOp)
{
case GT_LCL_VAR:
case GT_LCL_FLD:
case GT_REG_VAR:
case GT_PHI_ARG:
RewriteAssignmentIntoStoreLclCore(assignment, location, value, locationOp);
BlockRange().Remove(location);
break;
case GT_IND:
{
GenTreeStoreInd* store =
new (comp, GT_STOREIND) GenTreeStoreInd(location->TypeGet(), location->gtGetOp1(), value);
copyFlags(store, assignment, GTF_ALL_EFFECT);
copyFlags(store, location, GTF_IND_FLAGS);
if (assignment->IsReverseOp())
{
store->gtFlags |= GTF_REVERSE_OPS;
}
// TODO: JIT dump
// Remove the GT_IND node and replace the assignment node with the store
BlockRange().Remove(location);
BlockRange().InsertBefore(assignment, store);
use.ReplaceWith(comp, store);
BlockRange().Remove(assignment);
}
break;
case GT_CLS_VAR:
{
location->SetOper(GT_CLS_VAR_ADDR);
location->gtType = TYP_BYREF;
assignment->SetOper(GT_STOREIND);
// TODO: JIT dump
}
break;
default:
unreached();
break;
}
}
示例3: RewriteSIMDOperand
// Rewrite a SIMD indirection as GT_IND(GT_LEA(obj.op1)), or as a simple
// lclVar if possible.
//
// Arguments:
// use - A use reference for a block node
// keepBlk - True if this should remain a block node if it is not a lclVar
//
// Return Value:
// None.
//
// TODO-1stClassStructs: These should be eliminated earlier, once we can handle
// lclVars in all the places that used to have GT_OBJ.
//
void Rationalizer::RewriteSIMDOperand(LIR::Use& use, bool keepBlk)
{
#ifdef FEATURE_SIMD
// No lowering is needed for non-SIMD nodes, so early out if featureSIMD is not enabled.
if (!comp->featureSIMD)
{
return;
}
GenTree* tree = use.Def();
if (!tree->OperIsIndir())
{
return;
}
var_types simdType = tree->TypeGet();
if (!varTypeIsSIMD(simdType))
{
return;
}
// If we have GT_IND(GT_LCL_VAR_ADDR) and the GT_LCL_VAR_ADDR is TYP_BYREF/TYP_I_IMPL,
// and the var is a SIMD type, replace the expression by GT_LCL_VAR.
GenTree* addr = tree->AsIndir()->Addr();
if (addr->OperIsLocalAddr() && comp->isAddrOfSIMDType(addr))
{
BlockRange().Remove(tree);
addr->SetOper(loadForm(addr->OperGet()));
addr->gtType = simdType;
use.ReplaceWith(comp, addr);
}
else if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->OperGet() == GT_SIMD))
{
// if we have GT_IND(GT_ADDR(GT_SIMD)), remove the GT_IND(GT_ADDR()), leaving just the GT_SIMD.
BlockRange().Remove(tree);
BlockRange().Remove(addr);
use.ReplaceWith(comp, addr->gtGetOp1());
}
else if (!keepBlk)
{
tree->SetOper(GT_IND);
tree->gtType = simdType;
}
#endif // FEATURE_SIMD
}
示例4: RewriteObj
// Rewrite GT_OBJ of SIMD Vector as GT_IND(GT_LEA(obj.op1)) of a SIMD type.
//
// Arguments:
// ppTree - A pointer-to-a-pointer for the GT_OBJ
// fgWalkData - A pointer to tree walk data providing the context
//
// Return Value:
// None.
//
// TODO-Cleanup: Once SIMD types are plumbed through the frontend, this will no longer
// be required.
//
void Rationalizer::RewriteObj(LIR::Use& use)
{
#ifdef FEATURE_SIMD
GenTreeObj* obj = use.Def()->AsObj();
// For UNIX struct passing, we can have Obj nodes for arguments.
// For other cases, we should never see a non-SIMD type here.
#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
if (!varTypeIsSIMD(obj))
{
return;
}
#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
// Should come here only if featureSIMD is enabled
noway_assert(comp->featureSIMD);
// We should only call this with a SIMD type.
noway_assert(varTypeIsSIMD(obj));
var_types simdType = obj->TypeGet();
// If the operand of obj is a GT_ADDR(GT_LCL_VAR) and LclVar is known to be a SIMD type,
// replace obj by GT_LCL_VAR.
GenTree* srcAddr = obj->gtGetOp1();
if (srcAddr->OperIsLocalAddr() && comp->isAddrOfSIMDType(srcAddr))
{
BlockRange().Remove(obj);
srcAddr->SetOper(loadForm(srcAddr->OperGet()));
srcAddr->gtType = simdType;
use.ReplaceWith(comp, srcAddr);
}
else
{
obj->SetOper(GT_IND);
obj->gtType = simdType;
}
#else
// we should never reach without feature SIMD
assert(!"Unexpected obj during rationalization\n");
unreached();
#endif
}
示例5: RewriteSIMDOperand
// Rewrite a SIMD indirection as GT_IND(GT_LEA(obj.op1)), or as a simple
// lclVar if possible.
//
// Arguments:
// use - A use reference for a block node
// keepBlk - True if this should remain a block node if it is not a lclVar
//
// Return Value:
// None.
//
// TODO-1stClassStructs: These should be eliminated earlier, once we can handle
// lclVars in all the places that used to have GT_OBJ.
//
void Rationalizer::RewriteSIMDOperand(LIR::Use& use, bool keepBlk)
{
#ifdef FEATURE_SIMD
// No lowering is needed for non-SIMD nodes, so early out if featureSIMD is not enabled.
if (!comp->featureSIMD)
{
return;
}
GenTree* tree = use.Def();
if (!tree->OperIsIndir())
{
return;
}
var_types simdType = tree->TypeGet();
if (!varTypeIsSIMD(simdType))
{
return;
}
// If the operand of is a GT_ADDR(GT_LCL_VAR) and LclVar is known to be of simdType,
// replace obj by GT_LCL_VAR.
GenTree* addr = tree->AsIndir()->Addr();
if (addr->OperIsLocalAddr() && comp->isAddrOfSIMDType(addr))
{
BlockRange().Remove(tree);
addr->SetOper(loadForm(addr->OperGet()));
addr->gtType = simdType;
use.ReplaceWith(comp, addr);
}
else if (!keepBlk)
{
tree->SetOper(GT_IND);
tree->gtType = simdType;
}
#endif // FEATURE_SIMD
}
示例6: RewriteNode
Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStack<GenTree*>& parentStack)
{
assert(useEdge != nullptr);
GenTree* node = *useEdge;
assert(node != nullptr);
#ifdef DEBUG
const bool isLateArg = (node->gtFlags & GTF_LATE_ARG) != 0;
#endif
// First, remove any preceeding list nodes, which are not otherwise visited by the tree walk.
//
// NOTE: GT_FIELD_LIST head nodes, and GT_LIST nodes used by phi nodes will in fact be visited.
for (GenTree* prev = node->gtPrev; prev != nullptr && prev->OperIsAnyList() && !(prev->OperIsFieldListHead());
prev = node->gtPrev)
{
BlockRange().Remove(prev);
}
// In addition, remove the current node if it is a GT_LIST node that is not an aggregate.
if (node->OperIsAnyList())
{
GenTreeArgList* list = node->AsArgList();
if (!list->OperIsFieldListHead())
{
BlockRange().Remove(list);
}
return Compiler::WALK_CONTINUE;
}
LIR::Use use;
if (parentStack.Height() < 2)
{
use = LIR::Use::GetDummyUse(BlockRange(), *useEdge);
}
else
{
use = LIR::Use(BlockRange(), useEdge, parentStack.Index(1));
}
assert(node == use.Def());
switch (node->OperGet())
{
case GT_ASG:
RewriteAssignment(use);
break;
case GT_BOX:
// GT_BOX at this level just passes through so get rid of it
use.ReplaceWith(comp, node->gtGetOp1());
BlockRange().Remove(node);
break;
case GT_ADDR:
RewriteAddress(use);
break;
case GT_IND:
// Clear the `GTF_IND_ASG_LHS` flag, which overlaps with `GTF_IND_REQ_ADDR_IN_REG`.
node->gtFlags &= ~GTF_IND_ASG_LHS;
if (varTypeIsSIMD(node))
{
RewriteSIMDOperand(use, false);
}
else
{
// Due to promotion of structs containing fields of type struct with a
// single scalar type field, we could potentially see IR nodes of the
// form GT_IND(GT_ADD(lclvarAddr, 0)) where 0 is an offset representing
// a field-seq. These get folded here.
//
// TODO: This code can be removed once JIT implements recursive struct
// promotion instead of lying about the type of struct field as the type
// of its single scalar field.
GenTree* addr = node->AsIndir()->Addr();
if (addr->OperGet() == GT_ADD && addr->gtGetOp1()->OperGet() == GT_LCL_VAR_ADDR &&
addr->gtGetOp2()->IsIntegralConst(0))
{
GenTreeLclVarCommon* lclVarNode = addr->gtGetOp1()->AsLclVarCommon();
unsigned lclNum = lclVarNode->GetLclNum();
LclVarDsc* varDsc = comp->lvaTable + lclNum;
if (node->TypeGet() == varDsc->TypeGet())
{
JITDUMP("Rewriting GT_IND(GT_ADD(LCL_VAR_ADDR,0)) to LCL_VAR\n");
lclVarNode->SetOper(GT_LCL_VAR);
lclVarNode->gtType = node->TypeGet();
use.ReplaceWith(comp, lclVarNode);
BlockRange().Remove(addr);
BlockRange().Remove(addr->gtGetOp2());
BlockRange().Remove(node);
}
}
}
break;
case GT_NOP:
// fgMorph sometimes inserts NOP nodes between defs and uses
// supposedly 'to prevent constant folding'. In this case, remove the
//.........这里部分代码省略.........
示例7: RewriteAssignment
void Rationalizer::RewriteAssignment(LIR::Use& use)
{
assert(use.IsInitialized());
GenTreeOp* assignment = use.Def()->AsOp();
assert(assignment->OperGet() == GT_ASG);
GenTree* location = assignment->gtGetOp1();
GenTree* value = assignment->gtGetOp2();
genTreeOps locationOp = location->OperGet();
if (assignment->OperIsBlkOp())
{
#ifdef FEATURE_SIMD
if (varTypeIsSIMD(location) && assignment->OperIsInitBlkOp())
{
if (location->OperGet() == GT_LCL_VAR)
{
var_types simdType = location->TypeGet();
GenTree* initVal = assignment->gtOp.gtOp2;
var_types baseType = comp->getBaseTypeOfSIMDLocal(location);
if (baseType != TYP_UNKNOWN)
{
GenTreeSIMD* simdTree = new (comp, GT_SIMD)
GenTreeSIMD(simdType, initVal, SIMDIntrinsicInit, baseType, genTypeSize(simdType));
assignment->gtOp.gtOp2 = simdTree;
value = simdTree;
initVal->gtNext = simdTree;
simdTree->gtPrev = initVal;
simdTree->gtNext = location;
location->gtPrev = simdTree;
}
}
}
#endif // FEATURE_SIMD
if ((location->TypeGet() == TYP_STRUCT) && !assignment->IsPhiDefn() && !value->IsMultiRegCall())
{
if ((location->OperGet() == GT_LCL_VAR))
{
// We need to construct a block node for the location.
// Modify lcl to be the address form.
location->SetOper(addrForm(locationOp));
LclVarDsc* varDsc = &(comp->lvaTable[location->AsLclVarCommon()->gtLclNum]);
location->gtType = TYP_BYREF;
GenTreeBlk* storeBlk = nullptr;
unsigned int size = varDsc->lvExactSize;
if (varDsc->lvStructGcCount != 0)
{
CORINFO_CLASS_HANDLE structHnd = varDsc->lvVerTypeInfo.GetClassHandle();
GenTreeObj* objNode = comp->gtNewObjNode(structHnd, location)->AsObj();
unsigned int slots = (unsigned)(roundUp(size, TARGET_POINTER_SIZE) / TARGET_POINTER_SIZE);
objNode->SetGCInfo(varDsc->lvGcLayout, varDsc->lvStructGcCount, slots);
objNode->ChangeOper(GT_STORE_OBJ);
objNode->SetData(value);
comp->fgMorphUnsafeBlk(objNode);
storeBlk = objNode;
}
else
{
storeBlk = new (comp, GT_STORE_BLK) GenTreeBlk(GT_STORE_BLK, TYP_STRUCT, location, value, size);
}
storeBlk->gtFlags |= (GTF_REVERSE_OPS | GTF_ASG);
storeBlk->gtFlags |= ((location->gtFlags | value->gtFlags) & GTF_ALL_EFFECT);
GenTree* insertionPoint = location->gtNext;
BlockRange().InsertBefore(insertionPoint, storeBlk);
use.ReplaceWith(comp, storeBlk);
BlockRange().Remove(assignment);
JITDUMP("After transforming local struct assignment into a block op:\n");
DISPTREERANGE(BlockRange(), use.Def());
JITDUMP("\n");
return;
}
else
{
assert(location->OperIsBlk());
}
}
}
switch (locationOp)
{
case GT_LCL_VAR:
case GT_LCL_FLD:
case GT_REG_VAR:
case GT_PHI_ARG:
RewriteAssignmentIntoStoreLclCore(assignment, location, value, locationOp);
BlockRange().Remove(location);
break;
case GT_IND:
{
GenTreeStoreInd* store =
new (comp, GT_STOREIND) GenTreeStoreInd(location->TypeGet(), location->gtGetOp1(), value);
copyFlags(store, assignment, GTF_ALL_EFFECT);
//.........这里部分代码省略.........
示例8: RewriteAssignment
void Rationalizer::RewriteAssignment(LIR::Use& use)
{
assert(use.IsInitialized());
GenTreeOp* assignment = use.Def()->AsOp();
assert(assignment->OperGet() == GT_ASG);
GenTree* location = assignment->gtGetOp1();
GenTree* value = assignment->gtGetOp2();
genTreeOps locationOp = location->OperGet();
#ifdef FEATURE_SIMD
if (varTypeIsSIMD(location) && assignment->OperIsInitBlkOp())
{
if (location->OperGet() == GT_LCL_VAR)
{
var_types simdType = location->TypeGet();
GenTree* initVal = assignment->gtOp.gtOp2;
var_types baseType = comp->getBaseTypeOfSIMDLocal(location);
if (baseType != TYP_UNKNOWN)
{
GenTreeSIMD* simdTree = new (comp, GT_SIMD)
GenTreeSIMD(simdType, initVal, SIMDIntrinsicInit, baseType, genTypeSize(simdType));
assignment->gtOp.gtOp2 = simdTree;
value = simdTree;
initVal->gtNext = simdTree;
simdTree->gtPrev = initVal;
simdTree->gtNext = location;
location->gtPrev = simdTree;
}
}
else
{
assert(location->OperIsBlk());
}
}
#endif // FEATURE_SIMD
switch (locationOp)
{
case GT_LCL_VAR:
case GT_LCL_FLD:
case GT_REG_VAR:
case GT_PHI_ARG:
RewriteAssignmentIntoStoreLclCore(assignment, location, value, locationOp);
BlockRange().Remove(location);
break;
case GT_IND:
{
GenTreeStoreInd* store =
new (comp, GT_STOREIND) GenTreeStoreInd(location->TypeGet(), location->gtGetOp1(), value);
copyFlags(store, assignment, GTF_ALL_EFFECT);
copyFlags(store, location, GTF_IND_FLAGS);
if (assignment->IsReverseOp())
{
store->gtFlags |= GTF_REVERSE_OPS;
}
// TODO: JIT dump
// Remove the GT_IND node and replace the assignment node with the store
BlockRange().Remove(location);
BlockRange().InsertBefore(assignment, store);
use.ReplaceWith(comp, store);
BlockRange().Remove(assignment);
}
break;
case GT_CLS_VAR:
{
location->SetOper(GT_CLS_VAR_ADDR);
location->gtType = TYP_BYREF;
assignment->SetOper(GT_STOREIND);
// TODO: JIT dump
}
break;
case GT_BLK:
case GT_OBJ:
case GT_DYN_BLK:
{
assert(varTypeIsStruct(location));
GenTreeBlk* storeBlk = location->AsBlk();
genTreeOps storeOper;
switch (location->gtOper)
{
case GT_BLK:
storeOper = GT_STORE_BLK;
break;
case GT_OBJ:
storeOper = GT_STORE_OBJ;
break;
case GT_DYN_BLK:
//.........这里部分代码省略.........
示例9: DecomposeNode
//.........这里部分代码省略.........
case GT_CALL:
nextNode = DecomposeCall(use);
break;
case GT_RETURN:
assert(tree->gtOp.gtOp1->OperGet() == GT_LONG);
break;
case GT_STOREIND:
nextNode = DecomposeStoreInd(use);
break;
case GT_STORE_LCL_FLD:
assert(tree->gtOp.gtOp1->OperGet() == GT_LONG);
NYI("st.lclFld of of TYP_LONG");
break;
case GT_IND:
nextNode = DecomposeInd(use);
break;
case GT_NOT:
nextNode = DecomposeNot(use);
break;
case GT_NEG:
nextNode = DecomposeNeg(use);
break;
// Binary operators. Those that require different computation for upper and lower half are
// handled by the use of GetHiOper().
case GT_ADD:
case GT_SUB:
case GT_OR:
case GT_XOR:
case GT_AND:
nextNode = DecomposeArith(use);
break;
case GT_MUL:
nextNode = DecomposeMul(use);
break;
case GT_DIV:
NYI("Arithmetic binary operators on TYP_LONG - GT_DIV");
break;
case GT_MOD:
NYI("Arithmetic binary operators on TYP_LONG - GT_MOD");
break;
case GT_UDIV:
NYI("Arithmetic binary operators on TYP_LONG - GT_UDIV");
break;
case GT_UMOD:
NYI("Arithmetic binary operators on TYP_LONG - GT_UMOD");
break;
case GT_LSH:
case GT_RSH:
case GT_RSZ:
nextNode = DecomposeShift(use);
break;
case GT_ROL:
case GT_ROR:
NYI("Arithmetic binary operators on TYP_LONG - ROTATE");
break;
case GT_MULHI:
NYI("Arithmetic binary operators on TYP_LONG - MULHI");
break;
case GT_LOCKADD:
case GT_XADD:
case GT_XCHG:
case GT_CMPXCHG:
NYI("Interlocked operations on TYP_LONG");
break;
default:
{
JITDUMP("Illegal TYP_LONG node %s in Decomposition.", GenTree::NodeName(tree->OperGet()));
noway_assert(!"Illegal TYP_LONG node in Decomposition.");
break;
}
}
#ifdef DEBUG
if (m_compiler->verbose)
{
// NOTE: st_lcl_var doesn't dump properly afterwards.
printf("Decomposing TYP_LONG tree. AFTER:\n");
m_compiler->gtDispTreeRange(Range(), use.Def());
}
#endif
return nextNode;
}
示例10: RewriteNode
Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStack<GenTree*>& parentStack)
{
assert(useEdge != nullptr);
GenTree* node = *useEdge;
assert(node != nullptr);
#ifdef DEBUG
const bool isLateArg = (node->gtFlags & GTF_LATE_ARG) != 0;
#endif
// First, remove any preceeding GT_LIST nodes, which are not otherwise visited by the tree walk.
//
// NOTE: GT_LIST nodes that are used by block ops and phi nodes will in fact be visited.
for (GenTree* prev = node->gtPrev; prev != nullptr && prev->OperGet() == GT_LIST; prev = node->gtPrev)
{
BlockRange().Remove(prev);
}
// In addition, remove the current node if it is a GT_LIST node.
if ((*useEdge)->OperGet() == GT_LIST)
{
BlockRange().Remove(*useEdge);
return Compiler::WALK_CONTINUE;
}
LIR::Use use;
if (parentStack.Height() < 2)
{
use = LIR::Use::GetDummyUse(BlockRange(), *useEdge);
}
else
{
use = LIR::Use(BlockRange(), useEdge, parentStack.Index(1));
}
assert(node == use.Def());
switch (node->OperGet())
{
case GT_ASG:
RewriteAssignment(use);
break;
case GT_BOX:
// GT_BOX at this level just passes through so get rid of it
use.ReplaceWith(comp, node->gtGetOp1());
BlockRange().Remove(node);
break;
case GT_ADDR:
RewriteAddress(use);
break;
case GT_NOP:
// fgMorph sometimes inserts NOP nodes between defs and uses
// supposedly 'to prevent constant folding'. In this case, remove the
// NOP.
if (node->gtGetOp1() != nullptr)
{
use.ReplaceWith(comp, node->gtGetOp1());
BlockRange().Remove(node);
}
break;
case GT_COMMA:
{
GenTree* op1 = node->gtGetOp1();
if ((op1->gtFlags & GTF_ALL_EFFECT) == 0)
{
// The LHS has no side effects. Remove it.
bool isClosed = false;
unsigned sideEffects = 0;
LIR::ReadOnlyRange lhsRange = BlockRange().GetTreeRange(op1, &isClosed, &sideEffects);
// None of the transforms performed herein violate tree order, so these
// should always be true.
assert(isClosed);
assert((sideEffects & GTF_ALL_EFFECT) == 0);
BlockRange().Delete(comp, m_block, std::move(lhsRange));
}
GenTree* replacement = node->gtGetOp2();
if (!use.IsDummyUse())
{
use.ReplaceWith(comp, replacement);
}
else
{
// This is a top-level comma. If the RHS has no side effects we can remove
// it as well.
if ((replacement->gtFlags & GTF_ALL_EFFECT) == 0)
{
bool isClosed = false;
unsigned sideEffects = 0;
LIR::ReadOnlyRange rhsRange = BlockRange().GetTreeRange(replacement, &isClosed, &sideEffects);
// None of the transforms performed herein violate tree order, so these
// should always be true.
assert(isClosed);
//.........这里部分代码省略.........
示例11: RewriteCopyBlk
// Transform CopyBlk involving SIMD vectors into stlclvar or stind of a SIMD type.
// Transformation is done if either src or dst are known to be SIMD vectors.
//
// Arguments:
// ppTree - A pointer-to-a-pointer for the GT_COPYBLK
// fgWalkData - A pointer to tree walk data providing the context
//
// Return Value:
// None.
//
// If either the source or the dst are known to be SIMD (a lclVar or SIMD intrinsic),
// get the simdType (TYP_DOUBLE or a SIMD type for SSE2) from the size of the SIMD node.
//
// For the source:
// - If it is a SIMD intrinsic or a lvSIMDType lclVar, change the node type to simdType.
// - Otherwise, add a GT_IND of simdType.
// For the dst:
// - If it is a lclVar of a SIMD type, chanage the node type to simdType.
// - Otherwise, change it to a GT_STORE_IND of simdType
//
// TODO-Cleanup: Once SIMD types are plumbed through the frontend, this will no longer
// be required.
//
void Rationalizer::RewriteCopyBlk(LIR::Use& use)
{
#ifdef FEATURE_SIMD
// No need to transofrm non-SIMD nodes, if featureSIMD is not enabled.
if (!comp->featureSIMD)
{
return;
}
// See if this is a SIMD copyBlk
GenTreeCpBlk* cpBlk = use.Def()->AsCpBlk();
GenTreePtr dstAddr = cpBlk->Dest();
GenTree* srcAddr = cpBlk->Source();
const bool srcIsSIMDAddr = comp->isAddrOfSIMDType(srcAddr);
const bool dstIsSIMDAddr = comp->isAddrOfSIMDType(dstAddr);
// Do not transform if neither src or dst is known to be a SIMD type.
// If src tree type is something we cannot reason but if dst is known to be of a SIMD type
// we will treat src tree as a SIMD type and vice versa.
if (!srcIsSIMDAddr && !dstIsSIMDAddr)
{
return;
}
// At this point it is known to be a copyblk of SIMD vectors and we can
// start transforming the original tree. Prior to this point do not perform
// any modifications to the original tree.
JITDUMP("\nRewriting SIMD CopyBlk\n");
DISPTREERANGE(BlockRange(), cpBlk);
// There are currently only three sizes supported: 8 bytes, 12 bytes, 16 bytes or the vector register length.
GenTreeIntConCommon* sizeNode = cpBlk->Size()->AsIntConCommon();
var_types simdType = comp->getSIMDTypeForSize((unsigned int)sizeNode->IconValue());
// Remove 'size' from execution order
BlockRange().Remove(sizeNode);
// Is destination a lclVar which is not an arg?
// If yes then we can turn it to a stlcl.var, otherwise turn into stind.
GenTree* simdDst = nullptr;
genTreeOps oper = GT_NONE;
if (dstIsSIMDAddr && dstAddr->OperIsLocalAddr())
{
simdDst = dstAddr;
simdDst->gtType = simdType;
oper = GT_STORE_LCL_VAR;
// For structs that are padded (e.g. Vector3f, Vector3i), the morpher will have marked them
// as GTF_VAR_USEASG. Unmark them.
simdDst->gtFlags &= ~(GTF_VAR_USEASG);
}
else
{
// Address of a non-local var
simdDst = dstAddr;
oper = GT_STOREIND;
}
GenTree* simdSrc = nullptr;
if ((srcAddr->OperGet() == GT_ADDR) && varTypeIsSIMD(srcAddr->gtGetOp1()))
{
// Get rid of parent node of GT_ADDR(..) if its child happens to be of a SIMD type.
BlockRange().Remove(srcAddr);
simdSrc = srcAddr->gtGetOp1();
}
else if (srcIsSIMDAddr && srcAddr->OperIsLocalAddr())
{
// If the source has been rewritten into a local addr node, rewrite it back into a
// local var node.
simdSrc = srcAddr;
simdSrc->SetOper(loadForm(srcAddr->OperGet()));
}
else
{
// Since destination is known to be a SIMD type, src must be a SIMD type too
// though we cannot figure it out easily enough. Transform src into
//.........这里部分代码省略.........
示例12: RewriteInitBlk
// Rewrite InitBlk involving SIMD vector into stlcl.var of a SIMD type.
//
// Arguments:
// ppTree - A pointer-to-a-pointer for the GT_INITBLK
// fgWalkData - A pointer to tree walk data providing the context
//
// Return Value:
// None.
//
// TODO-Cleanup: Once SIMD types are plumbed through the frontend, this will no longer
// be required.
//
void Rationalizer::RewriteInitBlk(LIR::Use& use)
{
#ifdef FEATURE_SIMD
// No lowering is needed for non-SIMD nodes, so early out if featureSIMD is not enabled.
if (!comp->featureSIMD)
{
return;
}
// See if this is a SIMD initBlk that needs to be changed to a simple st.lclVar.
GenTreeInitBlk* initBlk = use.Def()->AsInitBlk();
// Is the dstAddr is addr of a SIMD type lclVar?
GenTree* dstAddr = initBlk->Dest();
if (!comp->isAddrOfSIMDType(dstAddr) || !dstAddr->OperIsLocalAddr())
{
return;
}
unsigned lclNum = dstAddr->AsLclVarCommon()->gtLclNum;
if (!comp->lvaTable[lclNum].lvSIMDType)
{
return;
}
var_types baseType = comp->lvaTable[lclNum].lvBaseType;
CORINFO_CLASS_HANDLE typeHnd = comp->lvaTable[lclNum].lvVerTypeInfo.GetClassHandle();
unsigned simdLocalSize = comp->getSIMDTypeSizeInBytes(typeHnd);
JITDUMP("Rewriting SIMD InitBlk\n");
DISPTREERANGE(BlockRange(), initBlk);
assert((dstAddr->gtFlags & GTF_VAR_USEASG) == 0);
// There are currently only three sizes supported: 8 bytes, 16 bytes or the vector register length.
GenTreeIntConCommon* sizeNode = initBlk->Size()->AsIntConCommon();
unsigned int size = (unsigned int)roundUp(sizeNode->IconValue(), TARGET_POINTER_SIZE);
var_types simdType = comp->getSIMDTypeForSize(size);
assert(roundUp(simdLocalSize, TARGET_POINTER_SIZE) == size);
GenTree* initVal = initBlk->InitVal();
GenTreeSIMD* simdNode = new (comp, GT_SIMD)
GenTreeSIMD(simdType, initVal, SIMDIntrinsicInit, baseType, (unsigned)sizeNode->IconValue());
dstAddr->SetOper(GT_STORE_LCL_VAR);
GenTreeLclVar* store = dstAddr->AsLclVar();
store->gtType = simdType;
store->gtOp.gtOp1 = simdNode;
store->gtFlags |= ((simdNode->gtFlags & GTF_ALL_EFFECT) | GTF_ASG);
BlockRange().Remove(store);
// Insert the new nodes into the block
BlockRange().InsertAfter(initVal, simdNode, store);
use.ReplaceWith(comp, store);
// Remove the old size and GT_INITBLK nodes.
BlockRange().Remove(sizeNode);
BlockRange().Remove(initBlk);
JITDUMP("After rewriting SIMD InitBlk:\n");
DISPTREERANGE(BlockRange(), use.Def());
JITDUMP("\n");
#endif // FEATURE_SIMD
}