Skip to content

Commit 22eb1da

Browse files
committed
Revert "[AArch64] Adds SUBS and ADDS instructions to the MIPeepholeOpt."
This reverts commit af45d0f. This causes assertions failures when compiling the Linux kernel. See https://reviews.llvm.org/D118663 for a reduced reproducer.
1 parent a6e1b3c commit 22eb1da

File tree

5 files changed

+66
-365
lines changed

5 files changed

+66
-365
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,27 @@ findCondCodeUseOperandIdxForBranchOrSelect(const MachineInstr &Instr) {
15471547
}
15481548
}
15491549

1550+
namespace {
1551+
1552+
struct UsedNZCV {
1553+
bool N = false;
1554+
bool Z = false;
1555+
bool C = false;
1556+
bool V = false;
1557+
1558+
UsedNZCV() = default;
1559+
1560+
UsedNZCV &operator|=(const UsedNZCV &UsedFlags) {
1561+
this->N |= UsedFlags.N;
1562+
this->Z |= UsedFlags.Z;
1563+
this->C |= UsedFlags.C;
1564+
this->V |= UsedFlags.V;
1565+
return *this;
1566+
}
1567+
};
1568+
1569+
} // end anonymous namespace
1570+
15501571
/// Find a condition code used by the instruction.
15511572
/// Returns AArch64CC::Invalid if either the instruction does not use condition
15521573
/// codes or we don't optimize CmpInstr in the presence of such instructions.
@@ -1601,15 +1622,15 @@ static UsedNZCV getUsedNZCV(AArch64CC::CondCode CC) {
16011622
return UsedFlags;
16021623
}
16031624

1604-
/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
1605-
/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
1606-
/// \returns None otherwise.
1625+
/// \returns Conditions flags used after \p CmpInstr in its MachineBB if they
1626+
/// are not containing C or V flags and NZCV flags are not alive in successors
1627+
/// of the same \p CmpInstr and \p MI parent. \returns None otherwise.
16071628
///
16081629
/// Collect instructions using that flags in \p CCUseInstrs if provided.
1609-
Optional<UsedNZCV>
1610-
llvm::examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr,
1611-
const TargetRegisterInfo &TRI,
1612-
SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
1630+
static Optional<UsedNZCV>
1631+
examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr,
1632+
const TargetRegisterInfo &TRI,
1633+
SmallVectorImpl<MachineInstr *> *CCUseInstrs = nullptr) {
16131634
MachineBasicBlock *CmpParent = CmpInstr.getParent();
16141635
if (MI.getParent() != CmpParent)
16151636
return None;
@@ -1631,6 +1652,8 @@ llvm::examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr,
16311652
if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
16321653
break;
16331654
}
1655+
if (NZCVUsedAfterCmp.C || NZCVUsedAfterCmp.V)
1656+
return None;
16341657
return NZCVUsedAfterCmp;
16351658
}
16361659

@@ -1661,8 +1684,7 @@ static bool canInstrSubstituteCmpInstr(MachineInstr &MI, MachineInstr &CmpInstr,
16611684
if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
16621685
return false;
16631686

1664-
Optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
1665-
if (!NZVCUsed || NZVCUsed->C || NZVCUsed->V)
1687+
if (!examineCFlagsUse(MI, CmpInstr, TRI))
16661688
return false;
16671689

16681690
AccessKind AccessToCheck = AK_Write;
@@ -1751,7 +1773,7 @@ static bool canCmpInstrBeRemoved(MachineInstr &MI, MachineInstr &CmpInstr,
17511773
examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
17521774
// Condition flags are not used in CmpInstr basic block successors and only
17531775
// Z or N flags allowed to be used after CmpInstr within its basic block
1754-
if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
1776+
if (!NZCVUsedAfterCmp)
17551777
return false;
17561778
// Z or N flag used after CmpInstr must correspond to the flag used in MI
17571779
if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||

llvm/lib/Target/AArch64/AArch64InstrInfo.h

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -356,33 +356,6 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
356356
const MachineRegisterInfo *MRI) const;
357357
};
358358

359-
struct UsedNZCV {
360-
bool N = false;
361-
bool Z = false;
362-
bool C = false;
363-
bool V = false;
364-
365-
UsedNZCV() = default;
366-
367-
UsedNZCV &operator|=(const UsedNZCV &UsedFlags) {
368-
this->N |= UsedFlags.N;
369-
this->Z |= UsedFlags.Z;
370-
this->C |= UsedFlags.C;
371-
this->V |= UsedFlags.V;
372-
return *this;
373-
}
374-
};
375-
376-
/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
377-
/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
378-
/// \returns None otherwise.
379-
///
380-
/// Collect instructions using that flags in \p CCUseInstrs if provided.
381-
Optional<UsedNZCV>
382-
examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr,
383-
const TargetRegisterInfo &TRI,
384-
SmallVectorImpl<MachineInstr *> *CCUseInstrs = nullptr);
385-
386359
/// Return true if there is an instruction /after/ \p DefMI and before \p UseMI
387360
/// which either reads or clobbers NZCV.
388361
bool isNZCVTouchedInInstructionRange(const MachineInstr &DefMI,

llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp

Lines changed: 25 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,12 @@ struct AArch64MIPeepholeOpt : public MachineFunctionPass {
6060
MachineLoopInfo *MLI;
6161
MachineRegisterInfo *MRI;
6262

63-
using OpcodePair = std::pair<unsigned, unsigned>;
6463
template <typename T>
6564
using SplitAndOpcFunc =
66-
std::function<Optional<OpcodePair>(T, unsigned, T &, T &)>;
65+
std::function<Optional<unsigned>(T, unsigned, T &, T &)>;
6766
using BuildMIFunc =
68-
std::function<void(MachineInstr &, OpcodePair, unsigned, unsigned,
69-
Register, Register, Register)>;
67+
std::function<void(MachineInstr &, unsigned, unsigned, unsigned, Register,
68+
Register, Register)>;
7069

7170
/// For instructions where an immediate operand could be split into two
7271
/// separate immediate instructions, use the splitTwoPartImm two handle the
@@ -94,10 +93,6 @@ struct AArch64MIPeepholeOpt : public MachineFunctionPass {
9493
bool visitADDSUB(unsigned PosOpc, unsigned NegOpc, MachineInstr &MI,
9594
SmallSetVector<MachineInstr *, 8> &ToBeRemoved);
9695
template <typename T>
97-
bool visitADDSSUBS(OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI,
98-
SmallSetVector<MachineInstr *, 8> &ToBeRemoved);
99-
100-
template <typename T>
10196
bool visitAND(unsigned Opc, MachineInstr &MI,
10297
SmallSetVector<MachineInstr *, 8> &ToBeRemoved);
10398
bool visitORR(MachineInstr &MI,
@@ -176,20 +171,20 @@ bool AArch64MIPeepholeOpt::visitAND(
176171

177172
return splitTwoPartImm<T>(
178173
MI, ToBeRemoved,
179-
[Opc](T Imm, unsigned RegSize, T &Imm0, T &Imm1) -> Optional<OpcodePair> {
174+
[Opc](T Imm, unsigned RegSize, T &Imm0, T &Imm1) -> Optional<unsigned> {
180175
if (splitBitmaskImm(Imm, RegSize, Imm0, Imm1))
181-
return std::make_pair(Opc, Opc);
176+
return Opc;
182177
return None;
183178
},
184-
[&TII = TII](MachineInstr &MI, OpcodePair Opcode, unsigned Imm0,
179+
[&TII = TII](MachineInstr &MI, unsigned Opcode, unsigned Imm0,
185180
unsigned Imm1, Register SrcReg, Register NewTmpReg,
186181
Register NewDstReg) {
187182
DebugLoc DL = MI.getDebugLoc();
188183
MachineBasicBlock *MBB = MI.getParent();
189-
BuildMI(*MBB, MI, DL, TII->get(Opcode.first), NewTmpReg)
184+
BuildMI(*MBB, MI, DL, TII->get(Opcode), NewTmpReg)
190185
.addReg(SrcReg)
191186
.addImm(Imm0);
192-
BuildMI(*MBB, MI, DL, TII->get(Opcode.second), NewDstReg)
187+
BuildMI(*MBB, MI, DL, TII->get(Opcode), NewDstReg)
193188
.addReg(NewTmpReg)
194189
.addImm(Imm1);
195190
});
@@ -278,64 +273,23 @@ bool AArch64MIPeepholeOpt::visitADDSUB(
278273
return splitTwoPartImm<T>(
279274
MI, ToBeRemoved,
280275
[PosOpc, NegOpc](T Imm, unsigned RegSize, T &Imm0,
281-
T &Imm1) -> Optional<OpcodePair> {
276+
T &Imm1) -> Optional<unsigned> {
282277
if (splitAddSubImm(Imm, RegSize, Imm0, Imm1))
283-
return std::make_pair(PosOpc, PosOpc);
278+
return PosOpc;
284279
if (splitAddSubImm(-Imm, RegSize, Imm0, Imm1))
285-
return std::make_pair(NegOpc, NegOpc);
280+
return NegOpc;
286281
return None;
287282
},
288-
[&TII = TII](MachineInstr &MI, OpcodePair Opcode, unsigned Imm0,
289-
unsigned Imm1, Register SrcReg, Register NewTmpReg,
290-
Register NewDstReg) {
291-
DebugLoc DL = MI.getDebugLoc();
292-
MachineBasicBlock *MBB = MI.getParent();
293-
BuildMI(*MBB, MI, DL, TII->get(Opcode.first), NewTmpReg)
294-
.addReg(SrcReg)
295-
.addImm(Imm0)
296-
.addImm(12);
297-
BuildMI(*MBB, MI, DL, TII->get(Opcode.second), NewDstReg)
298-
.addReg(NewTmpReg)
299-
.addImm(Imm1)
300-
.addImm(0);
301-
});
302-
}
303-
304-
template <typename T>
305-
bool AArch64MIPeepholeOpt::visitADDSSUBS(
306-
OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI,
307-
SmallSetVector<MachineInstr *, 8> &ToBeRemoved) {
308-
// Try the same transformation as ADDSUB but with additional requirement
309-
// that the condition code usages are only for Equal and Not Equal
310-
return splitTwoPartImm<T>(
311-
MI, ToBeRemoved,
312-
[PosOpcs, NegOpcs, &MI, &TRI = TRI, &MRI = MRI](
313-
T Imm, unsigned RegSize, T &Imm0, T &Imm1) -> Optional<OpcodePair> {
314-
OpcodePair OP;
315-
if (splitAddSubImm(Imm, RegSize, Imm0, Imm1))
316-
OP = PosOpcs;
317-
else if (splitAddSubImm(-Imm, RegSize, Imm0, Imm1))
318-
OP = NegOpcs;
319-
else
320-
return None;
321-
// Check conditional uses last since it is expensive for scanning
322-
// proceeding instructions
323-
MachineInstr &SrcMI = *MRI->getUniqueVRegDef(MI.getOperand(1).getReg());
324-
Optional<UsedNZCV> NZCVUsed = examineCFlagsUse(SrcMI, MI, *TRI);
325-
if (!NZCVUsed || NZCVUsed->C || NZCVUsed->V)
326-
return None;
327-
return OP;
328-
},
329-
[&TII = TII](MachineInstr &MI, OpcodePair Opcode, unsigned Imm0,
283+
[&TII = TII](MachineInstr &MI, unsigned Opcode, unsigned Imm0,
330284
unsigned Imm1, Register SrcReg, Register NewTmpReg,
331285
Register NewDstReg) {
332286
DebugLoc DL = MI.getDebugLoc();
333287
MachineBasicBlock *MBB = MI.getParent();
334-
BuildMI(*MBB, MI, DL, TII->get(Opcode.first), NewTmpReg)
288+
BuildMI(*MBB, MI, DL, TII->get(Opcode), NewTmpReg)
335289
.addReg(SrcReg)
336290
.addImm(Imm0)
337291
.addImm(12);
338-
BuildMI(*MBB, MI, DL, TII->get(Opcode.second), NewDstReg)
292+
BuildMI(*MBB, MI, DL, TII->get(Opcode), NewDstReg)
339293
.addReg(NewTmpReg)
340294
.addImm(Imm1)
341295
.addImm(0);
@@ -403,49 +357,32 @@ bool AArch64MIPeepholeOpt::splitTwoPartImm(
403357
// number since it was sign extended when we assign to the 64-bit Imm.
404358
if (SubregToRegMI)
405359
Imm &= 0xFFFFFFFF;
406-
OpcodePair Opcode;
360+
unsigned Opcode;
407361
if (auto R = SplitAndOpc(Imm, RegSize, Imm0, Imm1))
408362
Opcode = R.getValue();
409363
else
410364
return false;
411365

412-
// Create new MIs using the first and second opcodes. Opcodes might differ for
413-
// flag setting operations that should only set flags on second instruction.
414-
// NewTmpReg = Opcode.first SrcReg Imm0
415-
// NewDstReg = Opcode.second NewTmpReg Imm1
416-
417-
// Determine register classes for destinations and register operands
366+
// Create new ADD/SUB MIs.
418367
MachineFunction *MF = MI.getMF();
419-
const TargetRegisterClass *FirstInstrDstRC =
420-
TII->getRegClass(TII->get(Opcode.first), 0, TRI, *MF);
421-
const TargetRegisterClass *FirstInstrOperandRC =
422-
TII->getRegClass(TII->get(Opcode.first), 1, TRI, *MF);
423-
const TargetRegisterClass *SecondInstrDstRC =
424-
(Opcode.first == Opcode.second)
425-
? FirstInstrDstRC
426-
: TII->getRegClass(TII->get(Opcode.second), 0, TRI, *MF);
427-
const TargetRegisterClass *SecondInstrOperandRC =
428-
(Opcode.first == Opcode.second)
429-
? FirstInstrOperandRC
430-
: TII->getRegClass(TII->get(Opcode.second), 1, TRI, *MF);
431-
432-
// Get old registers destinations and new register destinations
368+
const TargetRegisterClass *RC =
369+
TII->getRegClass(TII->get(Opcode), 0, TRI, *MF);
370+
const TargetRegisterClass *ORC =
371+
TII->getRegClass(TII->get(Opcode), 1, TRI, *MF);
433372
Register DstReg = MI.getOperand(0).getReg();
434373
Register SrcReg = MI.getOperand(1).getReg();
435-
Register NewTmpReg = MRI->createVirtualRegister(FirstInstrDstRC);
436-
Register NewDstReg = MRI->createVirtualRegister(SecondInstrDstRC);
374+
Register NewTmpReg = MRI->createVirtualRegister(RC);
375+
Register NewDstReg = MRI->createVirtualRegister(RC);
437376

438-
// Constrain registers based on their new uses
439-
MRI->constrainRegClass(SrcReg, FirstInstrOperandRC);
440-
MRI->constrainRegClass(NewTmpReg, SecondInstrOperandRC);
377+
MRI->constrainRegClass(SrcReg, RC);
378+
MRI->constrainRegClass(NewTmpReg, ORC);
441379
MRI->constrainRegClass(NewDstReg, MRI->getRegClass(DstReg));
442380

443-
// Call the delegating operation to build the instruction
444381
BuildInstr(MI, Opcode, Imm0, Imm1, SrcReg, NewTmpReg, NewDstReg);
445382

383+
MRI->replaceRegWith(DstReg, NewDstReg);
446384
// replaceRegWith changes MI's definition register. Keep it for SSA form until
447385
// deleting MI.
448-
MRI->replaceRegWith(DstReg, NewDstReg);
449386
MI.getOperand(0).setReg(DstReg);
450387

451388
// Record the MIs need to be removed.
@@ -502,26 +439,6 @@ bool AArch64MIPeepholeOpt::runOnMachineFunction(MachineFunction &MF) {
502439
Changed = visitADDSUB<uint64_t>(AArch64::SUBXri, AArch64::ADDXri, MI,
503440
ToBeRemoved);
504441
break;
505-
case AArch64::ADDSWrr:
506-
Changed = visitADDSSUBS<uint32_t>({AArch64::ADDWri, AArch64::ADDSWri},
507-
{AArch64::SUBWri, AArch64::SUBSWri},
508-
MI, ToBeRemoved);
509-
break;
510-
case AArch64::SUBSWrr:
511-
Changed = visitADDSSUBS<uint32_t>({AArch64::SUBWri, AArch64::SUBSWri},
512-
{AArch64::ADDWri, AArch64::ADDSWri},
513-
MI, ToBeRemoved);
514-
break;
515-
case AArch64::ADDSXrr:
516-
Changed = visitADDSSUBS<uint64_t>({AArch64::ADDXri, AArch64::ADDSXri},
517-
{AArch64::SUBXri, AArch64::SUBSXri},
518-
MI, ToBeRemoved);
519-
break;
520-
case AArch64::SUBSXrr:
521-
Changed = visitADDSSUBS<uint64_t>({AArch64::SUBXri, AArch64::SUBSXri},
522-
{AArch64::ADDXri, AArch64::ADDSXri},
523-
MI, ToBeRemoved);
524-
break;
525442
}
526443
}
527444
}

0 commit comments

Comments
 (0)