diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 2ec6ed5e5be4ff..2ea06b50c65ddb 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -4809,9 +4809,41 @@ bool Compiler::gtMarkAddrMode(GenTree* addr, int* pCostEx, int* pCostSz, var_typ gtWalkOp(&op2, &op1, nullptr, true); #endif // defined(TARGET_XARCH) - if ((mul > 1) && (op2 != nullptr) && op2->OperIs(GT_LSH, GT_MUL)) + bool noCSE = (mul > 1); +#if defined(TARGET_RISCV64) + noCSE = this->compOpportunisticallyDependsOn(InstructionSet_Zba); +#endif + + if (noCSE && (op2 != nullptr) && op2->OperIs(GT_LSH, GT_MUL)) { op2->gtFlags |= GTF_ADDRMODE_NO_CSE; + +#if defined(TARGET_RISCV64) + // RISC-V addressing mode is based on: (base + index*scale) + offset. + // To emit shXadd.uw, GT_ADD + GT_LSH(or MUL) + GT_CAST nodes are required. + // GT_CAST nodes benefit from shXadd.uw variants(Zba) by disabling CSEs. + // + // Example: + // ADD + // |- ADD + // | |- LCL_VAR (base) + // | |- LSH (or MUL) (index * scale) + // | |- GT_CAST (index, CSE shouldn't be applied on this node to emit shXadd.uw) + // | |- OP1 (CSE/ConstCSE possible on this node and its children) + // | |- CNS_INT (scale) + // |- CNS_INT (offset) + // + // Other nodes than GT_CAST can benefit from shXadd variants without GTF_DONT_CSE flags, + // because shXadd doesn't require a GT_CAST node. + + GenTree* index = op2->gtGetOp1(); + if ((index != nullptr) && index->OperIs(GT_CAST)) + { + assert(index->TypeIs(TYP_I_IMPL)); + index->gtFlags |= GTF_DONT_CSE; + } + +#endif } // Finally, adjust the costs on the parenting COMMAs.