@@ -12446,7 +12446,19 @@ void CodeGenInterface::VariableLiveKeeper::dumpLvaVariableLiveRanges() const
12446
12446
void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
12447
12447
{
12448
12448
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
12450
12462
12451
12463
// The first time we need to poison something we will initialize a register to the largest immediate cccccccc that
12452
12464
// we can fit.
@@ -12461,49 +12473,63 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
12461
12473
12462
12474
assert(varDsc->lvOnFrame);
12463
12475
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)
12467
12478
{
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);
12479
12493
#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;
12481
12500
#endif
12482
- hasPoisonImm = true;
12483
12501
}
12502
+ else
12503
+ {
12504
+ if (!hasPoisonImm)
12505
+ {
12506
+ instGen_Set_Reg_To_Imm(EA_PTRSIZE, poisonValReg, poisonVal);
12507
+ hasPoisonImm = true;
12508
+ }
12484
12509
12485
12510
// For 64-bit we check if the local is 8-byte aligned. For 32-bit, we assume everything is always 4-byte aligned.
12486
12511
#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);
12489
12514
#else
12490
- int addr = 0;
12515
+ int addr = 0;
12491
12516
#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;)
12497
12519
{
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
+ }
12502
12527
#endif
12503
12528
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
+ }
12507
12533
}
12508
12534
}
12509
12535
}
0 commit comments