@@ -125,9 +125,10 @@ class X86AsmBackend : public MCAsmBackend {
125
125
unsigned TargetPrefixMax = 0 ;
126
126
127
127
MCInst PrevInst;
128
+ unsigned PrevInstOpcode = 0 ;
128
129
MCBoundaryAlignFragment *PendingBA = nullptr ;
129
130
std::pair<MCFragment *, size_t > PrevInstPosition;
130
- bool CanPadInst = false ;
131
+ bool IsRightAfterData = false ;
131
132
132
133
uint8_t determinePaddingPrefix (const MCInst &Inst) const ;
133
134
bool isMacroFused (const MCInst &Cmp, const MCInst &Jcc) const ;
@@ -267,8 +268,8 @@ static bool isRIPRelative(const MCInst &MI, const MCInstrInfo &MCII) {
267
268
}
268
269
269
270
// / Check if the instruction is a prefix.
270
- static bool isPrefix (const MCInst &MI , const MCInstrInfo &MCII) {
271
- return X86II::isPrefix (MCII.get (MI. getOpcode () ).TSFlags );
271
+ static bool isPrefix (unsigned Opcode , const MCInstrInfo &MCII) {
272
+ return X86II::isPrefix (MCII.get (Opcode ).TSFlags );
272
273
}
273
274
274
275
// / Check if the instruction is valid as the first instruction in macro fusion.
@@ -382,9 +383,9 @@ bool X86AsmBackend::allowEnhancedRelaxation() const {
382
383
383
384
// / X86 has certain instructions which enable interrupts exactly one
384
385
// / instruction *after* the instruction which stores to SS. Return true if the
385
- // / given instruction has such an interrupt delay slot.
386
- static bool hasInterruptDelaySlot ( const MCInst &Inst ) {
387
- switch (Inst. getOpcode () ) {
386
+ // / given instruction may have such an interrupt delay slot.
387
+ static bool mayHaveInterruptDelaySlot ( unsigned InstOpcode ) {
388
+ switch (InstOpcode ) {
388
389
case X86::POPSS16:
389
390
case X86::POPSS32:
390
391
case X86::STI:
@@ -394,9 +395,9 @@ static bool hasInterruptDelaySlot(const MCInst &Inst) {
394
395
case X86::MOV32sr:
395
396
case X86::MOV64sr:
396
397
case X86::MOV16sm:
397
- if (Inst. getOperand ( 0 ). getReg () == X86::SS)
398
- return true ;
399
- break ;
398
+ // In fact, this is only the case if the first operand is SS. However, as
399
+ // segment moves occur extremely rarely, this is just a minor pessimization.
400
+ return true ;
400
401
}
401
402
return false ;
402
403
}
@@ -450,22 +451,22 @@ bool X86AsmBackend::canPadInst(const MCInst &Inst, MCObjectStreamer &OS) const {
450
451
// TLSCALL).
451
452
return false ;
452
453
453
- if (hasInterruptDelaySlot (PrevInst ))
454
+ if (mayHaveInterruptDelaySlot (PrevInstOpcode ))
454
455
// If this instruction follows an interrupt enabling instruction with a one
455
456
// instruction delay, inserting a nop would change behavior.
456
457
return false ;
457
458
458
- if (isPrefix (PrevInst , *MCII))
459
+ if (isPrefix (PrevInstOpcode , *MCII))
459
460
// If this instruction follows a prefix, inserting a nop/prefix would change
460
461
// semantic.
461
462
return false ;
462
463
463
- if (isPrefix (Inst, *MCII))
464
+ if (isPrefix (Inst. getOpcode () , *MCII))
464
465
// If this instruction is a prefix, inserting a prefix would change
465
466
// semantic.
466
467
return false ;
467
468
468
- if (isRightAfterData (OS. getCurrentFragment (), PrevInstPosition) )
469
+ if (IsRightAfterData )
469
470
// If this instruction follows any data, there is no clear
470
471
// instruction boundary, inserting a nop/prefix would change semantic.
471
472
return false ;
@@ -509,16 +510,24 @@ bool X86AsmBackend::needAlign(const MCInst &Inst) const {
509
510
// / Insert BoundaryAlignFragment before instructions to align branches.
510
511
void X86AsmBackend::emitInstructionBegin (MCObjectStreamer &OS,
511
512
const MCInst &Inst, const MCSubtargetInfo &STI) {
512
- CanPadInst = canPadInst (Inst, OS);
513
+ // Used by canPadInst. Done here, because in emitInstructionEnd, the current
514
+ // fragment will have changed.
515
+ IsRightAfterData =
516
+ isRightAfterData (OS.getCurrentFragment (), PrevInstPosition);
513
517
514
518
if (!canPadBranches (OS))
515
519
return ;
516
520
521
+ // NB: PrevInst only valid if canPadBranches is true.
517
522
if (!isMacroFused (PrevInst, Inst))
518
523
// Macro fusion doesn't happen indeed, clear the pending.
519
524
PendingBA = nullptr ;
520
525
521
- if (!CanPadInst)
526
+ // When branch padding is enabled (basically the skx102 erratum => unlikely),
527
+ // we call canPadInst (not cheap) twice. However, in the common case, we can
528
+ // avoid unnecessary calls to that, as this is otherwise only used for
529
+ // relaxable fragments.
530
+ if (!canPadInst (Inst, OS))
522
531
return ;
523
532
524
533
if (PendingBA && PendingBA->getNextNode () == OS.getCurrentFragment ()) {
@@ -552,16 +561,22 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
552
561
}
553
562
554
563
// / Set the last fragment to be aligned for the BoundaryAlignFragment.
555
- void X86AsmBackend::emitInstructionEnd (MCObjectStreamer &OS, const MCInst &Inst) {
556
- PrevInst = Inst;
564
+ void X86AsmBackend::emitInstructionEnd (MCObjectStreamer &OS,
565
+ const MCInst & Inst) {
557
566
MCFragment *CF = OS.getCurrentFragment ();
558
- PrevInstPosition = std::make_pair (CF, getSizeForInstFragment (CF));
559
567
if (auto *F = dyn_cast_or_null<MCRelaxableFragment>(CF))
560
- F->setAllowAutoPadding (CanPadInst);
568
+ F->setAllowAutoPadding (canPadInst (Inst, OS));
569
+
570
+ // Update PrevInstOpcode here, canPadInst() reads that.
571
+ PrevInstOpcode = Inst.getOpcode ();
572
+ PrevInstPosition = std::make_pair (CF, getSizeForInstFragment (CF));
561
573
562
574
if (!canPadBranches (OS))
563
575
return ;
564
576
577
+ // PrevInst is only needed if canPadBranches. Copying an MCInst isn't cheap.
578
+ PrevInst = Inst;
579
+
565
580
if (!needAlign (Inst) || !PendingBA)
566
581
return ;
567
582
0 commit comments