@@ -5412,195 +5412,21 @@ AArch64InstrInfo::findRegisterToSaveLRTo(const outliner::Candidate &C) const {
5412
5412
return 0u ;
5413
5413
}
5414
5414
5415
- static bool
5416
- outliningCandidatesSigningScopeConsensus (const outliner::Candidate &a,
5417
- const outliner::Candidate &b) {
5418
- const Function &Fa = a.getMF ()->getFunction ();
5419
- const Function &Fb = b.getMF ()->getFunction ();
5420
-
5421
- // If none of the functions have the "sign-return-address" attribute their
5422
- // signing behaviour is equal
5423
- if (!Fa.hasFnAttribute (" sign-return-address" ) &&
5424
- !Fb.hasFnAttribute (" sign-return-address" )) {
5425
- return true ;
5426
- }
5427
-
5428
- // If both functions have the "sign-return-address" attribute their signing
5429
- // behaviour is equal, if the values of the attributes are equal
5430
- if (Fa.hasFnAttribute (" sign-return-address" ) &&
5431
- Fb.hasFnAttribute (" sign-return-address" )) {
5432
- StringRef ScopeA =
5433
- Fa.getFnAttribute (" sign-return-address" ).getValueAsString ();
5434
- StringRef ScopeB =
5435
- Fb.getFnAttribute (" sign-return-address" ).getValueAsString ();
5436
- return ScopeA.equals (ScopeB);
5437
- }
5438
-
5439
- // If function B doesn't have the "sign-return-address" attribute but A does,
5440
- // the functions' signing behaviour is equal if A's value for
5441
- // "sign-return-address" is "none" and vice versa.
5442
- if (Fa.hasFnAttribute (" sign-return-address" )) {
5443
- StringRef ScopeA =
5444
- Fa.getFnAttribute (" sign-return-address" ).getValueAsString ();
5445
- return ScopeA.equals (" none" );
5446
- }
5447
-
5448
- if (Fb.hasFnAttribute (" sign-return-address" )) {
5449
- StringRef ScopeB =
5450
- Fb.getFnAttribute (" sign-return-address" ).getValueAsString ();
5451
- return ScopeB.equals (" none" );
5452
- }
5453
-
5454
- llvm_unreachable (" Unkown combination of sign-return-address attributes" );
5455
- }
5456
-
5457
- static bool
5458
- outliningCandidatesSigningKeyConsensus (const outliner::Candidate &a,
5459
- const outliner::Candidate &b) {
5460
- const Function &Fa = a.getMF ()->getFunction ();
5461
- const Function &Fb = b.getMF ()->getFunction ();
5462
-
5463
- // If none of the functions have the "sign-return-address-key" attribute
5464
- // their keys are equal
5465
- if (!Fa.hasFnAttribute (" sign-return-address-key" ) &&
5466
- !Fb.hasFnAttribute (" sign-return-address-key" )) {
5467
- return true ;
5468
- }
5469
-
5470
- // If both functions have the "sign-return-address-key" attribute their
5471
- // keys are equal if the values of "sign-return-address-key" are equal
5472
- if (Fa.hasFnAttribute (" sign-return-address-key" ) &&
5473
- Fb.hasFnAttribute (" sign-return-address-key" )) {
5474
- StringRef KeyA =
5475
- Fa.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5476
- StringRef KeyB =
5477
- Fb.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5478
- return KeyA.equals (KeyB);
5479
- }
5480
-
5481
- // If B doesn't have the "sign-return-address-key" attribute, both keys are
5482
- // equal, if function a has the default key (a_key)
5483
- if (Fa.hasFnAttribute (" sign-return-address-key" )) {
5484
- StringRef KeyA =
5485
- Fa.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5486
- return KeyA.equals_lower (" a_key" );
5487
- }
5488
-
5489
- if (Fb.hasFnAttribute (" sign-return-address-key" )) {
5490
- StringRef KeyB =
5491
- Fb.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5492
- return KeyB.equals_lower (" a_key" );
5493
- }
5494
-
5495
- llvm_unreachable (" Unkown combination of sign-return-address-key attributes" );
5496
- }
5497
-
5498
- static bool outliningCandidatesV8_3OpsConsensus (const outliner::Candidate &a,
5499
- const outliner::Candidate &b) {
5500
- const AArch64Subtarget &SubtargetA =
5501
- a.getMF ()->getSubtarget <AArch64Subtarget>();
5502
- const AArch64Subtarget &SubtargetB =
5503
- b.getMF ()->getSubtarget <AArch64Subtarget>();
5504
- return SubtargetA.hasV8_3aOps () == SubtargetB.hasV8_3aOps ();
5505
- }
5506
-
5507
- outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo (
5415
+ outliner::OutlinedFunction
5416
+ AArch64InstrInfo::getOutliningCandidateInfo (
5508
5417
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
5509
5418
outliner::Candidate &FirstCand = RepeatedSequenceLocs[0 ];
5510
5419
unsigned SequenceSize =
5511
5420
std::accumulate (FirstCand.front (), std::next (FirstCand.back ()), 0 ,
5512
5421
[this ](unsigned Sum, const MachineInstr &MI) {
5513
5422
return Sum + getInstSizeInBytes (MI);
5514
5423
});
5515
- unsigned NumBytesToCreateFrame = 0 ;
5516
-
5517
- // We only allow outlining for functions having exactly matching return
5518
- // address signing attributes, i.e., all share the same value for the
5519
- // attribute "sign-return-address" and all share the same type of key they
5520
- // are signed with.
5521
- // Additionally we require all functions to simultaniously either support
5522
- // v8.3a features or not. Otherwise an outlined function could get signed
5523
- // using dedicated v8.3 instructions and a call from a function that doesn't
5524
- // support v8.3 instructions would therefore be invalid.
5525
- if (std::adjacent_find (
5526
- RepeatedSequenceLocs.begin (), RepeatedSequenceLocs.end (),
5527
- [](const outliner::Candidate &a, const outliner::Candidate &b) {
5528
- // Return true if a and b are non-equal w.r.t. return address
5529
- // signing or support of v8.3a features
5530
- if (outliningCandidatesSigningScopeConsensus (a, b) &&
5531
- outliningCandidatesSigningKeyConsensus (a, b) &&
5532
- outliningCandidatesV8_3OpsConsensus (a, b)) {
5533
- return false ;
5534
- }
5535
- return true ;
5536
- }) != RepeatedSequenceLocs.end ()) {
5537
- return outliner::OutlinedFunction ();
5538
- }
5539
-
5540
- // Since at this point all candidates agree on their return address signing
5541
- // picking just one is fine. If the candidate functions potentially sign their
5542
- // return addresses, the outlined function should do the same. Note that in
5543
- // the case of "sign-return-address"="non-leaf" this is an assumption: It is
5544
- // not certainly true that the outlined function will have to sign its return
5545
- // address but this decision is made later, when the decision to outline
5546
- // has already been made.
5547
- // The same holds for the number of additional instructions we need: On
5548
- // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
5549
- // necessary. However, at this point we don't know if the outlined function
5550
- // will have a RET instruction so we assume the worst.
5551
- const Function &FCF = FirstCand.getMF ()->getFunction ();
5552
- const TargetRegisterInfo &TRI = getRegisterInfo ();
5553
- if (FCF.hasFnAttribute (" sign-return-address" )) {
5554
- // One PAC and one AUT instructions
5555
- NumBytesToCreateFrame += 8 ;
5556
-
5557
- // We have to check if sp modifying instructions would get outlined.
5558
- // If so we only allow outlining if sp is unchanged overall, so matching
5559
- // sub and add instructions are okay to outline, all other sp modifications
5560
- // are not
5561
- auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) {
5562
- int SPValue = 0 ;
5563
- MachineBasicBlock::iterator MBBI = C.front ();
5564
- for (;;) {
5565
- if (MBBI->modifiesRegister (AArch64::SP, &TRI)) {
5566
- switch (MBBI->getOpcode ()) {
5567
- case AArch64::ADDXri:
5568
- case AArch64::ADDWri:
5569
- assert (MBBI->getNumOperands () == 4 && " Wrong number of operands" );
5570
- assert (MBBI->getOperand (2 ).isImm () &&
5571
- " Expected operand to be immediate" );
5572
- SPValue += MBBI->getOperand (2 ).getImm ();
5573
- break ;
5574
- case AArch64::SUBXri:
5575
- case AArch64::SUBWri:
5576
- assert (MBBI->getNumOperands () == 4 && " Wrong number of operands" );
5577
- assert (MBBI->getOperand (2 ).isImm () &&
5578
- " Expected operand to be immediate" );
5579
- SPValue -= MBBI->getOperand (2 ).getImm ();
5580
- break ;
5581
- default :
5582
- return true ;
5583
- }
5584
- }
5585
- if (MBBI == C.back ())
5586
- break ;
5587
- ++MBBI;
5588
- }
5589
- if (SPValue)
5590
- return true ;
5591
- return false ;
5592
- };
5593
- // Remove candidates with illegal stack modifying instructions
5594
- RepeatedSequenceLocs.erase (std::remove_if (RepeatedSequenceLocs.begin (),
5595
- RepeatedSequenceLocs.end (),
5596
- hasIllegalSPModification),
5597
- RepeatedSequenceLocs.end ());
5598
- }
5599
5424
5600
5425
// Properties about candidate MBBs that hold for all of them.
5601
5426
unsigned FlagsSetInAll = 0xF ;
5602
5427
5603
5428
// Compute liveness information for each candidate, and set FlagsSetInAll.
5429
+ const TargetRegisterInfo &TRI = getRegisterInfo ();
5604
5430
std::for_each (RepeatedSequenceLocs.begin (), RepeatedSequenceLocs.end (),
5605
5431
[&FlagsSetInAll](outliner::Candidate &C) {
5606
5432
FlagsSetInAll &= C.Flags ;
@@ -5656,7 +5482,7 @@ outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo(
5656
5482
};
5657
5483
5658
5484
unsigned FrameID = MachineOutlinerDefault;
5659
- NumBytesToCreateFrame + = 4 ;
5485
+ unsigned NumBytesToCreateFrame = 4 ;
5660
5486
5661
5487
bool HasBTI = any_of (RepeatedSequenceLocs, [](outliner::Candidate &C) {
5662
5488
return C.getMF ()->getFunction ().hasFnAttribute (" branch-target-enforcement" );
@@ -5925,19 +5751,6 @@ AArch64InstrInfo::getOutliningType(MachineBasicBlock::iterator &MIT,
5925
5751
MachineFunction *MF = MBB->getParent ();
5926
5752
AArch64FunctionInfo *FuncInfo = MF->getInfo <AArch64FunctionInfo>();
5927
5753
5928
- // Don't outline anything used for return address signing. The outlined
5929
- // function will get signed later if needed
5930
- switch (MI.getOpcode ()) {
5931
- case AArch64::PACIASP:
5932
- case AArch64::PACIBSP:
5933
- case AArch64::AUTIASP:
5934
- case AArch64::AUTIBSP:
5935
- case AArch64::RETAA:
5936
- case AArch64::RETAB:
5937
- case AArch64::EMITBKEY:
5938
- return outliner::InstrType::Illegal;
5939
- }
5940
-
5941
5754
// Don't outline LOHs.
5942
5755
if (FuncInfo->getLOHRelated ().count (&MI))
5943
5756
return outliner::InstrType::Illegal;
@@ -6090,59 +5903,6 @@ void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
6090
5903
}
6091
5904
}
6092
5905
6093
- static void signOutlinedFunction (MachineFunction &MF, MachineBasicBlock &MBB,
6094
- bool ShouldSignReturnAddr,
6095
- bool ShouldSignReturnAddrWithAKey) {
6096
- if (ShouldSignReturnAddr) {
6097
- MachineBasicBlock::iterator MBBPAC = MBB.begin ();
6098
- MachineBasicBlock::iterator MBBAUT = MBB.getFirstTerminator ();
6099
- const AArch64Subtarget &Subtarget = MF.getSubtarget <AArch64Subtarget>();
6100
- const TargetInstrInfo *TII = Subtarget.getInstrInfo ();
6101
- DebugLoc DL;
6102
-
6103
- if (MBBAUT != MBB.end ())
6104
- DL = MBBAUT->getDebugLoc ();
6105
-
6106
- // At the very beginning of the basic block we insert the following
6107
- // depending on the key type
6108
- //
6109
- // a_key: b_key:
6110
- // PACIASP EMITBKEY
6111
- // CFI_INSTRUCTION PACIBSP
6112
- // CFI_INSTRUCTION
6113
- if (ShouldSignReturnAddrWithAKey) {
6114
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::PACIASP))
6115
- .setMIFlag (MachineInstr::FrameSetup);
6116
- } else {
6117
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::EMITBKEY))
6118
- .setMIFlag (MachineInstr::FrameSetup);
6119
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::PACIBSP))
6120
- .setMIFlag (MachineInstr::FrameSetup);
6121
- }
6122
- unsigned CFIIndex =
6123
- MF.addFrameInst (MCCFIInstruction::createNegateRAState (nullptr ));
6124
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::CFI_INSTRUCTION))
6125
- .addCFIIndex (CFIIndex)
6126
- .setMIFlags (MachineInstr::FrameSetup);
6127
-
6128
- // If v8.3a features are available we can replace a RET instruction by
6129
- // RETAA or RETAB and omit the AUT instructions
6130
- if (Subtarget.hasV8_3aOps () && MBBAUT != MBB.end () &&
6131
- MBBAUT->getOpcode () == AArch64::RET) {
6132
- BuildMI (MBB, MBBAUT, DL,
6133
- TII->get (ShouldSignReturnAddrWithAKey ? AArch64::RETAA
6134
- : AArch64::RETAB))
6135
- .copyImplicitOps (*MBBAUT);
6136
- MBB.erase (MBBAUT);
6137
- } else {
6138
- BuildMI (MBB, MBBAUT, DL,
6139
- TII->get (ShouldSignReturnAddrWithAKey ? AArch64::AUTIASP
6140
- : AArch64::AUTIBSP))
6141
- .setMIFlag (MachineInstr::FrameDestroy);
6142
- }
6143
- }
6144
- }
6145
-
6146
5906
void AArch64InstrInfo::buildOutlinedFrame (
6147
5907
MachineBasicBlock &MBB, MachineFunction &MF,
6148
5908
const outliner::OutlinedFunction &OF) const {
@@ -6158,28 +5918,23 @@ void AArch64InstrInfo::buildOutlinedFrame(
6158
5918
TailOpcode = AArch64::TCRETURNriALL;
6159
5919
}
6160
5920
MachineInstr *TC = BuildMI (MF, DebugLoc (), get (TailOpcode))
6161
- .add (Call->getOperand (0 ))
6162
- .addImm (0 );
5921
+ .add (Call->getOperand (0 ))
5922
+ .addImm (0 );
6163
5923
MBB.insert (MBB.end (), TC);
6164
5924
Call->eraseFromParent ();
6165
5925
}
6166
5926
6167
- bool IsLeafFunction = true ;
6168
-
6169
5927
// Is there a call in the outlined range?
6170
- auto IsNonTailCall = [](const MachineInstr &MI) {
5928
+ auto IsNonTailCall = [](MachineInstr &MI) {
6171
5929
return MI.isCall () && !MI.isReturn ();
6172
5930
};
6173
-
6174
5931
if (std::any_of (MBB.instr_begin (), MBB.instr_end (), IsNonTailCall)) {
6175
5932
// Fix up the instructions in the range, since we're going to modify the
6176
5933
// stack.
6177
5934
assert (OF.FrameConstructionID != MachineOutlinerDefault &&
6178
5935
" Can only fix up stack references once" );
6179
5936
fixupPostOutline (MBB);
6180
5937
6181
- IsLeafFunction = false ;
6182
-
6183
5938
// LR has to be a live in so that we can save it.
6184
5939
MBB.addLiveIn (AArch64::LR);
6185
5940
@@ -6226,47 +5981,16 @@ void AArch64InstrInfo::buildOutlinedFrame(
6226
5981
Et = MBB.insert (Et, LDRXpost);
6227
5982
}
6228
5983
6229
- // If a bunch of candidates reach this point they must agree on their return
6230
- // address signing. It is therefore enough to just consider the signing
6231
- // behaviour of one of them
6232
- const Function &CF = OF.Candidates .front ().getMF ()->getFunction ();
6233
- bool ShouldSignReturnAddr = false ;
6234
- if (CF.hasFnAttribute (" sign-return-address" )) {
6235
- StringRef Scope =
6236
- CF.getFnAttribute (" sign-return-address" ).getValueAsString ();
6237
- if (Scope.equals (" all" ))
6238
- ShouldSignReturnAddr = true ;
6239
- else if (Scope.equals (" non-leaf" ) && !IsLeafFunction)
6240
- ShouldSignReturnAddr = true ;
6241
- }
6242
-
6243
- // a_key is the default
6244
- bool ShouldSignReturnAddrWithAKey = true ;
6245
- if (CF.hasFnAttribute (" sign-return-address-key" )) {
6246
- const StringRef Key =
6247
- CF.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
6248
- // Key can either be a_key or b_key
6249
- assert ((Key.equals_lower (" a_key" ) || Key.equals_lower (" b_key" )) &&
6250
- " Return address signing key must be either a_key or b_key" );
6251
- ShouldSignReturnAddrWithAKey = Key.equals_lower (" a_key" );
6252
- }
6253
-
6254
5984
// If this is a tail call outlined function, then there's already a return.
6255
5985
if (OF.FrameConstructionID == MachineOutlinerTailCall ||
6256
- OF.FrameConstructionID == MachineOutlinerThunk) {
6257
- signOutlinedFunction (MF, MBB, ShouldSignReturnAddr,
6258
- ShouldSignReturnAddrWithAKey);
5986
+ OF.FrameConstructionID == MachineOutlinerThunk)
6259
5987
return ;
6260
- }
6261
5988
6262
5989
// It's not a tail call, so we have to insert the return ourselves.
6263
5990
MachineInstr *ret = BuildMI (MF, DebugLoc (), get (AArch64::RET))
6264
5991
.addReg (AArch64::LR, RegState::Undef);
6265
5992
MBB.insert (MBB.end (), ret);
6266
5993
6267
- signOutlinedFunction (MF, MBB, ShouldSignReturnAddr,
6268
- ShouldSignReturnAddrWithAKey);
6269
-
6270
5994
// Did we have to modify the stack by saving the link register?
6271
5995
if (OF.FrameConstructionID != MachineOutlinerDefault)
6272
5996
return ;
0 commit comments