@@ -12446,7 +12446,19 @@ void CodeGenInterface::VariableLiveKeeper::dumpLvaVariableLiveRanges() const
1244612446void CodeGen::genPoisonFrame (regMaskTP regLiveIn)
1244712447{
1244812448 assert (compiler->compShouldPoisonFrame ());
12449- assert ((regLiveIn & genRegMask (REG_SCRATCH)) == 0 );
12449+ #if defined(TARGET_XARCH)
12450+ regNumber poisonValReg = REG_EAX;
12451+ assert ((regLiveIn & (RBM_EDI | RBM_ECX | RBM_EAX)) == 0 );
12452+ #else
12453+ regNumber poisonValReg = REG_SCRATCH;
12454+ assert ((regLiveIn & (genRegMask (REG_SCRATCH) | RBM_ARG_0 | RBM_ARG_1 | RBM_ARG_2)) == 0 );
12455+ #endif
12456+
12457+ #ifdef TARGET_64BIT
12458+ const ssize_t poisonVal = (ssize_t )0xcdcdcdcdcdcdcdcd ;
12459+ #else
12460+ const ssize_t poisonVal = (ssize_t )0xcdcdcdcd ;
12461+ #endif
1245012462
1245112463 // The first time we need to poison something we will initialize a register to the largest immediate cccccccc that
1245212464 // we can fit.
@@ -12461,49 +12473,63 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
1246112473
1246212474 assert (varDsc->lvOnFrame );
1246312475
12464- int size = (int )compiler->lvaLclSize (varNum);
12465-
12466- if (size / TARGET_POINTER_SIZE > 16 )
12476+ unsigned int size = compiler->lvaLclSize (varNum);
12477+ if ((size / TARGET_POINTER_SIZE) > 16 )
1246712478 {
12468- // For very large structs the offsets in the movs we emit below can
12469- // grow too large to be handled properly by JIT. Furthermore, while
12470- // this is only debug code, for very large structs this can bloat
12471- // the code too much due to the singular movs used.
12472- continue ;
12473- }
12474-
12475- if (!hasPoisonImm)
12476- {
12477- #ifdef TARGET_64BIT
12478- instGen_Set_Reg_To_Imm (EA_8BYTE, REG_SCRATCH, (ssize_t )0xcdcdcdcdcdcdcdcd );
12479+ // This will require more than 16 instructions, switch to rep stosd/memset call.
12480+ CLANG_FORMAT_COMMENT_ANCHOR;
12481+ #if defined(TARGET_XARCH)
12482+ GetEmitter ()->emitIns_R_S (INS_lea, EA_PTRSIZE, REG_EDI, (int )varNum, 0 );
12483+ assert (size % 4 == 0 );
12484+ instGen_Set_Reg_To_Imm (EA_4BYTE, REG_ECX, size / 4 );
12485+ // On xarch we can leave the value in eax and only set eax once
12486+ // since rep stosd does not kill eax.
12487+ if (!hasPoisonImm)
12488+ {
12489+ instGen_Set_Reg_To_Imm (EA_PTRSIZE, REG_EAX, poisonVal);
12490+ hasPoisonImm = true ;
12491+ }
12492+ instGen (INS_r_stosd);
1247912493#else
12480- instGen_Set_Reg_To_Imm (EA_4BYTE, REG_SCRATCH, (ssize_t )0xcdcdcdcd );
12494+ GetEmitter ()->emitIns_R_S (INS_lea, EA_PTRSIZE, REG_ARG_0, (int )varNum, 0 );
12495+ instGen_Set_Reg_To_Imm (EA_4BYTE, REG_ARG_1, static_cast <char >(poisonVal));
12496+ instGen_Set_Reg_To_Imm (EA_4BYTE, REG_ARG_2, size);
12497+ genEmitHelperCall (CORINFO_HELP_MEMSET, 0 , EA_UNKNOWN);
12498+ // May kill REG_SCRATCH, so we need to reload it.
12499+ hasPoisonImm = false ;
1248112500#endif
12482- hasPoisonImm = true ;
1248312501 }
12502+ else
12503+ {
12504+ if (!hasPoisonImm)
12505+ {
12506+ instGen_Set_Reg_To_Imm (EA_PTRSIZE, poisonValReg, poisonVal);
12507+ hasPoisonImm = true ;
12508+ }
1248412509
1248512510// For 64-bit we check if the local is 8-byte aligned. For 32-bit, we assume everything is always 4-byte aligned.
1248612511#ifdef TARGET_64BIT
12487- bool fpBased;
12488- int addr = compiler->lvaFrameAddress ((int )varNum, &fpBased);
12512+ bool fpBased;
12513+ int addr = compiler->lvaFrameAddress ((int )varNum, &fpBased);
1248912514#else
12490- int addr = 0 ;
12515+ int addr = 0 ;
1249112516#endif
12492- int end = addr + size;
12493- for (int offs = addr; offs < end;)
12494- {
12495- #ifdef TARGET_64BIT
12496- if ((offs % 8 ) == 0 && end - offs >= 8 )
12517+ int end = addr + (int )size;
12518+ for (int offs = addr; offs < end;)
1249712519 {
12498- GetEmitter ()->emitIns_S_R (ins_Store (TYP_LONG), EA_8BYTE, REG_SCRATCH, (int )varNum, offs - addr);
12499- offs += 8 ;
12500- continue ;
12501- }
12520+ #ifdef TARGET_64BIT
12521+ if ((offs % 8 ) == 0 && end - offs >= 8 )
12522+ {
12523+ GetEmitter ()->emitIns_S_R (ins_Store (TYP_LONG), EA_8BYTE, REG_SCRATCH, (int )varNum, offs - addr);
12524+ offs += 8 ;
12525+ continue ;
12526+ }
1250212527#endif
1250312528
12504- assert ((offs % 4 ) == 0 && end - offs >= 4 );
12505- GetEmitter ()->emitIns_S_R (ins_Store (TYP_INT), EA_4BYTE, REG_SCRATCH, (int )varNum, offs - addr);
12506- offs += 4 ;
12529+ assert ((offs % 4 ) == 0 && end - offs >= 4 );
12530+ GetEmitter ()->emitIns_S_R (ins_Store (TYP_INT), EA_4BYTE, REG_SCRATCH, (int )varNum, offs - addr);
12531+ offs += 4 ;
12532+ }
1250712533 }
1250812534 }
1250912535}
0 commit comments