@@ -4578,48 +4578,112 @@ void CodeGen::genSIMDIntrinsicGetItem(GenTreeSIMD* simdNode)
45784578 // - the source of SIMD type (op1)
45794579 // - the index of the value to be returned.
45804580 genConsumeOperands (simdNode);
4581- regNumber srcReg = op1->gtRegNum ;
45824581
4583- // TODO-ARM64-CQ Optimize SIMDIntrinsicGetItem
4584- // Optimize the case of op1 is in memory and trying to access ith element.
4585- assert (op1->isUsedFromReg ());
4586-
4587- emitAttr baseTypeSize = emitTypeSize (baseType);
4582+ emitAttr baseTypeSize = emitTypeSize (baseType);
4583+ unsigned baseTypeScale = genLog2 (EA_SIZE_IN_BYTES (baseTypeSize));
45884584
45894585 if (op2->IsCnsIntOrI ())
45904586 {
45914587 assert (op2->isContained ());
45924588
45934589 ssize_t index = op2->gtIntCon .gtIconVal ;
45944590
4591+ // We only need to generate code for the get if the index is valid
4592+ // If the index is invalid, previously generated for the range check will throw
45954593 if (getEmitter ()->isValidVectorIndex (emitTypeSize (simdType), baseTypeSize, index))
45964594 {
4597- // Only generate code for the get if the index is valid
4598- // Otherwise generated code will throw
4599- getEmitter ()->emitIns_R_R_I (INS_mov, baseTypeSize, targetReg, srcReg, index);
4595+ if (op1->isContained ())
4596+ {
4597+ int offset = (int )index * genTypeSize (baseType);
4598+ instruction ins = ins_Load (baseType);
4599+ baseTypeSize = varTypeIsFloating (baseType)
4600+ ? baseTypeSize
4601+ : getEmitter ()->emitInsAdjustLoadStoreAttr (ins, baseTypeSize);
4602+
4603+ assert (!op1->isUsedFromReg ());
4604+
4605+ if (op1->OperIsLocal ())
4606+ {
4607+ unsigned varNum = op1->gtLclVarCommon .gtLclNum ;
4608+
4609+ getEmitter ()->emitIns_R_S (ins, baseTypeSize, targetReg, varNum, offset);
4610+ }
4611+ else
4612+ {
4613+ assert (op1->OperGet () == GT_IND);
4614+
4615+ GenTree* addr = op1->AsIndir ()->Addr ();
4616+ assert (!addr->isContained ());
4617+ regNumber baseReg = addr->gtRegNum ;
4618+
4619+ // ldr targetReg, [baseReg, #offset]
4620+ getEmitter ()->emitIns_R_R_I (ins, baseTypeSize, targetReg, baseReg, offset);
4621+ }
4622+ }
4623+ else
4624+ {
4625+ assert (op1->isUsedFromReg ());
4626+ regNumber srcReg = op1->gtRegNum ;
4627+
4628+ // mov targetReg, srcReg[#index]
4629+ getEmitter ()->emitIns_R_R_I (INS_mov, baseTypeSize, targetReg, srcReg, index);
4630+ }
46004631 }
46014632 }
46024633 else
46034634 {
4604- unsigned simdInitTempVarNum = compiler->lvaSIMDInitTempVarNum ;
4605- noway_assert (compiler->lvaSIMDInitTempVarNum != BAD_VAR_NUM);
4635+ assert (!op2->isContained ());
46064636
4637+ regNumber baseReg = REG_NA;
46074638 regNumber indexReg = op2->gtRegNum ;
4608- regNumber tmpReg = simdNode->ExtractTempReg ();
46094639
4610- assert (genIsValidIntReg (tmpReg));
4611- assert (tmpReg != indexReg);
4640+ if (op1->isContained ())
4641+ {
4642+ // Optimize the case of op1 is in memory and trying to access ith element.
4643+ assert (!op1->isUsedFromReg ());
4644+ if (op1->OperIsLocal ())
4645+ {
4646+ unsigned varNum = op1->gtLclVarCommon .gtLclNum ;
4647+
4648+ baseReg = simdNode->ExtractTempReg ();
4649+
4650+ // Load the address of varNum
4651+ getEmitter ()->emitIns_R_S (INS_lea, EA_PTRSIZE, baseReg, varNum, 0 );
4652+ }
4653+ else
4654+ {
4655+ // Require GT_IND addr to be not contained.
4656+ assert (op1->OperGet () == GT_IND);
4657+
4658+ GenTree* addr = op1->AsIndir ()->Addr ();
4659+ assert (!addr->isContained ());
46124660
4613- unsigned baseTypeScale = genLog2 (EA_SIZE_IN_BYTES (baseTypeSize));
4661+ baseReg = addr->gtRegNum ;
4662+ }
4663+ }
4664+ else
4665+ {
4666+ assert (op1->isUsedFromReg ());
4667+ regNumber srcReg = op1->gtRegNum ;
46144668
4615- // Load the address of simdInitTempVarNum
4616- getEmitter ()->emitIns_R_S (INS_lea, EA_PTRSIZE, tmpReg, simdInitTempVarNum, 0 );
4669+ unsigned simdInitTempVarNum = compiler->lvaSIMDInitTempVarNum ;
4670+ noway_assert (compiler->lvaSIMDInitTempVarNum != BAD_VAR_NUM);
4671+
4672+ baseReg = simdNode->ExtractTempReg ();
4673+
4674+ // Load the address of simdInitTempVarNum
4675+ getEmitter ()->emitIns_R_S (INS_lea, EA_PTRSIZE, baseReg, simdInitTempVarNum, 0 );
4676+
4677+ // Store the vector to simdInitTempVarNum
4678+ getEmitter ()->emitIns_R_R (INS_str, emitTypeSize (simdType), srcReg, baseReg);
4679+ }
46174680
4618- // Store the vector to simdInitTempVarNum
4619- getEmitter ()->emitIns_R_R (INS_str, emitTypeSize (simdType), srcReg, tmpReg);
4681+ assert (genIsValidIntReg (indexReg));
4682+ assert (genIsValidIntReg (baseReg));
4683+ assert (baseReg != indexReg);
46204684
4621- // Load item at simdInitTempVarNum [index]
4622- getEmitter ()->emitIns_R_R_R_Ext (ins_Load (baseType), baseTypeSize, targetReg, tmpReg , indexReg, INS_OPTS_LSL,
4685+ // Load item at baseReg [index]
4686+ getEmitter ()->emitIns_R_R_R_Ext (ins_Load (baseType), baseTypeSize, targetReg, baseReg , indexReg, INS_OPTS_LSL,
46234687 baseTypeScale);
46244688 }
46254689
0 commit comments