From c36d746e17c37f5112b0b2d4967b5cba33c93b55 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 14 Oct 2024 13:27:45 +0200 Subject: [PATCH] JIT: Produce correctly typed IR in TLS helper expansion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TLS helper expansion would produce `ADD(long, int)` trees like ``` ▌ STORE_LCL_VAR long V01 rat0 └──▌ ADD long ├──▌ ADD long │ ├──▌ LCL_VAR long V02 rat1 │ └──▌ CNS_INT int 72 $41 └──▌ CNS_INT long 192 ``` which is not legal IR. Fix that by inserting a cast. Also do some more aggressive folding to get rid of these casts in the normal cases, and to fold some constant arithmeticf in other cases. --- src/coreclr/jit/helperexpansion.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index 3d5678d2743b42..7243b750996e7c 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -991,6 +991,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* tlsValueDef = gtNewStoreLclVarNode(tlsLclNum, tlsValue); GenTree* tlsLclValueUse = gtNewLclVarNode(tlsLclNum); GenTree* typeThreadStaticBlockIndexValue = call->gtArgs.GetArgByIndex(0)->GetNode(); + assert(genActualType(typeThreadStaticBlockIndexValue) == TYP_INT); if (helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2) { @@ -1007,12 +1008,19 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* // use(tlsRoot); // ... - GenTree* typeThreadStaticBlockIndexValue = call->gtArgs.GetArgByIndex(0)->GetNode(); - GenTree* threadStaticBase = - gtNewOperNode(GT_ADD, TYP_I_IMPL, - gtNewOperNode(GT_ADD, TYP_I_IMPL, gtCloneExpr(tlsLclValueUse), - gtCloneExpr(typeThreadStaticBlockIndexValue)), + typeThreadStaticBlockIndexValue = gtCloneExpr(typeThreadStaticBlockIndexValue); +#ifdef TARGET_64BIT + typeThreadStaticBlockIndexValue = gtNewCastNode(TYP_I_IMPL, typeThreadStaticBlockIndexValue, true, TYP_I_IMPL); + // Usually a constant, try to fold + typeThreadStaticBlockIndexValue = gtFoldExpr(typeThreadStaticBlockIndexValue); +#endif + + GenTree* offset = + gtNewOperNode(GT_ADD, TYP_I_IMPL, typeThreadStaticBlockIndexValue, gtNewIconNode(threadStaticBlocksInfo.offsetOfBaseOfThreadLocalData, TYP_I_IMPL)); + offset = gtFoldExpr(offset); + + GenTree* threadStaticBase = gtNewOperNode(GT_ADD, TYP_I_IMPL, gtCloneExpr(tlsLclValueUse), offset); GenTree* tlsStaticBaseStoreLcl = gtNewStoreLclVarNode(threadStaticBlockLclNum, threadStaticBase); BasicBlock* tlsBaseComputeBB = fgNewBBFromTreeAfter(BBJ_ALWAYS, prevBb, tlsValueDef, debugInfo, true); @@ -1060,6 +1068,14 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* // Create tree to "threadStaticBlockValue = threadStaticBlockBase[typeIndex]" typeThreadStaticBlockIndexValue = gtNewOperNode(GT_MUL, TYP_INT, gtCloneExpr(typeThreadStaticBlockIndexValue), gtNewIconNode(TARGET_POINTER_SIZE, TYP_INT)); + // Usually a constant, try to fold + typeThreadStaticBlockIndexValue = gtFoldExpr(typeThreadStaticBlockIndexValue); +#ifdef TARGET_64BIT + typeThreadStaticBlockIndexValue = gtNewCastNode(TYP_I_IMPL, typeThreadStaticBlockIndexValue, true, TYP_I_IMPL); + + // Usually a constant, try to fold + typeThreadStaticBlockIndexValue = gtFoldExpr(typeThreadStaticBlockIndexValue); +#endif GenTree* typeThreadStaticBlockRef = gtNewOperNode(GT_ADD, TYP_BYREF, threadStaticBlocksValue, typeThreadStaticBlockIndexValue); GenTree* typeThreadStaticBlockValue = gtNewIndir(TYP_BYREF, typeThreadStaticBlockRef, GTF_IND_NONFAULTING); @@ -1416,7 +1432,7 @@ bool Compiler::fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, G } // Don't fold ADD(CNS1, CNS2) here since the result won't be reloc-friendly for AOT - GenTree* offsetNode = gtNewOperNode(GT_ADD, TYP_I_IMPL, baseAddr, gtNewIconNode(isInitOffset)); + GenTree* offsetNode = gtNewOperNode(GT_ADD, TYP_I_IMPL, baseAddr, gtNewIconNode(isInitOffset, TYP_I_IMPL)); isInitedActualValueNode = gtNewIndir(TYP_I_IMPL, offsetNode, GTF_IND_NONFAULTING | GTF_IND_VOLATILE); // 0 means "initialized" on NativeAOT