1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
20 #include "sideeffects.h"
22 class Lowering : public Phase
25 inline Lowering(Compiler* compiler, LinearScanInterface* lsra)
26 : Phase(compiler, "Lowering", PHASE_LOWERING), vtableCallTemp(BAD_VAR_NUM)
28 m_lsra = (LinearScan*)lsra;
31 virtual void DoPhase() override;
33 // This variant of LowerRange is called from outside of the main Lowering pass,
34 // so it creates its own instance of Lowering to do so.
35 void LowerRange(BasicBlock* block, LIR::ReadOnlyRange& range)
37 Lowering lowerer(comp, m_lsra);
38 lowerer.m_block = block;
40 lowerer.LowerRange(range);
44 // LowerRange handles new code that is introduced by or after Lowering.
45 void LowerRange(LIR::ReadOnlyRange& range)
47 for (GenTree* newNode : range)
52 void LowerRange(GenTree* firstNode, GenTree* lastNode)
54 LIR::ReadOnlyRange range(firstNode, lastNode);
58 // ContainCheckRange handles new code that is introduced by or after Lowering,
59 // and that is known to be already in Lowered form.
60 void ContainCheckRange(LIR::ReadOnlyRange& range)
62 for (GenTree* newNode : range)
64 ContainCheckNode(newNode);
67 void ContainCheckRange(GenTree* firstNode, GenTree* lastNode)
69 LIR::ReadOnlyRange range(firstNode, lastNode);
70 ContainCheckRange(range);
73 void InsertTreeBeforeAndContainCheck(GenTree* insertionPoint, GenTree* tree)
75 LIR::Range range = LIR::SeqTree(comp, tree);
76 ContainCheckRange(range);
77 BlockRange().InsertBefore(insertionPoint, std::move(range));
80 void ContainCheckNode(GenTree* node);
82 void ContainCheckDivOrMod(GenTreeOp* node);
83 void ContainCheckReturnTrap(GenTreeOp* node);
84 void ContainCheckArrOffset(GenTreeArrOffs* node);
85 void ContainCheckLclHeap(GenTreeOp* node);
86 void ContainCheckRet(GenTreeOp* node);
87 void ContainCheckJTrue(GenTreeOp* node);
89 void ContainCheckCallOperands(GenTreeCall* call);
90 void ContainCheckIndir(GenTreeIndir* indirNode);
91 void ContainCheckStoreIndir(GenTreeIndir* indirNode);
92 void ContainCheckMul(GenTreeOp* node);
93 void ContainCheckShiftRotate(GenTreeOp* node);
94 void ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc);
95 void ContainCheckCast(GenTreeCast* node);
96 void ContainCheckCompare(GenTreeOp* node);
97 void ContainCheckBinary(GenTreeOp* node);
98 void ContainCheckBoundsChk(GenTreeBoundsChk* node);
100 void ContainCheckFloatBinary(GenTreeOp* node);
101 void ContainCheckIntrinsic(GenTreeOp* node);
102 #endif // _TARGET_XARCH_
104 void ContainCheckSIMD(GenTreeSIMD* simdNode);
105 #endif // FEATURE_SIMD
106 #ifdef FEATURE_HW_INTRINSICS
107 void ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node);
108 #endif // FEATURE_HW_INTRINSICS
111 static void CheckCallArg(GenTree* arg);
112 static void CheckCall(GenTreeCall* call);
113 static void CheckNode(Compiler* compiler, GenTree* node);
114 static bool CheckBlock(Compiler* compiler, BasicBlock* block);
117 void LowerBlock(BasicBlock* block);
118 GenTree* LowerNode(GenTree* node);
120 void CheckVSQuirkStackPaddingNeeded(GenTreeCall* call);
122 // ------------------------------
124 // ------------------------------
125 void LowerCall(GenTree* call);
126 #ifndef _TARGET_64BIT_
127 GenTree* DecomposeLongCompare(GenTree* cmp);
129 GenTree* OptimizeConstCompare(GenTree* cmp);
130 GenTree* LowerCompare(GenTree* cmp);
131 GenTree* LowerJTrue(GenTreeOp* jtrue);
132 void LowerJmpMethod(GenTree* jmp);
133 void LowerRet(GenTree* ret);
134 GenTree* LowerDelegateInvoke(GenTreeCall* call);
135 GenTree* LowerIndirectNonvirtCall(GenTreeCall* call);
136 GenTree* LowerDirectCall(GenTreeCall* call);
137 GenTree* LowerNonvirtPinvokeCall(GenTreeCall* call);
138 GenTree* LowerTailCallViaHelper(GenTreeCall* callNode, GenTree* callTarget);
139 void LowerFastTailCall(GenTreeCall* callNode);
140 void InsertProfTailCallHook(GenTreeCall* callNode, GenTree* insertionPoint);
141 GenTree* LowerVirtualVtableCall(GenTreeCall* call);
142 GenTree* LowerVirtualStubCall(GenTreeCall* call);
143 void LowerArgsForCall(GenTreeCall* call);
144 void ReplaceArgWithPutArgOrBitcast(GenTree** ppChild, GenTree* newNode);
145 GenTree* NewPutArg(GenTreeCall* call, GenTree* arg, fgArgTabEntry* info, var_types type);
146 void LowerArg(GenTreeCall* call, GenTree** ppTree);
147 #ifdef _TARGET_ARMARCH_
148 GenTree* LowerFloatArg(GenTree** pArg, fgArgTabEntry* info);
149 GenTree* LowerFloatArgReg(GenTree* arg, regNumber regNum);
152 void InsertPInvokeCallProlog(GenTreeCall* call);
153 void InsertPInvokeCallEpilog(GenTreeCall* call);
154 void InsertPInvokeMethodProlog();
155 void InsertPInvokeMethodEpilog(BasicBlock* returnBB DEBUGARG(GenTree* lastExpr));
156 GenTree* SetGCState(int cns);
157 GenTree* CreateReturnTrapSeq();
163 GenTree* CreateFrameLinkUpdate(FrameLinkAction);
164 GenTree* AddrGen(ssize_t addr);
165 GenTree* AddrGen(void* addr);
167 GenTree* Ind(GenTree* tree)
169 return comp->gtNewOperNode(GT_IND, TYP_I_IMPL, tree);
172 GenTree* PhysReg(regNumber reg, var_types type = TYP_I_IMPL)
174 return comp->gtNewPhysRegNode(reg, type);
177 GenTree* ThisReg(GenTreeCall* call)
179 return PhysReg(comp->codeGen->genGetThisArgReg(call), TYP_REF);
182 GenTree* Offset(GenTree* base, unsigned offset)
184 var_types resultType = (base->TypeGet() == TYP_REF) ? TYP_BYREF : base->TypeGet();
185 return new (comp, GT_LEA) GenTreeAddrMode(resultType, base, nullptr, 0, offset);
188 GenTree* OffsetByIndex(GenTree* base, GenTree* index)
190 var_types resultType = (base->TypeGet() == TYP_REF) ? TYP_BYREF : base->TypeGet();
191 return new (comp, GT_LEA) GenTreeAddrMode(resultType, base, index, 0, 0);
194 GenTree* OffsetByIndexWithScale(GenTree* base, GenTree* index, unsigned scale)
196 var_types resultType = (base->TypeGet() == TYP_REF) ? TYP_BYREF : base->TypeGet();
197 return new (comp, GT_LEA) GenTreeAddrMode(resultType, base, index, scale, 0);
200 // Replace the definition of the given use with a lclVar, allocating a new temp
201 // if 'tempNum' is BAD_VAR_NUM. Returns the LclVar node.
202 GenTreeLclVar* ReplaceWithLclVar(LIR::Use& use, unsigned tempNum = BAD_VAR_NUM)
204 GenTree* oldUseNode = use.Def();
205 if ((oldUseNode->gtOper != GT_LCL_VAR) || (tempNum != BAD_VAR_NUM))
207 use.ReplaceWithLclVar(comp, m_block->getBBWeight(comp), tempNum);
208 GenTree* newUseNode = use.Def();
209 ContainCheckRange(oldUseNode->gtNext, newUseNode);
210 return newUseNode->AsLclVar();
212 return oldUseNode->AsLclVar();
215 // return true if this call target is within range of a pc-rel call on the machine
216 bool IsCallTargetInRange(void* addr);
218 #if defined(_TARGET_XARCH_)
219 GenTree* PreferredRegOptionalOperand(GenTree* tree);
221 // ------------------------------------------------------------------
222 // SetRegOptionalBinOp - Indicates which of the operands of a bin-op
223 // register requirement is optional. Xarch instruction set allows
224 // either of op1 or op2 of binary operation (e.g. add, mul etc) to be
225 // a memory operand. This routine provides info to register allocator
226 // which of its operands optionally require a register. Lsra might not
227 // allocate a register to RefTypeUse positions of such operands if it
228 // is beneficial. In such a case codegen will treat them as memory
232 // tree - Gentree of a binary operation.
233 // isSafeToMarkOp1 True if it's safe to mark op1 as register optional
234 // isSafeToMarkOp2 True if it's safe to mark op2 as register optional
237 // The caller is expected to get isSafeToMarkOp1 and isSafeToMarkOp2
238 // by calling IsSafeToContainMem.
240 // Note: On xarch at most only one of the operands will be marked as
241 // reg optional, even when both operands could be considered register
243 void SetRegOptionalForBinOp(GenTree* tree, bool isSafeToMarkOp1, bool isSafeToMarkOp2)
245 assert(GenTree::OperIsBinary(tree->OperGet()));
247 GenTree* const op1 = tree->gtGetOp1();
248 GenTree* const op2 = tree->gtGetOp2();
250 const unsigned operatorSize = genTypeSize(tree->TypeGet());
252 const bool op1Legal =
253 isSafeToMarkOp1 && tree->OperIsCommutative() && (operatorSize == genTypeSize(op1->TypeGet()));
254 const bool op2Legal = isSafeToMarkOp2 && (operatorSize == genTypeSize(op2->TypeGet()));
256 GenTree* regOptionalOperand = nullptr;
259 regOptionalOperand = op2Legal ? PreferredRegOptionalOperand(tree) : op1;
263 regOptionalOperand = op2;
265 if (regOptionalOperand != nullptr)
267 regOptionalOperand->SetRegOptional();
270 #endif // defined(_TARGET_XARCH_)
272 // Per tree node member functions
273 void LowerStoreIndir(GenTreeIndir* node);
274 GenTree* LowerAdd(GenTree* node);
275 bool LowerUnsignedDivOrMod(GenTreeOp* divMod);
276 GenTree* LowerConstIntDivOrMod(GenTree* node);
277 GenTree* LowerSignedDivOrMod(GenTree* node);
278 void LowerBlockStore(GenTreeBlk* blkNode);
279 void LowerPutArgStk(GenTreePutArgStk* tree);
281 GenTree* TryCreateAddrMode(LIR::Use&& use, bool isIndir);
282 void AddrModeCleanupHelper(GenTreeAddrMode* addrMode, GenTree* node);
284 GenTree* LowerSwitch(GenTree* node);
285 bool TryLowerSwitchToBitTest(
286 BasicBlock* jumpTable[], unsigned jumpCount, unsigned targetCount, BasicBlock* bbSwitch, GenTree* switchValue);
288 void LowerCast(GenTree* node);
290 #if !CPU_LOAD_STORE_ARCH
291 bool IsRMWIndirCandidate(GenTree* operand, GenTree* storeInd);
292 bool IsBinOpInRMWStoreInd(GenTree* tree);
293 bool IsRMWMemOpRootedAtStoreInd(GenTree* storeIndTree, GenTree** indirCandidate, GenTree** indirOpSource);
294 bool LowerRMWMemOp(GenTreeIndir* storeInd);
297 void WidenSIMD12IfNecessary(GenTreeLclVarCommon* node);
298 void LowerStoreLoc(GenTreeLclVarCommon* tree);
299 GenTree* LowerArrElem(GenTree* node);
300 void LowerRotate(GenTree* tree);
301 void LowerShift(GenTreeOp* shift);
303 void LowerSIMD(GenTreeSIMD* simdNode);
304 #endif // FEATURE_SIMD
305 #ifdef FEATURE_HW_INTRINSICS
306 void LowerHWIntrinsic(GenTreeHWIntrinsic* node);
307 #endif // FEATURE_HW_INTRINSICS
311 static bool IndirsAreEquivalent(GenTree* pTreeA, GenTree* pTreeB);
313 // return true if 'childNode' is an immediate that can be contained
314 // by the 'parentNode' (i.e. folded into an instruction)
315 // for example small enough and non-relocatable
316 bool IsContainableImmed(GenTree* parentNode, GenTree* childNode);
318 // Return true if 'node' is a containable memory op.
319 bool IsContainableMemoryOp(GenTree* node)
321 return m_lsra->isContainableMemoryOp(node);
324 #ifdef FEATURE_HW_INTRINSICS
325 // Return true if 'node' is a containable HWIntrinsic op.
326 bool IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, GenTree* node, bool* supportsRegOptional);
327 #endif // FEATURE_HW_INTRINSICS
330 static bool NodesAreEquivalentLeaves(GenTree* candidate, GenTree* storeInd);
332 bool AreSourcesPossiblyModifiedLocals(GenTree* addr, GenTree* base, GenTree* index);
334 // Makes 'childNode' contained in the 'parentNode'
335 void MakeSrcContained(GenTree* parentNode, GenTree* childNode);
337 // Checks and makes 'childNode' contained in the 'parentNode'
338 bool CheckImmedAndMakeContained(GenTree* parentNode, GenTree* childNode);
340 // Checks for memory conflicts in the instructions between childNode and parentNode, and returns true if childNode
342 bool IsSafeToContainMem(GenTree* parentNode, GenTree* childNode);
344 inline LIR::Range& BlockRange() const
346 return LIR::AsRange(m_block);
349 // Any tracked lclVar accessed by a LCL_FLD or STORE_LCL_FLD should be marked doNotEnregister.
350 // This method checks, and asserts in the DEBUG case if it is not so marked,
351 // but in the non-DEBUG case (asserts disabled) set the flag so that we don't generate bad code.
352 // This ensures that the local's value is valid on-stack as expected for a *LCL_FLD.
353 void verifyLclFldDoNotEnregister(unsigned lclNum)
355 LclVarDsc* varDsc = &(comp->lvaTable[lclNum]);
356 // Do a couple of simple checks before setting lvDoNotEnregister.
357 // This may not cover all cases in 'isRegCandidate()' but we don't want to
358 // do an expensive check here. For non-candidates it is not harmful to set lvDoNotEnregister.
359 if (varDsc->lvTracked && !varDsc->lvDoNotEnregister)
361 assert(!m_lsra->isRegCandidate(varDsc));
362 comp->lvaSetVarDoNotEnregister(lclNum DEBUG_ARG(Compiler::DNER_LocalField));
367 unsigned vtableCallTemp; // local variable we use as a temp for vtable calls
368 SideEffectSet m_scratchSideEffects; // SideEffectSet used for IsSafeToContainMem and isRMWIndirCandidate