aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/PowerPC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-18 20:30:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-04-06 20:11:55 +0000
commit5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch)
tree1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/llvm/lib/Target/PowerPC
parent3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff)
parent312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/PowerPC')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp55
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp25
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h5
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h6
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp11
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp13
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp3
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h1
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp27
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp1
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp114
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp87
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h89
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp1
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td22
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h76
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td11
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp101
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def1
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp16
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp38
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def6
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp132
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp266
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h24
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td67
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td37
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp300
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h261
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td67
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td240
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp55
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp277
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp365
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h52
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td3
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td66
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td661
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td698
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td40
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp5
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp54
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp28
55 files changed, 2564 insertions, 1905 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 4f93cdaaa137..8108cfa521c8 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -105,10 +105,9 @@ class PPCAsmParser : public MCTargetAsmParser {
bool MatchRegisterName(MCRegister &RegNo, int64_t &IntVal);
- bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
- SMLoc &EndLoc) override;
- OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
- SMLoc &EndLoc) override;
+ bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+ ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
+ SMLoc &EndLoc) override;
const MCExpr *ExtractModifierFromExpr(const MCExpr *E,
PPCMCExpr::VariantKind &Variant);
@@ -887,6 +886,26 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst,
Inst = TmpInst;
break;
}
+ case PPC::PLA8:
+ case PPC::PLA: {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Opcode == PPC::PLA ? PPC::PADDI : PPC::PADDI8);
+ TmpInst.addOperand(Inst.getOperand(0));
+ TmpInst.addOperand(Inst.getOperand(1));
+ TmpInst.addOperand(Inst.getOperand(2));
+ Inst = TmpInst;
+ break;
+ }
+ case PPC::PLA8pc:
+ case PPC::PLApc: {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Opcode == PPC::PLApc ? PPC::PADDIpc : PPC::PADDI8pc);
+ TmpInst.addOperand(Inst.getOperand(0));
+ TmpInst.addOperand(MCOperand::createImm(0));
+ TmpInst.addOperand(Inst.getOperand(1));
+ Inst = TmpInst;
+ break;
+ }
case PPC::SUBI: {
MCInst TmpInst;
TmpInst.setOpcode(PPC::ADDI);
@@ -896,6 +915,15 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst,
Inst = TmpInst;
break;
}
+ case PPC::PSUBI: {
+ MCInst TmpInst;
+ TmpInst.setOpcode(PPC::PADDI);
+ TmpInst.addOperand(Inst.getOperand(0));
+ TmpInst.addOperand(Inst.getOperand(1));
+ addNegOperand(TmpInst, Inst.getOperand(2), getContext());
+ Inst = TmpInst;
+ break;
+ }
case PPC::SUBIS: {
MCInst TmpInst;
TmpInst.setOpcode(PPC::ADDIS);
@@ -1320,24 +1348,23 @@ bool PPCAsmParser::MatchRegisterName(MCRegister &RegNo, int64_t &IntVal) {
return false;
}
-bool PPCAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
+bool PPCAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
SMLoc &EndLoc) {
- if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
+ if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
return TokError("invalid register name");
return false;
}
-OperandMatchResultTy PPCAsmParser::tryParseRegister(MCRegister &RegNo,
- SMLoc &StartLoc,
- SMLoc &EndLoc) {
+ParseStatus PPCAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
+ SMLoc &EndLoc) {
const AsmToken &Tok = getParser().getTok();
StartLoc = Tok.getLoc();
EndLoc = Tok.getEndLoc();
- RegNo = 0;
+ Reg = PPC::NoRegister;
int64_t IntVal;
- if (MatchRegisterName(RegNo, IntVal))
- return MatchOperand_NoMatch;
- return MatchOperand_Success;
+ if (MatchRegisterName(Reg, IntVal))
+ return ParseStatus::NoMatch;
+ return ParseStatus::Success;
}
/// Extract \code @l/@ha \endcode modifier from expression. Recursively scan
@@ -1717,7 +1744,7 @@ bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) {
ParseDirectiveAbiVersion(DirectiveID.getLoc());
else if (IDVal == ".localentry")
ParseDirectiveLocalEntry(DirectiveID.getLoc());
- else if (IDVal.startswith(".gnu_attribute"))
+ else if (IDVal.starts_with(".gnu_attribute"))
ParseGNUAttribute(DirectiveID.getLoc());
else
return true;
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp
index 3913ede3dc18..99ecc3fe360d 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp
@@ -36,9 +36,10 @@ struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler {
: OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
void assignValueToReg(Register ValVReg, Register PhysReg,
- CCValAssign VA) override;
+ const CCValAssign &VA) override;
void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
- MachinePointerInfo &MPO, CCValAssign &VA) override;
+ const MachinePointerInfo &MPO,
+ const CCValAssign &VA) override;
Register getStackAddress(uint64_t Size, int64_t Offset,
MachinePointerInfo &MPO,
ISD::ArgFlagsTy Flags) override;
@@ -48,7 +49,7 @@ struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler {
} // namespace
void OutgoingArgHandler::assignValueToReg(Register ValVReg, Register PhysReg,
- CCValAssign VA) {
+ const CCValAssign &VA) {
MIB.addUse(PhysReg, RegState::Implicit);
Register ExtReg = extendRegister(ValVReg, VA);
MIRBuilder.buildCopy(PhysReg, ExtReg);
@@ -56,8 +57,8 @@ void OutgoingArgHandler::assignValueToReg(Register ValVReg, Register PhysReg,
void OutgoingArgHandler::assignValueToAddress(Register ValVReg, Register Addr,
LLT MemTy,
- MachinePointerInfo &MPO,
- CCValAssign &VA) {
+ const MachinePointerInfo &MPO,
+ const CCValAssign &VA) {
llvm_unreachable("unimplemented");
}
@@ -143,18 +144,18 @@ bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
void PPCIncomingValueHandler::assignValueToReg(Register ValVReg,
Register PhysReg,
- CCValAssign VA) {
+ const CCValAssign &VA) {
markPhysRegUsed(PhysReg);
IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
}
-void PPCIncomingValueHandler::assignValueToAddress(Register ValVReg,
- Register Addr, LLT MemTy,
- MachinePointerInfo &MPO,
- CCValAssign &VA) {
+void PPCIncomingValueHandler::assignValueToAddress(
+ Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
+ const CCValAssign &VA) {
// define a lambda expression to load value
- auto BuildLoad = [](MachineIRBuilder &MIRBuilder, MachinePointerInfo &MPO,
- LLT MemTy, const DstOp &Res, Register Addr) {
+ auto BuildLoad = [](MachineIRBuilder &MIRBuilder,
+ const MachinePointerInfo &MPO, LLT MemTy,
+ const DstOp &Res, Register Addr) {
MachineFunction &MF = MIRBuilder.getMF();
auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
inferAlignFromPtrInfo(MF, MPO));
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h
index cc2cb7b26e84..17e8c57e563f 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h
@@ -46,10 +46,11 @@ public:
private:
void assignValueToReg(Register ValVReg, Register PhysReg,
- CCValAssign VA) override;
+ const CCValAssign &VA) override;
void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
- MachinePointerInfo &MPO, CCValAssign &VA) override;
+ const MachinePointerInfo &MPO,
+ const CCValAssign &VA) override;
Register getStackAddress(uint64_t Size, int64_t Offset,
MachinePointerInfo &MPO,
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
index 25587b39b97f..6aeef145e307 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
@@ -12,6 +12,7 @@
#include "PPCRegisterBankInfo.h"
#include "PPCRegisterInfo.h"
+#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
@@ -289,8 +290,11 @@ bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
const TargetRegisterInfo &TRI,
unsigned Depth) const {
unsigned Op = MI.getOpcode();
- if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MI.getIntrinsicID()))
- return true;
+
+ if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
+ if (isFPIntrinsic(GI->getIntrinsicID()))
+ return true;
+ }
// Do we have an explicit floating point instruction?
if (isPreISelGenericFloatingPointOpcode(Op))
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h
index c2a16c92ba85..1477fdca917d 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h
@@ -37,9 +37,9 @@ protected:
PMI_Min = PMI_GPR32,
};
- static RegisterBankInfo::PartialMapping PartMappings[];
- static RegisterBankInfo::ValueMapping ValMappings[];
- static PartialMappingIdx BankIDToCopyMapIdx[];
+ static const RegisterBankInfo::PartialMapping PartMappings[];
+ static const RegisterBankInfo::ValueMapping ValMappings[];
+ static const PartialMappingIdx BankIDToCopyMapIdx[];
/// Get the pointer to the ValueMapping representing the RegisterBank
/// at \p RBIdx.
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
index 89d04dbe378e..251737ed1275 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
@@ -87,7 +87,8 @@ protected:
Triple TT;
public:
PPCAsmBackend(const Target &T, const Triple &TT)
- : MCAsmBackend(TT.isLittleEndian() ? support::little : support::big),
+ : MCAsmBackend(TT.isLittleEndian() ? llvm::endianness::little
+ : llvm::endianness::big),
TT(TT) {}
unsigned getNumFixupKinds() const override {
@@ -132,7 +133,7 @@ public:
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
- return (Endian == support::little
+ return (Endian == llvm::endianness::little
? InfosLE
: InfosBE)[Kind - FirstTargetFixupKind];
}
@@ -154,13 +155,15 @@ public:
// from the fixup value. The Value has been "split up" into the appropriate
// bitfields above.
for (unsigned i = 0; i != NumBytes; ++i) {
- unsigned Idx = Endian == support::little ? i : (NumBytes - 1 - i);
+ unsigned Idx =
+ Endian == llvm::endianness::little ? i : (NumBytes - 1 - i);
Data[Offset + i] |= uint8_t((Value >> (Idx * 8)) & 0xff);
}
}
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
- const MCValue &Target) override {
+ const MCValue &Target,
+ const MCSubtargetInfo *STI) override {
MCFixupKind Kind = Fixup.getKind();
switch ((unsigned)Kind) {
default:
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
index 1e58039582c2..6a72b7b9ad05 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
@@ -28,7 +28,7 @@ namespace {
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsPCRel) const override;
- bool needsRelocateWithSymbol(const MCSymbol &Sym,
+ bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
unsigned Type) const override;
};
}
@@ -456,7 +456,13 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
}
break;
case FK_Data_4:
- Type = ELF::R_PPC_ADDR32;
+ switch (Modifier) {
+ case MCSymbolRefExpr::VK_DTPREL:
+ Type = ELF::R_PPC_DTPREL32;
+ break;
+ default:
+ Type = ELF::R_PPC_ADDR32;
+ }
break;
case FK_Data_2:
Type = ELF::R_PPC_ADDR16;
@@ -466,7 +472,8 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
return Type;
}
-bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
+bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
+ const MCSymbol &Sym,
unsigned Type) const {
switch (Type) {
default:
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp
index 2f03aa37745f..1eaa57e16260 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp
@@ -17,11 +17,10 @@
//
//===----------------------------------------------------------------------===//
-
#include "PPCELFStreamer.h"
#include "PPCFixupKinds.h"
-#include "PPCInstrInfo.h"
#include "PPCMCCodeEmitter.h"
+#include "PPCMCTargetDesc.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h
index 7d786ac13bb9..10204b184a49 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h
@@ -13,7 +13,6 @@
#ifndef LLVM_LIB_TARGET_PPC_MCELFSTREAMER_PPCELFSTREAMER_H
#define LLVM_LIB_TARGET_PPC_MCELFSTREAMER_PPCELFSTREAMER_H
-#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCELFStreamer.h"
#include <memory>
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
index 13480da4e731..9a4291c90408 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
@@ -13,14 +13,14 @@
#include "MCTargetDesc/PPCInstPrinter.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCPredicates.h"
-#include "PPCInstrInfo.h"
-#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -484,7 +484,10 @@ void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo,
if (!MI->getOperand(OpNo).isImm())
return printOperand(MI, OpNo, STI, O);
- O << SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2);
+ uint64_t Imm = static_cast<uint64_t>(MI->getOperand(OpNo).getImm()) << 2;
+ if (!TT.isPPC64())
+ Imm = static_cast<uint32_t>(Imm);
+ O << formatHex(Imm);
}
void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
@@ -597,7 +600,8 @@ void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
/// showRegistersWithPercentPrefix - Check if this register name should be
/// printed with a percentage symbol as prefix.
bool PPCInstPrinter::showRegistersWithPercentPrefix(const char *RegName) const {
- if (!FullRegNamesWithPercent || TT.getOS() == Triple::AIX)
+ if ((!FullRegNamesWithPercent && !MAI.useFullRegisterNames()) ||
+ TT.getOS() == Triple::AIX)
return false;
switch (RegName[0]) {
@@ -614,10 +618,10 @@ bool PPCInstPrinter::showRegistersWithPercentPrefix(const char *RegName) const {
/// getVerboseConditionalRegName - This method expands the condition register
/// when requested explicitly or targetting Darwin.
-const char *PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum,
- unsigned RegEncoding)
- const {
- if (!FullRegNames)
+const char *
+PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum,
+ unsigned RegEncoding) const {
+ if (!FullRegNames && !MAI.useFullRegisterNames())
return nullptr;
if (RegNum < PPC::CR0EQ || RegNum > PPC::CR7UN)
return nullptr;
@@ -637,7 +641,7 @@ const char *PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum,
// showRegistersWithPrefix - This method determines whether registers
// should be number-only or include the prefix.
bool PPCInstPrinter::showRegistersWithPrefix() const {
- return FullRegNamesWithPercent || FullRegNames;
+ return FullRegNamesWithPercent || FullRegNames || MAI.useFullRegisterNames();
}
void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
@@ -646,8 +650,7 @@ void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
if (Op.isReg()) {
unsigned Reg = Op.getReg();
if (!ShowVSRNumsAsVR)
- Reg = PPCInstrInfo::getRegNumForOperand(MII.get(MI->getOpcode()),
- Reg, OpNo);
+ Reg = PPC::getRegNumForOperand(MII.get(MI->getOpcode()), Reg, OpNo);
const char *RegName;
RegName = getVerboseConditionRegName(Reg, MRI.getEncodingValue(Reg));
@@ -656,7 +659,7 @@ void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
if (showRegistersWithPercentPrefix(RegName))
O << "%";
if (!showRegistersWithPrefix())
- RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
+ RegName = PPC::stripRegisterPrefix(RegName);
O << RegName;
return;
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
index a5dc0b45b13c..4716e37b3443 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
@@ -12,7 +12,6 @@
#include "PPCMCAsmInfo.h"
#include "llvm/TargetParser/Triple.h"
-#include <cassert>
using namespace llvm;
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
index da0174ce1982..910b5892d033 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -12,12 +12,14 @@
#include "PPCMCCodeEmitter.h"
#include "MCTargetDesc/PPCFixupKinds.h"
-#include "PPCInstrInfo.h"
+#include "PPCMCTargetDesc.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
@@ -47,16 +49,108 @@ getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
if (MO.isReg() || MO.isImm())
return getMachineOpValue(MI, MO, Fixups, STI);
- const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo *>(&MCII);
- unsigned Opcode = MI.getOpcode();
// Add a fixup for the branch target.
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
- (InstrInfo->isNoTOCCallInstr(Opcode)
+ (isNoTOCCallInstr(MI)
? (MCFixupKind)PPC::fixup_ppc_br24_notoc
: (MCFixupKind)PPC::fixup_ppc_br24)));
return 0;
}
+/// Check if Opcode corresponds to a call instruction that should be marked
+/// with the NOTOC relocation.
+bool PPCMCCodeEmitter::isNoTOCCallInstr(const MCInst &MI) const {
+ unsigned Opcode = MI.getOpcode();
+ if (!MCII.get(Opcode).isCall())
+ return false;
+
+ switch (Opcode) {
+ default:
+#ifndef NDEBUG
+ llvm_unreachable("Unknown call opcode");
+#endif
+ return false;
+ case PPC::BL8_NOTOC:
+ case PPC::BL8_NOTOC_TLS:
+ case PPC::BL8_NOTOC_RM:
+ return true;
+#ifndef NDEBUG
+ case PPC::BL8:
+ case PPC::BL:
+ case PPC::BL8_TLS:
+ case PPC::BL_TLS:
+ case PPC::BLA8:
+ case PPC::BLA:
+ case PPC::BCCL:
+ case PPC::BCCLA:
+ case PPC::BCL:
+ case PPC::BCLn:
+ case PPC::BL8_NOP:
+ case PPC::BL_NOP:
+ case PPC::BL8_NOP_TLS:
+ case PPC::BLA8_NOP:
+ case PPC::BCTRL8:
+ case PPC::BCTRL:
+ case PPC::BCCCTRL8:
+ case PPC::BCCCTRL:
+ case PPC::BCCTRL8:
+ case PPC::BCCTRL:
+ case PPC::BCCTRL8n:
+ case PPC::BCCTRLn:
+ case PPC::BL8_RM:
+ case PPC::BLA8_RM:
+ case PPC::BL8_NOP_RM:
+ case PPC::BLA8_NOP_RM:
+ case PPC::BCTRL8_RM:
+ case PPC::BCTRL8_LDinto_toc:
+ case PPC::BCTRL8_LDinto_toc_RM:
+ case PPC::BL8_TLS_:
+ case PPC::TCRETURNdi8:
+ case PPC::TCRETURNai8:
+ case PPC::TCRETURNri8:
+ case PPC::TAILBCTR8:
+ case PPC::TAILB8:
+ case PPC::TAILBA8:
+ case PPC::BCLalways:
+ case PPC::BLRL:
+ case PPC::BCCLRL:
+ case PPC::BCLRL:
+ case PPC::BCLRLn:
+ case PPC::BDZL:
+ case PPC::BDNZL:
+ case PPC::BDZLA:
+ case PPC::BDNZLA:
+ case PPC::BDZLp:
+ case PPC::BDNZLp:
+ case PPC::BDZLAp:
+ case PPC::BDNZLAp:
+ case PPC::BDZLm:
+ case PPC::BDNZLm:
+ case PPC::BDZLAm:
+ case PPC::BDNZLAm:
+ case PPC::BDZLRL:
+ case PPC::BDNZLRL:
+ case PPC::BDZLRLp:
+ case PPC::BDNZLRLp:
+ case PPC::BDZLRLm:
+ case PPC::BDNZLRLm:
+ case PPC::BL_RM:
+ case PPC::BLA_RM:
+ case PPC::BL_NOP_RM:
+ case PPC::BCTRL_RM:
+ case PPC::TCRETURNdi:
+ case PPC::TCRETURNai:
+ case PPC::TCRETURNri:
+ case PPC::BCTRL_LWZinto_toc:
+ case PPC::BCTRL_LWZinto_toc_RM:
+ case PPC::TAILBCTR:
+ case PPC::TAILB:
+ case PPC::TAILBA:
+ return false;
+#endif
+ }
+}
+
unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
@@ -372,7 +466,7 @@ get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
}
// Get the index for this operand in this instruction. This is needed for
-// computing the register number in PPCInstrInfo::getRegNumForOperand() for
+// computing the register number in PPC::getRegNumForOperand() for
// any instructions that use a different numbering scheme for registers in
// different operands.
static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {
@@ -397,8 +491,7 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
unsigned OpNo = getOpIdxForMO(MI, MO);
unsigned Reg =
- PPCInstrInfo::getRegNumForOperand(MCII.get(MI.getOpcode()),
- MO.getReg(), OpNo);
+ PPC::getRegNumForOperand(MCII.get(MI.getOpcode()), MO.getReg(), OpNo);
return CTX.getRegisterInfo()->getEncodingValue(Reg);
}
@@ -415,7 +508,8 @@ void PPCMCCodeEmitter::encodeInstruction(const MCInst &MI,
// Output the constant in big/little endian byte order.
unsigned Size = getInstSizeInBytes(MI);
- support::endianness E = IsLittleEndian ? support::little : support::big;
+ llvm::endianness E =
+ IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;
switch (Size) {
case 0:
break;
@@ -443,9 +537,7 @@ unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {
}
bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const {
- unsigned Opcode = MI.getOpcode();
- const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo*>(&MCII);
- return InstrInfo->isPrefixed(Opcode);
+ return MCII.get(MI.getOpcode()).TSFlags & PPCII::Prefixed;
}
#include "PPCGenMCCodeEmitter.inc"
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
index 17a15ef18cb7..b57455718319 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
@@ -121,6 +121,10 @@ public:
// Is this instruction a prefixed instruction.
bool isPrefixedInstruction(const MCInst &MI) const;
+
+ /// Check if Opcode corresponds to a call instruction that should be marked
+ /// with the NOTOC relocation.
+ bool isNoTOCCallInstr(const MCInst &MI) const;
};
} // namespace llvm
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 271f7ab757e1..a804dd823daa 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -57,6 +57,90 @@ using namespace llvm;
#define GET_REGINFO_MC_DESC
#include "PPCGenRegisterInfo.inc"
+/// stripRegisterPrefix - This method strips the character prefix from a
+/// register name so that only the number is left. Used by for linux asm.
+const char *PPC::stripRegisterPrefix(const char *RegName) {
+ switch (RegName[0]) {
+ case 'a':
+ if (RegName[1] == 'c' && RegName[2] == 'c')
+ return RegName + 3;
+ break;
+ case 'f':
+ if (RegName[1] == 'p')
+ return RegName + 2;
+ [[fallthrough]];
+ case 'r':
+ case 'v':
+ if (RegName[1] == 's') {
+ if (RegName[2] == 'p')
+ return RegName + 3;
+ return RegName + 2;
+ }
+ return RegName + 1;
+ case 'c':
+ if (RegName[1] == 'r')
+ return RegName + 2;
+ break;
+ case 'w':
+ // For wacc and wacc_hi
+ if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') {
+ if (RegName[4] == '_')
+ return RegName + 7;
+ else
+ return RegName + 4;
+ }
+ break;
+ case 'd':
+ // For dmr, dmrp, dmrrow, dmrrowp
+ if (RegName[1] == 'm' && RegName[2] == 'r') {
+ if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' &&
+ RegName[6] == 'p')
+ return RegName + 7;
+ else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w')
+ return RegName + 6;
+ else if (RegName[3] == 'p')
+ return RegName + 4;
+ else
+ return RegName + 3;
+ }
+ break;
+ }
+
+ return RegName;
+}
+
+/// getRegNumForOperand - some operands use different numbering schemes
+/// for the same registers. For example, a VSX instruction may have any of
+/// vs0-vs63 allocated whereas an Altivec instruction could only have
+/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual
+/// register number needed for the opcode/operand number combination.
+/// The operand number argument will be useful when we need to extend this
+/// to instructions that use both Altivec and VSX numbering (for different
+/// operands).
+unsigned PPC::getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg,
+ unsigned OpNo) {
+ int16_t regClass = Desc.operands()[OpNo].RegClass;
+ switch (regClass) {
+ // We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31,
+ // VSX32-VSX63 during encoding/disassembling
+ case PPC::VSSRCRegClassID:
+ case PPC::VSFRCRegClassID:
+ if (PPC::isVFRegister(Reg))
+ return PPC::VSX32 + (Reg - PPC::VF0);
+ break;
+ // We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31,
+ // VSX32-VSX63 during encoding/disassembling
+ case PPC::VSRCRegClassID:
+ if (PPC::isVRRegister(Reg))
+ return PPC::VSX32 + (Reg - PPC::V0);
+ break;
+ // Other RegClass doesn't need mapping
+ default:
+ break;
+ }
+ return Reg;
+}
+
PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
// Pin the vtable to this file.
@@ -148,9 +232,10 @@ public:
cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
->getQualNameSymbol();
// On AIX, we have a region handle (symbol@m) and the variable offset
- // (symbol@{gd|le}) for TLS variables, depending on the TLS model.
+ // (symbol@{gd|ie|le}) for TLS variables, depending on the TLS model.
if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD ||
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
+ Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE ||
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE)
OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
<< MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index 86ca1386fed9..16777725990a 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -26,6 +26,7 @@ namespace llvm {
class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
+class MCInstrDesc;
class MCInstrInfo;
class MCObjectTargetWriter;
class MCRegisterInfo;
@@ -33,6 +34,24 @@ class MCSubtargetInfo;
class MCTargetOptions;
class Target;
+namespace PPC {
+/// stripRegisterPrefix - This method strips the character prefix from a
+/// register name so that only the number is left. Used by for linux asm.
+const char *stripRegisterPrefix(const char *RegName);
+
+/// getRegNumForOperand - some operands use different numbering schemes
+/// for the same registers. For example, a VSX instruction may have any of
+/// vs0-vs63 allocated whereas an Altivec instruction could only have
+/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual
+/// register number needed for the opcode/operand number combination.
+/// The operand number argument will be useful when we need to extend this
+/// to instructions that use both Altivec and VSX numbering (for different
+/// operands).
+unsigned getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg,
+ unsigned OpNo);
+
+} // namespace PPC
+
MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII,
MCContext &Ctx);
@@ -102,11 +121,61 @@ static inline bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME) {
return false;
}
-} // end namespace llvm
+/// PPCII - This namespace holds all of the PowerPC target-specific
+/// per-instruction flags. These must match the corresponding definitions in
+/// PPC.td and PPCInstrFormats.td.
+namespace PPCII {
+enum {
+ // PPC970 Instruction Flags. These flags describe the characteristics of the
+ // PowerPC 970 (aka G5) dispatch groups and how they are formed out of
+ // raw machine instructions.
-// Generated files will use "namespace PPC". To avoid symbol clash,
-// undefine PPC here. PPC may be predefined on some hosts.
-#undef PPC
+ /// PPC970_First - This instruction starts a new dispatch group, so it will
+ /// always be the first one in the group.
+ PPC970_First = 0x1,
+
+ /// PPC970_Single - This instruction starts a new dispatch group and
+ /// terminates it, so it will be the sole instruction in the group.
+ PPC970_Single = 0x2,
+
+ /// PPC970_Cracked - This instruction is cracked into two pieces, requiring
+ /// two dispatch pipes to be available to issue.
+ PPC970_Cracked = 0x4,
+
+ /// PPC970_Mask/Shift - This is a bitmask that selects the pipeline type that
+ /// an instruction is issued to.
+ PPC970_Shift = 3,
+ PPC970_Mask = 0x07 << PPC970_Shift
+};
+enum PPC970_Unit {
+ /// These are the various PPC970 execution unit pipelines. Each instruction
+ /// is one of these.
+ PPC970_Pseudo = 0 << PPC970_Shift, // Pseudo instruction
+ PPC970_FXU = 1 << PPC970_Shift, // Fixed Point (aka Integer/ALU) Unit
+ PPC970_LSU = 2 << PPC970_Shift, // Load Store Unit
+ PPC970_FPU = 3 << PPC970_Shift, // Floating Point Unit
+ PPC970_CRU = 4 << PPC970_Shift, // Control Register Unit
+ PPC970_VALU = 5 << PPC970_Shift, // Vector ALU
+ PPC970_VPERM = 6 << PPC970_Shift, // Vector Permute Unit
+ PPC970_BRU = 7 << PPC970_Shift // Branch Unit
+};
+
+enum {
+ /// Shift count to bypass PPC970 flags
+ NewDef_Shift = 6,
+
+ /// This instruction is an X-Form memory operation.
+ XFormMemOp = 0x1 << NewDef_Shift,
+ /// This instruction is prefixed.
+ Prefixed = 0x1 << (NewDef_Shift + 1),
+ /// This instruction produced a sign extended result.
+ SExt32To64 = 0x1 << (NewDef_Shift + 2),
+ /// This instruction produced a zero extended result.
+ ZExt32To64 = 0x1 << (NewDef_Shift + 3)
+};
+} // end namespace PPCII
+
+} // end namespace llvm
// Defines symbolic names for PowerPC registers. This defines a mapping from
// register name to register number.
@@ -214,4 +283,16 @@ using llvm::MCPhysReg;
static const MCPhysReg DMRRegs[8] = PPC_REGS0_7(PPC::DMR); \
static const MCPhysReg DMRpRegs[4] = PPC_REGS0_3(PPC::DMRp);
+namespace llvm {
+namespace PPC {
+static inline bool isVFRegister(unsigned Reg) {
+ return Reg >= PPC::VF0 && Reg <= PPC::VF31;
+}
+
+static inline bool isVRRegister(unsigned Reg) {
+ return Reg >= PPC::V0 && Reg <= PPC::V31;
+}
+} // namespace PPC
+} // namespace llvm
+
#endif // LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCTARGETDESC_H
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp
index 284e52c298a2..80c37f82bf29 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp
@@ -12,7 +12,6 @@
#include "PPCPredicates.h"
#include "llvm/Support/ErrorHandling.h"
-#include <cassert>
using namespace llvm;
PPC::Predicate PPC::InvertPredicate(PPC::Predicate Opcode) {
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
index df671f53cbd8..065daf42fe6e 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
@@ -69,6 +69,8 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
return {XCOFF::RelocationType::R_TOCU, SignAndSizeForHalf16};
case MCSymbolRefExpr::VK_PPC_L:
return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16};
+ case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
+ return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForHalf16};
}
} break;
case PPC::fixup_ppc_half16ds:
@@ -82,6 +84,8 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
return {XCOFF::RelocationType::R_TOC, 15};
case MCSymbolRefExpr::VK_PPC_L:
return {XCOFF::RelocationType::R_TOCL, 15};
+ case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
+ return {XCOFF::RelocationType::R_TLS_LE, 15};
}
} break;
case PPC::fixup_ppc_br24:
@@ -108,6 +112,8 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData};
case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM:
return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData};
+ case MCSymbolRefExpr::VK_PPC_AIX_TLSIE:
+ return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData};
case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData};
case MCSymbolRefExpr::VK_None:
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td
index 0827e528a80f..3bbc5a63ca7a 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td
@@ -825,9 +825,7 @@ def : InstRW<[P10W_F2_4C, P10W_DISP_ANY, P10F2_Read, P10F2_Read, P10F2_Read],
def : InstRW<[P10W_F2_4C, P10W_DISP_EVEN, P10W_DISP_ANY, P10F2_Read],
(instrs
SRADI_rec,
- SRAWI_rec,
- TABORTDCI,
- TABORTWCI
+ SRAWI_rec
)>;
// Single crack instructions
@@ -835,9 +833,7 @@ def : InstRW<[P10W_F2_4C, P10W_DISP_EVEN, P10W_DISP_ANY, P10F2_Read],
def : InstRW<[P10W_F2_4C, P10W_DISP_EVEN, P10W_DISP_ANY, P10F2_Read, P10F2_Read],
(instrs
SRAD_rec,
- SRAW_rec,
- TABORTDC,
- TABORTWC
+ SRAW_rec
)>;
// 2-way crack instructions
@@ -879,7 +875,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_ANY],
MCRXRX,
MFCTR, MFCTR8,
MFLR, MFLR8,
- WAIT
+ WAIT, WAITP10
)>;
// 3 Cycles ALU operations, 1 input operands
@@ -1130,10 +1126,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_EVEN, P10W_DISP_ANY],
MFFSCRNI,
MFFSL,
MFVSCR,
- MTFSB0,
- TBEGIN,
- TRECHKPT,
- TSR
+ MTFSB0
)>;
// Single crack instructions
@@ -1153,9 +1146,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_EVEN, P10W_DISP_ANY, P10FX_Read],
SUBFME8_rec, SUBFME_rec,
SUBFME8O_rec, SUBFMEO_rec,
SUBFZE8_rec, SUBFZE_rec,
- SUBFZE8O_rec, SUBFZEO_rec,
- TABORT,
- TRECLAIM
+ SUBFZE8O_rec, SUBFZEO_rec
)>;
// Single crack instructions
@@ -1862,8 +1853,6 @@ def : InstRW<[P10W_ST_3C, P10W_DISP_EVEN, P10W_DISP_ANY],
EnforceIEIO,
MSGSYNC,
SLBSYNC,
- TCHECK,
- TEND,
TLBSYNC
)>;
@@ -1895,6 +1884,7 @@ def : InstRW<[P10W_ST_3C, P10W_DISP_EVEN, P10W_DISP_ANY, P10ST_Read, P10ST_Read,
def : InstRW<[P10W_ST_3C, P10W_DISP_EVEN, P10W_FX_3C, P10W_DISP_ANY],
(instrs
ISYNC,
+ SYNCP10,
SYNC
)>;
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h
index 0d3d71742bfb..3d9ea5608193 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h
@@ -46,13 +46,14 @@ class ModulePass;
FunctionPass *createPPCMIPeepholePass();
FunctionPass *createPPCBranchSelectionPass();
FunctionPass *createPPCBranchCoalescingPass();
- FunctionPass *createPPCISelDag(PPCTargetMachine &TM, CodeGenOpt::Level OL);
+ FunctionPass *createPPCISelDag(PPCTargetMachine &TM, CodeGenOptLevel OL);
FunctionPass *createPPCTLSDynamicCallPass();
FunctionPass *createPPCBoolRetToIntPass();
FunctionPass *createPPCExpandISELPass();
FunctionPass *createPPCPreEmitPeepholePass();
FunctionPass *createPPCExpandAtomicPseudoPass();
FunctionPass *createPPCCTRLoopsPass();
+ ModulePass *createPPCMergeStringPoolPass();
void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP);
bool LowerPPCMachineOperandToMCOperand(const MachineOperand &MO,
@@ -78,6 +79,7 @@ class ModulePass;
void initializePPCExpandAtomicPseudoPass(PassRegistry &);
void initializePPCCTRLoopsPass(PassRegistry &);
void initializePPCDAGToDAGISelPass(PassRegistry &);
+ void initializePPCMergeStringPoolPass(PassRegistry &);
extern char &PPCVSXFMAMutateID;
@@ -100,79 +102,99 @@ class ModulePass;
// PPC Specific MachineOperand flags.
MO_NO_FLAG,
+ /// On PPC, the 12 bits are not enough for all target operand flags.
+ /// Treat all PPC target flags as direct flags. To define new flag that is
+ /// combination of other flags, add new enum entry instead of combining
+ /// existing flags. See example MO_GOT_TPREL_PCREL_FLAG.
+
/// On a symbol operand "FOO", this indicates that the reference is actually
/// to "FOO@plt". This is used for calls and jumps to external functions
/// and for PIC calls on 32-bit ELF systems.
- MO_PLT = 1,
+ MO_PLT,
/// MO_PIC_FLAG - If this bit is set, the symbol reference is relative to
/// the function's picbase, e.g. lo16(symbol-picbase).
- MO_PIC_FLAG = 2,
+ MO_PIC_FLAG,
/// MO_PCREL_FLAG - If this bit is set, the symbol reference is relative to
/// the current instruction address(pc), e.g., var@pcrel. Fixup is VK_PCREL.
- MO_PCREL_FLAG = 4,
+ MO_PCREL_FLAG,
/// MO_GOT_FLAG - If this bit is set the symbol reference is to be computed
/// via the GOT. For example when combined with the MO_PCREL_FLAG it should
/// produce the relocation @got@pcrel. Fixup is VK_PPC_GOT_PCREL.
- MO_GOT_FLAG = 8,
+ MO_GOT_FLAG,
- // MO_PCREL_OPT_FLAG - If this bit is set the operand is part of a
- // PC Relative linker optimization.
- MO_PCREL_OPT_FLAG = 16,
+ /// MO_PCREL_OPT_FLAG - If this bit is set the operand is part of a
+ /// PC Relative linker optimization.
+ MO_PCREL_OPT_FLAG,
/// MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to
/// TLS General Dynamic model for Linux and the variable offset of TLS
/// General Dynamic model for AIX.
- MO_TLSGD_FLAG = 32,
+ MO_TLSGD_FLAG,
/// MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to
/// the thread pointer and the symbol can be used for the TLS Initial Exec
/// and Local Exec models.
- MO_TPREL_FLAG = 64,
+ MO_TPREL_FLAG,
/// MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to
/// TLS Local Dynamic model.
- MO_TLSLD_FLAG = 128,
+ MO_TLSLD_FLAG,
/// MO_TLSGDM_FLAG - If this bit is set the symbol reference is relative
/// to the region handle of TLS General Dynamic model for AIX.
- MO_TLSGDM_FLAG = 256,
+ MO_TLSGDM_FLAG,
/// MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set
/// they should produce the relocation @got@tlsgd@pcrel.
/// Fix up is VK_PPC_GOT_TLSGD_PCREL
- MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG,
+ /// MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG,
+ MO_GOT_TLSGD_PCREL_FLAG,
/// MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set
/// they should produce the relocation @got@tlsld@pcrel.
/// Fix up is VK_PPC_GOT_TLSLD_PCREL
- MO_GOT_TLSLD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSLD_FLAG,
+ /// MO_GOT_TLSLD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSLD_FLAG,
+ MO_GOT_TLSLD_PCREL_FLAG,
/// MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set
/// they should produce the relocation @got@tprel@pcrel.
/// Fix up is VK_PPC_GOT_TPREL_PCREL
- MO_GOT_TPREL_PCREL_FLAG = MO_GOT_FLAG | MO_TPREL_FLAG | MO_PCREL_FLAG,
-
- /// The next are not flags but distinct values.
- MO_ACCESS_MASK = 0xf00,
+ /// MO_GOT_TPREL_PCREL_FLAG = MO_GOT_FLAG | MO_TPREL_FLAG | MO_PCREL_FLAG,
+ MO_GOT_TPREL_PCREL_FLAG,
/// MO_LO, MO_HA - lo16(symbol) and ha16(symbol)
- MO_LO = 1 << 8,
- MO_HA = 2 << 8,
+ MO_LO,
+ MO_HA,
- MO_TPREL_LO = 4 << 8,
- MO_TPREL_HA = 3 << 8,
+ MO_TPREL_LO,
+ MO_TPREL_HA,
/// These values identify relocations on immediates folded
/// into memory operations.
- MO_DTPREL_LO = 5 << 8,
- MO_TLSLD_LO = 6 << 8,
- MO_TOC_LO = 7 << 8,
+ MO_DTPREL_LO,
+ MO_TLSLD_LO,
+ MO_TOC_LO,
+
+ /// Symbol for VK_PPC_TLS fixup attached to an ADD instruction
+ MO_TLS,
+
+ /// MO_PIC_HA_FLAG = MO_PIC_FLAG | MO_HA
+ MO_PIC_HA_FLAG,
+
+ /// MO_PIC_LO_FLAG = MO_PIC_FLAG | MO_LO
+ MO_PIC_LO_FLAG,
+
+ /// MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TPREL_FLAG
+ MO_TPREL_PCREL_FLAG,
+
+ /// MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TLS
+ MO_TLS_PCREL_FLAG,
- // Symbol for VK_PPC_TLS fixup attached to an ADD instruction
- MO_TLS = 8 << 8
+ /// MO_GOT_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG
+ MO_GOT_PCREL_FLAG,
};
} // end namespace PPCII
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td
index 3ba36f4f01e1..535616d33a80 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td
@@ -318,6 +318,17 @@ def FeaturePrivileged :
SubtargetFeature<"privileged", "HasPrivileged", "true",
"Add privileged instructions">;
+// Specifies that local-exec TLS accesses in any function with this target
+// attribute should use the optimized TOC-free sequence (where the offset is an
+// immediate off of R13 for which the linker might add fix-up code if the
+// immediate is too large).
+// Clearly, this isn't really a feature of the subtarget, but is used as a
+// convenient way to affect code generation for individual functions.
+def FeatureAIXLocalExecTLS :
+ SubtargetFeature<"aix-small-local-exec-tls", "HasAIXSmallLocalExecTLS", "true",
+ "Produce a TOC-free local-exec TLS sequence for this function "
+ "for 64-bit AIX">;
+
def FeaturePredictableSelectIsExpensive :
SubtargetFeature<"predictable-select-expensive",
"PredictableSelectIsExpensive",
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 5c10d6307c76..780b22b4fbe6 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -68,6 +68,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Threading.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
@@ -316,7 +317,7 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
// Linux assembler (Others?) does not take register mnemonics.
// FIXME - What about special registers used in mfspr/mtspr?
- O << PPCRegisterInfo::stripRegisterPrefix(RegName);
+ O << PPC::stripRegisterPrefix(RegName);
return;
}
case MachineOperand::MO_Immediate:
@@ -376,13 +377,13 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
// This operand uses VSX numbering.
// If the operand is a VMX register, convert it to a VSX register.
Register Reg = MI->getOperand(OpNo).getReg();
- if (PPCInstrInfo::isVRRegister(Reg))
+ if (PPC::isVRRegister(Reg))
Reg = PPC::VSX32 + (Reg - PPC::V0);
- else if (PPCInstrInfo::isVFRegister(Reg))
+ else if (PPC::isVFRegister(Reg))
Reg = PPC::VSX32 + (Reg - PPC::VF0);
const char *RegName;
RegName = PPCInstPrinter::getRegisterName(Reg);
- RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
+ RegName = PPC::stripRegisterPrefix(RegName);
O << RegName;
return false;
}
@@ -632,7 +633,6 @@ void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) {
const MCExpr *TlsRef =
MCSymbolRefExpr::create(TlsCall, MCSymbolRefExpr::VK_None, OutContext);
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));
- return;
}
/// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a
@@ -715,25 +715,11 @@ static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
}
}
-static bool hasTLSFlag(const MachineOperand &MO) {
- unsigned Flags = MO.getTargetFlags();
- if (Flags & PPCII::MO_TLSGD_FLAG || Flags & PPCII::MO_TPREL_FLAG ||
- Flags & PPCII::MO_TLSLD_FLAG || Flags & PPCII::MO_TLSGDM_FLAG)
- return true;
-
- if (Flags == PPCII::MO_TPREL_LO || Flags == PPCII::MO_TPREL_HA ||
- Flags == PPCII::MO_DTPREL_LO || Flags == PPCII::MO_TLSLD_LO ||
- Flags == PPCII::MO_TLS)
- return true;
-
- return false;
-}
-
static PPCAsmPrinter::TOCEntryType
getTOCEntryTypeForMO(const MachineOperand &MO) {
// Use the target flags to determine if this MO is Thread Local.
// If we don't do this it comes out as Global.
- if (hasTLSFlag(MO))
+ if (PPCInstrInfo::hasTLSFlag(MO.getTargetFlags()))
return PPCAsmPrinter::TOCType_ThreadLocal;
switch (MO.getType()) {
@@ -827,24 +813,27 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
return Expr;
};
auto GetVKForMO = [&](const MachineOperand &MO) {
- // For TLS local-exec accesses on AIX, we have one TOC entry for the symbol
- // (with the variable offset), which is differentiated by MO_TPREL_FLAG.
- if (MO.getTargetFlags() & PPCII::MO_TPREL_FLAG) {
- // TODO: Update the query and the comment above to add a check for initial
- // exec when this TLS model is supported on AIX in the future, as both
- // local-exec and initial-exec can use MO_TPREL_FLAG.
+ // For TLS initial-exec and local-exec accesses on AIX, we have one TOC
+ // entry for the symbol (with the variable offset), which is differentiated
+ // by MO_TPREL_FLAG.
+ unsigned Flag = MO.getTargetFlags();
+ if (Flag == PPCII::MO_TPREL_FLAG ||
+ Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
+ Flag == PPCII::MO_TPREL_PCREL_FLAG) {
assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");
TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
if (Model == TLSModel::LocalExec)
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
- llvm_unreachable("Only expecting local-exec accesses!");
+ if (Model == TLSModel::InitialExec)
+ return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
+ llvm_unreachable("Only expecting local-exec or initial-exec accesses!");
}
// For GD TLS access on AIX, we have two TOC entries for the symbol (one for
// the variable offset and the other for the region handle). They are
// differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG.
- if (MO.getTargetFlags() & PPCII::MO_TLSGDM_FLAG)
+ if (Flag == PPCII::MO_TLSGDM_FLAG)
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;
- if (MO.getTargetFlags() & PPCII::MO_TLSGD_FLAG)
+ if (Flag == PPCII::MO_TLSGD_FLAG || Flag == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;
return MCSymbolRefExpr::VariantKind::VK_None;
};
@@ -1534,6 +1523,24 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));
return;
}
+ case PPC::ADDI8: {
+ // The faster non-TOC-based local-exec sequence is represented by `addi`
+ // with an immediate operand having the MO_TPREL_FLAG. Such an instruction
+ // does not otherwise arise.
+ unsigned Flag = MI->getOperand(2).getTargetFlags();
+ if (Flag == PPCII::MO_TPREL_FLAG ||
+ Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
+ Flag == PPCII::MO_TPREL_PCREL_FLAG) {
+ assert(
+ Subtarget->hasAIXSmallLocalExecTLS() &&
+ "addi with thread-pointer only expected with local-exec small TLS");
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
+ TmpInst.setOpcode(PPC::LA8);
+ EmitToStreamer(*OutStreamer, TmpInst);
+ return;
+ }
+ break;
+ }
}
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
@@ -2512,7 +2519,7 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
}
void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
- assert(!GV->getName().startswith("llvm.") &&
+ assert(!GV->getName().starts_with("llvm.") &&
"Unhandled intrinsic global variable.");
if (GV->hasComdat())
@@ -2759,14 +2766,18 @@ bool PPCAIXAsmPrinter::doInitialization(Module &M) {
// and add a format indicator as a part of function name in case we
// will support more than one format.
FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);
- else
- // Use the Pid and current time as the unique module id when we cannot
- // generate one based on a module's strong external symbols.
- // FIXME: Adjust the comment accordingly after we use source file full
- // path instead.
+ else {
+ // Use threadId, Pid, and current time as the unique module id when we
+ // cannot generate one based on a module's strong external symbols.
+ auto CurTime =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
FormatIndicatorAndUniqueModId =
- "clangPidTime_" + llvm::itostr(sys::Process::getProcessId()) +
- "_" + llvm::itostr(time(nullptr));
+ "clangPidTidTime_" + llvm::itostr(sys::Process::getProcessId()) +
+ "_" + llvm::itostr(llvm::get_threadid()) + "_" +
+ llvm::itostr(CurTime);
+ }
}
emitSpecialLLVMGlobal(&G);
@@ -2781,11 +2792,21 @@ bool PPCAIXAsmPrinter::doInitialization(Module &M) {
// Construct an aliasing list for each GlobalObject.
for (const auto &Alias : M.aliases()) {
- const GlobalObject *Base = Alias.getAliaseeObject();
- if (!Base)
+ const GlobalObject *Aliasee = Alias.getAliaseeObject();
+ if (!Aliasee)
report_fatal_error(
"alias without a base object is not yet supported on AIX");
- GOAliasMap[Base].push_back(&Alias);
+
+ if (Aliasee->hasCommonLinkage()) {
+ report_fatal_error("Aliases to common variables are not allowed on AIX:"
+ "\n\tAlias attribute for " +
+ Alias.getGlobalIdentifier() +
+ " is invalid because " + Aliasee->getName() +
+ " is common.",
+ false);
+ }
+
+ GOAliasMap[Aliasee].push_back(&Alias);
}
return Result;
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def
index 5d97d187b296..8bbe315a2bb9 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def
@@ -958,6 +958,7 @@ FUSION_FEATURE(GeneralBack2Back, hasBack2BackFusion, -1,
V_SET0B,
V_SET0H,
WAIT,
+ WAITP10,
XOR,
XOR8,
XOR8_rec,
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp
index 3c6b1f84b821..20f53bd4badf 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp
@@ -45,6 +45,7 @@
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/OperandTraits.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
@@ -95,8 +96,6 @@ class PPCBoolRetToInt : public FunctionPass {
Type *IntTy = ST->isPPC64() ? Type::getInt64Ty(V->getContext())
: Type::getInt32Ty(V->getContext());
- if (auto *C = dyn_cast<Constant>(V))
- return ConstantExpr::getZExt(C, IntTy);
if (auto *P = dyn_cast<PHINode>(V)) {
// Temporarily set the operands to 0. We'll fix this later in
// runOnUse.
@@ -108,13 +107,12 @@ class PPCBoolRetToInt : public FunctionPass {
return Q;
}
- auto *A = dyn_cast<Argument>(V);
- auto *I = dyn_cast<Instruction>(V);
- assert((A || I) && "Unknown value type");
-
- auto InstPt =
- A ? &*A->getParent()->getEntryBlock().begin() : I->getNextNode();
- return new ZExtInst(V, IntTy, "", InstPt);
+ IRBuilder IRB(V->getContext());
+ if (auto *I = dyn_cast<Instruction>(V))
+ IRB.SetInsertPoint(I->getNextNode());
+ else
+ IRB.SetInsertPoint(&Func->getEntryBlock(), Func->getEntryBlock().begin());
+ return IRB.CreateZExt(V, IntTy);
}
typedef SmallPtrSet<const PHINode *, 8> PHINodeSet;
@@ -196,6 +194,7 @@ class PPCBoolRetToInt : public FunctionPass {
auto &TM = TPC->getTM<PPCTargetMachine>();
ST = TM.getSubtargetImpl(F);
+ Func = &F;
PHINodeSet PromotablePHINodes = getPromotablePHINodes(F);
B2IMap Bool2IntMap;
@@ -277,6 +276,7 @@ class PPCBoolRetToInt : public FunctionPass {
private:
const PPCSubtarget *ST;
+ Function *Func;
};
} // end anonymous namespace
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp
index 9d580ff57471..799890928577 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "PPC.h"
-#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -702,6 +701,7 @@ bool PPCBranchCoalescing::mergeCandidates(CoalescingCandidateInfo &SourceRegion,
TargetRegion.FallThroughBlock->transferSuccessorsAndUpdatePHIs(
SourceRegion.FallThroughBlock);
TargetRegion.FallThroughBlock->removeSuccessor(SourceRegion.BranchBlock);
+ TargetRegion.FallThroughBlock->normalizeSuccProbs();
// Remove the blocks from the function.
assert(SourceRegion.BranchBlock->empty() &&
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp
index b1f5bdd885cd..1f9947f6f327 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp
@@ -16,8 +16,6 @@
// something that needs to be run (or even defined) for Release builds so the
// entire file is guarded by NDEBUG.
#ifndef NDEBUG
-#include <vector>
-
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "PPC.h"
#include "llvm/ADT/SmallSet.h"
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp
index a9794ddd0566..aee57a5075ff 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp
@@ -239,23 +239,18 @@ bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128(
// loop:
// old = lqarx ptr
// <compare old, cmp>
- // bne 0, fail
+ // bne 0, exit
// succ:
// stqcx new ptr
// bne 0, loop
- // b exit
- // fail:
- // stqcx old ptr
// exit:
// ....
MachineFunction::iterator MFI = ++MBB.getIterator();
MachineBasicBlock *LoopCmpMBB = MF->CreateMachineBasicBlock(BB);
MachineBasicBlock *CmpSuccMBB = MF->CreateMachineBasicBlock(BB);
- MachineBasicBlock *CmpFailMBB = MF->CreateMachineBasicBlock(BB);
MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB);
MF->insert(MFI, LoopCmpMBB);
MF->insert(MFI, CmpSuccMBB);
- MF->insert(MFI, CmpFailMBB);
MF->insert(MFI, ExitMBB);
ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()),
MBB.end());
@@ -276,9 +271,9 @@ bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128(
BuildMI(CurrentMBB, DL, TII->get(PPC::BCC))
.addImm(PPC::PRED_NE)
.addReg(PPC::CR0)
- .addMBB(CmpFailMBB);
+ .addMBB(ExitMBB);
CurrentMBB->addSuccessor(CmpSuccMBB);
- CurrentMBB->addSuccessor(CmpFailMBB);
+ CurrentMBB->addSuccessor(ExitMBB);
// Build succ.
CurrentMBB = CmpSuccMBB;
PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo,
@@ -288,16 +283,11 @@ bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128(
.addImm(PPC::PRED_NE)
.addReg(PPC::CR0)
.addMBB(LoopCmpMBB);
- BuildMI(CurrentMBB, DL, TII->get(PPC::B)).addMBB(ExitMBB);
CurrentMBB->addSuccessor(LoopCmpMBB);
CurrentMBB->addSuccessor(ExitMBB);
- CurrentMBB = CmpFailMBB;
- BuildMI(CurrentMBB, DL, SC).addReg(Old).addReg(RA).addReg(RB);
- CurrentMBB->addSuccessor(ExitMBB);
recomputeLiveIns(*LoopCmpMBB);
recomputeLiveIns(*CmpSuccMBB);
- recomputeLiveIns(*CmpFailMBB);
recomputeLiveIns(*ExitMBB);
NMBBI = MBB.end();
MI.eraseFromParent();
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
index d5e4ae34dde7..245e78641ed6 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -466,7 +466,7 @@ PPCFrameLowering::findScratchRegister(MachineBasicBlock *MBB,
RS.enterBasicBlock(*MBB);
} else {
RS.enterBasicBlockEnd(*MBB);
- RS.backward(std::prev(MBBI));
+ RS.backward(MBBI);
}
} else {
// The scratch register will be used at the start of the block.
@@ -2334,24 +2334,16 @@ bool PPCFrameLowering::assignCalleeSavedSpillSlots(
// In case of SPE we only have SuperRegs and CRs
// in our CalleSaveInfo vector.
- unsigned Idx = 0;
for (auto &CalleeSaveReg : CSI) {
- const MCPhysReg &Reg = CalleeSaveReg.getReg();
- const MCPhysReg &Lower = RegInfo->getSubReg(Reg, 1);
- const MCPhysReg &Higher = RegInfo->getSubReg(Reg, 2);
+ MCPhysReg Reg = CalleeSaveReg.getReg();
+ MCPhysReg Lower = RegInfo->getSubReg(Reg, 1);
+ MCPhysReg Higher = RegInfo->getSubReg(Reg, 2);
- // Check only for SuperRegs.
- if (Lower) {
- if (MRI.isPhysRegModified(Higher)) {
- Idx++;
- continue;
- } else {
+ if ( // Check only for SuperRegs.
+ Lower &&
// Replace Reg if only lower-32 bits modified
- CSI.erase(CSI.begin() + Idx);
- CSI.insert(CSI.begin() + Idx, CalleeSavedInfo(Lower));
- }
- }
- Idx++;
+ !MRI.isPhysRegModified(Higher))
+ CalleeSaveReg = CalleeSavedInfo(Lower);
}
}
@@ -2740,3 +2732,17 @@ bool PPCFrameLowering::enableShrinkWrapping(const MachineFunction &MF) const {
return false;
return !MF.getSubtarget<PPCSubtarget>().is32BitELFABI();
}
+
+uint64_t PPCFrameLowering::getStackThreshold() const {
+ // On PPC64, we use `stux r1, r1, <scratch_reg>` to extend the stack;
+ // use `add r1, r1, <scratch_reg>` to release the stack frame.
+ // Scratch register contains a signed 64-bit number, which is negative
+ // when extending the stack and is positive when releasing the stack frame.
+ // To make `stux` and `add` paired, the absolute value of the number contained
+ // in the scratch register should be the same. Thus the maximum stack size
+ // is (2^63)-1, i.e., LONG_MAX.
+ if (Subtarget.isPPC64())
+ return LONG_MAX;
+
+ return TargetFrameLowering::getStackThreshold();
+}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h
index 21883b19a575..e19087ce0e18 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h
@@ -173,6 +173,8 @@ public:
/// function prologue/epilogue.
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override;
+
+ uint64_t getStackThreshold() const override;
};
} // End llvm namespace
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def
index eff4432206e1..b42f9247f691 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def
@@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
namespace llvm {
-RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{
+const RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{
/* StartIdx, Length, RegBank */
// 0: GPR 32-bit value.
{0, 32, PPC::GPRRegBank},
@@ -39,7 +39,7 @@ RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{
// 3-operands instructions.
// - Last, mappings for cross-register bank moves follow. Since COPY has only
// 2 operands, a mapping consists of 2 entries.
-RegisterBankInfo::ValueMapping PPCGenRegisterBankInfo::ValMappings[]{
+const RegisterBankInfo::ValueMapping PPCGenRegisterBankInfo::ValMappings[]{
/* BreakDown, NumBreakDowns */
// 0: invalid
{nullptr, 0},
@@ -77,7 +77,7 @@ PPCGenRegisterBankInfo::getValueMapping(PartialMappingIdx RBIdx) {
return &ValMappings[1 + 3 * ValMappingIdx];
}
-PPCGenRegisterBankInfo::PartialMappingIdx
+const PPCGenRegisterBankInfo::PartialMappingIdx
PPCGenRegisterBankInfo::BankIDToCopyMapIdx[]{
PMI_None,
PMI_FPR64, // FPR
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 96fd83ab6a7b..b57d185bb638 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -151,7 +151,7 @@ namespace {
PPCDAGToDAGISel() = delete;
- explicit PPCDAGToDAGISel(PPCTargetMachine &tm, CodeGenOpt::Level OptLevel)
+ explicit PPCDAGToDAGISel(PPCTargetMachine &tm, CodeGenOptLevel OptLevel)
: SelectionDAGISel(ID, tm, OptLevel), TM(tm) {}
bool runOnMachineFunction(MachineFunction &MF) override {
@@ -387,18 +387,19 @@ namespace {
/// register can be improved, but it is wrong to substitute Reg+Reg for
/// Reg in an asm, because the load or store opcode would have to change.
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
- unsigned ConstraintID,
+ InlineAsm::ConstraintCode ConstraintID,
std::vector<SDValue> &OutOps) override {
switch(ConstraintID) {
default:
- errs() << "ConstraintID: " << ConstraintID << "\n";
+ errs() << "ConstraintID: "
+ << InlineAsm::getMemConstraintName(ConstraintID) << "\n";
llvm_unreachable("Unexpected asm memory constraint");
- case InlineAsm::Constraint_es:
- case InlineAsm::Constraint_m:
- case InlineAsm::Constraint_o:
- case InlineAsm::Constraint_Q:
- case InlineAsm::Constraint_Z:
- case InlineAsm::Constraint_Zy:
+ case InlineAsm::ConstraintCode::es:
+ case InlineAsm::ConstraintCode::m:
+ case InlineAsm::ConstraintCode::o:
+ case InlineAsm::ConstraintCode::Q:
+ case InlineAsm::ConstraintCode::Z:
+ case InlineAsm::ConstraintCode::Zy:
// We need to make sure that this one operand does not end up in r0
// (because we might end up lowering this as 0(%op)).
const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
@@ -424,6 +425,7 @@ private:
bool tryFoldSWTestBRCC(SDNode *N);
bool trySelectLoopCountIntrinsic(SDNode *N);
bool tryAsSingleRLDICL(SDNode *N);
+ bool tryAsSingleRLDCL(SDNode *N);
bool tryAsSingleRLDICR(SDNode *N);
bool tryAsSingleRLWINM(SDNode *N);
bool tryAsSingleRLWINM8(SDNode *N);
@@ -754,8 +756,8 @@ static bool isThreadPointerAcquisitionNode(SDValue Base, SelectionDAG *CurDAG) {
static bool canOptimizeTLSDFormToXForm(SelectionDAG *CurDAG, SDValue Base) {
// Do not do this transformation at -O0.
- if (CurDAG->getTarget().getOptLevel() == CodeGenOpt::None)
- return false;
+ if (CurDAG->getTarget().getOptLevel() == CodeGenOptLevel::None)
+ return false;
// In order to perform this optimization inside tryTLSXForm[Load|Store],
// Base is expected to be an ADD_TLS node.
@@ -1165,6 +1167,31 @@ static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl,
return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
getI32Imm(Shift), getI32Imm(0));
}
+ // 2-7) Patterns : High word == Low word
+ // This may require 2 to 3 instructions, depending on whether Lo32 can be
+ // materialized in 1 instruction.
+ if (Hi32 == Lo32) {
+ // Handle the first 32 bits.
+ uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;
+ uint64_t ImmLo16 = Lo32 & 0xffff;
+ if (isInt<16>(Lo32))
+ Result =
+ CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, getI32Imm(ImmLo16));
+ else if (!ImmLo16)
+ Result =
+ CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(ImmHi16));
+ else {
+ InstCnt = 3;
+ Result =
+ CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(ImmHi16));
+ Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64,
+ SDValue(Result, 0), getI32Imm(ImmLo16));
+ }
+ // Use rldimi to insert the Low word into High word.
+ SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32),
+ getI32Imm(0)};
+ return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
+ }
// Following patterns use 3 instructions to materialize the Imm.
InstCnt = 3;
@@ -1215,20 +1242,7 @@ static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl,
return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
getI32Imm(TO), getI32Imm(LZ));
}
- // 3-4) Patterns : High word == Low word
- if (Hi32 == Lo32) {
- // Handle the first 32 bits.
- uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;
- unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
- Result = CurDAG->getMachineNode(Opcode, dl, MVT::i64, getI32Imm(ImmHi16));
- Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(Lo32 & 0xffff));
- // Use rldimi to insert the Low word into High word.
- SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32),
- getI32Imm(0)};
- return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
- }
- // 3-5) Patterns : {******}{33 zeros}{******}
+ // 3-4) Patterns : {******}{33 zeros}{******}
// {******}{33 ones}{******}
// If the Imm contains 33 consecutive zeros/ones, it means that a total of 31
// bits remain on both sides. Rotate right the Imm to construct an int<32>
@@ -4041,7 +4055,7 @@ bool PPCDAGToDAGISel::tryIntCompareInGPR(SDNode *N) {
// This optimization will emit code that assumes 64-bit registers
// so we don't want to run it in 32-bit mode. Also don't run it
// on functions that are not to be optimized.
- if (TM.getOptLevel() == CodeGenOpt::None || !TM.isPPC64())
+ if (TM.getOptLevel() == CodeGenOptLevel::None || !TM.isPPC64())
return false;
// For POWER10, it is more profitable to use the set boolean extension
@@ -4835,8 +4849,7 @@ bool PPCDAGToDAGISel::tryFoldSWTestBRCC(SDNode *N) {
return false;
SDValue CmpRHS = N->getOperand(3);
- if (!isa<ConstantSDNode>(CmpRHS) ||
- cast<ConstantSDNode>(CmpRHS)->getSExtValue() != 0)
+ if (!isNullConstant(CmpRHS))
return false;
SDValue CmpLHS = N->getOperand(2);
@@ -5085,6 +5098,35 @@ bool PPCDAGToDAGISel::tryAsSingleRLWIMI(SDNode *N) {
return false;
}
+bool PPCDAGToDAGISel::tryAsSingleRLDCL(SDNode *N) {
+ assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
+
+ uint64_t Imm64;
+ if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) || !isMask_64(Imm64))
+ return false;
+
+ SDValue Val = N->getOperand(0);
+
+ if (Val.getOpcode() != ISD::ROTL)
+ return false;
+
+ // Looking to try to avoid a situation like this one:
+ // %2 = tail call i64 @llvm.fshl.i64(i64 %word, i64 %word, i64 23)
+ // %and1 = and i64 %2, 9223372036854775807
+ // In this function we are looking to try to match RLDCL. However, the above
+ // DAG would better match RLDICL instead which is not what we are looking
+ // for here.
+ SDValue RotateAmt = Val.getOperand(1);
+ if (RotateAmt.getOpcode() == ISD::Constant)
+ return false;
+
+ unsigned MB = 64 - llvm::countr_one(Imm64);
+ SDLoc dl(N);
+ SDValue Ops[] = {Val.getOperand(0), RotateAmt, getI32Imm(MB, dl)};
+ CurDAG->SelectNodeTo(N, PPC::RLDCL, MVT::i64, Ops);
+ return true;
+}
+
bool PPCDAGToDAGISel::tryAsSingleRLDICL(SDNode *N) {
assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
uint64_t Imm64;
@@ -5605,8 +5647,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
case ISD::AND:
// If this is an 'and' with a mask, try to emit rlwinm/rldicl/rldicr
- if (tryAsSingleRLWINM(N) || tryAsSingleRLWIMI(N) || tryAsSingleRLDICL(N) ||
- tryAsSingleRLDICR(N) || tryAsSingleRLWINM8(N) || tryAsPairOfRLDICL(N))
+ if (tryAsSingleRLWINM(N) || tryAsSingleRLWIMI(N) || tryAsSingleRLDCL(N) ||
+ tryAsSingleRLDICL(N) || tryAsSingleRLDICR(N) || tryAsSingleRLWINM8(N) ||
+ tryAsPairOfRLDICL(N))
return;
// Other cases are autogenerated.
@@ -6624,7 +6667,7 @@ void PPCDAGToDAGISel::PreprocessISelDAG() {
/// on the DAG representation.
void PPCDAGToDAGISel::PostprocessISelDAG() {
// Skip peepholes at -O0.
- if (TM.getOptLevel() == CodeGenOpt::None)
+ if (TM.getOptLevel() == CodeGenOptLevel::None)
return;
PeepholePPC64();
@@ -6659,11 +6702,7 @@ bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
Op2->getMachineOpcode() != PPC::LI8)
return false;
- ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op2->getOperand(0));
- if (!C)
- return false;
-
- if (!C->isZero())
+ if (!isNullConstant(Op2->getOperand(0)))
return false;
}
@@ -7616,13 +7655,6 @@ void PPCDAGToDAGISel::PeepholePPC64() {
// is already in place on the operand, so copying the operand
// is sufficient.
ReplaceFlags = false;
- // For these cases, the immediate may not be divisible by 4, in
- // which case the fold is illegal for DS-form instructions. (The
- // other cases provide aligned addresses and are always safe.)
- if (RequiresMod4Offset &&
- (!isa<ConstantSDNode>(Base.getOperand(1)) ||
- Base.getConstantOperandVal(1) % 4 != 0))
- continue;
break;
case PPC::ADDIdtprelL:
Flags = PPCII::MO_DTPREL_LO;
@@ -7674,6 +7706,18 @@ void PPCDAGToDAGISel::PeepholePPC64() {
UpdateHBase = true;
}
} else {
+ // Global addresses can be folded, but only if they are sufficiently
+ // aligned.
+ if (RequiresMod4Offset) {
+ if (GlobalAddressSDNode *GA =
+ dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
+ const GlobalValue *GV = GA->getGlobal();
+ Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
+ if (Alignment < 4)
+ continue;
+ }
+ }
+
// If we're directly folding the addend from an addi instruction, then:
// 1. In general, the offset on the memory access must be zero.
// 2. If the addend is a constant, then it can be combined with a
@@ -7748,6 +7792,6 @@ void PPCDAGToDAGISel::PeepholePPC64() {
/// PowerPC-specific DAG, ready for instruction scheduling.
///
FunctionPass *llvm::createPPCISelDag(PPCTargetMachine &TM,
- CodeGenOpt::Level OptLevel) {
+ CodeGenOptLevel OptLevel) {
return new PPCDAGToDAGISel(TM, OptLevel);
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 547b71a6101a..22c662a79d87 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -132,6 +132,10 @@ cl::opt<bool> DisableAutoPairedVecSt(
cl::desc("disable automatically generated 32byte paired vector stores"),
cl::init(true), cl::Hidden);
+static cl::opt<unsigned> PPCMinimumJumpTableEntries(
+ "ppc-min-jump-table-entries", cl::init(64), cl::Hidden,
+ cl::desc("Set minimum number of entries to use a jump table on PPC"));
+
STATISTIC(NumTailCalls, "Number of tail calls");
STATISTIC(NumSiblingCalls, "Number of sibling calls");
STATISTIC(ShufflesHandledWithVPERM,
@@ -144,6 +148,12 @@ static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl);
static const char AIXSSPCanaryWordName[] = "__ssp_canary_word";
+// A faster local-exec TLS access sequence (enabled with the
+// -maix-small-local-exec-tls option) can be produced for TLS variables;
+// consistent with the IBM XL compiler, we apply a max size of slightly under
+// 32KB.
+constexpr uint64_t AIXSmallTlsPolicySizeLimit = 32751;
+
// FIXME: Remove this once the bug has been fixed!
extern cl::opt<bool> ANDIGlueBug;
@@ -389,7 +399,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
// MASS transformation for LLVM intrinsics with replicating fast-math flag
// to be consistent to PPCGenScalarMASSEntries pass
- if (TM.getOptLevel() == CodeGenOpt::Aggressive) {
+ if (TM.getOptLevel() == CodeGenOptLevel::Aggressive) {
setOperationAction(ISD::FSIN , MVT::f64, Custom);
setOperationAction(ISD::FCOS , MVT::f64, Custom);
setOperationAction(ISD::FPOW , MVT::f64, Custom);
@@ -1419,6 +1429,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setLibcallName(RTLIB::LLRINT_F128, "llrintf128");
setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128");
setLibcallName(RTLIB::FMA_F128, "fmaf128");
+ setLibcallName(RTLIB::FREXP_F128, "frexpf128");
if (Subtarget.isAIXABI()) {
setLibcallName(RTLIB::MEMCPY, isPPC64 ? "___memmove64" : "___memmove");
@@ -1434,6 +1445,12 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setJumpIsExpensive();
}
+ // TODO: The default entry number is set to 64. This stops most jump table
+ // generation on PPC. But it is good for current PPC HWs because the indirect
+ // branch instruction mtctr to the jump table may lead to bad branch predict.
+ // Re-evaluate this value on future HWs that can do better with mtctr.
+ setMinimumJumpTableEntries(PPCMinimumJumpTableEntries);
+
setMinFunctionAlignment(Align(4));
switch (Subtarget.getCPUDirective()) {
@@ -1627,6 +1644,27 @@ bool PPCTargetLowering::preferIncOfAddToSubOfNot(EVT VT) const {
return VT.isScalarInteger();
}
+bool PPCTargetLowering::shallExtractConstSplatVectorElementToStore(
+ Type *VectorTy, unsigned ElemSizeInBits, unsigned &Index) const {
+ if (!Subtarget.isPPC64() || !Subtarget.hasVSX())
+ return false;
+
+ if (auto *VTy = dyn_cast<VectorType>(VectorTy)) {
+ if (VTy->getScalarType()->isIntegerTy()) {
+ // ElemSizeInBits 8/16 can fit in immediate field, not needed here.
+ if (ElemSizeInBits == 32) {
+ Index = Subtarget.isLittleEndian() ? 2 : 1;
+ return true;
+ }
+ if (ElemSizeInBits == 64) {
+ Index = Subtarget.isLittleEndian() ? 1 : 0;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch ((PPCISD::NodeType)Opcode) {
case PPCISD::FIRST_NUMBER: break;
@@ -2936,7 +2974,7 @@ bool PPCTargetLowering::SelectAddressRegRegOnly(SDValue N, SDValue &Base,
template <typename Ty> static bool isValidPCRelNode(SDValue N) {
Ty *PCRelCand = dyn_cast<Ty>(N);
- return PCRelCand && (PCRelCand->getTargetFlags() & PPCII::MO_PCREL_FLAG);
+ return PCRelCand && (PPCInstrInfo::hasPCRelFlag(PCRelCand->getTargetFlags()));
}
/// Returns true if this address is a PC Relative address.
@@ -3097,8 +3135,8 @@ static void getLabelAccessInfo(bool IsPIC, const PPCSubtarget &Subtarget,
// Don't use the pic base if not in PIC relocation model.
if (IsPIC) {
- HiOpFlags |= PPCII::MO_PIC_FLAG;
- LoOpFlags |= PPCII::MO_PIC_FLAG;
+ HiOpFlags = PPCII::MO_PIC_HA_FLAG;
+ LoOpFlags = PPCII::MO_PIC_LO_FLAG;
}
}
@@ -3326,36 +3364,60 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
const GlobalValue *GV = GA->getGlobal();
EVT PtrVT = getPointerTy(DAG.getDataLayout());
bool Is64Bit = Subtarget.isPPC64();
+ bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS();
TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+ bool IsTLSLocalExecModel = Model == TLSModel::LocalExec;
- if (Model == TLSModel::LocalExec) {
+ if (IsTLSLocalExecModel || Model == TLSModel::InitialExec) {
SDValue VariableOffsetTGA =
DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TPREL_FLAG);
SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
SDValue TLSReg;
- if (Is64Bit)
- // For local-exec on AIX (64-bit), the sequence that is generated involves
- // a load of the variable offset (from the TOC), followed by an add of the
- // loaded variable offset to R13 (the thread pointer).
+ if (Is64Bit) {
+ // For local-exec and initial-exec on AIX (64-bit), the sequence generated
+ // involves a load of the variable offset (from the TOC), followed by an
+ // add of the loaded variable offset to R13 (the thread pointer).
// This code sequence looks like:
// ld reg1,var[TC](2)
// add reg2, reg1, r13 // r13 contains the thread pointer
TLSReg = DAG.getRegister(PPC::X13, MVT::i64);
- else
- // For local-exec on AIX (32-bit), the sequence that is generated involves
- // loading the variable offset from the TOC, generating a call to
+
+ // With the -maix-small-local-exec-tls option, produce a faster access
+ // sequence for local-exec TLS variables where the offset from the TLS
+ // base is encoded as an immediate operand.
+ //
+ // We only utilize the faster local-exec access sequence when the TLS
+ // variable has a size within the policy limit. We treat types that are
+ // not sized or are empty as being over the policy size limit.
+ if (HasAIXSmallLocalExecTLS && IsTLSLocalExecModel) {
+ Type *GVType = GV->getValueType();
+ if (GVType->isSized() && !GVType->isEmptyTy() &&
+ GV->getParent()->getDataLayout().getTypeAllocSize(GVType) <=
+ AIXSmallTlsPolicySizeLimit)
+ return DAG.getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA, TLSReg);
+ }
+ } else {
+ // For local-exec and initial-exec on AIX (32-bit), the sequence generated
+ // involves loading the variable offset from the TOC, generating a call to
// .__get_tpointer to get the thread pointer (which will be in R3), and
// adding the two together:
// lwz reg1,var[TC](2)
// bla .__get_tpointer
// add reg2, reg1, r3
TLSReg = DAG.getNode(PPCISD::GET_TPOINTER, dl, PtrVT);
+
+ // We do not implement the 32-bit version of the faster access sequence
+ // for local-exec that is controlled by -maix-small-local-exec-tls.
+ if (HasAIXSmallLocalExecTLS)
+ report_fatal_error("The small-local-exec TLS access sequence is "
+ "currently only supported on AIX (64-bit mode).");
+ }
return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
}
- // The Local-Exec and General-Dynamic TLS models are currently the only
- // supported access models. If Local-exec is not possible or specified, all
- // GlobalTLSAddress nodes are lowered using the general-dynamic model.
+ // Only Local-Exec, Initial-Exec and General-Dynamic TLS models are currently
+ // supported models. If Local- or Initial-exec are not possible or specified,
+ // all GlobalTLSAddress nodes are lowered using the general-dynamic model.
// We need to generate two TOC entries, one for the variable offset, one for
// the region handle. The global address for the TOC entry of the region
// handle is created with the MO_TLSGDM_FLAG flag and the global address
@@ -3393,8 +3455,8 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressLinux(SDValue Op,
if (Model == TLSModel::LocalExec) {
if (Subtarget.isUsingPCRelativeCalls()) {
SDValue TLSReg = DAG.getRegister(PPC::X13, MVT::i64);
- SDValue TGA = DAG.getTargetGlobalAddress(
- GV, dl, PtrVT, 0, (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG));
+ SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,
+ PPCII::MO_TPREL_PCREL_FLAG);
SDValue MatAddr =
DAG.getNode(PPCISD::TLS_LOCAL_EXEC_MAT_ADDR, dl, PtrVT, TGA);
return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, MatAddr);
@@ -3416,8 +3478,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressLinux(SDValue Op,
SDValue TGA = DAG.getTargetGlobalAddress(
GV, dl, PtrVT, 0, IsPCRel ? PPCII::MO_GOT_TPREL_PCREL_FLAG : 0);
SDValue TGATLS = DAG.getTargetGlobalAddress(
- GV, dl, PtrVT, 0,
- IsPCRel ? (PPCII::MO_TLS | PPCII::MO_PCREL_FLAG) : PPCII::MO_TLS);
+ GV, dl, PtrVT, 0, IsPCRel ? PPCII::MO_TLS_PCREL_FLAG : PPCII::MO_TLS);
SDValue TPOffset;
if (IsPCRel) {
SDValue MatPCRel = DAG.getNode(PPCISD::MAT_PCREL_ADDR, dl, PtrVT, TGA);
@@ -3513,8 +3574,7 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op,
EVT Ty = getPointerTy(DAG.getDataLayout());
if (isAccessedAsGotIndirect(Op)) {
SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty, GSDN->getOffset(),
- PPCII::MO_PCREL_FLAG |
- PPCII::MO_GOT_FLAG);
+ PPCII::MO_GOT_PCREL_FLAG);
SDValue MatPCRel = DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, GA);
SDValue Load = DAG.getLoad(MVT::i64, DL, DAG.getEntryNode(), MatPCRel,
MachinePointerInfo());
@@ -3764,21 +3824,22 @@ SDValue PPCTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
// Check all operands that may contain the LR.
for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
- unsigned Flags = cast<ConstantSDNode>(Op.getOperand(i))->getZExtValue();
- unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
+ const InlineAsm::Flag Flags(
+ cast<ConstantSDNode>(Op.getOperand(i))->getZExtValue());
+ unsigned NumVals = Flags.getNumOperandRegisters();
++i; // Skip the ID value.
- switch (InlineAsm::getKind(Flags)) {
+ switch (Flags.getKind()) {
default:
llvm_unreachable("Bad flags!");
- case InlineAsm::Kind_RegUse:
- case InlineAsm::Kind_Imm:
- case InlineAsm::Kind_Mem:
+ case InlineAsm::Kind::RegUse:
+ case InlineAsm::Kind::Imm:
+ case InlineAsm::Kind::Mem:
i += NumVals;
break;
- case InlineAsm::Kind_Clobber:
- case InlineAsm::Kind_RegDef:
- case InlineAsm::Kind_RegDefEarlyClobber: {
+ case InlineAsm::Kind::Clobber:
+ case InlineAsm::Kind::RegDef:
+ case InlineAsm::Kind::RegDefEarlyClobber: {
for (; NumVals; --NumVals, ++i) {
Register Reg = cast<RegisterSDNode>(Op.getOperand(i))->getReg();
if (Reg != PPC::LR && Reg != PPC::LR8)
@@ -5278,7 +5339,7 @@ static unsigned getCallOpcode(PPCTargetLowering::CallFlags CFlags,
// inserted into the DAG as part of call lowering. The restore of the TOC
// pointer is modeled by using a pseudo instruction for the call opcode that
// represents the 2 instruction sequence of an indirect branch and link,
- // immediately followed by a load of the TOC pointer from the the stack save
+ // immediately followed by a load of the TOC pointer from the stack save
// slot into gpr2. For 64-bit ELFv2 ABI with PCRel, do not restore the TOC
// as it is not saved or used.
RetOpc = isTOCSaveRestoreRequired(Subtarget) ? PPCISD::BCTRL_LOAD_TOC
@@ -7193,7 +7254,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
// be future work.
SDValue Store = DAG.getStore(
CopyFrom.getValue(1), dl, CopyFrom,
- DAG.getObjectPtrOffset(dl, FIN, TypeSize::Fixed(Offset)),
+ DAG.getObjectPtrOffset(dl, FIN, TypeSize::getFixed(Offset)),
MachinePointerInfo::getFixedStack(MF, FI, Offset));
MemOps.push_back(Store);
@@ -7373,12 +7434,12 @@ SDValue PPCTargetLowering::LowerCall_AIX(
}
auto GetLoad = [&](EVT VT, unsigned LoadOffset) {
- return DAG.getExtLoad(
- ISD::ZEXTLOAD, dl, PtrVT, Chain,
- (LoadOffset != 0)
- ? DAG.getObjectPtrOffset(dl, Arg, TypeSize::Fixed(LoadOffset))
- : Arg,
- MachinePointerInfo(), VT);
+ return DAG.getExtLoad(ISD::ZEXTLOAD, dl, PtrVT, Chain,
+ (LoadOffset != 0)
+ ? DAG.getObjectPtrOffset(
+ dl, Arg, TypeSize::getFixed(LoadOffset))
+ : Arg,
+ MachinePointerInfo(), VT);
};
unsigned LoadOffset = 0;
@@ -7408,11 +7469,11 @@ SDValue PPCTargetLowering::LowerCall_AIX(
// Only memcpy the bytes that don't pass in register.
MemcpyFlags.setByValSize(ByValSize - LoadOffset);
Chain = CallSeqStart = createMemcpyOutsideCallSeq(
- (LoadOffset != 0)
- ? DAG.getObjectPtrOffset(dl, Arg, TypeSize::Fixed(LoadOffset))
- : Arg,
- DAG.getObjectPtrOffset(dl, StackPtr,
- TypeSize::Fixed(ByValVA.getLocMemOffset())),
+ (LoadOffset != 0) ? DAG.getObjectPtrOffset(
+ dl, Arg, TypeSize::getFixed(LoadOffset))
+ : Arg,
+ DAG.getObjectPtrOffset(
+ dl, StackPtr, TypeSize::getFixed(ByValVA.getLocMemOffset())),
CallSeqStart, MemcpyFlags, DAG, dl);
continue;
}
@@ -8020,7 +8081,8 @@ SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
// For more information, see section F.3 of the 2.06 ISA specification.
// With ISA 3.0
if ((!DAG.getTarget().Options.NoInfsFPMath && !Flags.hasNoInfs()) ||
- (!DAG.getTarget().Options.NoNaNsFPMath && !Flags.hasNoNaNs()))
+ (!DAG.getTarget().Options.NoNaNsFPMath && !Flags.hasNoNaNs()) ||
+ ResVT == MVT::f128)
return Op;
// If the RHS of the comparison is a 0.0, we don't need to do the
@@ -10254,11 +10316,6 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG,
bool isLittleEndian = Subtarget.isLittleEndian();
bool isPPC64 = Subtarget.isPPC64();
- // Only need to place items backwards in LE,
- // the mask will be properly calculated.
- if (isLittleEndian)
- std::swap(V1, V2);
-
if (Subtarget.hasVSX() && Subtarget.hasP9Vector() &&
(V1->hasOneUse() || V2->hasOneUse())) {
LLVM_DEBUG(dbgs() << "At least one of two input vectors are dead - using "
@@ -10268,7 +10325,8 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG,
// The second input to XXPERM is also an output so if the second input has
// multiple uses then copying is necessary, as a result we want the
// single-use operand to be used as the second input to prevent copying.
- if (!V2->hasOneUse() && V1->hasOneUse()) {
+ if ((!isLittleEndian && !V2->hasOneUse() && V1->hasOneUse()) ||
+ (isLittleEndian && !V1->hasOneUse() && V2->hasOneUse())) {
std::swap(V1, V2);
NeedSwap = !NeedSwap;
}
@@ -10307,27 +10365,24 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG,
for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) {
unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i];
- if (Opcode == PPCISD::XXPERM) {
- if (V1HasXXSWAPD) {
- if (SrcElt < 8)
- SrcElt += 8;
- else if (SrcElt < 16)
- SrcElt -= 8;
- }
- if (V2HasXXSWAPD) {
- if (SrcElt > 23)
- SrcElt -= 8;
- else if (SrcElt > 15)
- SrcElt += 8;
- }
- if (NeedSwap) {
- if (SrcElt < 16)
- SrcElt += 16;
- else
- SrcElt -= 16;
- }
+ if (V1HasXXSWAPD) {
+ if (SrcElt < 8)
+ SrcElt += 8;
+ else if (SrcElt < 16)
+ SrcElt -= 8;
+ }
+ if (V2HasXXSWAPD) {
+ if (SrcElt > 23)
+ SrcElt -= 8;
+ else if (SrcElt > 15)
+ SrcElt += 8;
+ }
+ if (NeedSwap) {
+ if (SrcElt < 16)
+ SrcElt += 16;
+ else
+ SrcElt -= 16;
}
-
for (unsigned j = 0; j != BytesPerElement; ++j)
if (isLittleEndian)
ResultMask.push_back(
@@ -10337,18 +10392,19 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG,
DAG.getConstant(SrcElt * BytesPerElement + j, dl, MVT::i32));
}
- if (Opcode == PPCISD::XXPERM && (V1HasXXSWAPD || V2HasXXSWAPD)) {
- if (V1HasXXSWAPD) {
- dl = SDLoc(V1->getOperand(0));
- V1 = V1->getOperand(0)->getOperand(1);
- }
- if (V2HasXXSWAPD) {
- dl = SDLoc(V2->getOperand(0));
- V2 = V2->getOperand(0)->getOperand(1);
- }
- if (isPPC64 && ValType != MVT::v2f64)
+ if (V1HasXXSWAPD) {
+ dl = SDLoc(V1->getOperand(0));
+ V1 = V1->getOperand(0)->getOperand(1);
+ }
+ if (V2HasXXSWAPD) {
+ dl = SDLoc(V2->getOperand(0));
+ V2 = V2->getOperand(0)->getOperand(1);
+ }
+
+ if (isPPC64 && (V1HasXXSWAPD || V2HasXXSWAPD)) {
+ if (ValType != MVT::v2f64)
V1 = DAG.getBitcast(MVT::v2f64, V1);
- if (isPPC64 && V2.getValueType() != MVT::v2f64)
+ if (V2.getValueType() != MVT::v2f64)
V2 = DAG.getBitcast(MVT::v2f64, V2);
}
@@ -10369,6 +10425,11 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG,
if (Opcode == PPCISD::XXPERM)
VPermMask = DAG.getBitcast(MVT::v4i32, VPermMask);
+ // Only need to place items backwards in LE,
+ // the mask was properly calculated.
+ if (isLittleEndian)
+ std::swap(V1, V2);
+
SDValue VPERMNode =
DAG.getNode(Opcode, dl, V1.getValueType(), V1, V2, VPermMask);
@@ -11037,14 +11098,14 @@ SDValue PPCTargetLowering::LowerATOMIC_LOAD_STORE(SDValue Op,
SmallVector<SDValue, 4> Ops{
N->getOperand(0),
DAG.getConstant(Intrinsic::ppc_atomic_store_i128, dl, MVT::i32)};
- SDValue Val = N->getOperand(2);
+ SDValue Val = N->getOperand(1);
SDValue ValLo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i64, Val);
SDValue ValHi = DAG.getNode(ISD::SRL, dl, MVT::i128, Val,
DAG.getConstant(64, dl, MVT::i32));
ValHi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i64, ValHi);
Ops.push_back(ValLo);
Ops.push_back(ValHi);
- Ops.push_back(N->getOperand(1));
+ Ops.push_back(N->getOperand(2));
return DAG.getMemIntrinsicNode(ISD::INTRINSIC_VOID, dl, Tys, Ops, MemVT,
N->getMemOperand());
}
@@ -16659,13 +16720,14 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops.
void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
- std::string &Constraint,
- std::vector<SDValue>&Ops,
+ StringRef Constraint,
+ std::vector<SDValue> &Ops,
SelectionDAG &DAG) const {
SDValue Result;
// Only support length 1 constraints.
- if (Constraint.length() > 1) return;
+ if (Constraint.size() > 1)
+ return;
char Letter = Constraint[0];
switch (Letter) {
@@ -17075,13 +17137,23 @@ bool PPCTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
/// target-independent logic.
EVT PPCTargetLowering::getOptimalMemOpType(
const MemOp &Op, const AttributeList &FuncAttributes) const {
- if (getTargetMachine().getOptLevel() != CodeGenOpt::None) {
+ if (getTargetMachine().getOptLevel() != CodeGenOptLevel::None) {
// We should use Altivec/VSX loads and stores when available. For unaligned
// addresses, unaligned VSX loads are only fast starting with the P8.
- if (Subtarget.hasAltivec() && Op.size() >= 16 &&
- (Op.isAligned(Align(16)) ||
- ((Op.isMemset() && Subtarget.hasVSX()) || Subtarget.hasP8Vector())))
- return MVT::v4i32;
+ if (Subtarget.hasAltivec() && Op.size() >= 16) {
+ if (Op.isMemset() && Subtarget.hasVSX()) {
+ uint64_t TailSize = Op.size() % 16;
+ // For memset lowering, EXTRACT_VECTOR_ELT tries to return constant
+ // element if vector element type matches tail store. For tail size
+ // 3/4, the tail store is i32, v4i32 cannot be used, need a legal one.
+ if (TailSize > 2 && TailSize <= 4) {
+ return MVT::v8i16;
+ }
+ return MVT::v4i32;
+ }
+ if (Op.isAligned(Align(16)) || Subtarget.hasP8Vector())
+ return MVT::v4i32;
+ }
}
if (Subtarget.isPPC64()) {
@@ -17227,7 +17299,7 @@ bool PPCTargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
bool PPCTargetLowering::isFMAFasterThanFMulAndFAdd(const Function &F,
Type *Ty) const {
- if (Subtarget.hasSPE())
+ if (Subtarget.hasSPE() || Subtarget.useSoftFloat())
return false;
switch (Ty->getScalarType()->getTypeID()) {
case Type::FloatTyID:
@@ -17431,7 +17503,7 @@ bool PPCTargetLowering::useLoadStackGuardNode() const {
void PPCTargetLowering::insertSSPDeclarations(Module &M) const {
if (Subtarget.isAIXABI()) {
M.getOrInsertGlobal(AIXSSPCanaryWordName,
- Type::getInt8PtrTy(M.getContext()));
+ PointerType::getUnqual(M.getContext()));
return;
}
if (!Subtarget.isTargetLinux())
@@ -18539,9 +18611,7 @@ Value *PPCTargetLowering::emitMaskedAtomicRMWIntrinsic(
Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty, "incr_lo");
Value *IncrHi =
Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty, "incr_hi");
- Value *Addr =
- Builder.CreateBitCast(AlignedAddr, Type::getInt8PtrTy(M->getContext()));
- Value *LoHi = Builder.CreateCall(RMW, {Addr, IncrLo, IncrHi});
+ Value *LoHi = Builder.CreateCall(RMW, {AlignedAddr, IncrLo, IncrHi});
Value *Lo = Builder.CreateExtractValue(LoHi, 0, "lo");
Value *Hi = Builder.CreateExtractValue(LoHi, 1, "hi");
Lo = Builder.CreateZExt(Lo, ValTy, "lo64");
@@ -18566,11 +18636,9 @@ Value *PPCTargetLowering::emitMaskedAtomicCmpXchgIntrinsic(
Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty, "new_lo");
Value *NewHi =
Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty, "new_hi");
- Value *Addr =
- Builder.CreateBitCast(AlignedAddr, Type::getInt8PtrTy(M->getContext()));
emitLeadingFence(Builder, CI, Ord);
Value *LoHi =
- Builder.CreateCall(IntCmpXchg, {Addr, CmpLo, CmpHi, NewLo, NewHi});
+ Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi});
emitTrailingFence(Builder, CI, Ord);
Value *Lo = Builder.CreateExtractValue(LoHi, 0, "lo");
Value *Hi = Builder.CreateExtractValue(LoHi, 1, "hi");
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h
index e6ebc68008fb..d8679dcf4018 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -356,9 +356,9 @@ namespace llvm {
/// ADDIS_TLSGD_L_ADDR until after register assignment.
GET_TLS_ADDR,
- /// %x3 = GET_TPOINTER - Used for the local-exec TLS model on 32-bit AIX,
- /// produces a call to .__get_tpointer to retrieve the thread pointer
- /// At the end of the call, the thread pointer is found in R3.
+ /// %x3 = GET_TPOINTER - Used for the local- and initial-exec TLS model on
+ /// 32-bit AIX, produces a call to .__get_tpointer to retrieve the thread
+ /// pointer. At the end of the call, the thread pointer is found in R3.
GET_TPOINTER,
/// G8RC = ADDI_TLSGD_L_ADDR G8RReg, Symbol, Symbol - Op that
@@ -791,6 +791,11 @@ namespace llvm {
return true;
}
+ bool
+ shallExtractConstSplatVectorElementToStore(Type *VectorTy,
+ unsigned ElemSizeInBits,
+ unsigned &Index) const override;
+
bool isCtlzFast() const override {
return true;
}
@@ -970,21 +975,20 @@ namespace llvm {
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops.
- void LowerAsmOperandForConstraint(SDValue Op,
- std::string &Constraint,
+ void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const override;
- unsigned
+ InlineAsm::ConstraintCode
getInlineAsmMemConstraint(StringRef ConstraintCode) const override {
if (ConstraintCode == "es")
- return InlineAsm::Constraint_es;
+ return InlineAsm::ConstraintCode::es;
else if (ConstraintCode == "Q")
- return InlineAsm::Constraint_Q;
+ return InlineAsm::ConstraintCode::Q;
else if (ConstraintCode == "Z")
- return InlineAsm::Constraint_Z;
+ return InlineAsm::ConstraintCode::Z;
else if (ConstraintCode == "Zy")
- return InlineAsm::Constraint_Zy;
+ return InlineAsm::ConstraintCode::Zy;
return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index fd44efa1b3f4..0322bb37b1fd 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -380,7 +380,7 @@ let mayStore = 1, mayLoad = 1,
Defs = [CR0],
Constraints = "@earlyclobber $scratch,@earlyclobber $RTp" in {
// Atomic pseudo instructions expanded post-ra.
-def ATOMIC_SWAP_I128 : AtomicRMW128<"#ATOMIC_SWAP_I128">;
+def ATOMIC_SWAP_I128 : AtomicRMW128<"#ATOMIC_SWAP_I128">;
def ATOMIC_LOAD_ADD_I128 : AtomicRMW128<"#ATOMIC_LOAD_ADD_I128">;
def ATOMIC_LOAD_SUB_I128 : AtomicRMW128<"#ATOMIC_LOAD_SUB_I128">;
def ATOMIC_LOAD_AND_I128 : AtomicRMW128<"#ATOMIC_LOAD_AND_I128">;
@@ -395,48 +395,21 @@ def ATOMIC_CMP_SWAP_I128 : PPCPostRAExpPseudo<
"#ATOMIC_CMP_SWAP_I128", []>;
}
-def : Pat<(int_ppc_atomicrmw_add_i128 ForceXForm:$ptr,
- i64:$incr_lo,
- i64:$incr_hi),
- (SPLIT_QUADWORD (ATOMIC_LOAD_ADD_I128 memrr:$ptr,
- g8rc:$incr_lo,
- g8rc:$incr_hi))>;
-def : Pat<(int_ppc_atomicrmw_sub_i128 ForceXForm:$ptr,
- i64:$incr_lo,
- i64:$incr_hi),
- (SPLIT_QUADWORD (ATOMIC_LOAD_SUB_I128 memrr:$ptr,
- g8rc:$incr_lo,
- g8rc:$incr_hi))>;
-def : Pat<(int_ppc_atomicrmw_xor_i128 ForceXForm:$ptr,
- i64:$incr_lo,
- i64:$incr_hi),
- (SPLIT_QUADWORD (ATOMIC_LOAD_XOR_I128 memrr:$ptr,
- g8rc:$incr_lo,
- g8rc:$incr_hi))>;
-def : Pat<(int_ppc_atomicrmw_and_i128 ForceXForm:$ptr,
- i64:$incr_lo,
- i64:$incr_hi),
- (SPLIT_QUADWORD (ATOMIC_LOAD_AND_I128 memrr:$ptr,
- g8rc:$incr_lo,
- g8rc:$incr_hi))>;
-def : Pat<(int_ppc_atomicrmw_nand_i128 ForceXForm:$ptr,
- i64:$incr_lo,
- i64:$incr_hi),
- (SPLIT_QUADWORD (ATOMIC_LOAD_NAND_I128 memrr:$ptr,
- g8rc:$incr_lo,
- g8rc:$incr_hi))>;
-def : Pat<(int_ppc_atomicrmw_or_i128 ForceXForm:$ptr,
- i64:$incr_lo,
- i64:$incr_hi),
- (SPLIT_QUADWORD (ATOMIC_LOAD_OR_I128 memrr:$ptr,
- g8rc:$incr_lo,
- g8rc:$incr_hi))>;
-def : Pat<(int_ppc_atomicrmw_xchg_i128 ForceXForm:$ptr,
- i64:$incr_lo,
- i64:$incr_hi),
- (SPLIT_QUADWORD (ATOMIC_SWAP_I128 memrr:$ptr,
- g8rc:$incr_lo,
- g8rc:$incr_hi))>;
+class PatAtomicRMWI128<SDPatternOperator OpNode, AtomicRMW128 Inst> :
+ Pat<(OpNode ForceXForm:$ptr,
+ i64:$incr_lo,
+ i64:$incr_hi),
+ (SPLIT_QUADWORD (Inst memrr:$ptr,
+ g8rc:$incr_lo,
+ g8rc:$incr_hi))>;
+
+def : PatAtomicRMWI128<int_ppc_atomicrmw_add_i128, ATOMIC_LOAD_ADD_I128>;
+def : PatAtomicRMWI128<int_ppc_atomicrmw_sub_i128, ATOMIC_LOAD_SUB_I128>;
+def : PatAtomicRMWI128<int_ppc_atomicrmw_xor_i128, ATOMIC_LOAD_XOR_I128>;
+def : PatAtomicRMWI128<int_ppc_atomicrmw_and_i128, ATOMIC_LOAD_AND_I128>;
+def : PatAtomicRMWI128<int_ppc_atomicrmw_nand_i128, ATOMIC_LOAD_NAND_I128>;
+def : PatAtomicRMWI128<int_ppc_atomicrmw_or_i128, ATOMIC_LOAD_OR_I128>;
+def : PatAtomicRMWI128<int_ppc_atomicrmw_xchg_i128, ATOMIC_SWAP_I128>;
def : Pat<(int_ppc_cmpxchg_i128 ForceXForm:$ptr,
i64:$cmp_lo,
i64:$cmp_hi,
@@ -1958,8 +1931,8 @@ def : Pat<(add i64:$in, (PPChi tblockaddress:$g, 0)),
def : Pat<(i64 (PPCtoc_entry tglobaltlsaddr:$disp, i64:$reg)),
(i64 (LDtoc tglobaltlsaddr:$disp, i64:$reg))>;
-// The following pattern matches 64-bit local-exec TLS accesses on AIX.
-// PPCaddTls is used in local-exec accesses in order to:
+// The following pattern matches 64-bit local- and initial-exec TLS accesses on AIX.
+// PPCaddTls is used in local- and initial-exec accesses in order to:
// - Get the address of a variable (adding the variable offset to the thread
// pointer in r13).
// - Create an opportunity to optimize the user of the loaded address.
@@ -1970,8 +1943,8 @@ def : Pat<(PPCaddTls i64:$in, i64:$addr),
def : Pat<(atomic_load_64 DSForm:$src), (LD memrix:$src)>;
def : Pat<(atomic_load_64 XForm:$src), (LDX memrr:$src)>;
-def : Pat<(atomic_store_64 DSForm:$ptr, i64:$val), (STD g8rc:$val, memrix:$ptr)>;
-def : Pat<(atomic_store_64 XForm:$ptr, i64:$val), (STDX g8rc:$val, memrr:$ptr)>;
+def : Pat<(atomic_store_64 i64:$val, DSForm:$ptr), (STD g8rc:$val, memrix:$ptr)>;
+def : Pat<(atomic_store_64 i64:$val, XForm:$ptr), (STDX g8rc:$val, memrr:$ptr)>;
let Predicates = [IsISA3_0, In64BitMode] in {
def : Pat<(i64 (int_ppc_cmpeqb g8rc:$a, g8rc:$b)),
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 224c7b281ac4..5389f42a325c 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -220,7 +220,7 @@ BForm_4<bits<6> opcode, bits<5> bo, bit aa, bit lk,
}
// 1.7.3 SC-Form
-class SCForm<bits<6> opcode, bits<1> xo,
+class SCForm<bits<6> opcode, bits<1> xo1, bits<1> xo2,
dag OOL, dag IOL, string asmstr, InstrItinClass itin,
list<dag> pattern>
: I<opcode, OOL, IOL, asmstr, itin> {
@@ -229,7 +229,8 @@ class SCForm<bits<6> opcode, bits<1> xo,
let Pattern = pattern;
let Inst{20-26} = LEV;
- let Inst{30} = xo;
+ let Inst{30} = xo1;
+ let Inst{31} = xo2;
}
// 1.7.4 D-Form
@@ -724,6 +725,38 @@ class XForm_24_sync<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
let Inst{31} = 0;
}
+class XForm_IMM2_IMM2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
+ string asmstr, InstrItinClass itin, list<dag> pattern>
+ : I<opcode, OOL, IOL, asmstr, itin> {
+ bits<2> L;
+ bits<2> PL;
+
+ let Pattern = pattern;
+ let Inst{6-8} = 0;
+ let Inst{9-10} = L;
+ let Inst{11-13} = 0;
+ let Inst{14-15} = PL;
+ let Inst{16-20} = 0;
+ let Inst{21-30} = xo;
+ let Inst{31} = 0;
+}
+
+class XForm_IMM3_IMM2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
+ string asmstr, InstrItinClass itin, list<dag> pattern>
+ : I<opcode, OOL, IOL, asmstr, itin> {
+ bits<3> L;
+ bits<2> SC;
+
+ let Pattern = pattern;
+ let Inst{6-7} = 0;
+ let Inst{8-10} = L;
+ let Inst{11-13} = 0;
+ let Inst{14-15} = SC;
+ let Inst{16-20} = 0;
+ let Inst{21-30} = xo;
+ let Inst{31} = 0;
+}
+
class XForm_24_eieio<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin, list<dag> pattern>
: XForm_24_sync<opcode, xo, OOL, IOL, asmstr, itin, pattern> {
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index 784953dbc847..d0a6cced1b19 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -17,11 +17,11 @@
#include "PPCInstrBuilder.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCTargetMachine.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineCombinerPattern.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -155,22 +155,21 @@ unsigned PPCInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
if (!MO.isReg() || !MO.isDef() || MO.isImplicit())
continue;
- int Cycle = ItinData->getOperandCycle(DefClass, i);
- if (Cycle < 0)
+ std::optional<unsigned> Cycle = ItinData->getOperandCycle(DefClass, i);
+ if (!Cycle)
continue;
- Latency = std::max(Latency, (unsigned) Cycle);
+ Latency = std::max(Latency, *Cycle);
}
return Latency;
}
-int PPCInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
- const MachineInstr &DefMI, unsigned DefIdx,
- const MachineInstr &UseMI,
- unsigned UseIdx) const {
- int Latency = PPCGenInstrInfo::getOperandLatency(ItinData, DefMI, DefIdx,
- UseMI, UseIdx);
+std::optional<unsigned> PPCInstrInfo::getOperandLatency(
+ const InstrItineraryData *ItinData, const MachineInstr &DefMI,
+ unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const {
+ std::optional<unsigned> Latency = PPCGenInstrInfo::getOperandLatency(
+ ItinData, DefMI, DefIdx, UseMI, UseIdx);
if (!DefMI.getParent())
return Latency;
@@ -190,7 +189,7 @@ int PPCInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
}
if (UseMI.isBranch() && IsRegCR) {
- if (Latency < 0)
+ if (!Latency)
Latency = getInstrLatency(ItinData, DefMI);
// On some cores, there is an additional delay between writing to a condition
@@ -210,34 +209,14 @@ int PPCInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
case PPC::DIR_PWR7:
case PPC::DIR_PWR8:
// FIXME: Is this needed for POWER9?
- Latency += 2;
- break;
+ Latency = *Latency + 2;
+ break;
}
}
return Latency;
}
-/// This is an architecture-specific helper function of reassociateOps.
-/// Set special operand attributes for new instructions after reassociation.
-void PPCInstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1,
- MachineInstr &OldMI2,
- MachineInstr &NewMI1,
- MachineInstr &NewMI2) const {
- // Propagate FP flags from the original instructions.
- // But clear poison-generating flags because those may not be valid now.
- uint32_t IntersectedFlags = OldMI1.getFlags() & OldMI2.getFlags();
- NewMI1.setFlags(IntersectedFlags);
- NewMI1.clearFlag(MachineInstr::MIFlag::NoSWrap);
- NewMI1.clearFlag(MachineInstr::MIFlag::NoUWrap);
- NewMI1.clearFlag(MachineInstr::MIFlag::IsExact);
-
- NewMI2.setFlags(IntersectedFlags);
- NewMI2.clearFlag(MachineInstr::MIFlag::NoSWrap);
- NewMI2.clearFlag(MachineInstr::MIFlag::NoUWrap);
- NewMI2.clearFlag(MachineInstr::MIFlag::IsExact);
-}
-
void PPCInstrInfo::setSpecialOperandAttr(MachineInstr &MI,
uint32_t Flags) const {
MI.setFlags(Flags);
@@ -763,7 +742,7 @@ bool PPCInstrInfo::getMachineCombinerPatterns(
bool DoRegPressureReduce) const {
// Using the machine combiner in this way is potentially expensive, so
// restrict to when aggressive optimizations are desired.
- if (Subtarget.getTargetMachine().getOptLevel() != CodeGenOpt::Aggressive)
+ if (Subtarget.getTargetMachine().getOptLevel() != CodeGenOptLevel::Aggressive)
return false;
if (getFMAPatterns(Root, Patterns, DoRegPressureReduce))
@@ -1121,7 +1100,7 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable(
case PPC::XXSETACCZW:
return true;
}
- return false;
+ return TargetInstrInfo::isReallyTriviallyReMaterializable(MI);
}
unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
@@ -1174,8 +1153,8 @@ MachineInstr *PPCInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
// If machine instrs are no longer in two-address forms, update
// destination register as well.
if (Reg0 == Reg1) {
- // Must be two address instruction!
- assert(MI.getDesc().getOperandConstraint(0, MCOI::TIED_TO) &&
+ // Must be two address instruction (i.e. op1 is tied to op0).
+ assert(MI.getDesc().getOperandConstraint(1, MCOI::TIED_TO) == 0 &&
"Expecting a two-address instruction!");
assert(MI.getOperand(0).getSubReg() == SubReg1 && "Tied subreg mismatch");
Reg2IsKill = false;
@@ -1530,6 +1509,9 @@ bool PPCInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
Register DstReg, Register TrueReg,
Register FalseReg, int &CondCycles,
int &TrueCycles, int &FalseCycles) const {
+ if (!Subtarget.hasISEL())
+ return false;
+
if (Cond.size() != 2)
return false;
@@ -2833,10 +2815,6 @@ bool PPCInstrInfo::optimizeCmpPostRA(MachineInstr &CmpMI) const {
.addReg(CRReg, RegState::ImplicitDefine);
SrcMI->clearRegisterDeads(CRReg);
- // Fix up killed/dead flag for SrcReg after transformation.
- if (SrcRegHasOtherUse || CmpMI.getOperand(1).isKill())
- fixupIsDeadOrKill(SrcMI, &CmpMI, SrcReg);
-
assert(SrcMI->definesRegister(PPC::CR0) &&
"Record-form instruction does not define cr0?");
@@ -2899,8 +2877,9 @@ static bool isClusterableLdStOpcPair(unsigned FirstOpc, unsigned SecondOpc,
}
bool PPCInstrInfo::shouldClusterMemOps(
- ArrayRef<const MachineOperand *> BaseOps1,
- ArrayRef<const MachineOperand *> BaseOps2, unsigned NumLoads,
+ ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
+ bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
+ int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
unsigned NumBytes) const {
assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
@@ -2909,9 +2888,10 @@ bool PPCInstrInfo::shouldClusterMemOps(
assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
"Only base registers and frame indices are supported.");
- // The NumLoads means the number of loads that has been clustered.
+ // ClusterSize means the number of memory operations that will have been
+ // clustered if this hook returns true.
// Don't cluster memory op if there are already two ops clustered at least.
- if (NumLoads > 2)
+ if (ClusterSize > 2)
return false;
// Cluster the load/store only when they have the same base
@@ -2976,41 +2956,40 @@ unsigned PPCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
std::pair<unsigned, unsigned>
PPCInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
- const unsigned Mask = PPCII::MO_ACCESS_MASK;
- return std::make_pair(TF & Mask, TF & ~Mask);
+ // PPC always uses a direct mask.
+ return std::make_pair(TF, 0u);
}
ArrayRef<std::pair<unsigned, const char *>>
PPCInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
using namespace PPCII;
static const std::pair<unsigned, const char *> TargetFlags[] = {
- {MO_LO, "ppc-lo"},
- {MO_HA, "ppc-ha"},
- {MO_TPREL_LO, "ppc-tprel-lo"},
- {MO_TPREL_HA, "ppc-tprel-ha"},
- {MO_DTPREL_LO, "ppc-dtprel-lo"},
- {MO_TLSLD_LO, "ppc-tlsld-lo"},
- {MO_TOC_LO, "ppc-toc-lo"},
- {MO_TLS, "ppc-tls"}};
- return ArrayRef(TargetFlags);
-}
-
-ArrayRef<std::pair<unsigned, const char *>>
-PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
- using namespace PPCII;
- static const std::pair<unsigned, const char *> TargetFlags[] = {
{MO_PLT, "ppc-plt"},
{MO_PIC_FLAG, "ppc-pic"},
{MO_PCREL_FLAG, "ppc-pcrel"},
{MO_GOT_FLAG, "ppc-got"},
{MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"},
{MO_TLSGD_FLAG, "ppc-tlsgd"},
- {MO_TLSLD_FLAG, "ppc-tlsld"},
{MO_TPREL_FLAG, "ppc-tprel"},
+ {MO_TLSLD_FLAG, "ppc-tlsld"},
{MO_TLSGDM_FLAG, "ppc-tlsgdm"},
{MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"},
{MO_GOT_TLSLD_PCREL_FLAG, "ppc-got-tlsld-pcrel"},
- {MO_GOT_TPREL_PCREL_FLAG, "ppc-got-tprel-pcrel"}};
+ {MO_GOT_TPREL_PCREL_FLAG, "ppc-got-tprel-pcrel"},
+ {MO_LO, "ppc-lo"},
+ {MO_HA, "ppc-ha"},
+ {MO_TPREL_LO, "ppc-tprel-lo"},
+ {MO_TPREL_HA, "ppc-tprel-ha"},
+ {MO_DTPREL_LO, "ppc-dtprel-lo"},
+ {MO_TLSLD_LO, "ppc-tlsld-lo"},
+ {MO_TOC_LO, "ppc-toc-lo"},
+ {MO_TLS, "ppc-tls"},
+ {MO_PIC_HA_FLAG, "ppc-ha-pic"},
+ {MO_PIC_LO_FLAG, "ppc-lo-pic"},
+ {MO_TPREL_PCREL_FLAG, "ppc-tprel-pcrel"},
+ {MO_TLS_PCREL_FLAG, "ppc-tls-pcrel"},
+ {MO_GOT_PCREL_FLAG, "ppc-got-pcrel"},
+ };
return ArrayRef(TargetFlags);
}
@@ -3412,7 +3391,7 @@ MachineInstr *PPCInstrInfo::getForwardingDefMI(
Opc == PPC::RLWINM || Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8 ||
Opc == PPC::RLWINM8_rec;
bool IsVFReg = (MI.getNumOperands() && MI.getOperand(0).isReg())
- ? isVFRegister(MI.getOperand(0).getReg())
+ ? PPC::isVFRegister(MI.getOperand(0).getReg())
: false;
if (!ConvertibleImmForm && !instrHasImmForm(Opc, IsVFReg, III, true))
return nullptr;
@@ -3467,101 +3446,6 @@ ArrayRef<unsigned> PPCInstrInfo::getLoadOpcodesForSpillArray() const {
return {LoadSpillOpcodesArray[getSpillTarget()], SOK_LastOpcodeSpill};
}
-void PPCInstrInfo::fixupIsDeadOrKill(MachineInstr *StartMI, MachineInstr *EndMI,
- unsigned RegNo) const {
- // Conservatively clear kill flag for the register if the instructions are in
- // different basic blocks and in SSA form, because the kill flag may no longer
- // be right. There is no need to bother with dead flags since defs with no
- // uses will be handled by DCE.
- MachineRegisterInfo &MRI = StartMI->getParent()->getParent()->getRegInfo();
- if (MRI.isSSA() && (StartMI->getParent() != EndMI->getParent())) {
- MRI.clearKillFlags(RegNo);
- return;
- }
-
- // Instructions between [StartMI, EndMI] should be in same basic block.
- assert((StartMI->getParent() == EndMI->getParent()) &&
- "Instructions are not in same basic block");
-
- // If before RA, StartMI may be def through COPY, we need to adjust it to the
- // real def. See function getForwardingDefMI.
- if (MRI.isSSA()) {
- bool Reads, Writes;
- std::tie(Reads, Writes) = StartMI->readsWritesVirtualRegister(RegNo);
- if (!Reads && !Writes) {
- assert(Register::isVirtualRegister(RegNo) &&
- "Must be a virtual register");
- // Get real def and ignore copies.
- StartMI = MRI.getVRegDef(RegNo);
- }
- }
-
- bool IsKillSet = false;
-
- auto clearOperandKillInfo = [=] (MachineInstr &MI, unsigned Index) {
- MachineOperand &MO = MI.getOperand(Index);
- if (MO.isReg() && MO.isUse() && MO.isKill() &&
- getRegisterInfo().regsOverlap(MO.getReg(), RegNo))
- MO.setIsKill(false);
- };
-
- // Set killed flag for EndMI.
- // No need to do anything if EndMI defines RegNo.
- int UseIndex =
- EndMI->findRegisterUseOperandIdx(RegNo, false, &getRegisterInfo());
- if (UseIndex != -1) {
- EndMI->getOperand(UseIndex).setIsKill(true);
- IsKillSet = true;
- // Clear killed flag for other EndMI operands related to RegNo. In some
- // upexpected cases, killed may be set multiple times for same register
- // operand in same MI.
- for (int i = 0, e = EndMI->getNumOperands(); i != e; ++i)
- if (i != UseIndex)
- clearOperandKillInfo(*EndMI, i);
- }
-
- // Walking the inst in reverse order (EndMI -> StartMI].
- MachineBasicBlock::reverse_iterator It = *EndMI;
- MachineBasicBlock::reverse_iterator E = EndMI->getParent()->rend();
- // EndMI has been handled above, skip it here.
- It++;
- MachineOperand *MO = nullptr;
- for (; It != E; ++It) {
- // Skip insturctions which could not be a def/use of RegNo.
- if (It->isDebugInstr() || It->isPosition())
- continue;
-
- // Clear killed flag for all It operands related to RegNo. In some
- // upexpected cases, killed may be set multiple times for same register
- // operand in same MI.
- for (int i = 0, e = It->getNumOperands(); i != e; ++i)
- clearOperandKillInfo(*It, i);
-
- // If killed is not set, set killed for its last use or set dead for its def
- // if no use found.
- if (!IsKillSet) {
- if ((MO = It->findRegisterUseOperand(RegNo, false, &getRegisterInfo()))) {
- // Use found, set it killed.
- IsKillSet = true;
- MO->setIsKill(true);
- continue;
- } else if ((MO = It->findRegisterDefOperand(RegNo, false, true,
- &getRegisterInfo()))) {
- // No use found, set dead for its def.
- assert(&*It == StartMI && "No new def between StartMI and EndMI.");
- MO->setIsDead(true);
- break;
- }
- }
-
- if ((&*It) == StartMI)
- break;
- }
- // Ensure RegMo liveness is killed after EndMI.
- assert((IsKillSet || (MO && MO->isDead())) &&
- "RegNo should be killed or dead");
-}
-
// This opt tries to convert the following imm form to an index form to save an
// add for stack variables.
// Return false if no such pattern found.
@@ -3725,8 +3609,8 @@ bool PPCInstrInfo::isImmInstrEligibleForFolding(MachineInstr &MI,
return false;
// TODO: sync the logic between instrHasImmForm() and ImmToIdxMap.
- if (!instrHasImmForm(XFormOpcode, isVFRegister(MI.getOperand(0).getReg()),
- III, true))
+ if (!instrHasImmForm(XFormOpcode,
+ PPC::isVFRegister(MI.getOperand(0).getReg()), III, true))
return false;
if (!III.IsSummingOperands)
@@ -3796,6 +3680,7 @@ bool PPCInstrInfo::isValidToBeChangedReg(MachineInstr *ADDMI, unsigned Index,
// result of a load-immediate or an add-immediate, convert it to
// the immediate form if the constant is in range.
bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI,
+ SmallSet<Register, 4> &RegsToUpdate,
MachineInstr **KilledDef) const {
MachineFunction *MF = MI.getParent()->getParent();
MachineRegisterInfo *MRI = &MF->getRegInfo();
@@ -3813,6 +3698,15 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI,
if (KilledDef && KillFwdDefMI)
*KilledDef = DefMI;
+ // Conservatively add defs from DefMI and defs/uses from MI to the set of
+ // registers that need their kill flags updated.
+ for (const MachineOperand &MO : DefMI->operands())
+ if (MO.isReg() && MO.isDef())
+ RegsToUpdate.insert(MO.getReg());
+ for (const MachineOperand &MO : MI.operands())
+ if (MO.isReg())
+ RegsToUpdate.insert(MO.getReg());
+
// If this is a imm instruction and its register operands is produced by ADDI,
// put the imm into imm inst directly.
if (RI.getMappedIdxOpcForImmOpc(MI.getOpcode()) !=
@@ -3822,7 +3716,7 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI,
ImmInstrInfo III;
bool IsVFReg = MI.getOperand(0).isReg()
- ? isVFRegister(MI.getOperand(0).getReg())
+ ? PPC::isVFRegister(MI.getOperand(0).getReg())
: false;
bool HasImmForm = instrHasImmForm(MI.getOpcode(), IsVFReg, III, PostRA);
// If this is a reg+reg instruction that has a reg+imm form,
@@ -4615,9 +4509,6 @@ bool PPCInstrInfo::simplifyToLI(MachineInstr &MI, MachineInstr &DefMI,
// Sign-extend to 64-bits.
int64_t SExtImm = SignExtend64<16>(Immediate);
- bool IsForwardingOperandKilled = MI.getOperand(OpNoForForwarding).isKill();
- Register ForwardingOperandReg = MI.getOperand(OpNoForForwarding).getReg();
-
bool ReplaceWithLI = false;
bool Is64BitLI = false;
int64_t NewImm = 0;
@@ -4829,12 +4720,8 @@ bool PPCInstrInfo::simplifyToLI(MachineInstr &MI, MachineInstr &DefMI,
*KilledDef = nullptr;
replaceInstrWithLI(MI, LII);
- // Fixup killed/dead flag after transformation.
- // Pattern:
- // ForwardingOperandReg = LI imm1
- // y = op2 imm2, ForwardingOperandReg(killed)
- if (IsForwardingOperandKilled)
- fixupIsDeadOrKill(&DefMI, &MI, ForwardingOperandReg);
+ if (PostRA)
+ recomputeLivenessFlags(*MI.getParent());
LLVM_DEBUG(dbgs() << "With:\n");
LLVM_DEBUG(MI.dump());
@@ -4864,7 +4751,7 @@ bool PPCInstrInfo::transformToNewImmFormFedByAdd(
// get Imm Form info.
ImmInstrInfo III;
bool IsVFReg = MI.getOperand(0).isReg()
- ? isVFRegister(MI.getOperand(0).getReg())
+ ? PPC::isVFRegister(MI.getOperand(0).getReg())
: false;
if (!instrHasImmForm(XFormOpcode, IsVFReg, III, PostRA))
@@ -4895,11 +4782,6 @@ bool PPCInstrInfo::transformToNewImmFormFedByAdd(
if (!isImmElgibleForForwarding(*ImmMO, DefMI, III, Imm, ImmBase))
return false;
- // Get killed info in case fixup needed after transformation.
- unsigned ForwardKilledOperandReg = ~0U;
- if (MI.getOperand(III.OpNoForForwarding).isKill())
- ForwardKilledOperandReg = MI.getOperand(III.OpNoForForwarding).getReg();
-
// Do the transform
LLVM_DEBUG(dbgs() << "Replacing existing reg+imm instruction:\n");
LLVM_DEBUG(MI.dump());
@@ -4907,35 +4789,8 @@ bool PPCInstrInfo::transformToNewImmFormFedByAdd(
LLVM_DEBUG(DefMI.dump());
MI.getOperand(III.OpNoForForwarding).setReg(RegMO->getReg());
- if (RegMO->isKill()) {
- MI.getOperand(III.OpNoForForwarding).setIsKill(true);
- // Clear the killed flag in RegMO. Doing this here can handle some cases
- // that DefMI and MI are not in same basic block.
- RegMO->setIsKill(false);
- }
MI.getOperand(III.ImmOpNo).setImm(Imm);
- // FIXME: fix kill/dead flag if MI and DefMI are not in same basic block.
- if (DefMI.getParent() == MI.getParent()) {
- // Check if reg is killed between MI and DefMI.
- auto IsKilledFor = [&](unsigned Reg) {
- MachineBasicBlock::const_reverse_iterator It = MI;
- MachineBasicBlock::const_reverse_iterator E = DefMI;
- It++;
- for (; It != E; ++It) {
- if (It->killsRegister(Reg))
- return true;
- }
- return false;
- };
-
- // Update kill flag
- if (RegMO->isKill() || IsKilledFor(RegMO->getReg()))
- fixupIsDeadOrKill(&DefMI, &MI, RegMO->getReg());
- if (ForwardKilledOperandReg != ~0U)
- fixupIsDeadOrKill(&DefMI, &MI, ForwardKilledOperandReg);
- }
-
LLVM_DEBUG(dbgs() << "With:\n");
LLVM_DEBUG(MI.dump());
return true;
@@ -4979,12 +4834,8 @@ bool PPCInstrInfo::transformToImmFormFedByAdd(
IsFwdFeederRegKilled, SeenIntermediateUse))
return false;
- // Get killed info in case fixup needed after transformation.
- unsigned ForwardKilledOperandReg = ~0U;
MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
bool PostRA = !MRI.isSSA();
- if (PostRA && MI.getOperand(OpNoForForwarding).isKill())
- ForwardKilledOperandReg = MI.getOperand(OpNoForForwarding).getReg();
// We know that, the MI and DefMI both meet the pattern, and
// the Imm also meet the requirement with the new Imm-form.
@@ -5036,22 +4887,8 @@ bool PPCInstrInfo::transformToImmFormFedByAdd(
// Update the opcode.
MI.setDesc(get(III.ImmOpcode));
- // Fix up killed/dead flag after transformation.
- // Pattern 1:
- // x = ADD KilledFwdFeederReg, imm
- // n = opn KilledFwdFeederReg(killed), regn
- // y = XOP 0, x
- // Pattern 2:
- // x = ADD reg(killed), imm
- // y = XOP 0, x
- if (IsFwdFeederRegKilled || RegMO->isKill())
- fixupIsDeadOrKill(&DefMI, &MI, RegMO->getReg());
- // Pattern 3:
- // ForwardKilledOperandReg = ADD reg, imm
- // y = XOP 0, ForwardKilledOperandReg(killed)
- if (ForwardKilledOperandReg != ~0U)
- fixupIsDeadOrKill(&DefMI, &MI, ForwardKilledOperandReg);
-
+ if (PostRA)
+ recomputeLivenessFlags(*MI.getParent());
LLVM_DEBUG(dbgs() << "With:\n");
LLVM_DEBUG(MI.dump());
@@ -5107,11 +4944,6 @@ bool PPCInstrInfo::transformToImmFormFedByLI(MachineInstr &MI,
return false;
}
- // Get killed info in case fixup needed after transformation.
- unsigned ForwardKilledOperandReg = ~0U;
- if (PostRA && MI.getOperand(ConstantOpNo).isKill())
- ForwardKilledOperandReg = MI.getOperand(ConstantOpNo).getReg();
-
unsigned Opc = MI.getOpcode();
bool SpecialShift32 = Opc == PPC::SLW || Opc == PPC::SLW_rec ||
Opc == PPC::SRW || Opc == PPC::SRW_rec ||
@@ -5205,12 +5037,8 @@ bool PPCInstrInfo::transformToImmFormFedByLI(MachineInstr &MI,
}
}
- // Fix up killed/dead flag after transformation.
- // Pattern:
- // ForwardKilledOperandReg = LI imm
- // y = XOP reg, ForwardKilledOperandReg(killed)
- if (ForwardKilledOperandReg != ~0U)
- fixupIsDeadOrKill(&DefMI, &MI, ForwardKilledOperandReg);
+ if (PostRA)
+ recomputeLivenessFlags(*MI.getParent());
LLVM_DEBUG(dbgs() << "With: ");
LLVM_DEBUG(MI.dump());
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h
index 3dc5e2680c61..75f9cd1c206d 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -13,7 +13,10 @@
#ifndef LLVM_LIB_TARGET_POWERPC_PPCINSTRINFO_H
#define LLVM_LIB_TARGET_POWERPC_PPCINSTRINFO_H
+#include "MCTargetDesc/PPCMCTargetDesc.h"
+#include "PPC.h"
#include "PPCRegisterInfo.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#define GET_INSTRINFO_HEADER
@@ -21,60 +24,6 @@
namespace llvm {
-/// PPCII - This namespace holds all of the PowerPC target-specific
-/// per-instruction flags. These must match the corresponding definitions in
-/// PPC.td and PPCInstrFormats.td.
-namespace PPCII {
-enum {
- // PPC970 Instruction Flags. These flags describe the characteristics of the
- // PowerPC 970 (aka G5) dispatch groups and how they are formed out of
- // raw machine instructions.
-
- /// PPC970_First - This instruction starts a new dispatch group, so it will
- /// always be the first one in the group.
- PPC970_First = 0x1,
-
- /// PPC970_Single - This instruction starts a new dispatch group and
- /// terminates it, so it will be the sole instruction in the group.
- PPC970_Single = 0x2,
-
- /// PPC970_Cracked - This instruction is cracked into two pieces, requiring
- /// two dispatch pipes to be available to issue.
- PPC970_Cracked = 0x4,
-
- /// PPC970_Mask/Shift - This is a bitmask that selects the pipeline type that
- /// an instruction is issued to.
- PPC970_Shift = 3,
- PPC970_Mask = 0x07 << PPC970_Shift
-};
-enum PPC970_Unit {
- /// These are the various PPC970 execution unit pipelines. Each instruction
- /// is one of these.
- PPC970_Pseudo = 0 << PPC970_Shift, // Pseudo instruction
- PPC970_FXU = 1 << PPC970_Shift, // Fixed Point (aka Integer/ALU) Unit
- PPC970_LSU = 2 << PPC970_Shift, // Load Store Unit
- PPC970_FPU = 3 << PPC970_Shift, // Floating Point Unit
- PPC970_CRU = 4 << PPC970_Shift, // Control Register Unit
- PPC970_VALU = 5 << PPC970_Shift, // Vector ALU
- PPC970_VPERM = 6 << PPC970_Shift, // Vector Permute Unit
- PPC970_BRU = 7 << PPC970_Shift // Branch Unit
-};
-
-enum {
- /// Shift count to bypass PPC970 flags
- NewDef_Shift = 6,
-
- /// This instruction is an X-Form memory operation.
- XFormMemOp = 0x1 << NewDef_Shift,
- /// This instruction is prefixed.
- Prefixed = 0x1 << (NewDef_Shift + 1),
- /// This instruction produced a sign extended result.
- SExt32To64 = 0x1 << (NewDef_Shift + 2),
- /// This instruction produced a zero extended result.
- ZExt32To64 = 0x1 << (NewDef_Shift + 3)
-};
-} // end namespace PPCII
-
// Instructions that have an immediate form might be convertible to that
// form if the correct input is a result of a load immediate. In order to
// know whether the transformation is special, we might need to know some
@@ -324,99 +273,6 @@ public:
return get(Opcode).TSFlags & PPCII::ZExt32To64;
}
- /// Check if Opcode corresponds to a call instruction that should be marked
- /// with the NOTOC relocation.
- bool isNoTOCCallInstr(unsigned Opcode) const {
- if (!get(Opcode).isCall())
- return false;
-
- switch (Opcode) {
- default:
-#ifndef NDEBUG
- llvm_unreachable("Unknown call opcode");
-#endif
- return false;
- case PPC::BL8_NOTOC:
- case PPC::BL8_NOTOC_TLS:
- case PPC::BL8_NOTOC_RM:
- return true;
-#ifndef NDEBUG
- case PPC::BL8:
- case PPC::BL:
- case PPC::BL8_TLS:
- case PPC::BL_TLS:
- case PPC::BLA8:
- case PPC::BLA:
- case PPC::BCCL:
- case PPC::BCCLA:
- case PPC::BCL:
- case PPC::BCLn:
- case PPC::BL8_NOP:
- case PPC::BL_NOP:
- case PPC::BL8_NOP_TLS:
- case PPC::BLA8_NOP:
- case PPC::BCTRL8:
- case PPC::BCTRL:
- case PPC::BCCCTRL8:
- case PPC::BCCCTRL:
- case PPC::BCCTRL8:
- case PPC::BCCTRL:
- case PPC::BCCTRL8n:
- case PPC::BCCTRLn:
- case PPC::BL8_RM:
- case PPC::BLA8_RM:
- case PPC::BL8_NOP_RM:
- case PPC::BLA8_NOP_RM:
- case PPC::BCTRL8_RM:
- case PPC::BCTRL8_LDinto_toc:
- case PPC::BCTRL8_LDinto_toc_RM:
- case PPC::BL8_TLS_:
- case PPC::TCRETURNdi8:
- case PPC::TCRETURNai8:
- case PPC::TCRETURNri8:
- case PPC::TAILBCTR8:
- case PPC::TAILB8:
- case PPC::TAILBA8:
- case PPC::BCLalways:
- case PPC::BLRL:
- case PPC::BCCLRL:
- case PPC::BCLRL:
- case PPC::BCLRLn:
- case PPC::BDZL:
- case PPC::BDNZL:
- case PPC::BDZLA:
- case PPC::BDNZLA:
- case PPC::BDZLp:
- case PPC::BDNZLp:
- case PPC::BDZLAp:
- case PPC::BDNZLAp:
- case PPC::BDZLm:
- case PPC::BDNZLm:
- case PPC::BDZLAm:
- case PPC::BDNZLAm:
- case PPC::BDZLRL:
- case PPC::BDNZLRL:
- case PPC::BDZLRLp:
- case PPC::BDNZLRLp:
- case PPC::BDZLRLm:
- case PPC::BDNZLRLm:
- case PPC::BL_RM:
- case PPC::BLA_RM:
- case PPC::BL_NOP_RM:
- case PPC::BCTRL_RM:
- case PPC::TCRETURNdi:
- case PPC::TCRETURNai:
- case PPC::TCRETURNri:
- case PPC::BCTRL_LWZinto_toc:
- case PPC::BCTRL_LWZinto_toc_RM:
- case PPC::TAILBCTR:
- case PPC::TAILB:
- case PPC::TAILBA:
- return false;
-#endif
- }
- }
-
static bool isSameClassPhysRegCopy(unsigned Opcode) {
unsigned CopyOpcodes[] = {PPC::OR, PPC::OR8, PPC::FMR,
PPC::VOR, PPC::XXLOR, PPC::XXLORf,
@@ -428,6 +284,32 @@ public:
return false;
}
+ static bool hasPCRelFlag(unsigned TF) {
+ return TF == PPCII::MO_PCREL_FLAG || TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
+ TF == PPCII::MO_TPREL_PCREL_FLAG || TF == PPCII::MO_TLS_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_PCREL_FLAG;
+ }
+
+ static bool hasGOTFlag(unsigned TF) {
+ return TF == PPCII::MO_GOT_FLAG || TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_PCREL_FLAG;
+ }
+
+ static bool hasTLSFlag(unsigned TF) {
+ return TF == PPCII::MO_TLSGD_FLAG || TF == PPCII::MO_TPREL_FLAG ||
+ TF == PPCII::MO_TLSLD_FLAG || TF == PPCII::MO_TLSGDM_FLAG ||
+ TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG ||
+ TF == PPCII::MO_GOT_TPREL_PCREL_FLAG || TF == PPCII::MO_TPREL_LO ||
+ TF == PPCII::MO_TPREL_HA || TF == PPCII::MO_DTPREL_LO ||
+ TF == PPCII::MO_TLSLD_LO || TF == PPCII::MO_TLS ||
+ TF == PPCII::MO_TPREL_PCREL_FLAG || TF == PPCII::MO_TLS_PCREL_FLAG;
+ }
+
ScheduleHazardRecognizer *
CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI,
const ScheduleDAG *DAG) const override;
@@ -439,13 +321,15 @@ public:
const MachineInstr &MI,
unsigned *PredCost = nullptr) const override;
- int getOperandLatency(const InstrItineraryData *ItinData,
- const MachineInstr &DefMI, unsigned DefIdx,
- const MachineInstr &UseMI,
- unsigned UseIdx) const override;
- int getOperandLatency(const InstrItineraryData *ItinData,
- SDNode *DefNode, unsigned DefIdx,
- SDNode *UseNode, unsigned UseIdx) const override {
+ std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,
+ const MachineInstr &DefMI,
+ unsigned DefIdx,
+ const MachineInstr &UseMI,
+ unsigned UseIdx) const override;
+ std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,
+ SDNode *DefNode, unsigned DefIdx,
+ SDNode *UseNode,
+ unsigned UseIdx) const override {
return PPCGenInstrInfo::getOperandLatency(ItinData, DefNode, DefIdx,
UseNode, UseIdx);
}
@@ -512,12 +396,9 @@ public:
/// perserved for more FMA chain reassociations on PowerPC.
int getExtendResourceLenLimit() const override { return 1; }
- void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2,
- MachineInstr &NewMI1,
- MachineInstr &NewMI2) const override;
-
// PowerPC specific version of setSpecialOperandAttr that copies Flags to MI
// and clears nuw, nsw, and exact flags.
+ using TargetInstrInfo::setSpecialOperandAttr;
void setSpecialOperandAttr(MachineInstr &MI, uint32_t Flags) const;
bool isCoalescableExtInstr(const MachineInstr &MI,
@@ -678,8 +559,11 @@ public:
/// Returns true if the two given memory operations should be scheduled
/// adjacent.
bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,
+ int64_t Offset1, bool OffsetIsScalable1,
ArrayRef<const MachineOperand *> BaseOps2,
- unsigned NumLoads, unsigned NumBytes) const override;
+ int64_t Offset2, bool OffsetIsScalable2,
+ unsigned ClusterSize,
+ unsigned NumBytes) const override;
/// Return true if two MIs access different memory addresses and false
/// otherwise
@@ -700,21 +584,12 @@ public:
ArrayRef<std::pair<unsigned, const char *>>
getSerializableDirectMachineOperandTargetFlags() const override;
- ArrayRef<std::pair<unsigned, const char *>>
- getSerializableBitmaskMachineOperandTargetFlags() const override;
-
// Expand VSX Memory Pseudo instruction to either a VSX or a FP instruction.
bool expandVSXMemPseudo(MachineInstr &MI) const;
// Lower pseudo instructions after register allocation.
bool expandPostRAPseudo(MachineInstr &MI) const override;
- static bool isVFRegister(unsigned Reg) {
- return Reg >= PPC::VF0 && Reg <= PPC::VF31;
- }
- static bool isVRRegister(unsigned Reg) {
- return Reg >= PPC::V0 && Reg <= PPC::V31;
- }
const TargetRegisterClass *updatedRC(const TargetRegisterClass *RC) const;
static int getRecordFormOpcode(unsigned Opcode);
@@ -737,6 +612,7 @@ public:
}
bool convertToImmediateForm(MachineInstr &MI,
+ SmallSet<Register, 4> &RegsToUpdate,
MachineInstr **KilledDef = nullptr) const;
bool foldFrameOffset(MachineInstr &MI) const;
bool combineRLWINM(MachineInstr &MI, MachineInstr **ToErase = nullptr) const;
@@ -750,23 +626,6 @@ public:
MachineInstr *&ADDIMI, int64_t &OffsetAddi,
int64_t OffsetImm) const;
- /// Fixup killed/dead flag for register \p RegNo between instructions [\p
- /// StartMI, \p EndMI]. Some pre-RA or post-RA transformations may violate
- /// register killed/dead flags semantics, this function can be called to fix
- /// up. Before calling this function,
- /// 1. Ensure that \p RegNo liveness is killed after instruction \p EndMI.
- /// 2. Ensure that there is no new definition between (\p StartMI, \p EndMI)
- /// and possible definition for \p RegNo is \p StartMI or \p EndMI. For
- /// pre-RA cases, definition may be \p StartMI through COPY, \p StartMI
- /// will be adjust to true definition.
- /// 3. We can do accurate fixup for the case when all instructions between
- /// [\p StartMI, \p EndMI] are in same basic block.
- /// 4. For the case when \p StartMI and \p EndMI are not in same basic block,
- /// we conservatively clear kill flag for all uses of \p RegNo for pre-RA
- /// and for post-RA, we give an assertion as without reaching definition
- /// analysis post-RA, \p StartMI and \p EndMI are hard to keep right.
- void fixupIsDeadOrKill(MachineInstr *StartMI, MachineInstr *EndMI,
- unsigned RegNo) const;
void replaceInstrWithLI(MachineInstr &MI, const LoadImmediateInfo &LII) const;
void replaceInstrOperandWithImm(MachineInstr &MI, unsigned OpNo,
int64_t Imm) const;
@@ -785,38 +644,6 @@ public:
const DebugLoc &DL, Register Reg,
int64_t Imm) const;
- /// getRegNumForOperand - some operands use different numbering schemes
- /// for the same registers. For example, a VSX instruction may have any of
- /// vs0-vs63 allocated whereas an Altivec instruction could only have
- /// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual
- /// register number needed for the opcode/operand number combination.
- /// The operand number argument will be useful when we need to extend this
- /// to instructions that use both Altivec and VSX numbering (for different
- /// operands).
- static unsigned getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg,
- unsigned OpNo) {
- int16_t regClass = Desc.operands()[OpNo].RegClass;
- switch (regClass) {
- // We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31,
- // VSX32-VSX63 during encoding/disassembling
- case PPC::VSSRCRegClassID:
- case PPC::VSFRCRegClassID:
- if (isVFRegister(Reg))
- return PPC::VSX32 + (Reg - PPC::VF0);
- break;
- // We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31,
- // VSX32-VSX63 during encoding/disassembling
- case PPC::VSRCRegClassID:
- if (isVRRegister(Reg))
- return PPC::VSX32 + (Reg - PPC::V0);
- break;
- // Other RegClass doesn't need mapping
- default:
- break;
- }
- return Reg;
- }
-
/// Check \p Opcode is BDNZ (Decrement CTR and branch if it is still nonzero).
bool isBDNZ(unsigned Opcode) const;
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 2992f78aa38a..6199785206b2 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1641,10 +1641,18 @@ let isBranch = 1, isTerminator = 1, Size = 0 in {
// System call.
let PPC970_Unit = 7 in {
- def SC : SCForm<17, 1, (outs), (ins i32imm:$LEV),
+ def SC : SCForm<17, 1, 0, (outs), (ins i32imm:$LEV),
"sc $LEV", IIC_BrB, [(PPCsc (i32 imm:$LEV))]>;
}
+// We mark SCV as having no scheduling model since it is only meant to be used
+// as inline assembly. If we implement a builtin pattern for it we will need to
+// add it to the P9 and P10 scheduling models.
+let Predicates = [IsISA3_0], hasNoSchedulingInfo = 1 in {
+ def SCV : SCForm<17, 0, 1, (outs), (ins i32imm:$LEV),
+ "scv $LEV", IIC_BrB, []>;
+}
+
// Branch history rolling buffer.
def CLRBHRB : XForm_0<31, 430, (outs), (ins), "clrbhrb", IIC_BrB,
[(PPCclrbhrb)]>,
@@ -1713,11 +1721,11 @@ def : Pat<(int_ppc_dcbf xoaddr:$dst),
def : Pat<(int_ppc_icbt xoaddr:$dst),
(ICBT 0, xoaddr:$dst)>;
-def : Pat<(prefetch xoaddr:$dst, (i32 0), imm, (i32 1)),
+def : Pat<(prefetch xoaddr:$dst, (i32 0), timm, (i32 1)),
(DCBT 0, xoaddr:$dst)>; // data prefetch for loads
-def : Pat<(prefetch xoaddr:$dst, (i32 1), imm, (i32 1)),
+def : Pat<(prefetch xoaddr:$dst, (i32 1), timm, (i32 1)),
(DCBTST 0, xoaddr:$dst)>; // data prefetch for stores
-def : Pat<(prefetch xoaddr:$dst, (i32 0), imm, (i32 0)),
+def : Pat<(prefetch xoaddr:$dst, (i32 0), timm, (i32 0)),
(ICBT 0, xoaddr:$dst)>, Requires<[HasICBT]>; // inst prefetch (for read)
def : Pat<(int_ppc_dcbt_with_hint xoaddr:$dst, i32:$TH),
@@ -3180,6 +3188,7 @@ def : Pat<(PPCtc_return CTRRC:$dst, imm:$imm),
(TCRETURNri CTRRC:$dst, imm:$imm)>;
def : Pat<(int_ppc_readflm), (MFFS)>;
+def : Pat<(int_ppc_mffsl), (MFFSL)>;
// Hi and Lo for Darwin Global Addresses.
def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
@@ -3251,8 +3260,8 @@ def GETtlsTpointer32AIX : PPCEmitTimePseudo<(outs gprc:$rD), (ins),
"GETtlsTpointer32AIX",
[(set i32:$rD, (PPCgetTpointer))]>;
-// The following pattern matches local-exec TLS accesses on 32-bit AIX.
-// PPCaddTls is used in local-exec accesses in order to:
+// The following pattern matches local- and initial-exec TLS accesses on 32-bit AIX.
+// PPCaddTls is used in local- and initial-exec accesses in order to:
// - Get the address of a variable (add the variable offset to the thread
// pointer, retrieved by calling .__get_tpointer).
// - Create an opportunity to optimize the user of the loaded address.
@@ -3428,6 +3437,23 @@ def crnot : OutPatFrag<(ops node:$in),
def : Pat<(not i1:$in),
(crnot $in)>;
+// Pseudo-instructions for alternate assembly syntax (never used by codegen).
+// These are aliases that require C++ handling to convert to the target
+// instruction, while InstAliases can be handled directly by tblgen.
+class PPCAsmPseudo<string asm, dag iops>
+ : Instruction {
+ let Namespace = "PPC";
+ bit PPC64 = 0; // Default value, override with isPPC64
+
+ let OutOperandList = (outs);
+ let InOperandList = iops;
+ let Pattern = [];
+ let AsmString = asm;
+ let isAsmParserOnly = 1;
+ let isPseudo = 1;
+ let hasNoSchedulingInfo = 1;
+}
+
// Prefixed instructions may require access to the above defs at a later
// time so we include this after the def.
include "PPCInstrP10.td"
@@ -4449,23 +4475,6 @@ def ICBIEP : XForm_1a<31, 991, (outs), (ins (memrr $RA, $RB):$addr), "icbiep $a
// PowerPC Assembler Instruction Aliases
//
-// Pseudo-instructions for alternate assembly syntax (never used by codegen).
-// These are aliases that require C++ handling to convert to the target
-// instruction, while InstAliases can be handled directly by tblgen.
-class PPCAsmPseudo<string asm, dag iops>
- : Instruction {
- let Namespace = "PPC";
- bit PPC64 = 0; // Default value, override with isPPC64
-
- let OutOperandList = (outs);
- let InOperandList = iops;
- let Pattern = [];
- let AsmString = asm;
- let isAsmParserOnly = 1;
- let isPseudo = 1;
- let hasNoSchedulingInfo = 1;
-}
-
def : InstAlias<"sc", (SC 0)>;
def : InstAlias<"sync", (SYNC 0)>, Requires<[HasSYNC]>;
@@ -5027,12 +5036,12 @@ def : Pat<(atomic_load_16 XForm:$src), (LHZX memrr:$src)>;
def : Pat<(atomic_load_32 XForm:$src), (LWZX memrr:$src)>;
// Atomic stores
-def : Pat<(atomic_store_8 DForm:$ptr, i32:$val), (STB gprc:$val, memri:$ptr)>;
-def : Pat<(atomic_store_16 DForm:$ptr, i32:$val), (STH gprc:$val, memri:$ptr)>;
-def : Pat<(atomic_store_32 DForm:$ptr, i32:$val), (STW gprc:$val, memri:$ptr)>;
-def : Pat<(atomic_store_8 XForm:$ptr, i32:$val), (STBX gprc:$val, memrr:$ptr)>;
-def : Pat<(atomic_store_16 XForm:$ptr, i32:$val), (STHX gprc:$val, memrr:$ptr)>;
-def : Pat<(atomic_store_32 XForm:$ptr, i32:$val), (STWX gprc:$val, memrr:$ptr)>;
+def : Pat<(atomic_store_8 i32:$val, DForm:$ptr), (STB gprc:$val, memri:$ptr)>;
+def : Pat<(atomic_store_16 i32:$val, DForm:$ptr), (STH gprc:$val, memri:$ptr)>;
+def : Pat<(atomic_store_32 i32:$val, DForm:$ptr), (STW gprc:$val, memri:$ptr)>;
+def : Pat<(atomic_store_8 i32:$val, XForm:$ptr), (STBX gprc:$val, memrr:$ptr)>;
+def : Pat<(atomic_store_16 i32:$val, XForm:$ptr), (STHX gprc:$val, memrr:$ptr)>;
+def : Pat<(atomic_store_32 i32:$val, XForm:$ptr), (STWX gprc:$val, memrr:$ptr)>;
let Predicates = [IsISA3_0] in {
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td
index 8cb8e4d91db2..d5a372e4dc10 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -575,33 +575,54 @@ class XForm_XT5_BI5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
}
multiclass MLS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
- dag PCRel_IOL, string asmstr,
+ dag PCRel_IOL, dag PCRelOnly_IOL,
+ string asmstr, string asmstr_pcext,
InstrItinClass itin> {
def NAME : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL,
!strconcat(asmstr, ", 0"), itin, []>;
def pc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRel_IOL,
!strconcat(asmstr, ", 1"), itin, []>,
isPCRel;
+ let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
+ def nopc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
+ let RA = 0 in
+ def onlypc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
+ asmstr_pcext, itin, []>, isPCRel;
+ }
}
multiclass 8LS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
- dag PCRel_IOL, string asmstr,
+ dag PCRel_IOL, dag PCRelOnly_IOL,
+ string asmstr, string asmstr_pcext,
InstrItinClass itin> {
def NAME : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL,
!strconcat(asmstr, ", 0"), itin, []>;
def pc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRel_IOL,
!strconcat(asmstr, ", 1"), itin, []>,
isPCRel;
+ let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
+ def nopc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
+ let RA = 0 in
+ def onlypc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
+ asmstr_pcext, itin, []>, isPCRel;
+ }
}
multiclass 8LS_DForm_R_SI34_XT6_RA5_MEM_p<bits<5> opcode, dag OOL, dag IOL,
- dag PCRel_IOL, string asmstr,
+ dag PCRel_IOL, dag PCRelOnly_IOL,
+ string asmstr, string asmstr_pcext,
InstrItinClass itin> {
def NAME : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL,
!strconcat(asmstr, ", 0"), itin, []>;
def pc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRel_IOL,
!strconcat(asmstr, ", 1"), itin, []>,
isPCRel;
+ let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
+ def nopc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
+ let RA = 0 in
+ def onlypc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRelOnly_IOL,
+ asmstr_pcext, itin, []>, isPCRel;
+ }
}
def PrefixInstrs : Predicate<"Subtarget->hasPrefixInstrs()">;
@@ -615,7 +636,7 @@ def RCCp {
let Predicates = [PrefixInstrs] in {
let Interpretation64Bit = 1, isCodeGenOnly = 1 in {
defm PADDI8 :
- MLS_DForm_R_SI34_RTA5_p<14, (outs g8rc:$RT), (ins g8rc:$RA, s34imm:$SI),
+ MLS_DForm_R_SI34_RTA5_p<14, (outs g8rc:$RT), (ins g8rc_nox0:$RA, s34imm:$SI),
(ins immZero:$RA, s34imm_pcrel:$SI),
"paddi $RT, $RA, $SI", IIC_LdStLFD>;
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in {
@@ -625,7 +646,7 @@ let Predicates = [PrefixInstrs] in {
}
}
defm PADDI :
- MLS_DForm_R_SI34_RTA5_p<14, (outs gprc:$RT), (ins gprc:$RA, s34imm:$SI),
+ MLS_DForm_R_SI34_RTA5_p<14, (outs gprc:$RT), (ins gprc_nor0:$RA, s34imm:$SI),
(ins immZero:$RA, s34imm_pcrel:$SI),
"paddi $RT, $RA, $SI", IIC_LdStLFD>;
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in {
@@ -638,68 +659,88 @@ let Predicates = [PrefixInstrs] in {
defm PLXV :
8LS_DForm_R_SI34_XT6_RA5_MEM_p<25, (outs vsrc:$XST), (ins (memri34 $D, $RA):$addr),
(ins (memri34_pcrel $D, $RA):$addr),
- "plxv $XST, $addr", IIC_LdStLFD>;
+ (ins s34imm_pcrel:$D),
+ "plxv $XST, $addr", "plxv $XST, $D", IIC_LdStLFD>;
defm PLFS :
MLS_DForm_R_SI34_RTA5_MEM_p<48, (outs f4rc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plfs $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plfs $RST, $addr",
+ "plfs $RST, $D", IIC_LdStLFD>;
defm PLFD :
MLS_DForm_R_SI34_RTA5_MEM_p<50, (outs f8rc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plfd $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plfd $RST, $addr",
+ "plfd $RST, $D", IIC_LdStLFD>;
defm PLXSSP :
8LS_DForm_R_SI34_RTA5_MEM_p<43, (outs vfrc:$RST), (ins (memri34 $D, $RA):$addr),
(ins (memri34_pcrel $D, $RA):$addr),
- "plxssp $RST, $addr", IIC_LdStLFD>;
+ (ins s34imm_pcrel:$D),
+ "plxssp $RST, $addr", "plxssp $RST, $D",
+ IIC_LdStLFD>;
defm PLXSD :
8LS_DForm_R_SI34_RTA5_MEM_p<42, (outs vfrc:$RST), (ins (memri34 $D, $RA):$addr),
(ins (memri34_pcrel $D, $RA):$addr),
- "plxsd $RST, $addr", IIC_LdStLFD>;
+ (ins s34imm_pcrel:$D),
+ "plxsd $RST, $addr", "plxsd $RST, $D",
+ IIC_LdStLFD>;
let Interpretation64Bit = 1, isCodeGenOnly = 1 in {
defm PLBZ8 :
MLS_DForm_R_SI34_RTA5_MEM_p<34, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plbz $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plbz $RST, $addr",
+ "plbz $RST, $D", IIC_LdStLFD>;
defm PLHZ8 :
MLS_DForm_R_SI34_RTA5_MEM_p<40, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plhz $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plhz $RST, $addr",
+ "plhz $RST, $D", IIC_LdStLFD>;
defm PLHA8 :
MLS_DForm_R_SI34_RTA5_MEM_p<42, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plha $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plha $RST, $addr",
+ "plha $RST, $D", IIC_LdStLFD>;
defm PLWA8 :
8LS_DForm_R_SI34_RTA5_MEM_p<41, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr),
(ins (memri34_pcrel $D, $RA):$addr),
- "plwa $RST, $addr", IIC_LdStLFD>;
+ (ins s34imm_pcrel:$D),
+ "plwa $RST, $addr", "plwa $RST, $D", IIC_LdStLFD>;
defm PLWZ8 :
MLS_DForm_R_SI34_RTA5_MEM_p<32, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plwz $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plwz $RST, $addr",
+ "plwz $RST, $D", IIC_LdStLFD>;
}
defm PLBZ :
MLS_DForm_R_SI34_RTA5_MEM_p<34, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plbz $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plbz $RST, $addr",
+ "plbz $RST, $D", IIC_LdStLFD>;
defm PLHZ :
MLS_DForm_R_SI34_RTA5_MEM_p<40, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plhz $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plhz $RST, $addr",
+ "plhz $RST, $D", IIC_LdStLFD>;
defm PLHA :
MLS_DForm_R_SI34_RTA5_MEM_p<42, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plha $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plha $RST, $addr",
+ "plha $RST, $D", IIC_LdStLFD>;
defm PLWZ :
MLS_DForm_R_SI34_RTA5_MEM_p<32, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plwz $RST, $addr",
- IIC_LdStLFD>;
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D), "plwz $RST, $addr",
+ "plwz $RST, $D", IIC_LdStLFD>;
defm PLWA :
8LS_DForm_R_SI34_RTA5_MEM_p<41, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plwa $RST, $addr",
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D),
+ "plwa $RST, $addr", "plwa $RST, $D",
IIC_LdStLFD>;
defm PLD :
8LS_DForm_R_SI34_RTA5_MEM_p<57, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "pld $RST, $addr",
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D),
+ "pld $RST, $addr", "pld $RST, $D",
IIC_LdStLFD>;
}
@@ -707,53 +748,65 @@ let Predicates = [PrefixInstrs] in {
defm PSTXV :
8LS_DForm_R_SI34_XT6_RA5_MEM_p<27, (outs), (ins vsrc:$XST, (memri34 $D, $RA):$addr),
(ins vsrc:$XST, (memri34_pcrel $D, $RA):$addr),
- "pstxv $XST, $addr", IIC_LdStLFD>;
+ (ins vsrc:$XST, s34imm_pcrel:$D),
+ "pstxv $XST, $addr", "pstxv $XST, $D", IIC_LdStLFD>;
defm PSTFS :
MLS_DForm_R_SI34_RTA5_MEM_p<52, (outs), (ins f4rc:$RST, (memri34 $D, $RA):$addr),
(ins f4rc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstfs $RST, $addr", IIC_LdStLFD>;
+ (ins f4rc:$RST, s34imm_pcrel:$D),
+ "pstfs $RST, $addr", "pstfs $RST, $D", IIC_LdStLFD>;
defm PSTFD :
MLS_DForm_R_SI34_RTA5_MEM_p<54, (outs), (ins f8rc:$RST, (memri34 $D, $RA):$addr),
(ins f8rc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstfd $RST, $addr", IIC_LdStLFD>;
+ (ins f8rc:$RST, s34imm_pcrel:$D),
+ "pstfd $RST, $addr", "pstfd $RST, $D", IIC_LdStLFD>;
defm PSTXSSP :
8LS_DForm_R_SI34_RTA5_MEM_p<47, (outs), (ins vfrc:$RST, (memri34 $D, $RA):$addr),
(ins vfrc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstxssp $RST, $addr", IIC_LdStLFD>;
+ (ins vfrc:$RST, s34imm_pcrel:$D),
+ "pstxssp $RST, $addr", "pstxssp $RST, $D", IIC_LdStLFD>;
defm PSTXSD :
8LS_DForm_R_SI34_RTA5_MEM_p<46, (outs), (ins vfrc:$RST, (memri34 $D, $RA):$addr),
(ins vfrc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstxsd $RST, $addr", IIC_LdStLFD>;
+ (ins vfrc:$RST, s34imm_pcrel:$D),
+ "pstxsd $RST, $addr", "pstxsd $RST, $D", IIC_LdStLFD>;
let Interpretation64Bit = 1, isCodeGenOnly = 1 in {
defm PSTB8 :
MLS_DForm_R_SI34_RTA5_MEM_p<38, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr),
(ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstb $RST, $addr", IIC_LdStLFD>;
+ (ins g8rc:$RST, s34imm_pcrel:$D),
+ "pstb $RST, $addr", "pstb $RST, $D", IIC_LdStLFD>;
defm PSTH8 :
MLS_DForm_R_SI34_RTA5_MEM_p<44, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr),
(ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr),
- "psth $RST, $addr", IIC_LdStLFD>;
+ (ins g8rc:$RST, s34imm_pcrel:$D),
+ "psth $RST, $addr", "psth $RST, $D", IIC_LdStLFD>;
defm PSTW8 :
MLS_DForm_R_SI34_RTA5_MEM_p<36, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr),
(ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstw $RST, $addr", IIC_LdStLFD>;
+ (ins g8rc:$RST, s34imm_pcrel:$D),
+ "pstw $RST, $addr", "pstw $RST, $D", IIC_LdStLFD>;
}
defm PSTB :
MLS_DForm_R_SI34_RTA5_MEM_p<38, (outs), (ins gprc:$RST, (memri34 $D, $RA):$addr),
(ins gprc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstb $RST, $addr", IIC_LdStLFD>;
+ (ins gprc:$RST, s34imm_pcrel:$D),
+ "pstb $RST, $addr", "pstb $RST, $D", IIC_LdStLFD>;
defm PSTH :
MLS_DForm_R_SI34_RTA5_MEM_p<44, (outs), (ins gprc:$RST, (memri34 $D, $RA):$addr),
(ins gprc:$RST, (memri34_pcrel $D, $RA):$addr),
- "psth $RST, $addr", IIC_LdStLFD>;
+ (ins gprc:$RST, s34imm_pcrel:$D),
+ "psth $RST, $addr", "psth $RST, $D", IIC_LdStLFD>;
defm PSTW :
MLS_DForm_R_SI34_RTA5_MEM_p<36, (outs), (ins gprc:$RST, (memri34 $D, $RA):$addr),
(ins gprc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstw $RST, $addr", IIC_LdStLFD>;
+ (ins gprc:$RST, s34imm_pcrel:$D),
+ "pstw $RST, $addr", "pstw $RST, $D", IIC_LdStLFD>;
defm PSTD :
8LS_DForm_R_SI34_RTA5_MEM_p<61, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr),
(ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr),
- "pstd $RST, $addr", IIC_LdStLFD>;
+ (ins g8rc:$RST, s34imm_pcrel:$D),
+ "pstd $RST, $addr", "pstd $RST, $D", IIC_LdStLFD>;
}
}
@@ -812,13 +865,20 @@ class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
}
multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL,
- dag IOL, dag PCRel_IOL,
- string asmstr, InstrItinClass itin> {
+ dag IOL, dag PCRel_IOL, dag PCRelOnly_IOL,
+ string asmstr, string asmstr_pcext,
+ InstrItinClass itin> {
def NAME : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL,
!strconcat(asmstr, ", 0"), itin, []>;
def pc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRel_IOL,
!strconcat(asmstr, ", 1"), itin, []>,
isPCRel;
+ let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
+ def nopc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, asmstr, itin, []>;
+ let RA = 0 in
+ def onlypc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRelOnly_IOL,
+ asmstr_pcext, itin, []>, isPCRel;
+ }
}
@@ -1079,7 +1139,9 @@ let mayLoad = 0, mayStore = 1, Predicates = [PairedVectorMemops] in {
let mayLoad = 1, mayStore = 0, Predicates = [PairedVectorMemops, PrefixInstrs] in {
defm PLXVP :
8LS_DForm_R_XTp5_SI34_MEM_p<58, (outs vsrprc:$XTp), (ins (memri34 $D, $RA):$addr),
- (ins (memri34_pcrel $D, $RA):$addr), "plxvp $XTp, $addr",
+ (ins (memri34_pcrel $D, $RA):$addr),
+ (ins s34imm_pcrel:$D),
+ "plxvp $XTp, $addr", "plxvp $XTp, $D",
IIC_LdStLFD>;
}
@@ -1087,7 +1149,8 @@ let mayLoad = 0, mayStore = 1, Predicates = [PairedVectorMemops, PrefixInstrs] i
defm PSTXVP :
8LS_DForm_R_XTp5_SI34_MEM_p<62, (outs), (ins vsrprc:$XTp, (memri34 $D, $RA):$addr),
(ins vsrprc:$XTp, (memri34_pcrel $D, $RA):$addr),
- "pstxvp $XTp, $addr", IIC_LdStLFD>;
+ (ins vsrprc:$XTp, s34imm_pcrel:$D),
+ "pstxvp $XTp, $addr", "pstxvp $XTp, $D", IIC_LdStLFD>;
}
let Predicates = [PairedVectorMemops] in {
@@ -1236,19 +1299,19 @@ let Predicates = [PCRelativeMemops] in {
(PLDpc $ga, 0)>;
// Atomic Store
- def : Pat<(atomic_store_8 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS),
+ def : Pat<(atomic_store_8 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)),
(PSTBpc $RS, $ga, 0)>;
- def : Pat<(atomic_store_16 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS),
+ def : Pat<(atomic_store_16 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)),
(PSTHpc $RS, $ga, 0)>;
- def : Pat<(atomic_store_32 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS),
+ def : Pat<(atomic_store_32 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)),
(PSTWpc $RS, $ga, 0)>;
- def : Pat<(atomic_store_8 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS),
+ def : Pat<(atomic_store_8 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)),
(PSTB8pc $RS, $ga, 0)>;
- def : Pat<(atomic_store_16 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS),
+ def : Pat<(atomic_store_16 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)),
(PSTH8pc $RS, $ga, 0)>;
- def : Pat<(atomic_store_32 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS),
+ def : Pat<(atomic_store_32 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)),
(PSTW8pc $RS, $ga, 0)>;
- def : Pat<(atomic_store_64 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS),
+ def : Pat<(atomic_store_64 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)),
(PSTDpc $RS, $ga, 0)>;
// Special Cases For PPCstore_scal_int_from_vsr
@@ -1855,6 +1918,13 @@ let Predicates = [IsISA3_1, HasVSX] in {
[(set f128:$RST, (PPCxsminc f128:$RA, f128:$RB))]>;
}
+let Predicates = [IsISA3_1] in {
+ def WAITP10 : XForm_IMM2_IMM2<31, 30, (outs), (ins u2imm:$L, u2imm:$PL),
+ "wait $L $PL", IIC_LdStLoad, []>;
+ def SYNCP10 : XForm_IMM3_IMM2<31, 598, (outs), (ins u3imm:$L, u2imm:$SC),
+ "sync $L, $SC", IIC_LdStSync, []>;
+}
+
// Multiclass defining patterns for Set Boolean Extension Reverse Instructions.
// This is analogous to the CRNotPat multiclass but specifically for Power10
// and newer subtargets since the extended forms use Set Boolean instructions.
@@ -2031,8 +2101,15 @@ let AddedComplexity = 400, Predicates = [IsISA3_1, IsLittleEndian] in {
(v8i16 (COPY_TO_REGCLASS (LXVRHX ForceXForm:$src), VSRC))>;
def : Pat<(v16i8 (scalar_to_vector (i32 (extloadi8 ForceXForm:$src)))),
(v16i8 (COPY_TO_REGCLASS (LXVRBX ForceXForm:$src), VSRC))>;
+ def : Pat<(store (i64 (extractelt v2i64:$A, 1)), ForceXForm:$src),
+ (XFSTOREf64 (EXTRACT_SUBREG $A, sub_64), ForceXForm:$src)>;
}
+let Predicates = [IsISA3_1, IsBigEndian] in {
+ def : Pat<(store (i64 (extractelt v2i64:$A, 0)), ForceXForm:$src),
+ (XFSTOREf64 (EXTRACT_SUBREG $A, sub_64), ForceXForm:$src)>;
+}
+
// FIXME: The swap is overkill when the shift amount is a constant.
// We should just fix the constant in the DAG.
let AddedComplexity = 400, Predicates = [IsISA3_1, HasVSX] in {
@@ -2276,10 +2353,10 @@ let Predicates = [PrefixInstrs] in {
def : Pat<(atomic_load_64 PDForm:$src), (PLD memri34:$src)>;
// Atomic Store
- def : Pat<(atomic_store_8 PDForm:$dst, i32:$RS), (PSTB $RS, memri34:$dst)>;
- def : Pat<(atomic_store_16 PDForm:$dst, i32:$RS), (PSTH $RS, memri34:$dst)>;
- def : Pat<(atomic_store_32 PDForm:$dst, i32:$RS), (PSTW $RS, memri34:$dst)>;
- def : Pat<(atomic_store_64 PDForm:$dst, i64:$RS), (PSTD $RS, memri34:$dst)>;
+ def : Pat<(atomic_store_8 i32:$RS, PDForm:$dst), (PSTB $RS, memri34:$dst)>;
+ def : Pat<(atomic_store_16 i32:$RS, PDForm:$dst), (PSTH $RS, memri34:$dst)>;
+ def : Pat<(atomic_store_32 i32:$RS, PDForm:$dst), (PSTW $RS, memri34:$dst)>;
+ def : Pat<(atomic_store_64 i64:$RS, PDForm:$dst), (PSTD $RS, memri34:$dst)>;
// Prefixed fpext to v2f64
def : Pat<(v4f32 (PPCldvsxlh PDForm:$src)),
@@ -2379,3 +2456,50 @@ let AddedComplexity = 400, Predicates = [IsISA3_1, HasVSX, IsBigEndian] in {
def : Pat<(v2i64 (insertelt v2i64:$vDi, i64:$rA, Idx)),
(VINSD $vDi, !mul(Idx, 8), $rA)>;
}
+
+
+//===----------------------------------------------------------------------===//
+// PowerPC ISA 3.1 Extended Mnemonics.
+//
+
+let Predicates = [IsISA3_1] in {
+ def : InstAlias<"wait", (WAITP10 0, 0)>;
+ def : InstAlias<"wait 0", (WAITP10 0, 0), 0>;
+ def : InstAlias<"wait 1", (WAITP10 1, 0), 0>;
+ def : InstAlias<"waitrsv", (WAITP10 1, 0)>;
+ def : InstAlias<"pause_short", (WAITP10 2, 0), 0>;
+
+ def : InstAlias<"sync", (SYNCP10 0, 0)>;
+ def : InstAlias<"hwsync", (SYNCP10 0, 0), 0>;
+ def : InstAlias<"wsync", (SYNCP10 1, 0), 0>;
+ def : InstAlias<"ptesync", (SYNCP10 2, 0)>;
+ def : InstAlias<"phwsync", (SYNCP10 4, 0)>;
+ def : InstAlias<"plwsync", (SYNCP10 5, 0)>;
+ def : InstAlias<"sync $L", (SYNCP10 u3imm:$L, 0)>;
+ def : InstAlias<"stncisync", (SYNCP10 1, 1)>;
+ def : InstAlias<"stcisync", (SYNCP10 0, 2)>;
+ def : InstAlias<"stsync", (SYNCP10 0, 3)>;
+
+ def : InstAlias<"paddi $RT, $RA, $SI", (PADDI8 g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>;
+}
+
+let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
+ let Interpretation64Bit = 1 in {
+ def PLA8 : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
+ (ins g8rc_nox0:$RA, s34imm:$SI),
+ "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
+ def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
+ (ins s34imm_pcrel:$SI),
+ "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
+ }
+
+ def PSUBI : PPCAsmPseudo<"psubi $RT, $RA, $SI",
+ (ins g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>;
+
+ def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
+ (ins gprc_nor0:$RA, s34imm:$SI),
+ "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
+ def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
+ (ins s34imm_pcrel:$SI),
+ "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
+}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp
index f29a7af1bdf1..dc739a2c7a4d 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp
@@ -660,8 +660,8 @@ PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV,
Type *I8Ty = Type::getInt8Ty(BaseMemI->getParent()->getContext());
Type *I8PtrTy =
- Type::getInt8PtrTy(BaseMemI->getParent()->getContext(),
- BasePtr->getType()->getPointerAddressSpace());
+ PointerType::get(BaseMemI->getParent()->getContext(),
+ BasePtr->getType()->getPointerAddressSpace());
bool IsConstantInc = false;
const SCEV *BasePtrIncSCEV = BasePtrSCEV->getStepRecurrence(*SE);
@@ -707,8 +707,8 @@ PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV,
BasicBlock *LoopPredecessor = L->getLoopPredecessor();
PHINode *NewPHI = PHINode::Create(I8PtrTy, HeaderLoopPredCount,
- getInstrName(BaseMemI, PHINodeNameSuffix),
- Header->getFirstNonPHI());
+ getInstrName(BaseMemI, PHINodeNameSuffix));
+ NewPHI->insertBefore(Header->getFirstNonPHIIt());
Value *BasePtrStart = SCEVE.expandCodeFor(BasePtrStartSCEV, I8PtrTy,
LoopPredecessor->getTerminator());
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
index 976effb96adc..9a3ca5a78293 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
@@ -31,22 +31,21 @@ using namespace llvm;
static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO,
AsmPrinter &AP) {
- const TargetMachine &TM = AP.TM;
- Mangler &Mang = TM.getObjFileLowering()->getMangler();
- const DataLayout &DL = AP.getDataLayout();
- MCContext &Ctx = AP.OutContext;
-
- SmallString<128> Name;
- if (!MO.isGlobal()) {
- assert(MO.isSymbol() && "Isn't a symbol reference");
- Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL);
- } else {
+ if (MO.isGlobal()) {
+ // Get the symbol from the global, accounting for XCOFF-specific
+ // intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol).
const GlobalValue *GV = MO.getGlobal();
- TM.getNameWithPrefix(Name, GV, Mang);
+ return AP.getSymbol(GV);
}
- MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
+ assert(MO.isSymbol() && "Isn't a symbol reference");
+
+ SmallString<128> Name;
+ const DataLayout &DL = AP.getDataLayout();
+ Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL);
+ MCContext &Ctx = AP.OutContext;
+ MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
return Sym;
}
@@ -55,7 +54,7 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
MCContext &Ctx = Printer.OutContext;
MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
- unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;
+ unsigned access = MO.getTargetFlags();
switch (access) {
case PPCII::MO_TPREL_LO:
@@ -74,19 +73,22 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
break;
case PPCII::MO_TLS:
- bool IsPCRel = (MO.getTargetFlags() & ~access) == PPCII::MO_PCREL_FLAG;
- RefKind = IsPCRel ? MCSymbolRefExpr::VK_PPC_TLS_PCREL
- : MCSymbolRefExpr::VK_PPC_TLS;
+ RefKind = MCSymbolRefExpr::VK_PPC_TLS;
+ break;
+ case PPCII::MO_TLS_PCREL_FLAG:
+ RefKind = MCSymbolRefExpr::VK_PPC_TLS_PCREL;
break;
}
+ const TargetMachine &TM = Printer.TM;
+
if (MO.getTargetFlags() == PPCII::MO_PLT)
RefKind = MCSymbolRefExpr::VK_PLT;
else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PCREL;
- else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG))
+ else if (MO.getTargetFlags() == PPCII::MO_GOT_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL;
- else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG))
+ else if (MO.getTargetFlags() == PPCII::MO_TPREL_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_TPREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL;
@@ -94,12 +96,21 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL;
+ else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG) {
+ assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
+ TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
+ // For the local-exec TLS model, we may generate the offset from the TLS
+ // base as an immediate operand (instead of using a TOC entry).
+ // Set the relocation type in case the result is used for purposes other
+ // than a TOC reference. In TOC reference cases, this result is discarded.
+ if (Model == TLSModel::LocalExec)
+ RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE;
+ }
const MachineInstr *MI = MO.getParent();
const MachineFunction *MF = MI->getMF();
const Module *M = MF->getFunction().getParent();
const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>());
- const TargetMachine &TM = Printer.TM;
unsigned MIOpcode = MI->getOpcode();
assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) &&
@@ -128,7 +139,9 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
Ctx);
// Subtract off the PIC base if required.
- if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) {
+ if (MO.getTargetFlags() == PPCII::MO_PIC_FLAG ||
+ MO.getTargetFlags() == PPCII::MO_PIC_HA_FLAG ||
+ MO.getTargetFlags() == PPCII::MO_PIC_LO_FLAG) {
const MachineFunction *MF = MO.getParent()->getParent()->getParent();
const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx);
@@ -138,9 +151,11 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
// Add ha16() / lo16() markers if required.
switch (access) {
case PPCII::MO_LO:
+ case PPCII::MO_PIC_LO_FLAG:
Expr = PPCMCExpr::createLo(Expr, Ctx);
break;
case PPCII::MO_HA:
+ case PPCII::MO_PIC_HA_FLAG:
Expr = PPCMCExpr::createHa(Expr, Ctx);
break;
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
index 410f4cba97c6..494e4b52a5b5 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -16,6 +16,15 @@
// removal, and it would miss cleanups made possible following VSX
// swap removal.
//
+// NOTE: We run the verifier after this pass in Asserts/Debug builds so it
+// is important to keep the code valid after transformations.
+// Common causes of errors stem from violating the contract specified
+// by kill flags. Whenever a transformation changes the live range of
+// a register, that register should be added to the work list using
+// addRegToUpdate(RegsToUpdate, <Reg>). Furthermore, if a transformation
+// is changing the definition of a register (i.e. removing the single
+// definition of the original vreg), it needs to provide a dummy
+// definition of that register using addDummyDef(<MBB>, <Reg>).
//===---------------------------------------------------------------------===//
#include "MCTargetDesc/PPCMCTargetDesc.h"
@@ -26,6 +35,7 @@
#include "PPCMachineFunctionInfo.h"
#include "PPCTargetMachine.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -93,6 +103,7 @@ struct PPCMIPeephole : public MachineFunctionPass {
const PPCInstrInfo *TII;
MachineFunction *MF;
MachineRegisterInfo *MRI;
+ LiveVariables *LV;
PPCMIPeephole() : MachineFunctionPass(ID) {
initializePPCMIPeepholePass(*PassRegistry::getPassRegistry());
@@ -102,7 +113,8 @@ private:
MachineDominatorTree *MDT;
MachinePostDominatorTree *MPDT;
MachineBlockFrequencyInfo *MBFI;
- uint64_t EntryFreq;
+ BlockFrequency EntryFreq;
+ SmallSet<Register, 16> RegsToUpdate;
// Initialize class variables.
void initialize(MachineFunction &MFParm);
@@ -114,16 +126,32 @@ private:
bool eliminateRedundantCompare();
bool eliminateRedundantTOCSaves(std::map<MachineInstr *, bool> &TOCSaves);
bool combineSEXTAndSHL(MachineInstr &MI, MachineInstr *&ToErase);
- bool emitRLDICWhenLoweringJumpTables(MachineInstr &MI);
+ bool emitRLDICWhenLoweringJumpTables(MachineInstr &MI,
+ MachineInstr *&ToErase);
void UpdateTOCSaves(std::map<MachineInstr *, bool> &TOCSaves,
MachineInstr *MI);
+ // A number of transformations will eliminate the definition of a register
+ // as all of its uses will be removed. However, this leaves a register
+ // without a definition for LiveVariables. Such transformations should
+ // use this function to provide a dummy definition of the register that
+ // will simply be removed by DCE.
+ void addDummyDef(MachineBasicBlock &MBB, MachineInstr *At, Register Reg) {
+ BuildMI(MBB, At, At->getDebugLoc(), TII->get(PPC::IMPLICIT_DEF), Reg);
+ }
+ void addRegToUpdateWithLine(Register Reg, int Line);
+ void convertUnprimedAccPHIs(const PPCInstrInfo *TII, MachineRegisterInfo *MRI,
+ SmallVectorImpl<MachineInstr *> &PHIs,
+ Register Dst);
+
public:
void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<LiveVariables>();
AU.addRequired<MachineDominatorTree>();
AU.addRequired<MachinePostDominatorTree>();
AU.addRequired<MachineBlockFrequencyInfo>();
+ AU.addPreserved<LiveVariables>();
AU.addPreserved<MachineDominatorTree>();
AU.addPreserved<MachinePostDominatorTree>();
AU.addPreserved<MachineBlockFrequencyInfo>();
@@ -140,10 +168,26 @@ public:
"TOC pointer used in a function using PC-Relative addressing!");
if (skipFunction(MF.getFunction()))
return false;
- return simplifyCode();
+ bool Changed = simplifyCode();
+#ifndef NDEBUG
+ if (Changed)
+ MF.verify(this, "Error in PowerPC MI Peephole optimization, compile with "
+ "-mllvm -disable-ppc-peephole");
+#endif
+ return Changed;
}
};
+#define addRegToUpdate(R) addRegToUpdateWithLine(R, __LINE__)
+void PPCMIPeephole::addRegToUpdateWithLine(Register Reg, int Line) {
+ if (!Register::isVirtualRegister(Reg))
+ return;
+ if (RegsToUpdate.insert(Reg).second)
+ LLVM_DEBUG(dbgs() << "Adding register: " << Register::virtReg2Index(Reg)
+ << " on line " << Line
+ << " for re-computation of kill flags\n");
+}
+
// Initialize class variables.
void PPCMIPeephole::initialize(MachineFunction &MFParm) {
MF = &MFParm;
@@ -151,8 +195,10 @@ void PPCMIPeephole::initialize(MachineFunction &MFParm) {
MDT = &getAnalysis<MachineDominatorTree>();
MPDT = &getAnalysis<MachinePostDominatorTree>();
MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
+ LV = &getAnalysis<LiveVariables>();
EntryFreq = MBFI->getEntryFreq();
TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo();
+ RegsToUpdate.clear();
LLVM_DEBUG(dbgs() << "*** PowerPC MI peephole pass ***\n\n");
LLVM_DEBUG(MF->dump());
}
@@ -254,7 +300,7 @@ void PPCMIPeephole::UpdateTOCSaves(
PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
MachineBasicBlock *Entry = &MF->front();
- uint64_t CurrBlockFreq = MBFI->getBlockFreq(MI->getParent()).getFrequency();
+ BlockFrequency CurrBlockFreq = MBFI->getBlockFreq(MI->getParent());
// If the block in which the TOC save resides is in a block that
// post-dominates Entry, or a block that is hotter than entry (keep in mind
@@ -338,10 +384,9 @@ static bool collectUnprimedAccPHIs(MachineRegisterInfo *MRI,
// primed accumulator PHI nodes. The list is traversed in reverse order to
// change all the PHI operands of a PHI node before changing the node itself.
// We keep a map to associate each changed PHI node to its non-changed form.
-static void convertUnprimedAccPHIs(const PPCInstrInfo *TII,
- MachineRegisterInfo *MRI,
- SmallVectorImpl<MachineInstr *> &PHIs,
- Register Dst) {
+void PPCMIPeephole::convertUnprimedAccPHIs(
+ const PPCInstrInfo *TII, MachineRegisterInfo *MRI,
+ SmallVectorImpl<MachineInstr *> &PHIs, Register Dst) {
DenseMap<MachineInstr *, MachineInstr *> ChangedPHIMap;
for (MachineInstr *PHI : llvm::reverse(PHIs)) {
SmallVector<std::pair<MachineOperand, MachineOperand>, 4> PHIOps;
@@ -390,8 +435,11 @@ static void convertUnprimedAccPHIs(const PPCInstrInfo *TII,
AccReg = MRI->createVirtualRegister(&PPC::ACCRCRegClass);
MachineInstrBuilder NewPHI = BuildMI(
*PHI->getParent(), PHI, PHI->getDebugLoc(), TII->get(PPC::PHI), AccReg);
- for (auto RegMBB : PHIOps)
+ for (auto RegMBB : PHIOps) {
NewPHI.add(RegMBB.first).add(RegMBB.second);
+ if (MRI->isSSA())
+ addRegToUpdate(RegMBB.first.getReg());
+ }
ChangedPHIMap[PHI] = NewPHI.getInstr();
LLVM_DEBUG(dbgs() << "Converting PHI: ");
LLVM_DEBUG(PHI->dump());
@@ -421,21 +469,51 @@ bool PPCMIPeephole::simplifyCode() {
if (MI.isDebugInstr())
continue;
- if (TII->convertToImmediateForm(MI)) {
- // We don't erase anything in case the def has other uses. Let DCE
- // remove it if it can be removed.
- LLVM_DEBUG(dbgs() << "Converted instruction to imm form: ");
- LLVM_DEBUG(MI.dump());
- NumConvertedToImmediateForm++;
- SomethingChanged = true;
- Simplified = true;
+ SmallSet<Register, 4> RRToRIRegsToUpdate;
+ if (!TII->convertToImmediateForm(MI, RRToRIRegsToUpdate))
continue;
- }
+ for (Register R : RRToRIRegsToUpdate)
+ addRegToUpdate(R);
+ // The updated instruction may now have new register operands.
+ // Conservatively add them to recompute the flags as well.
+ for (const MachineOperand &MO : MI.operands())
+ if (MO.isReg())
+ addRegToUpdate(MO.getReg());
+ // We don't erase anything in case the def has other uses. Let DCE
+ // remove it if it can be removed.
+ LLVM_DEBUG(dbgs() << "Converted instruction to imm form: ");
+ LLVM_DEBUG(MI.dump());
+ NumConvertedToImmediateForm++;
+ SomethingChanged = true;
+ Simplified = true;
+ continue;
}
}
} while (SomethingChanged && FixedPointRegToImm);
}
+ // Since we are deleting this instruction, we need to run LiveVariables
+ // on any of its definitions that are marked as needing an update since
+ // we can't run LiveVariables on a deleted register. This only needs
+ // to be done for defs since uses will have their own defining
+ // instructions so we won't be running LiveVariables on a deleted reg.
+ auto recomputeLVForDyingInstr = [&]() {
+ if (RegsToUpdate.empty())
+ return;
+ for (MachineOperand &MO : ToErase->operands()) {
+ if (!MO.isReg() || !MO.isDef() || !RegsToUpdate.count(MO.getReg()))
+ continue;
+ Register RegToUpdate = MO.getReg();
+ RegsToUpdate.erase(RegToUpdate);
+ // If some transformation has introduced an additional definition of
+ // this register (breaking SSA), we can safely convert this def to
+ // a def of an invalid register as the instruction is going away.
+ if (!MRI->getUniqueVRegDef(RegToUpdate))
+ MO.setReg(PPC::NoRegister);
+ LV->recomputeForSingleDefVirtReg(RegToUpdate);
+ }
+ };
+
for (MachineBasicBlock &MBB : *MF) {
for (MachineInstr &MI : MBB) {
@@ -444,6 +522,7 @@ bool PPCMIPeephole::simplifyCode() {
if (ToErase) {
LLVM_DEBUG(dbgs() << "Deleting instruction: ");
LLVM_DEBUG(ToErase->dump());
+ recomputeLVForDyingInstr();
ToErase->eraseFromParent();
ToErase = nullptr;
}
@@ -503,12 +582,16 @@ bool PPCMIPeephole::simplifyCode() {
if (!MI.getOperand(1).isImm() || MI.getOperand(1).getImm() != 0)
break;
Register MIDestReg = MI.getOperand(0).getReg();
+ bool Folded = false;
for (MachineInstr& UseMI : MRI->use_instructions(MIDestReg))
- Simplified |= TII->onlyFoldImmediate(UseMI, MI, MIDestReg);
+ Folded |= TII->onlyFoldImmediate(UseMI, MI, MIDestReg);
if (MRI->use_nodbg_empty(MIDestReg)) {
++NumLoadImmZeroFoldedAndRemoved;
ToErase = &MI;
}
+ if (Folded)
+ addRegToUpdate(MIDestReg);
+ Simplified |= Folded;
break;
}
case PPC::STW:
@@ -579,6 +662,7 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(MI.getOperand(1));
+ addRegToUpdate(MI.getOperand(1).getReg());
ToErase = &MI;
Simplified = true;
}
@@ -608,6 +692,7 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(MI.getOperand(1));
+ addRegToUpdate(MI.getOperand(1).getReg());
ToErase = &MI;
Simplified = true;
}
@@ -618,9 +703,13 @@ bool PPCMIPeephole::simplifyCode() {
else if ((Immed == 0 || Immed == 3) && DefImmed == 2) {
LLVM_DEBUG(dbgs() << "Optimizing swap/splat => splat: ");
LLVM_DEBUG(MI.dump());
+ addRegToUpdate(MI.getOperand(1).getReg());
+ addRegToUpdate(MI.getOperand(2).getReg());
MI.getOperand(1).setReg(DefReg1);
MI.getOperand(2).setReg(DefReg2);
MI.getOperand(3).setImm(3 - Immed);
+ addRegToUpdate(DefReg1);
+ addRegToUpdate(DefReg2);
Simplified = true;
}
@@ -629,9 +718,12 @@ bool PPCMIPeephole::simplifyCode() {
else if (Immed == 2 && DefImmed == 2) {
LLVM_DEBUG(dbgs() << "Optimizing swap/swap => copy: ");
LLVM_DEBUG(MI.dump());
+ addRegToUpdate(MI.getOperand(1).getReg());
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(DefMI->getOperand(1));
+ addRegToUpdate(DefMI->getOperand(0).getReg());
+ addRegToUpdate(DefMI->getOperand(1).getReg());
ToErase = &MI;
Simplified = true;
}
@@ -648,6 +740,7 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(MI.getOperand(1));
+ addRegToUpdate(MI.getOperand(1).getReg());
break;
}
// Splat fed by another splat - switch the output of the first
@@ -669,6 +762,7 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(MI.getOperand(1));
+ addRegToUpdate(MI.getOperand(1).getReg());
} else if ((Immed == 0 || Immed == 3 || Immed == 2) &&
TII->isLoadFromConstantPool(DefMI)) {
const Constant *C = TII->getConstantFromConstantPool(DefMI);
@@ -682,6 +776,7 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(MI.getOperand(1));
+ addRegToUpdate(MI.getOperand(1).getReg());
}
}
break;
@@ -724,6 +819,7 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(MI.getOperand(OpNo));
+ addRegToUpdate(MI.getOperand(OpNo).getReg());
ToErase = &MI;
Simplified = true;
}
@@ -747,7 +843,9 @@ bool PPCMIPeephole::simplifyCode() {
LLVM_DEBUG(dbgs() << "Changing splat immediate from " << SplatImm
<< " to " << NewElem << " in instruction: ");
LLVM_DEBUG(MI.dump());
- MI.getOperand(1).setReg(ShiftOp1);
+ addRegToUpdate(MI.getOperand(OpNo).getReg());
+ addRegToUpdate(ShiftOp1);
+ MI.getOperand(OpNo).setReg(ShiftOp1);
MI.getOperand(2).setImm(NewElem);
}
}
@@ -797,7 +895,9 @@ bool PPCMIPeephole::simplifyCode() {
LLVM_DEBUG(MI.dump());
LLVM_DEBUG(dbgs() << "Through instruction:\n");
LLVM_DEBUG(DefMI->dump());
- RoundInstr->eraseFromParent();
+ addRegToUpdate(ConvReg1);
+ addRegToUpdate(FRSPDefines);
+ ToErase = RoundInstr;
}
};
@@ -844,6 +944,13 @@ bool PPCMIPeephole::simplifyCode() {
else if (MIIs64Bit)
Opc = PPC::LHA8;
+ addRegToUpdate(NarrowReg);
+ addRegToUpdate(MI.getOperand(0).getReg());
+
+ // We are removing a definition of NarrowReg which will cause
+ // problems in AliveBlocks. Add an implicit def that will be
+ // removed so that AliveBlocks are updated correctly.
+ addDummyDef(MBB, &MI, NarrowReg);
LLVM_DEBUG(dbgs() << "Zero-extending load\n");
LLVM_DEBUG(SrcMI->dump());
LLVM_DEBUG(dbgs() << "and sign-extension\n");
@@ -909,6 +1016,13 @@ bool PPCMIPeephole::simplifyCode() {
if (!IsWordAligned && (Opc == PPC::LWA || Opc == PPC::LWA_32))
break;
+ addRegToUpdate(NarrowReg);
+ addRegToUpdate(MI.getOperand(0).getReg());
+
+ // We are removing a definition of NarrowReg which will cause
+ // problems in AliveBlocks. Add an implicit def that will be
+ // removed so that AliveBlocks are updated correctly.
+ addDummyDef(MBB, &MI, NarrowReg);
LLVM_DEBUG(dbgs() << "Zero-extending load\n");
LLVM_DEBUG(SrcMI->dump());
LLVM_DEBUG(dbgs() << "and sign-extension\n");
@@ -981,6 +1095,7 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.addReg(SrcReg);
+ addRegToUpdate(SrcReg);
ToErase = &MI;
Simplified = true;
NumEliminatedZExt++;
@@ -1071,23 +1186,96 @@ bool PPCMIPeephole::simplifyCode() {
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
MI.getOperand(0).getReg())
.add(Op1);
+ addRegToUpdate(Op1.getReg());
+ addRegToUpdate(Op2.getReg());
ToErase = &MI;
Simplified = true;
NumOptADDLIs++;
break;
}
case PPC::RLDICR: {
- Simplified |= emitRLDICWhenLoweringJumpTables(MI) ||
+ Simplified |= emitRLDICWhenLoweringJumpTables(MI, ToErase) ||
combineSEXTAndSHL(MI, ToErase);
break;
}
+ case PPC::ANDI_rec:
+ case PPC::ANDI8_rec:
+ case PPC::ANDIS_rec:
+ case PPC::ANDIS8_rec: {
+ Register TrueReg =
+ TRI->lookThruCopyLike(MI.getOperand(1).getReg(), MRI);
+ if (!TrueReg.isVirtual() || !MRI->hasOneNonDBGUse(TrueReg))
+ break;
+
+ MachineInstr *SrcMI = MRI->getVRegDef(TrueReg);
+ if (!SrcMI)
+ break;
+
+ unsigned SrcOpCode = SrcMI->getOpcode();
+ if (SrcOpCode != PPC::RLDICL && SrcOpCode != PPC::RLDICR)
+ break;
+
+ Register SrcReg, DstReg;
+ SrcReg = SrcMI->getOperand(1).getReg();
+ DstReg = MI.getOperand(1).getReg();
+ const TargetRegisterClass *SrcRC = MRI->getRegClassOrNull(SrcReg);
+ const TargetRegisterClass *DstRC = MRI->getRegClassOrNull(DstReg);
+ if (DstRC != SrcRC)
+ break;
+
+ uint64_t AndImm = MI.getOperand(2).getImm();
+ if (MI.getOpcode() == PPC::ANDIS_rec ||
+ MI.getOpcode() == PPC::ANDIS8_rec)
+ AndImm <<= 16;
+ uint64_t LZeroAndImm = llvm::countl_zero<uint64_t>(AndImm);
+ uint64_t RZeroAndImm = llvm::countr_zero<uint64_t>(AndImm);
+ uint64_t ImmSrc = SrcMI->getOperand(3).getImm();
+
+ // We can transfer `RLDICL/RLDICR + ANDI_rec/ANDIS_rec` to `ANDI_rec 0`
+ // if all bits to AND are already zero in the input.
+ bool PatternResultZero =
+ (SrcOpCode == PPC::RLDICL && (RZeroAndImm + ImmSrc > 63)) ||
+ (SrcOpCode == PPC::RLDICR && LZeroAndImm > ImmSrc);
+
+ // We can eliminate RLDICL/RLDICR if it's used to clear bits and all
+ // bits cleared will be ANDed with 0 by ANDI_rec/ANDIS_rec.
+ bool PatternRemoveRotate =
+ SrcMI->getOperand(2).getImm() == 0 &&
+ ((SrcOpCode == PPC::RLDICL && LZeroAndImm >= ImmSrc) ||
+ (SrcOpCode == PPC::RLDICR && (RZeroAndImm + ImmSrc > 63)));
+
+ if (!PatternResultZero && !PatternRemoveRotate)
+ break;
+
+ LLVM_DEBUG(dbgs() << "Combining pair: ");
+ LLVM_DEBUG(SrcMI->dump());
+ LLVM_DEBUG(MI.dump());
+ if (PatternResultZero)
+ MI.getOperand(2).setImm(0);
+ MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg());
+ LLVM_DEBUG(dbgs() << "To: ");
+ LLVM_DEBUG(MI.dump());
+ addRegToUpdate(MI.getOperand(1).getReg());
+ addRegToUpdate(SrcMI->getOperand(0).getReg());
+ Simplified = true;
+ break;
+ }
case PPC::RLWINM:
case PPC::RLWINM_rec:
case PPC::RLWINM8:
case PPC::RLWINM8_rec: {
+ // We might replace operand 1 of the instruction which will
+ // require we recompute kill flags for it.
+ Register OrigOp1Reg = MI.getOperand(1).isReg()
+ ? MI.getOperand(1).getReg()
+ : PPC::NoRegister;
Simplified = TII->combineRLWINM(MI, &ToErase);
- if (Simplified)
+ if (Simplified) {
+ addRegToUpdate(OrigOp1Reg);
+ if (MI.getOperand(1).isReg())
+ addRegToUpdate(MI.getOperand(1).getReg());
++NumRotatesCollapsed;
+ }
break;
}
// We will replace TD/TW/TDI/TWI with an unconditional trap if it will
@@ -1141,6 +1329,7 @@ bool PPCMIPeephole::simplifyCode() {
// If the last instruction was marked for elimination,
// remove it now.
if (ToErase) {
+ recomputeLVForDyingInstr();
ToErase->eraseFromParent();
ToErase = nullptr;
}
@@ -1158,6 +1347,13 @@ bool PPCMIPeephole::simplifyCode() {
// We try to eliminate redundant compare instruction.
Simplified |= eliminateRedundantCompare();
+ // If we have made any modifications and added any registers to the set of
+ // registers for which we need to update the kill flags, do so by recomputing
+ // LiveVariables for those registers.
+ for (Register Reg : RegsToUpdate) {
+ if (!MRI->reg_empty(Reg))
+ LV->recomputeForSingleDefVirtReg(Reg);
+ }
return Simplified;
}
@@ -1586,6 +1782,12 @@ bool PPCMIPeephole::eliminateRedundantCompare() {
LLVM_DEBUG(BI1->dump());
LLVM_DEBUG(CMPI2->dump());
LLVM_DEBUG(BI2->dump());
+ for (const MachineOperand &MO : CMPI1->operands())
+ if (MO.isReg())
+ addRegToUpdate(MO.getReg());
+ for (const MachineOperand &MO : CMPI2->operands())
+ if (MO.isReg())
+ addRegToUpdate(MO.getReg());
// We adjust opcode, predicates and immediate as we determined above.
if (NewOpCode != 0 && NewOpCode != CMPI1->getOpcode()) {
@@ -1623,6 +1825,7 @@ bool PPCMIPeephole::eliminateRedundantCompare() {
"We cannot support if an operand comes from this BB.");
unsigned SrcReg = getIncomingRegForBlock(Inst, MBBtoMoveCmp);
CMPI2->getOperand(I).setReg(SrcReg);
+ addRegToUpdate(SrcReg);
}
}
auto I = MachineBasicBlock::iterator(MBBtoMoveCmp->getFirstTerminator());
@@ -1635,14 +1838,20 @@ bool PPCMIPeephole::eliminateRedundantCompare() {
.addReg(BI1->getOperand(1).getReg()).addMBB(MBB1)
.addReg(BI2->getOperand(1).getReg()).addMBB(MBBtoMoveCmp);
BI2->getOperand(1).setReg(NewVReg);
+ addRegToUpdate(NewVReg);
}
else {
// We finally eliminate compare instruction in MBB2.
+ // We do not need to treat CMPI2 specially here in terms of re-computing
+ // live variables even though it is being deleted because:
+ // - It defines a register that has a single use (already checked in
+ // eligibleForCompareElimination())
+ // - The only user (BI2) is no longer using it so the register is dead (no
+ // def, no uses)
+ // - We do not attempt to recompute live variables for dead registers
BI2->getOperand(1).setReg(BI1->getOperand(1).getReg());
CMPI2->eraseFromParent();
}
- BI2->getOperand(1).setIsKill(true);
- BI1->getOperand(1).setIsKill(false);
LLVM_DEBUG(dbgs() << "into a compare and two branches:\n");
LLVM_DEBUG(CMPI1->dump());
@@ -1654,7 +1863,6 @@ bool PPCMIPeephole::eliminateRedundantCompare() {
<< " to handle partial redundancy.\n");
LLVM_DEBUG(CMPI2->dump());
}
-
Simplified = true;
}
@@ -1664,7 +1872,8 @@ bool PPCMIPeephole::eliminateRedundantCompare() {
// We miss the opportunity to emit an RLDIC when lowering jump tables
// since ISEL sees only a single basic block. When selecting, the clear
// and shift left will be in different blocks.
-bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI) {
+bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI,
+ MachineInstr *&ToErase) {
if (MI.getOpcode() != PPC::RLDICR)
return false;
@@ -1710,8 +1919,8 @@ bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI) {
MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg());
MI.getOperand(2).setImm(NewSH);
MI.getOperand(3).setImm(NewMB);
- MI.getOperand(1).setIsKill(SrcMI->getOperand(1).isKill());
- SrcMI->getOperand(1).setIsKill(false);
+ addRegToUpdate(MI.getOperand(1).getReg());
+ addRegToUpdate(SrcMI->getOperand(0).getReg());
LLVM_DEBUG(dbgs() << "To: ");
LLVM_DEBUG(MI.dump());
@@ -1720,7 +1929,7 @@ bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI) {
if (MRI->use_nodbg_empty(SrcReg)) {
assert(!SrcMI->hasImplicitDef() &&
"Not expecting an implicit def with this instr.");
- SrcMI->eraseFromParent();
+ ToErase = SrcMI;
}
return true;
}
@@ -1793,8 +2002,11 @@ bool PPCMIPeephole::combineSEXTAndSHL(MachineInstr &MI,
LLVM_DEBUG(NewInstr->dump());
++NumEXTSWAndSLDICombined;
ToErase = &MI;
- // SrcMI, which is extsw, is of no use now, erase it.
- SrcMI->eraseFromParent();
+ // SrcMI, which is extsw, is of no use now, but we don't erase it here so we
+ // can recompute its kill flags. We run DCE immediately after this pass
+ // to clean up dead instructions such as this.
+ addRegToUpdate(NewInstr->getOperand(1).getReg());
+ addRegToUpdate(SrcMI->getOperand(0).getReg());
return true;
}
@@ -1805,6 +2017,7 @@ INITIALIZE_PASS_BEGIN(PPCMIPeephole, DEBUG_TYPE,
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
+INITIALIZE_PASS_DEPENDENCY(LiveVariables)
INITIALIZE_PASS_END(PPCMIPeephole, DEBUG_TYPE,
"PowerPC MI Peephole Optimization", false, false)
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp
index bf1c39a3a3a2..7ad6ef8c3928 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp
@@ -286,7 +286,7 @@ static bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
namespace llvm {
-std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation () {
+std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation() {
return createMacroFusionDAGMutation(shouldScheduleAdjacent);
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp
new file mode 100644
index 000000000000..d9465e86d896
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp
@@ -0,0 +1,365 @@
+//===-- PPCMergeStringPool.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This transformation tries to merge the strings in the module into one pool
+// of strings. The idea is to reduce the number of TOC entries in the module so
+// that instead of having one TOC entry for each string there is only one global
+// TOC entry and all of the strings are referenced off of that one entry plus
+// an offset.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPC.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/DomTreeUpdater.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/LoopIterator.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueSymbolTable.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+
+#define DEBUG_TYPE "ppc-merge-strings"
+
+STATISTIC(NumPooledStrings, "Number of Strings Pooled");
+
+using namespace llvm;
+
+static cl::opt<unsigned>
+ MaxStringsPooled("ppc-max-strings-pooled", cl::Hidden, cl::init(-1),
+ cl::desc("Maximum Number of Strings to Pool."));
+
+static cl::opt<unsigned>
+ MinStringsBeforePool("ppc-min-strings-before-pool", cl::Hidden, cl::init(2),
+ cl::desc("Minimum number of string candidates before "
+ "pooling is considered."));
+
+namespace {
+struct {
+ bool operator()(const GlobalVariable *LHS, const GlobalVariable *RHS) const {
+ // First priority is alignment.
+ // If elements are sorted in terms of alignment then there won't be an
+ // issue with incorrect alignment that would require padding.
+ Align LHSAlign = LHS->getAlign().valueOrOne();
+ Align RHSAlign = RHS->getAlign().valueOrOne();
+ if (LHSAlign > RHSAlign)
+ return true;
+ else if (LHSAlign < RHSAlign)
+ return false;
+
+ // Next priority is the number of uses.
+ // Smaller offsets are easier to materialize because materializing a large
+ // offset may require more than one instruction. (ie addis, addi).
+ if (LHS->getNumUses() > RHS->getNumUses())
+ return true;
+ else if (LHS->getNumUses() < RHS->getNumUses())
+ return false;
+
+ const Constant *ConstLHS = LHS->getInitializer();
+ const ConstantDataSequential *ConstDataLHS =
+ dyn_cast<ConstantDataSequential>(ConstLHS);
+ unsigned LHSSize =
+ ConstDataLHS->getNumElements() * ConstDataLHS->getElementByteSize();
+ const Constant *ConstRHS = RHS->getInitializer();
+ const ConstantDataSequential *ConstDataRHS =
+ dyn_cast<ConstantDataSequential>(ConstRHS);
+ unsigned RHSSize =
+ ConstDataRHS->getNumElements() * ConstDataRHS->getElementByteSize();
+
+ // Finally smaller constants should go first. This is, again, trying to
+ // minimize the offsets into the final struct.
+ return LHSSize < RHSSize;
+ }
+} CompareConstants;
+
+class PPCMergeStringPool : public ModulePass {
+public:
+ static char ID;
+ PPCMergeStringPool() : ModulePass(ID) {}
+
+ bool runOnModule(Module &M) override { return mergeModuleStringPool(M); }
+
+ StringRef getPassName() const override { return "PPC Merge String Pool"; }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addPreserved<DominatorTreeWrapperPass>();
+ AU.addPreserved<LoopInfoWrapperPass>();
+ AU.addPreserved<ScalarEvolutionWrapperPass>();
+ AU.addPreserved<SCEVAAWrapperPass>();
+ }
+
+private:
+ // Globals in a Module are already unique so a set is not required and a
+ // vector will do.
+ std::vector<GlobalVariable *> MergeableStrings;
+ Align MaxAlignment;
+ Type *PooledStructType;
+ LLVMContext *Context;
+ void collectCandidateConstants(Module &M);
+ bool mergeModuleStringPool(Module &M);
+ void replaceUsesWithGEP(GlobalVariable *GlobalToReplace, GlobalVariable *GPool,
+ unsigned ElementIndex);
+};
+
+
+// In order for a constant to be pooled we need to be able to replace all of
+// the uses for that constant. This function checks all of the uses to make
+// sure that they can be replaced.
+static bool hasReplaceableUsers(GlobalVariable &GV) {
+ for (User *CurrentUser : GV.users()) {
+ // Instruction users are always valid.
+ if (isa<Instruction>(CurrentUser))
+ continue;
+
+ // We cannot replace GlobalValue users because they are not just nodes
+ // in IR. To replace a user like this we would need to create a new
+ // GlobalValue with the replacement and then try to delete the original
+ // GlobalValue. Deleting the original would only happen if it has no other
+ // uses.
+ if (isa<GlobalValue>(CurrentUser))
+ return false;
+
+ // We only support Instruction and Constant users.
+ if (!isa<Constant>(CurrentUser))
+ return false;
+ }
+
+ return true;
+}
+
+// Run through all of the constants in the module and determine if they are
+// valid candidates to be merged into the string pool. Valid candidates will
+// be added to MergeableStrings.
+void PPCMergeStringPool::collectCandidateConstants(Module &M) {
+ SmallVector<GlobalValue *, 4> UsedV;
+ collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false);
+ SmallVector<GlobalValue *, 4> UsedVCompiler;
+ collectUsedGlobalVariables(M, UsedVCompiler, /*CompilerUsed=*/true);
+ // Combine all of the Global Variables marked as used into a SmallPtrSet for
+ // faster lookup inside the loop.
+ SmallPtrSet<GlobalValue *, 8> AllUsedGlobals;
+ AllUsedGlobals.insert(UsedV.begin(), UsedV.end());
+ AllUsedGlobals.insert(UsedVCompiler.begin(), UsedVCompiler.end());
+
+ for (GlobalVariable &Global : M.globals()) {
+ LLVM_DEBUG(dbgs() << "Looking at global:");
+ LLVM_DEBUG(Global.dump());
+ LLVM_DEBUG(dbgs() << "isConstant() " << Global.isConstant() << "\n");
+ LLVM_DEBUG(dbgs() << "hasInitializer() " << Global.hasInitializer()
+ << "\n");
+
+ // We can only pool constants.
+ if (!Global.isConstant() || !Global.hasInitializer())
+ continue;
+
+ // If a global constant has a section we do not try to pool it because
+ // there is no guarantee that other constants will also be in the same
+ // section. Trying to pool constants from different sections (or no
+ // section) means that the pool has to be in multiple sections at the same
+ // time.
+ if (Global.hasSection())
+ continue;
+
+ // Do not pool constants with metadata because we should not add metadata
+ // to the pool when that metadata refers to a single constant in the pool.
+ if (Global.hasMetadata())
+ continue;
+
+ ConstantDataSequential *ConstData =
+ dyn_cast<ConstantDataSequential>(Global.getInitializer());
+
+ // If the constant is undef then ConstData will be null.
+ if (!ConstData)
+ continue;
+
+ // Do not pool globals that are part of llvm.used or llvm.compiler.end.
+ if (AllUsedGlobals.contains(&Global))
+ continue;
+
+ if (!hasReplaceableUsers(Global))
+ continue;
+
+ Align AlignOfGlobal = Global.getAlign().valueOrOne();
+
+ // TODO: At this point do not allow over-aligned types. Adding a type
+ // with larger alignment may lose the larger alignment once it is
+ // added to the struct.
+ // Fix this in a future patch.
+ if (AlignOfGlobal.value() > ConstData->getElementByteSize())
+ continue;
+
+ // Make sure that the global is only visible inside the compilation unit.
+ if (Global.getLinkage() != GlobalValue::PrivateLinkage &&
+ Global.getLinkage() != GlobalValue::InternalLinkage)
+ continue;
+
+ LLVM_DEBUG(dbgs() << "Constant data of Global: ");
+ LLVM_DEBUG(ConstData->dump());
+ LLVM_DEBUG(dbgs() << "\n\n");
+
+ MergeableStrings.push_back(&Global);
+ if (MaxAlignment < AlignOfGlobal)
+ MaxAlignment = AlignOfGlobal;
+
+ // If we have already reached the maximum number of pooled strings then
+ // there is no point in looking for more.
+ if (MergeableStrings.size() >= MaxStringsPooled)
+ break;
+ }
+}
+
+bool PPCMergeStringPool::mergeModuleStringPool(Module &M) {
+
+ LLVM_DEBUG(dbgs() << "Merging string pool for module: " << M.getName()
+ << "\n");
+ LLVM_DEBUG(dbgs() << "Number of globals is: " << M.global_size() << "\n");
+
+ collectCandidateConstants(M);
+
+ // If we have too few constants in the module that are merge candidates we
+ // will skip doing the merging.
+ if (MergeableStrings.size() < MinStringsBeforePool)
+ return false;
+
+ // Sort the global constants to make access more efficient.
+ std::sort(MergeableStrings.begin(), MergeableStrings.end(), CompareConstants);
+
+ SmallVector<Constant *> ConstantsInStruct;
+ for (GlobalVariable *GV : MergeableStrings)
+ ConstantsInStruct.push_back(GV->getInitializer());
+
+ // Use an anonymous struct to pool the strings.
+ // TODO: This pass uses a single anonymous struct for all of the pooled
+ // entries. This may cause a performance issue in the situation where
+ // computing the offset requires two instructions (addis, addi). For the
+ // future we may want to split this into multiple structs.
+ Constant *ConstantPool = ConstantStruct::getAnon(ConstantsInStruct);
+ PooledStructType = ConstantPool->getType();
+
+ // The GlobalVariable constructor calls
+ // MM->insertGlobalVariable(PooledGlobal).
+ GlobalVariable *PooledGlobal =
+ new GlobalVariable(M, PooledStructType,
+ /* isConstant */ true, GlobalValue::PrivateLinkage,
+ ConstantPool, "__ModuleStringPool");
+ PooledGlobal->setAlignment(MaxAlignment);
+
+ LLVM_DEBUG(dbgs() << "Constructing global variable for string pool: ");
+ LLVM_DEBUG(PooledGlobal->dump());
+
+ Context = &M.getContext();
+ size_t ElementIndex = 0;
+ for (GlobalVariable *GV : MergeableStrings) {
+
+ LLVM_DEBUG(dbgs() << "The global:\n");
+ LLVM_DEBUG(GV->dump());
+ LLVM_DEBUG(dbgs() << "Has " << GV->getNumUses() << " uses.\n");
+
+ // Access to the pooled constant strings require an offset. Add a GEP
+ // before every use in order to compute this offset.
+ replaceUsesWithGEP(GV, PooledGlobal, ElementIndex);
+
+ // This GV has no more uses so we can erase it.
+ if (GV->use_empty())
+ GV->eraseFromParent();
+
+ NumPooledStrings++;
+ ElementIndex++;
+ }
+ return true;
+}
+
+static bool userHasOperand(User *TheUser, GlobalVariable *GVOperand) {
+ for (Value *Op : TheUser->operands())
+ if (Op == GVOperand)
+ return true;
+ return false;
+}
+
+// For pooled strings we need to add the offset into the pool for each string.
+// This is done by adding a Get Element Pointer (GEP) before each user. This
+// function adds the GEP.
+void PPCMergeStringPool::replaceUsesWithGEP(GlobalVariable *GlobalToReplace,
+ GlobalVariable *GPool,
+ unsigned ElementIndex) {
+ SmallVector<Value *, 2> Indices;
+ Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), 0));
+ Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), ElementIndex));
+
+ // Need to save a temporary copy of each user list because we remove uses
+ // as we replace them.
+ SmallVector<User *> Users;
+ for (User *CurrentUser : GlobalToReplace->users())
+ Users.push_back(CurrentUser);
+
+ for (User *CurrentUser : Users) {
+ Instruction *UserInstruction = dyn_cast<Instruction>(CurrentUser);
+ Constant *UserConstant = dyn_cast<Constant>(CurrentUser);
+
+ // At this point we expect that the user is either an instruction or a
+ // constant.
+ assert((UserConstant || UserInstruction) &&
+ "Expected the user to be an instruction or a constant.");
+
+ // The user was not found so it must have been replaced earlier.
+ if (!userHasOperand(CurrentUser, GlobalToReplace))
+ continue;
+
+ // We cannot replace operands in globals so we ignore those.
+ if (isa<GlobalValue>(CurrentUser))
+ continue;
+
+ if (!UserInstruction) {
+ // User is a constant type.
+ Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr(
+ PooledStructType, GPool, Indices);
+ UserConstant->handleOperandChange(GlobalToReplace, ConstGEP);
+ continue;
+ }
+
+ if (PHINode *UserPHI = dyn_cast<PHINode>(UserInstruction)) {
+ // GEP instructions cannot be added before PHI nodes.
+ // With getInBoundsGetElementPtr we create the GEP and then replace it
+ // inline into the PHI.
+ Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr(
+ PooledStructType, GPool, Indices);
+ UserPHI->replaceUsesOfWith(GlobalToReplace, ConstGEP);
+ continue;
+ }
+ // The user is a valid instruction that is not a PHINode.
+ GetElementPtrInst *GEPInst =
+ GetElementPtrInst::Create(PooledStructType, GPool, Indices);
+ GEPInst->insertBefore(UserInstruction);
+
+ LLVM_DEBUG(dbgs() << "Inserting GEP before:\n");
+ LLVM_DEBUG(UserInstruction->dump());
+
+ LLVM_DEBUG(dbgs() << "Replacing this global:\n");
+ LLVM_DEBUG(GlobalToReplace->dump());
+ LLVM_DEBUG(dbgs() << "with this:\n");
+ LLVM_DEBUG(GEPInst->dump());
+
+ // After the GEP is inserted the GV can be replaced.
+ CurrentUser->replaceUsesOfWith(GlobalToReplace, GEPInst);
+ }
+}
+
+} // namespace
+
+char PPCMergeStringPool::ID = 0;
+
+INITIALIZE_PASS(PPCMergeStringPool, DEBUG_TYPE, "PPC Merge String Pool", false,
+ false)
+
+ModulePass *llvm::createPPCMergeStringPoolPass() {
+ return new PPCMergeStringPool();
+}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
index 6f1b34843343..6e3bf26a598a 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
@@ -14,7 +14,6 @@
#include "PPC.h"
#include "PPCInstrInfo.h"
#include "PPCSubtarget.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
@@ -240,7 +239,7 @@ static bool hasPCRelativeForm(MachineInstr &Use) {
return false;
// Finally return true only if the GOT flag is present.
- return (SymbolOp.getTargetFlags() & PPCII::MO_GOT_FLAG);
+ return PPCInstrInfo::hasGOTFlag(SymbolOp.getTargetFlags());
}
bool addLinkerOpt(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) {
@@ -495,7 +494,8 @@ static bool hasPCRelativeForm(MachineInstr &Use) {
}
}
MachineInstr *DefMIToErase = nullptr;
- if (TII->convertToImmediateForm(MI, &DefMIToErase)) {
+ SmallSet<Register, 4> UpdatedRegs;
+ if (TII->convertToImmediateForm(MI, UpdatedRegs, &DefMIToErase)) {
Changed = true;
NumRRConvertedInPreEmit++;
LLVM_DEBUG(dbgs() << "Converted instruction to imm form: ");
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
index 11dbbce42f61..36b8a24ba502 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -172,58 +172,6 @@ public:
Register getBaseRegister(const MachineFunction &MF) const;
bool hasBasePointer(const MachineFunction &MF) const;
- /// stripRegisterPrefix - This method strips the character prefix from a
- /// register name so that only the number is left. Used by for linux asm.
- static const char *stripRegisterPrefix(const char *RegName) {
- switch (RegName[0]) {
- case 'a':
- if (RegName[1] == 'c' && RegName[2] == 'c')
- return RegName + 3;
- break;
- case 'f':
- if (RegName[1] == 'p')
- return RegName + 2;
- [[fallthrough]];
- case 'r':
- case 'v':
- if (RegName[1] == 's') {
- if (RegName[2] == 'p')
- return RegName + 3;
- return RegName + 2;
- }
- return RegName + 1;
- case 'c':
- if (RegName[1] == 'r')
- return RegName + 2;
- break;
- case 'w':
- // For wacc and wacc_hi
- if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') {
- if (RegName[4] == '_')
- return RegName + 7;
- else
- return RegName + 4;
- }
- break;
- case 'd':
- // For dmr, dmrp, dmrrow, dmrrowp
- if (RegName[1] == 'm' && RegName[2] == 'r') {
- if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' &&
- RegName[6] == 'p')
- return RegName + 7;
- else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w')
- return RegName + 6;
- else if (RegName[3] == 'p')
- return RegName + 4;
- else
- return RegName + 3;
- }
- break;
- }
-
- return RegName;
- }
-
bool isNonallocatableRegisterCalleeSave(MCRegister Reg) const override {
return Reg == PPC::LR || Reg == PPC::LR8;
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 6151faf403aa..375e63654db1 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -798,6 +798,7 @@ def directbrtarget : Operand<OtherVT> {
def absdirectbrtarget : Operand<OtherVT> {
let PrintMethod = "printAbsBranchOperand";
let EncoderMethod = "getAbsDirectBrEncoding";
+ let DecoderMethod = "decodeDirectBrTarget";
let ParserMatchClass = PPCDirectBrAsmOperand;
}
def PPCCondBrAsmOperand : AsmOperandClass {
@@ -814,6 +815,7 @@ def condbrtarget : Operand<OtherVT> {
def abscondbrtarget : Operand<OtherVT> {
let PrintMethod = "printAbsBranchOperand";
let EncoderMethod = "getAbsCondBrEncoding";
+ let DecoderMethod = "decodeCondBrTarget";
let ParserMatchClass = PPCCondBrAsmOperand;
}
def calltarget : Operand<iPTR> {
@@ -826,6 +828,7 @@ def calltarget : Operand<iPTR> {
def abscalltarget : Operand<iPTR> {
let PrintMethod = "printAbsBranchOperand";
let EncoderMethod = "getAbsDirectBrEncoding";
+ let DecoderMethod = "decodeDirectBrTarget";
let ParserMatchClass = PPCDirectBrAsmOperand;
}
def PPCCRBitMaskOperand : AsmOperandClass {
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td
index 25be37718af2..f922f8a7d985 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td
@@ -29,8 +29,8 @@ def P10Model : SchedMachineModel {
let LoopMicroOpBufferSize = 60;
let CompleteModel = 1;
- // Do not support SPE (Signal Procesing Engine) on Power 10.
- let UnsupportedFeatures = [HasSPE, IsE500, IsBookE, IsISAFuture];
+ // Power 10 does not support instructions from SPE, Book E and HTM.
+ let UnsupportedFeatures = [HasSPE, IsE500, IsBookE, IsISAFuture, HasHTM];
}
let SchedModel = P10Model in {
@@ -87,27 +87,27 @@ let SchedModel = P10Model in {
}
def P10W_BF_22C : SchedWriteRes<[P10_BF]> {
- let ResourceCycles = [ 5 ];
+ let ReleaseAtCycles = [ 5 ];
let Latency = 22;
}
def P10W_BF_24C : SchedWriteRes<[P10_BF]> {
- let ResourceCycles = [ 8 ];
+ let ReleaseAtCycles = [ 8 ];
let Latency = 24;
}
def P10W_BF_26C : SchedWriteRes<[P10_BF]> {
- let ResourceCycles = [ 5 ];
+ let ReleaseAtCycles = [ 5 ];
let Latency = 26;
}
def P10W_BF_27C : SchedWriteRes<[P10_BF]> {
- let ResourceCycles = [ 7 ];
+ let ReleaseAtCycles = [ 7 ];
let Latency = 27;
}
def P10W_BF_36C : SchedWriteRes<[P10_BF]> {
- let ResourceCycles = [ 10 ];
+ let ReleaseAtCycles = [ 10 ];
let Latency = 36;
}
@@ -128,134 +128,134 @@ let SchedModel = P10Model in {
}
def P10W_DF_24C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 16 ];
+ let ReleaseAtCycles = [ 16 ];
let Latency = 24;
}
def P10W_DF_25C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 17 ];
+ let ReleaseAtCycles = [ 17 ];
let Latency = 25;
}
def P10W_DF_26C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 18 ];
+ let ReleaseAtCycles = [ 18 ];
let Latency = 26;
}
def P10W_DF_32C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 22 ];
+ let ReleaseAtCycles = [ 22 ];
let Latency = 32;
}
def P10W_DF_33C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 25 ];
+ let ReleaseAtCycles = [ 25 ];
let Latency = 33;
}
def P10W_DF_34C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 25 ];
+ let ReleaseAtCycles = [ 25 ];
let Latency = 34;
}
def P10W_DF_38C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 30 ];
+ let ReleaseAtCycles = [ 30 ];
let Latency = 38;
}
def P10W_DF_40C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 17 ];
+ let ReleaseAtCycles = [ 17 ];
let Latency = 40;
}
def P10W_DF_43C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 34 ];
+ let ReleaseAtCycles = [ 34 ];
let Latency = 43;
}
def P10W_DF_59C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 49 ];
+ let ReleaseAtCycles = [ 49 ];
let Latency = 59;
}
def P10W_DF_61C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 12 ];
+ let ReleaseAtCycles = [ 12 ];
let Latency = 61;
}
def P10W_DF_68C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 15 ];
+ let ReleaseAtCycles = [ 15 ];
let Latency = 68;
}
def P10W_DF_77C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 67 ];
+ let ReleaseAtCycles = [ 67 ];
let Latency = 77;
}
def P10W_DF_87C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 12 ];
+ let ReleaseAtCycles = [ 12 ];
let Latency = 87;
}
def P10W_DF_100C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 32 ];
+ let ReleaseAtCycles = [ 32 ];
let Latency = 100;
}
def P10W_DF_174C : SchedWriteRes<[P10_DF]> {
- let ResourceCycles = [ 33 ];
+ let ReleaseAtCycles = [ 33 ];
let Latency = 174;
}
// A DV pipeline may take from 20 to 83 cycles to complete.
// Some DV operations may keep the pipeline busy for up to 33 cycles.
def P10W_DV_20C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 10 ];
+ let ReleaseAtCycles = [ 10 ];
let Latency = 20;
}
def P10W_DV_25C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 10 ];
+ let ReleaseAtCycles = [ 10 ];
let Latency = 25;
}
def P10W_DV_27C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 10 ];
+ let ReleaseAtCycles = [ 10 ];
let Latency = 27;
}
def P10W_DV_41C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 10 ];
+ let ReleaseAtCycles = [ 10 ];
let Latency = 41;
}
def P10W_DV_43C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 21 ];
+ let ReleaseAtCycles = [ 21 ];
let Latency = 43;
}
def P10W_DV_47C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 21 ];
+ let ReleaseAtCycles = [ 21 ];
let Latency = 47;
}
def P10W_DV_54C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 33 ];
+ let ReleaseAtCycles = [ 33 ];
let Latency = 54;
}
def P10W_DV_60C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 33 ];
+ let ReleaseAtCycles = [ 33 ];
let Latency = 60;
}
def P10W_DV_75C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 21 ];
+ let ReleaseAtCycles = [ 21 ];
let Latency = 75;
}
def P10W_DV_83C : SchedWriteRes<[P10_DV]> {
- let ResourceCycles = [ 33 ];
+ let ReleaseAtCycles = [ 33 ];
let Latency = 83;
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td
index 5a8c1eb2b837..93399e5ddbca 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td
@@ -6,383 +6,10 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the itinerary class data for the POWER7 processor.
+// This file defines the SchedModel for the POWER7 processor.
//
//===----------------------------------------------------------------------===//
-// Primary reference:
-// IBM POWER7 multicore server processor
-// B. Sinharoy, et al.
-// IBM J. Res. & Dev. (55) 3. May/June 2011.
-
-// Scheduling for the P7 involves tracking two types of resources:
-// 1. The dispatch bundle slots
-// 2. The functional unit resources
-
-// Dispatch units:
-def P7_DU1 : FuncUnit;
-def P7_DU2 : FuncUnit;
-def P7_DU3 : FuncUnit;
-def P7_DU4 : FuncUnit;
-def P7_DU5 : FuncUnit;
-def P7_DU6 : FuncUnit;
-
-def P7_LS1 : FuncUnit; // Load/Store pipeline 1
-def P7_LS2 : FuncUnit; // Load/Store pipeline 2
-
-def P7_FX1 : FuncUnit; // FX pipeline 1
-def P7_FX2 : FuncUnit; // FX pipeline 2
-
-// VS pipeline 1 (vector integer ops. always here)
-def P7_VS1 : FuncUnit; // VS pipeline 1
-// VS pipeline 2 (128-bit stores and perms. here)
-def P7_VS2 : FuncUnit; // VS pipeline 2
-
-def P7_CRU : FuncUnit; // CR unit (CR logicals and move-from-SPRs)
-def P7_BRU : FuncUnit; // BR unit
-
-// Notes:
-// Each LSU pipeline can also execute FX add and logical instructions.
-// Each LSU pipeline can complete a load or store in one cycle.
-//
-// Each store is broken into two parts, AGEN goes to the LSU while a
-// "data steering" op. goes to the FXU or VSU.
-//
-// FX loads have a two cycle load-to-use latency (so one "bubble" cycle).
-// VSU loads have a three cycle load-to-use latency (so two "bubble" cycle).
-//
-// Frequent FX ops. take only one cycle and results can be used again in the
-// next cycle (there is a self-bypass). Getting results from the other FX
-// pipeline takes an additional cycle.
-//
-// The VSU XS is similar to the POWER6, but with a pipeline length of 2 cycles
-// (instead of 3 cycles on the POWER6). VSU XS handles vector FX-style ops.
-// Dispatch of an instruction to VS1 that uses four single prec. inputs
-// (either to a float or XC op). prevents dispatch in that cycle to VS2 of any
-// floating point instruction.
-//
-// The VSU PM is similar to the POWER6, but with a pipeline length of 3 cycles
-// (instead of 4 cycles on the POWER6). vsel is handled by the PM pipeline
-// (unlike on the POWER6).
-//
-// FMA from the VSUs can forward results in 6 cycles. VS1 XS and vector FP
-// share the same write-back, and have a 5-cycle latency difference, so the
-// IFU/IDU will not dispatch an XS instructon 5 cycles after a vector FP
-// op. has been dispatched to VS1.
-//
-// Three cycles after an L1 cache hit, a dependent VSU instruction can issue.
-//
-// Instruction dispatch groups have (at most) four non-branch instructions, and
-// two branches. Unlike on the POWER4/5, a branch does not automatically
-// end the dispatch group, but a second branch must be the last in the group.
-
-def P7Itineraries : ProcessorItineraries<
- [P7_DU1, P7_DU2, P7_DU3, P7_DU4, P7_DU5, P7_DU6,
- P7_LS1, P7_LS2, P7_FX1, P7_FX2, P7_VS1, P7_VS2, P7_CRU, P7_BRU], [], [
- InstrItinData<IIC_IntSimple , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2,
- P7_LS1, P7_LS2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntGeneral , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntISEL, [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_FX1, P7_FX2], 0>,
- InstrStage<1, [P7_BRU]>],
- [1, 1, 1, 1]>,
- InstrItinData<IIC_IntCompare , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- // FIXME: Add record-form itinerary data.
- InstrItinData<IIC_IntDivW , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<36, [P7_FX1, P7_FX2]>],
- [36, 1, 1]>,
- InstrItinData<IIC_IntDivD , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<68, [P7_FX1, P7_FX2]>],
- [68, 1, 1]>,
- InstrItinData<IIC_IntMulHW , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntMulHWU , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntMulHD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntMulLI , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntRotate , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntRotateD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntRotateDI , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntShift , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntTrapW , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1]>,
- InstrItinData<IIC_IntTrapD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1]>,
- InstrItinData<IIC_BrB , [InstrStage<1, [P7_DU5, P7_DU6], 0>,
- InstrStage<1, [P7_BRU]>],
- [3, 1, 1]>,
- InstrItinData<IIC_BrCR , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_CRU]>],
- [3, 1, 1]>,
- InstrItinData<IIC_BrMCR , [InstrStage<1, [P7_DU5, P7_DU6], 0>,
- InstrStage<1, [P7_BRU]>],
- [3, 1, 1]>,
- InstrItinData<IIC_BrMCRX , [InstrStage<1, [P7_DU5, P7_DU6], 0>,
- InstrStage<1, [P7_BRU]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLoad , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_LdStLoadUpd , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [2, 2, 1, 1]>,
- InstrItinData<IIC_LdStLoadUpdX, [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_LdStLDU , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [2, 2, 1, 1]>,
- InstrItinData<IIC_LdStLDUX , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLFD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLVecX , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLFDU , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLFDUX , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLHA , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLHAU , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [4, 4, 1, 1]>,
- InstrItinData<IIC_LdStLHAUX , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [4, 4, 1, 1]>,
- InstrItinData<IIC_LdStLWA , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLWARX, [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLDARX, [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLMW , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_LdStStore , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTU , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [2, 1, 1, 1]>,
- InstrItinData<IIC_LdStSTUX , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2]>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [2, 1, 1, 1]>,
- InstrItinData<IIC_LdStSTFD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTFDU , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_FX1, P7_FX2], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [2, 1, 1, 1]>,
- InstrItinData<IIC_LdStSTVEBX , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2], 0>,
- InstrStage<1, [P7_VS2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTDCX , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTWCX , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_LS1, P7_LS2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_BrMCRX , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_DU2], 0>,
- InstrStage<1, [P7_DU3], 0>,
- InstrStage<1, [P7_DU4], 0>,
- InstrStage<1, [P7_CRU]>,
- InstrStage<1, [P7_FX1, P7_FX2]>],
- [3, 1]>, // mtcr
- InstrItinData<IIC_SprMFCR , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_CRU]>],
- [6, 1]>,
- InstrItinData<IIC_SprMFCRF , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_CRU]>],
- [3, 1]>,
- InstrItinData<IIC_SprMTSPR , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_FX1]>],
- [4, 1]>, // mtctr
- InstrItinData<IIC_FPGeneral , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [5, 1, 1]>,
- InstrItinData<IIC_FPAddSub , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [5, 1, 1]>,
- InstrItinData<IIC_FPCompare , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [8, 1, 1]>,
- InstrItinData<IIC_FPDivD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [33, 1, 1]>,
- InstrItinData<IIC_FPDivS , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [27, 1, 1]>,
- InstrItinData<IIC_FPSqrtD , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [44, 1, 1]>,
- InstrItinData<IIC_FPSqrtS , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [32, 1, 1]>,
- InstrItinData<IIC_FPFused , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [5, 1, 1, 1]>,
- InstrItinData<IIC_FPRes , [InstrStage<1, [P7_DU1, P7_DU2,
- P7_DU3, P7_DU4], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [5, 1, 1]>,
- InstrItinData<IIC_VecGeneral , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_VS1]>],
- [2, 1, 1]>,
- InstrItinData<IIC_VecVSL , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_VS1]>],
- [2, 1, 1]>,
- InstrItinData<IIC_VecVSR , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_VS1]>],
- [2, 1, 1]>,
- InstrItinData<IIC_VecFP , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [6, 1, 1]>,
- InstrItinData<IIC_VecFPCompare, [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [6, 1, 1]>,
- InstrItinData<IIC_VecFPRound , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_VS1, P7_VS2]>],
- [6, 1, 1]>,
- InstrItinData<IIC_VecComplex , [InstrStage<1, [P7_DU1], 0>,
- InstrStage<1, [P7_VS1]>],
- [7, 1, 1]>,
- InstrItinData<IIC_VecPerm , [InstrStage<1, [P7_DU1, P7_DU2], 0>,
- InstrStage<1, [P7_VS2]>],
- [3, 1, 1]>
-]>;
-
-// ===---------------------------------------------------------------------===//
-// P7 machine model for scheduling and other instruction cost heuristics.
-
def P7Model : SchedMachineModel {
let IssueWidth = 6; // 4 (non-branch) instructions are dispatched per cycle.
// Note that the dispatch bundle size is 6 (including
@@ -394,11 +21,295 @@ def P7Model : SchedMachineModel {
// Itineraries are queried instead.
let MispredictPenalty = 16;
+ let MicroOpBufferSize = 44;
+
// Try to make sure we have at least 10 dispatch groups in a loop.
let LoopMicroOpBufferSize = 40;
let CompleteModel = 0;
- let Itineraries = P7Itineraries;
+ let UnsupportedFeatures = [HasSPE, PrefixInstrs, MMA,
+ PairedVectorMemops, IsISA3_0, IsISA2_07,
+ PCRelativeMemops, IsISA3_1, IsISAFuture];
}
+let SchedModel = P7Model in {
+ def P7_LSU_FXU: ProcResource<4>;
+ def P7_LSU: ProcResource<2> {
+ let Super = P7_LSU_FXU;
+ }
+ def P7_FXU: ProcResource<2> {
+ let Super = P7_LSU_FXU;
+ }
+ // Implemented as two 2-way SIMD operations for double- and single-precision.
+ def P7_FPU: ProcResource<4>;
+ // Scalar binary floating point instructions can only use two FPUs.
+ def P7_ScalarFPU: ProcResource<2> {
+ let Super = P7_FPU;
+ }
+ def P7_VectorFPU: ProcResource<2> {
+ let Super = P7_FPU;
+ }
+ // Executing simple FX, complex FX, permute and 4-way SIMD single-precision FP ops
+ def P7_VMX: ProcResource<1>;
+ def P7_VPM: ProcResource<1> {
+ let Super = P7_VMX;
+ let BufferSize = 1;
+ }
+ def P7_VXS: ProcResource<1> {
+ let Super = P7_VMX;
+ }
+ def P7_DFU: ProcResource<1>;
+ def P7_BRU: ProcResource<1>;
+ def P7_CRU: ProcResource<1>;
+
+ def P7_PORT_LS : ProcResource<2>;
+ def P7_PORT_FX : ProcResource<2>;
+ def P7_PORT_FP : ProcResource<2>;
+ def P7_PORT_BR : ProcResource<1>;
+ def P7_PORT_CR : ProcResource<1>;
+
+ def P7_DISP_LS : SchedWriteRes<[P7_PORT_LS]>;
+ def P7_DISP_FX : SchedWriteRes<[P7_PORT_FX]>;
+ def P7_DISP_FP : SchedWriteRes<[P7_PORT_FP]>;
+ def P7_DISP_BR : SchedWriteRes<[P7_PORT_BR]>;
+ def P7_DISP_CR : SchedWriteRes<[P7_PORT_CR]>;
+
+ def P7_BRU_NONE : SchedWriteRes<[P7_BRU]>;
+ def P7_BRU_3C : SchedWriteRes<[P7_BRU]> { let Latency = 3; }
+ def P7_BRU_4C : SchedWriteRes<[P7_BRU]> { let Latency = 4; }
+ def P7_CRU_NONE : SchedWriteRes<[P7_CRU]>;
+ def P7_CRU_3C : SchedWriteRes<[P7_CRU]> { let Latency = 3; }
+ def P7_CRU_6C : SchedWriteRes<[P7_CRU]> { let Latency = 6; }
+ def P7_LSU_NONE : SchedWriteRes<[P7_LSU]>;
+ def P7_LSU_2C : SchedWriteRes<[P7_LSU]> { let Latency = 2; }
+ def P7_LSU_3C : SchedWriteRes<[P7_LSU]> { let Latency = 3; }
+ def P7_LSU_4C : SchedWriteRes<[P7_LSU]> { let Latency = 4; }
+ def P7_FXU_NONE : SchedWriteRes<[P7_FXU]>;
+ def P7_FXU_2C : SchedWriteRes<[P7_FXU]> { let Latency = 2; }
+ def P7_FXU_3C : SchedWriteRes<[P7_FXU]> { let Latency = 3; }
+ def P7_FXU_4C : SchedWriteRes<[P7_FXU]> { let Latency = 4; }
+ def P7_FXU_5C : SchedWriteRes<[P7_FXU]> { let Latency = 5; }
+ def P7_FXU_38C : SchedWriteRes<[P7_FXU]> { let Latency = 38; }
+ def P7_FXU_69C : SchedWriteRes<[P7_FXU]> { let Latency = 69; }
+ def P7_LSU_FXU_2C : SchedWriteRes<[P7_LSU_FXU]> { let Latency = 2; }
+ def P7_FPU_NONE : SchedWriteRes<[P7_FPU]>;
+ def P7_VectorFPU_6C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 6; }
+ def P7_VectorFPU_25C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 25; }
+ def P7_VectorFPU_30C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 30; }
+ def P7_VectorFPU_31C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 31; }
+ def P7_VectorFPU_42C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 42; }
+ def P7_ScalarFPU_6C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 6; }
+ def P7_ScalarFPU_8C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 8; }
+ def P7_ScalarFPU_27C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 27; }
+ def P7_ScalarFPU_31C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 31; }
+ def P7_ScalarFPU_32C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 32; }
+ def P7_ScalarFPU_33C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 33; }
+ def P7_ScalarFPU_42C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 42; }
+ def P7_ScalarFPU_44C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 44; }
+ def P7_VXS_2C : SchedWriteRes<[P7_VXS]> { let Latency = 2; }
+ def P7_VPM_3C : SchedWriteRes<[P7_VPM]> { let Latency = 3; }
+
+ // Instruction of BRU pipeline
+
+ def : InstRW<[P7_BRU_NONE, P7_DISP_BR],
+ (instregex "^B(L)?(A)?(8)?(_NOP|_NOTOC)?(_TLS|_RM)?(_)?$")>;
+
+ def : InstRW<[P7_BRU_3C, P7_DISP_BR], (instrs
+ BDZLRLp, BDZLRm, BDZLRp, BDZLm, BDZLp, BDZm, BDZp,
+ BDNZ, BDNZ8, BDNZA, BDNZAm, BDNZAp, BDNZL, BDNZLA, BDNZLAm, BDNZLAp, BDNZLR,
+ BDNZLR8, BDNZLRL, BDNZLRLm, BDNZLRLp, BDNZLRm, BDNZLRp, BDNZLm, BDNZLp,
+ BDNZm, BDNZp, BDZ, BDZ8, BDZA, BDZAm, BDZAp, BDZL, BDZLA, BDZLAm, BDZLAp,
+ BDZLR, BDZLR8, BDZLRL, BDZLRLm, BLR, BLR8, BLRL, BCL, BCLR, BCLRL, BCLRLn,
+ BCLRn, BCLalways, BCLn, BCTR, BCTR8, BCTRL, BCTRL8, BCTRL8_LDinto_toc,
+ BCTRL8_LDinto_toc_RM, BCTRL8_RM, BCTRL_LWZinto_toc, BCTRL_LWZinto_toc_RM,
+ BCTRL_RM, BCn, BC, BCC, BCCA, BCCCTR, BCCCTR8, BCCCTRL, BCCCTRL8, BCCL,
+ BCCLA, BCCLR, BCCLRL, BCCTR, BCCTR8, BCCTR8n, BCCTRL, BCCTRL8,
+ BCCCTR, BCCCTR8, BCCCTRL, BCCCTRL8, BCCL, BCCLA, BCCLR, BCCLRL, BCCTR,
+ BCCTR8, BCCTR8n, BCCTRL, BCCTRL8, BCCTRL8n, BCCTRLn, BCCTRn, gBC, gBCA,
+ gBCAat, gBCCTR, gBCCTRL, gBCL, gBCLA, gBCLAat, gBCLR, gBCLRL, gBCLat, gBCat,
+ MFCTR, MFCTR8, MFLR, MFLR8
+ )>;
+
+ def : InstRW<[P7_BRU_4C], (instrs MTLR, MTLR8, MTCTR, MTCTR8, MTCTR8loop, MTCTRloop)>;
+
+ // Instructions of CRU pipeline
+
+ def : InstRW<[P7_CRU_NONE], (instrs MFCR, MFCR8)>;
+ def : InstRW<[P7_CRU_3C], (instrs MCRF)>;
+ def : InstRW<[P7_CRU_6C, P7_DISP_CR], (instrs
+ CR6SET, CR6UNSET, CRSET, CRUNSET,
+ CRAND, CRANDC, CREQV, CRNAND, CRNOR, CRNOT, CROR, CRORC
+ )>;
+
+ // Instructions of LSU and FXU pipelines
+
+ def : InstRW<[P7_LSU_NONE, P7_DISP_LS], (instrs LMW, LWARX, LWARXL, LDARX, LDARXL)>;
+ def : InstRW<[P7_LSU_2C, P7_DISP_LS], (instrs LHBRX, LHBRX8, LWBRX, LWBRX8)>;
+ def : InstRW<[P7_LSU_3C], (instrs MFSR, MFSRIN)>;
+
+ def : InstRW<[P7_LSU_3C, P7_DISP_LS], (instrs
+ LFS, LFSX, LFSXTLS, LFSXTLS_, LFD, LFDX, LFDXTLS, LFDXTLS_, LXSDX, LXVD2X,
+ LXVW4X, LXVDSX
+ )>;
+
+ def : InstRW<[P7_LSU_3C, P7_FXU_3C, P7_DISP_LS], (instrs
+ LFSU, LFSUX, LFDU, LFDUX)>;
+
+ def : InstRW<[P7_LSU_NONE, P7_FPU_NONE, P7_DISP_LS], (instrs
+ STXSDX, STXVD2X, STXVW4X)>;
+
+ def : InstRW<[P7_LSU_4C, P7_FXU_4C, P7_DISP_LS], (instrs
+ LBARX, LBZCIX, LDBRX, LDCIX, LFIWAX, LFIWZX, LHARX, LHZCIX, LSWI, LVEBX,
+ LVEHX, LVEWX, LVSL, LVSR, LVX, LVXL, LWZCIX,
+ STFD, STFDU, STFDUX, STFDX, STFIWX, STFS, STFSU, STFSUX, STFSX,
+ STHCIX, STSWI, STVEBX, STVEHX, STVEWX, STVX, STVXL, STWCIX,
+ LHA, LHA8, LHAX, LHAX8, LWA, LWAX, LWAX_32, LWA_32, LHAU, LHAU8,
+ LHAUX, LHAUX8, LWAUX
+ )>;
+
+ def : InstRW<[P7_LSU_NONE, P7_FXU_NONE, P7_DISP_LS], (instrs
+ STB, STB8, STH, STH8, STW, STW8, STD, STBX, STBX8, STHX, STHX8, STWX,
+ STWX8, STDX, STHBRX, STWBRX, STMW, STWCX, STDCX, STDU, STHU, STHU8,
+ STBU, STBU8, STWU, STWU8, STDUX, STWUX, STWUX8, STHUX, STHUX8, STBUX, STBUX8
+ )>;
+
+ def : InstRW<[P7_LSU_2C, P7_FXU_2C, P7_DISP_LS], (instrs
+ LWZU, LWZU8, LHZU, LHZU8, LBZU, LBZU8, LDU,
+ LWZUX, LWZUX8, LHZUX, LHZUX8, LBZUX, LBZUX8, LDUX
+ )>;
+
+ def : InstRW<[P7_LSU_FXU_2C, P7_DISP_FX], (instrs
+ (instregex "^(ADD|L)I(S)?(8)?$"),
+ (instregex "^(ADD|SUBF)(4|8)(TLS)?(_)?(_rec)?$"),
+ (instregex "^(X)?ORI(S)?(8)?$"),
+ (instregex "^(X)OR(8)?(_rec)?$"),
+ ADDIC, ADDIC8, SUBFIC, SUBFIC8, SUBFZE, SUBFZE8,
+ ADDE, ADDE8, ADDME, ADDME8, SUBFME, SUBFME8,
+ NEG, NEG8, NEG8_rec, NEG_rec, NEG8O, NEGO,
+ ANDI_rec, ANDIS_rec, AND, AND8, AND_rec, AND8_rec,
+ NAND, NAND8, NAND_rec, NAND8_rec, NOR, NOR8, NOR_rec, NOR8_rec,
+ EQV, EQV8, EQV_rec, EQV8_rec, ANDC, ANDC8, ANDC_rec, ANDC8_rec,
+ ORC, ORC8, ORC_rec, ORC8_rec
+ )>;
+
+ def : InstRW<[P7_FXU_2C, P7_DISP_FX], (instrs
+ CMPD, CMPDI, CMPLD, CMPLDI, CMPLW, CMPLWI, CMPW, CMPWI,
+ EXTSB8_32_64, EXTSB8_rec, EXTSH8_32_64, EXTSH8_rec, EXTSW_32,
+ EXTSW_32_64, EXTSW_32_64_rec, POPCNTB, POPCNTB8, POPCNTD, POPCNTW,
+ ADDPCIS, ANDI8_rec, ANDIS8_rec, SUBFUS, SUBFUS_rec,
+ ADD4O, ADD8O, ADDC, ADDC8, SUBFO, SUBF8O, SUBFC, SUBFC8,
+ ADDIC_rec, ADDE8_rec, ADDE_rec, SUBFE8_rec, SUBFE_rec,
+ ADDME8_rec, ADDME_rec, SUBFME8_rec, SUBFME_rec, ADDZE8_rec, ADDZE_rec,
+ SUBFZE_rec, SUBFZE8_rec, ADD8O_rec, SUBFO_rec, SUBF8O_rec, ADD4O_rec,
+ ADD8O_rec, SUBF8O_rec, SUBFO_rec, ADDE8O, ADDEO, SUBFE8O, SUBFEO, ADDME8O,
+ ADDMEO, SUBFME8O, SUBFMEO, ADDZE8O, ADDZEO, SUBFZE8O, SUBFZEO, NEG8O_rec,
+ NEGO_rec, ADDEO, ADDE8O, SUBFEO, SUBFE8O, ADDMEO, SUBFMEO, SUBFME8O, ADDME8O,
+ ADDZEO, ADDZE8O, SUBFZEO, SUBFZE8O, NEG8O_rec, NEGO_rec,
+ ADDE8O_rec, ADDEO_rec, ADDMEO_rec, ADDME8O_rec, SUBFMEO_rec, SUBFME8O_rec,
+ ADDZEO_rec, ADDZE8O_rec, SUBFZEO_rec, SUBFZE8O_rec,
+ ADDC8_rec, ADDC_rec, ADDCO, ADDCO_rec, ADDC8O, ADDC8O_rec,
+ SUBFC8_rec, SUBFC_rec, SUBFCO, SUBFC8O, SUBFCO_rec, SUBFC8O_rec,
+ EXTSB, EXTSB8, EXTSB_rec, EXTSH, EXTSH8, EXTSH_rec, EXTSW, EXTSW_rec,
+ RLDICL, RLDICL_rec, RLDICR, RLDICR_rec, RLDIC, RLDIC_rec,
+ RLWINM, RLWINM8, RLWINM_rec, RLDCL, RLDCL_rec, RLDCR, RLDCR_rec,
+ RLWNM, RLWNM8, RLWNM_rec, RLDIMI, RLDIMI_rec,
+ RLDICL_32, RLDICL_32_64, RLDICL_32_rec, RLDICR_32, RLWINM8_rec, RLWNM8_rec,
+ SLD, SLD_rec, SLW, SLW8, SLW_rec, SLW8_rec, SRD, SRD_rec, SRW, SRW8, SRW_rec,
+ SRW8_rec, SRADI, SRADI_rec, SRAWI, SRAWI_rec, SRAD, SRAD_rec, SRAW, SRAW_rec,
+ SRADI_32, SUBFE, SUBFE8, SUBFE8O_rec, SUBFEO_rec
+ )>;
+
+ def : InstRW<[P7_FXU_3C, P7_DISP_FX], (instregex "^CNT(L|T)Z(D|W)(8)?(M)?(_rec)?$")>;
+
+ def : InstRW<[P7_FXU_5C, P7_DISP_FX], (instrs
+ MULLI, MULLI8, MULLW, MULHW, MULHWU, MULLD, MULHD, MULHDU, MULLWO, MULLDO,
+ MULLW_rec, MULLD_rec, MULHD_rec, MULHW_rec, MULHDU_rec, MULHWU_rec, MULLWO_rec,
+ MULLDO_rec
+ )>;
+
+ def : InstRW<[P7_FXU_38C, P7_DISP_FX], (instrs
+ DIVDE, DIVDEO, DIVDEO_rec, DIVDEU, DIVDEUO, DIVDEUO_rec, DIVDEU_rec, DIVDE_rec,
+ DIVWE, DIVWEO, DIVWEO_rec, DIVWEU, DIVWEUO, DIVWEUO_rec, DIVWEU_rec, DIVWE_rec,
+ DIVW, DIVWU, DIVWU_rec, DIVWO, DIVWO_rec, DIVWUO, DIVWUO_rec, DIVW_rec
+ )>;
+
+ def : InstRW<[P7_FXU_69C, P7_DISP_FX], (instrs
+ DIVD, DIVDU, DIVDO, DIVDO_rec, DIVDUO, DIVDUO_rec, DIVDU_rec, DIVD_rec)>;
+
+ // Instructions of FPU and VMX pipeline
+
+ def : InstRW<[P7_ScalarFPU_6C, P7_DISP_FP], (instrs
+ (instregex "^F(N)?(M)?(R|ADD|SUB|ABS|NEG|NABS|UL)(D|S)?(_rec)?$"),
+ (instregex "^FC(T|F)I(D|W)(U)?(S)?(Z)?(_rec)?$"),
+ (instregex "^XS(N)?M(SUB|ADD)(A|M)(D|S)P$"),
+ (instregex "^XS(NEG|ABS|NABS|ADD|SUB|MUL)(D|S)P(s)?$"),
+ FRE, FRES_rec, FRE_rec, FRSP_rec, FTDIV, FTSQRT,
+ FRSP, FRES, FRSQRTE, FRSQRTES, FRSQRTES_rec, FRSQRTE_rec, FSELD, FSELS,
+ FSELD_rec, FSELS_rec, FCPSGND, FCPSGND_rec, FCPSGNS, FCPSGNS_rec,
+ FRIMD, FRIMD_rec, FRIMS, FRIMS_rec, FRIND, FRIND_rec, FRINS, FRINS_rec,
+ FRIPD, FRIPD_rec, FRIPS, FRIPS_rec, FRIZD, FRIZD_rec, FRIZS, FRIZS_rec,
+ XSCPSGNDP, XSCVDPSP, XSCVDPSXDS, XSCVDPSXDSs, XSCVDPSXWS, XSCVDPSXWSs,
+ XSCVDPUXDS, XSCVDPUXDSs, XSCVDPUXWS, XSCVDPUXWSs, XSCVSPDP, XSCVSXDDP,
+ XSCVUXDDP, XSMAXDP, XSMINDP, XSRDPI, XSRDPIC, XSRDPIM, XSRDPIP, XSRDPIZ,
+ XSREDP, XSRSQRTEDP, XSTDIVDP, XSTSQRTDP, XSCMPODP, XSCMPUDP
+ )>;
+
+ def : InstRW<[P7_VectorFPU_6C, P7_DISP_FP], (instrs
+ (instregex "^XV(N)?(M)?(ADD|SUB)(A|M)?(D|S)P$"),
+ (instregex "^XV(MAX|MIN|MUL|NEG|ABS|ADD|NABS)(D|S)P$"),
+ XVCMPEQDP, XVCMPEQDP_rec, XVCMPGEDP, XVCMPGEDP_rec, XVCMPGTDP, XVCMPGTDP_rec,
+ XVCPSGNDP, XVCVDPSXDS, XVCVDPSXWS, XVCVDPUXDS, XVCVDPUXWS, XVCVSPSXDS,
+ XVCVSPSXWS, XVCVSPUXDS, XVCVSPUXWS, XVCVSXDDP, XVCVSXWDP, XVCVUXDDP,
+ XVCVUXWDP, XVRDPI, XVRDPIC, XVRDPIM, XVRDPIP, XVRDPIZ, XVREDP,
+ XVRSPI, XVRSPIC, XVRSPIM, XVRSPIP, XVRSPIZ, XVRSQRTEDP, XVTDIVDP,
+ XVTSQRTDP
+ )>;
+
+ // TODO: Altivec instructions are not listed in Book IV.
+ def : InstRW<[P7_VPM_3C, P7_DISP_FP], (instrs
+ (instregex "^VPK(S|U)(H|W)(S|U)(S|M)$"),
+ (instregex "^VUPK(H|L)(S|P)(X|B|H)$"),
+ VPERM, XXMRGHW, XXMRGLW, XXPERMDI, XXPERMDIs, XXSLDWI, XXSLDWIs,
+ VSPLTB, VSPLTBs, VSPLTH, VSPLTHs, VSPLTISB, VSPLTISH, VSPLTISW, VSPLTW,
+ XXSPLTW, XXSPLTWs, VSEL, XXSEL, VPKPX
+ )>;
+
+ def : InstRW<[P7_VXS_2C, P7_DISP_FP], (instrs
+ (instregex "^VADD(U|S)(B|H|W)(S|M)$"),
+ (instregex "^V(MAX|MIN)(S|U)(B|H|W)$"),
+ (instregex "^V(MRG)(L|H)(B|H|W)$"),
+ XXLORf, XXLXORdpz, XXLXORspz, XXLXORz, XVRSQRTESP, XVRESP,
+ XVTDIVSP, XVTSQRTSP, XVCMPEQSP, XVCMPEQSP_rec, XVCMPGESP, XVCMPGESP_rec,
+ XVCMPGTSP, XVCMPGTSP_rec, XVCVSXDSP, XVCVSXWSP, XVCVUXDSP, XVCVUXWSP,
+ XVCPSGNSP, XVCVDPSP, VADDCUW, VADDFP, VAND, VANDC, VAVGSB, VAVGSH,
+ VAVGSW, VAVGUB, VAVGUH, VAVGUW, VCFSX, VCFUX, VCMPBFP, VCMPBFP_rec,
+ VCMPEQFP, VCMPEQFP_rec, VCMPEQUB, VCMPEQUB_rec, VCMPEQUH, VCMPEQUH_rec,
+ VCMPEQUW, VCMPEQUW_rec, VCMPGEFP, VCMPGEFP_rec, VCMPGTFP, VCMPGTFP_rec,
+ VCMPGTSB, VCMPGTSB_rec, VCMPGTSH, VCMPGTSH_rec, VCMPGTSW, VCMPGTSW_rec,
+ VCMPGTUB, VCMPGTUB_rec, VCMPGTUH, VCMPGTUH_rec, VCMPGTUW, VCMPGTUW_rec,
+ VCTSXS, VCTUXS, VEXPTEFP, VLOGEFP, VNOR, VOR,
+ VMADDFP, VMHADDSHS, VMHRADDSHS, VMLADDUHM, VNMSUBFP, VMAXFP, VMINFP,
+ VMSUMMBM, VMSUMSHM, VMSUMSHS, VMSUMUBM, VMSUMUDM, VMSUMUHM, VMSUMUHS,
+ VMULESB, VMULESH, VMULEUB, VMULEUH, VMULOSB, VMULOSH, VMULOUB, VMULOUH,
+ VREFP, VRFIM, VRFIN, VRFIP, VRFIZ, VRLB, VRLH, VRLW, VRSQRTEFP,
+ VSR, VSRAB, VSRAH, VSRAW, VSRB, VSRH, VSRO, VSRW, VSUBCUW, VSL, VSLB,
+ VSLDOI, VSLH, VSLO, VSLW, VSUBFP, VSUBSBS, VSUBSHS, VSUBSWS, VSUBUBM,
+ VSUBUBS, VSUBUHM, VSUBUHS, VSUBUWM, VSUBUWS, VSUM2SWS, VSUM4SBS, VSUM4SHS,
+ VSUM4UBS, VSUMSWS, VXOR, XXLAND, XXLANDC, XXLNOR, XXLOR, XXLXOR
+ )>;
+
+ def : InstRW<[P7_ScalarFPU_8C, P7_DISP_FP],
+ (instrs FCMPOD, FCMPOS, FCMPUD, FCMPUS)>;
+ def : InstRW<[P7_ScalarFPU_27C, P7_DISP_FP], (instrs FDIVS, FDIVS_rec)>;
+ def : InstRW<[P7_ScalarFPU_31C, P7_DISP_FP], (instrs XSDIVDP)>;
+ def : InstRW<[P7_ScalarFPU_32C, P7_DISP_FP], (instrs FSQRTS, XSSQRTSP, FSQRTS_rec)>;
+ def : InstRW<[P7_ScalarFPU_33C, P7_DISP_FP], (instrs FDIV, FDIV_rec)>;
+ def : InstRW<[P7_ScalarFPU_42C, P7_DISP_FP], (instrs XSSQRTDP)>;
+ def : InstRW<[P7_ScalarFPU_44C, P7_DISP_FP], (instrs FSQRT, FSQRT_rec)>;
+
+ def : InstRW<[P7_VectorFPU_25C, P7_DISP_FP], (instrs XVDIVSP)>;
+ def : InstRW<[P7_VectorFPU_30C, P7_DISP_FP], (instrs XVSQRTSP)>;
+ def : InstRW<[P7_VectorFPU_31C, P7_DISP_FP], (instrs XVDIVDP)>;
+ def : InstRW<[P7_VectorFPU_42C, P7_DISP_FP], (instrs XVSQRTDP)>;
+}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td
index 70a58f42a98a..3a2d9d9b3bc1 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td
@@ -6,408 +6,332 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the itinerary class data for the POWER8 processor.
+// This file defines the SchedModel for the POWER8 processor.
//
//===----------------------------------------------------------------------===//
-// Scheduling for the P8 involves tracking two types of resources:
-// 1. The dispatch bundle slots
-// 2. The functional unit resources
+def P8Model : SchedMachineModel {
+ let IssueWidth = 8;
+ let LoadLatency = 3;
+ let MispredictPenalty = 16;
+ let LoopMicroOpBufferSize = 60;
+ let MicroOpBufferSize = 64;
+ // TODO: Due to limitation of instruction definitions, non-P8 instructions
+ // are required to be listed here. Change this after it got fixed.
+ let CompleteModel = 0;
+ let UnsupportedFeatures = [HasSPE, PrefixInstrs, MMA,
+ PairedVectorMemops, PCRelativeMemops,
+ IsISA3_0, IsISA3_1, IsISAFuture];
+}
-// Dispatch units:
-def P8_DU1 : FuncUnit;
-def P8_DU2 : FuncUnit;
-def P8_DU3 : FuncUnit;
-def P8_DU4 : FuncUnit;
-def P8_DU5 : FuncUnit;
-def P8_DU6 : FuncUnit;
-def P8_DU7 : FuncUnit; // Only branch instructions will use DU7,DU8
-def P8_DU8 : FuncUnit;
+let SchedModel = P8Model in {
+ // Power8 Pipeline Units:
-// 10 insns per cycle (2-LU, 2-LSU, 2-FXU, 2-FPU, 1-CRU, 1-BRU).
+ def P8_LU_LS_FX : ProcResource<6>;
+ def P8_LU_LS : ProcResource<4> { let Super = P8_LU_LS_FX; }
+ def P8_LS : ProcResource<2> { let Super = P8_LU_LS; }
+ def P8_LU : ProcResource<2> { let Super = P8_LU_LS; }
+ def P8_FX : ProcResource<2> { let Super = P8_LU_LS_FX; }
+ def P8_DFU : ProcResource<1>;
+ def P8_BR : ProcResource<1> { let BufferSize = 16; }
+ def P8_CY : ProcResource<1>;
+ def P8_CRL : ProcResource<1>;
+ def P8_VMX : ProcResource<2>;
+ def P8_PM : ProcResource<2> {
+ // This is workaround for scheduler to respect latency of long permute chain.
+ let BufferSize = 1;
+ let Super = P8_VMX;
+ }
+ def P8_XS : ProcResource<2> { let Super = P8_VMX; }
+ def P8_VX : ProcResource<2> { let Super = P8_VMX; }
+ def P8_FPU : ProcResource<4>;
+ // Units for scalar, 2xDouble and 4xSingle
+ def P8_FP_Scal : ProcResource<2> { let Super = P8_FPU; }
+ def P8_FP_2x64 : ProcResource<2> { let Super = P8_FPU; }
+ def P8_FP_4x32 : ProcResource<2> { let Super = P8_FPU; }
-def P8_LU1 : FuncUnit; // Loads or fixed-point operations 1
-def P8_LU2 : FuncUnit; // Loads or fixed-point operations 2
+ // Power8 Dispatch Ports:
+ // Two ports to do loads or fixed-point operations.
+ // Two ports to do stores, fixed-point loads, or fixed-point operations.
+ // Two ports for fixed-point operations.
+ // Two issue ports shared by 2 DFP/2 VSX/2 VMX/1 CY/1 DFP operations.
+ // One for branch operations.
+ // One for condition register operations.
-// Load/Store pipelines can handle Stores, fixed-point loads, and simple
-// fixed-point operations.
-def P8_LSU1 : FuncUnit; // Load/Store pipeline 1
-def P8_LSU2 : FuncUnit; // Load/Store pipeline 2
+ // TODO: Model dispatch of cracked instructions.
-// Fixed Point unit
-def P8_FXU1 : FuncUnit; // FX pipeline 1
-def P8_FXU2 : FuncUnit; // FX pipeline 2
+ // Six ports in total are available for fixed-point operations.
+ def P8_PORT_ALLFX : ProcResource<6>;
+ // Four ports in total are available for fixed-point load operations.
+ def P8_PORT_FXLD : ProcResource<4> { let Super = P8_PORT_ALLFX; }
+ // Two ports to do loads or fixed-point operations.
+ def P8_PORT_LD_FX : ProcResource<2> { let Super = P8_PORT_FXLD; }
+ // Two ports to do stores, fixed-point loads, or fixed-point operations.
+ def P8_PORT_ST_FXLD_FX : ProcResource<2> { let Super = P8_PORT_FXLD; }
+ // Two issue ports shared by two floating-point, two VSX, two VMX, one crypto,
+ // and one DFP operations.
+ def P8_PORT_VMX_FP : ProcResource<2>;
+ // One port for branch operation.
+ def P8_PORT_BR : ProcResource<1>;
+ // One port for condition register operation.
+ def P8_PORT_CR : ProcResource<1>;
-// The Floating-Point Unit (FPU) and Vector Media Extension (VMX) units
-// are combined on P7 and newer into a Vector Scalar Unit (VSU).
-// The P8 Instruction latency documents still refers to the unit as the
-// FPU, so keep in mind that FPU==VSU.
-// In contrast to the P7, the VMX units on P8 are symmetric, so no need to
-// split vector integer ops or 128-bit load/store/perms to the specific units.
-def P8_FPU1 : FuncUnit; // VS pipeline 1
-def P8_FPU2 : FuncUnit; // VS pipeline 2
+ def P8_ISSUE_FX : SchedWriteRes<[P8_PORT_ALLFX]>;
+ def P8_ISSUE_FXLD : SchedWriteRes<[P8_PORT_FXLD]>;
+ def P8_ISSUE_LD : SchedWriteRes<[P8_PORT_LD_FX]>;
+ def P8_ISSUE_ST : SchedWriteRes<[P8_PORT_ST_FXLD_FX]>;
+ def P8_ISSUE_VSX : SchedWriteRes<[P8_PORT_VMX_FP]>;
+ def P8_ISSUE_BR : SchedWriteRes<[P8_PORT_BR]>;
+ def P8_ISSUE_CR : SchedWriteRes<[P8_PORT_CR]>;
-def P8_CRU : FuncUnit; // CR unit (CR logicals and move-from-SPRs)
-def P8_BRU : FuncUnit; // BR unit
+ // Power8 Instruction Latency & Port Groups:
-def P8Itineraries : ProcessorItineraries<
- [P8_DU1, P8_DU2, P8_DU3, P8_DU4, P8_DU5, P8_DU6, P8_DU7, P8_DU8,
- P8_LU1, P8_LU2, P8_LSU1, P8_LSU2, P8_FXU1, P8_FXU2,
- P8_FPU1, P8_FPU2, P8_CRU, P8_BRU], [], [
- InstrItinData<IIC_IntSimple , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2,
- P8_LU1, P8_LU2,
- P8_LSU1, P8_LSU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntGeneral , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2, P8_LU1,
- P8_LU2, P8_LSU1, P8_LSU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntISEL, [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2], 0>,
- InstrStage<1, [P8_BRU]>],
- [1, 1, 1, 1]>,
- InstrItinData<IIC_IntCompare , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntDivW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<15, [P8_FXU1, P8_FXU2]>],
- [15, 1, 1]>,
- InstrItinData<IIC_IntDivD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<23, [P8_FXU1, P8_FXU2]>],
- [23, 1, 1]>,
- InstrItinData<IIC_IntMulHW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntMulHWU , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntMulHD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntMulLI , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [4, 1, 1]>,
- InstrItinData<IIC_IntRotate , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntRotateD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntRotateDI , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntShift , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_IntTrapW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [1, 1]>,
- InstrItinData<IIC_IntTrapD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [1, 1]>,
- InstrItinData<IIC_BrB , [InstrStage<1, [P8_DU7, P8_DU8], 0>,
- InstrStage<1, [P8_BRU]>],
- [3, 1, 1]>,
- // FIXME - the Br* groups below are not branch related, so should probably
- // be renamed.
- // IIC_BrCR consists of the cr* instructions. (crand,crnor,creqv, etc).
- // and should be 'First' in dispatch.
- InstrItinData<IIC_BrCR , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_CRU]>],
- [3, 1, 1]>,
- // IIC_BrMCR consists of the mcrf instruction.
- InstrItinData<IIC_BrMCR , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_CRU]>],
- [3, 1, 1]>,
- // IIC_BrMCRX consists of mcrxr (obsolete instruction) and mtcrf, which
- // should be first in the dispatch group.
- InstrItinData<IIC_BrMCRX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_BrMCRX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [3, 1]>,
- InstrItinData<IIC_LdStLoad , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_LdStLoadUpd , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2 ], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [2, 2, 1, 1]>,
- // Update-Indexed form loads/stores are no longer first and last in the
- // dispatch group. They are simply cracked, so require DU1,DU2.
- InstrItinData<IIC_LdStLoadUpdX, [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_LdStLDU , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [2, 2, 1, 1]>,
- InstrItinData<IIC_LdStLDUX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLFD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LU1, P8_LU2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLVecX , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LU1, P8_LU2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLFDU , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLFDUX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [3, 3, 1, 1]>,
- InstrItinData<IIC_LdStLHA , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2,
- P8_LU1, P8_LU2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLHAU , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [4, 4, 1, 1]>,
- // first+last in dispatch group.
- InstrItinData<IIC_LdStLHAUX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_DU3], 0>,
- InstrStage<1, [P8_DU4], 0>,
- InstrStage<1, [P8_DU5], 0>,
- InstrStage<1, [P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [4, 4, 1, 1]>,
- InstrItinData<IIC_LdStLWA , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2]>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLWARX, [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_DU3], 0>,
- InstrStage<1, [P8_DU4], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2]>],
- [3, 1, 1]>,
- // first+last
- InstrItinData<IIC_LdStLDARX, [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_DU3], 0>,
- InstrStage<1, [P8_DU4], 0>,
- InstrStage<1, [P8_DU5], 0>,
- InstrStage<1, [P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2]>],
- [3, 1, 1]>,
- InstrItinData<IIC_LdStLMW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2,
- P8_LU1, P8_LU2]>],
- [2, 1, 1]>,
-// Stores are dual-issued from the issue queue, so may only take up one
-// dispatch slot. The instruction will be broken into two IOPS. The agen
-// op is issued to the LSU, and the data op (register fetch) is issued
-// to either the LU (GPR store) or the VSU (FPR store).
- InstrItinData<IIC_LdStStore , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2]>,
- InstrStage<1, [P8_LU1, P8_LU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LU1, P8_LU2,
- P8_LSU1, P8_LSU2]>]
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTU , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LU1, P8_LU2,
- P8_LSU1, P8_LSU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [2, 1, 1, 1]>,
- // First+last
- InstrItinData<IIC_LdStSTUX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_DU3], 0>,
- InstrStage<1, [P8_DU4], 0>,
- InstrStage<1, [P8_DU5], 0>,
- InstrStage<1, [P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [2, 1, 1, 1]>,
- InstrItinData<IIC_LdStSTFD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTFDU , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [2, 1, 1, 1]>,
- InstrItinData<IIC_LdStSTVEBX , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTDCX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_DU3], 0>,
- InstrStage<1, [P8_DU4], 0>,
- InstrStage<1, [P8_DU5], 0>,
- InstrStage<1, [P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2], 0>,
- InstrStage<1, [P8_LU1, P8_LU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_LdStSTWCX , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_DU2], 0>,
- InstrStage<1, [P8_DU3], 0>,
- InstrStage<1, [P8_DU4], 0>,
- InstrStage<1, [P8_DU5], 0>,
- InstrStage<1, [P8_DU6], 0>,
- InstrStage<1, [P8_LSU1, P8_LSU2], 0>,
- InstrStage<1, [P8_LU1, P8_LU2]>],
- [1, 1, 1]>,
- InstrItinData<IIC_SprMFCR , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_CRU]>],
- [6, 1]>,
- InstrItinData<IIC_SprMFCRF , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_CRU]>],
- [3, 1]>,
- InstrItinData<IIC_SprMTSPR , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FXU1, P8_FXU2]>],
- [4, 1]>, // mtctr
- InstrItinData<IIC_FPGeneral , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [5, 1, 1]>,
- InstrItinData<IIC_FPAddSub , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [5, 1, 1]>,
- InstrItinData<IIC_FPCompare , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [8, 1, 1]>,
- InstrItinData<IIC_FPDivD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [33, 1, 1]>,
- InstrItinData<IIC_FPDivS , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [27, 1, 1]>,
- InstrItinData<IIC_FPSqrtD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [44, 1, 1]>,
- InstrItinData<IIC_FPSqrtS , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [32, 1, 1]>,
- InstrItinData<IIC_FPFused , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [5, 1, 1, 1]>,
- InstrItinData<IIC_FPRes , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3,
- P8_DU4, P8_DU5, P8_DU6], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [5, 1, 1]>,
- InstrItinData<IIC_VecGeneral , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_VecVSL , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_VecVSR , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [2, 1, 1]>,
- InstrItinData<IIC_VecFP , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [6, 1, 1]>,
- InstrItinData<IIC_VecFPCompare, [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [6, 1, 1]>,
- InstrItinData<IIC_VecFPRound , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [6, 1, 1]>,
- InstrItinData<IIC_VecComplex , [InstrStage<1, [P8_DU1], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [7, 1, 1]>,
- InstrItinData<IIC_VecPerm , [InstrStage<1, [P8_DU1, P8_DU2], 0>,
- InstrStage<1, [P8_FPU1, P8_FPU2]>],
- [3, 1, 1]>
-]>;
+ def P8_LS_LU_NONE : SchedWriteRes<[P8_LU, P8_LS]>;
+ def P8_LS_FP_NONE : SchedWriteRes<[P8_LS, P8_FPU]>;
+ def P8_LU_or_LS_3C : SchedWriteRes<[P8_LU_LS]> { let Latency = 3; }
+ def P8_LS_FX_3C : SchedWriteRes<[P8_LS, P8_FX]> { let Latency = 3; }
+ def P8_LU_or_LS_or_FX_2C : SchedWriteRes<[P8_LU_LS_FX]> { let Latency = 2; }
+ def P8_LU_or_LS_FX_3C : SchedWriteRes<[P8_LU_LS, P8_FX]> { let Latency = 3; }
+ def P8_FX_NONE : SchedWriteRes<[P8_FX]>;
+ def P8_FX_1C : SchedWriteRes<[P8_FX]> { let Latency = 1; }
+ def P8_FX_2C : SchedWriteRes<[P8_FX]> { let Latency = 2; }
+ def P8_FX_3C : SchedWriteRes<[P8_FX]> { let Latency = 3; }
+ def P8_FX_5C : SchedWriteRes<[P8_FX]> { let Latency = 5; }
+ def P8_FX_10C : SchedWriteRes<[P8_FX]> { let Latency = 10; }
+ def P8_FX_23C : SchedWriteRes<[P8_FX]> { let Latency = 23; }
+ def P8_FX_15C : SchedWriteRes<[P8_FX]> { let Latency = 15; }
+ def P8_FX_41C : SchedWriteRes<[P8_FX]> { let Latency = 41; }
+ def P8_BR_2C : SchedWriteRes<[P8_BR]> { let Latency = 2; }
+ def P8_CR_NONE : SchedWriteRes<[P8_CRL]>;
+ def P8_CR_3C : SchedWriteRes<[P8_CRL]> { let Latency = 3; }
+ def P8_CR_5C : SchedWriteRes<[P8_CRL]> { let Latency = 5; }
+ def P8_LU_5C : SchedWriteRes<[P8_LU]> { let Latency = 5; }
+ def P8_LU_FX_5C : SchedWriteRes<[P8_LU, P8_FX]> { let Latency = 5; }
+ def P8_LS_FP_FX_2C : SchedWriteRes<[P8_LS, P8_FPU, P8_FX]> { let Latency = 2; }
+ def P8_LS_FP_FX_3C : SchedWriteRes<[P8_LS, P8_FPU, P8_FX]> { let Latency = 3; }
+ def P8_LS_3C : SchedWriteRes<[P8_LS]> { let Latency = 3; }
+ def P8_FP_3C : SchedWriteRes<[P8_FPU]> { let Latency = 3; }
+ def P8_FP_Scal_6C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 6; }
+ def P8_FP_4x32_6C : SchedWriteRes<[P8_FP_4x32]> { let Latency = 6; }
+ def P8_FP_2x64_6C : SchedWriteRes<[P8_FP_2x64]> { let Latency = 6; }
+ def P8_FP_26C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 26; }
+ def P8_FP_28C : SchedWriteRes<[P8_FP_4x32]> { let Latency = 28; }
+ def P8_FP_31C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 31; }
+ def P8_FP_Scal_32C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 32; }
+ def P8_FP_2x64_32C : SchedWriteRes<[P8_FP_2x64]> { let Latency = 32; }
+ def P8_FP_4x32_32C : SchedWriteRes<[P8_FP_4x32]> { let Latency = 32; }
+ def P8_FP_Scal_43C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 43; }
+ def P8_FP_2x64_43C : SchedWriteRes<[P8_FP_2x64]> { let Latency = 43; }
+ def P8_XS_2C : SchedWriteRes<[P8_XS]> { let Latency = 2; }
+ def P8_PM_2C : SchedWriteRes<[P8_PM]> { let Latency = 2; }
+ def P8_XS_4C : SchedWriteRes<[P8_XS]> { let Latency = 4; }
+ def P8_VX_7C : SchedWriteRes<[P8_VX]> { let Latency = 7; }
+ def P8_XS_9C : SchedWriteRes<[P8_XS]> { let Latency = 9; }
+ def P8_CY_6C : SchedWriteRes<[P8_CY]> { let Latency = 6; }
+ def P8_DFU_13C : SchedWriteRes<[P8_DFU]> { let Latency = 13; }
+ def P8_DFU_15C : SchedWriteRes<[P8_DFU]> { let Latency = 15; }
+ def P8_DFU_17C : SchedWriteRes<[P8_DFU]> { let Latency = 17; }
+ def P8_DFU_25C : SchedWriteRes<[P8_DFU]> { let Latency = 25; }
+ def P8_DFU_32C : SchedWriteRes<[P8_DFU]> { let Latency = 32; }
+ def P8_DFU_34C : SchedWriteRes<[P8_DFU]> { let Latency = 34; }
+ def P8_DFU_40C : SchedWriteRes<[P8_DFU]> { let Latency = 40; }
+ def P8_DFU_90C : SchedWriteRes<[P8_DFU]> { let Latency = 90; }
+ def P8_DFU_96C : SchedWriteRes<[P8_DFU]> { let Latency = 96; }
+ def P8_DFU_172C : SchedWriteRes<[P8_DFU]> { let Latency = 172; }
+ // Direct move instructions
+ def P8_DM_5C : SchedWriteRes<[]> { let Latency = 5; }
-// ===---------------------------------------------------------------------===//
-// P8 machine model for scheduling and other instruction cost heuristics.
-// P8 has an 8 insn dispatch group (6 non-branch, 2 branch) and can issue up
-// to 10 insns per cycle (2-LU, 2-LSU, 2-FXU, 2-FPU, 1-CRU, 1-BRU).
+ // Instructions of CR pipeline
-def P8Model : SchedMachineModel {
- let IssueWidth = 8; // up to 8 instructions dispatched per cycle.
- // up to six non-branch instructions.
- // up to two branches in a dispatch group.
+ def : InstRW<[P8_CR_NONE, P8_ISSUE_CR], (instrs MFCR, MFCR8)>;
+ def : InstRW<[P8_CR_3C, P8_ISSUE_CR], (instrs MFOCRF, MFOCRF8)>;
+ def : InstRW<[P8_CR_5C, P8_ISSUE_CR], (instrs MFLR, MFLR8, MFCTR, MFCTR8)>;
- let LoadLatency = 3; // Optimistic load latency assuming bypass.
- // This is overriden by OperandCycles if the
- // Itineraries are queried instead.
- let MispredictPenalty = 16;
+ // Instructions of CY pipeline
- // Try to make sure we have at least 10 dispatch groups in a loop.
- let LoopMicroOpBufferSize = 60;
+ def : InstRW<[P8_CY_6C, P8_ISSUE_VSX], (instrs
+ VCIPHER, VCIPHERLAST, VNCIPHER, VNCIPHERLAST, VPMSUMB, VPMSUMD, VPMSUMH, VPMSUMW, VSBOX)>;
- let CompleteModel = 0;
+ // Instructions of FPU pipeline
- let Itineraries = P8Itineraries;
-}
+ def : InstRW<[P8_FP_26C, P8_ISSUE_VSX], (instrs (instregex "^FDIVS(_rec)?$"), XSDIVSP)>;
+ def : InstRW<[P8_FP_28C, P8_ISSUE_VSX], (instrs XVDIVSP)>;
+ def : InstRW<[P8_FP_31C, P8_ISSUE_VSX], (instregex "^FSQRTS(_rec)?$")>;
+ def : InstRW<[P8_FP_Scal_32C, P8_ISSUE_VSX], (instrs FDIV, FDIV_rec, XSDIVDP)>;
+ def : InstRW<[P8_FP_2x64_32C, P8_ISSUE_VSX], (instrs XVDIVDP)>;
+ def : InstRW<[P8_FP_4x32_32C, P8_ISSUE_VSX], (instrs XVSQRTSP)>;
+ def : InstRW<[P8_FP_Scal_43C, P8_ISSUE_VSX], (instrs FSQRT, FSQRT_rec, XSSQRTDP)>;
+ def : InstRW<[P8_FP_2x64_43C, P8_ISSUE_VSX], (instrs XVSQRTDP)>;
+
+ def : InstRW<[P8_FP_3C, P8_ISSUE_VSX], (instrs
+ MTFSFI_rec, MTFSF_rec, MTFSFI, MTFSFIb, MTFSF, MTFSFb, MTFSB0, MTFSB1)>;
+
+ def : InstRW<[P8_FP_Scal_6C, P8_ISSUE_VSX], (instrs
+ (instregex "^F(N)?M(ADD|SUB)(S)?(_rec)?$"),
+ (instregex "^XS(N)?M(ADD|SUB)(A|M)(D|S)P$"),
+ (instregex "^FC(F|T)I(D|W)(U)?(S|Z)?(_rec)?$"),
+ (instregex "^(F|XS)(ABS|CPSGN|ADD|MUL|NABS|RE|NEG|SUB|SEL|RSQRTE)(D|S)?(P)?(s)?(_rec)?$"),
+ (instregex "^FRI(M|N|P|Z)(D|S)(_rec)?$"),
+ (instregex "^XSCVDP(S|U)X(W|D)S(s)?$"),
+ (instregex "^XSCV(S|U)XD(D|S)P$"),
+ (instregex "^XSCV(D|S)P(S|D)P(N)?$"),
+ (instregex "^XSRDPI(C|M|P|Z)?$"),
+ FMR, FRSP, FMR_rec, FRSP_rec, XSRSP)>;
+
+ def : InstRW<[P8_FP_4x32_6C, P8_ISSUE_VSX], (instrs
+ (instregex "^XV(N)?M(ADD|SUB)(A|M)SP$"),
+ (instregex "^VRFI(M|N|P|Z)$"),
+ XVRSQRTESP, XVSUBSP, VADDFP, VEXPTEFP, VLOGEFP, VMADDFP, VNMSUBFP, VREFP,
+ VRSQRTEFP, VSUBFP, XVCVSXWSP, XVCVUXWSP, XVMULSP, XVNABSSP, XVNEGSP, XVRESP,
+ XVCVDPSP, XVCVSXDSP, XVCVUXDSP, XVABSSP, XVADDSP, XVCPSGNSP)>;
+
+ def : InstRW<[P8_FP_2x64_6C, P8_ISSUE_VSX], (instrs
+ (instregex "^XVR(D|S)PI(C|M|P|Z)?$"),
+ (instregex "^XVCV(S|U)X(D|W)DP$"),
+ (instregex "^XVCV(D|W|S)P(S|U)X(D|W)S$"),
+ (instregex "^XV(N)?(M)?(RSQRTE|CPSGN|SUB|ADD|ABS|UL|NEG|RE)(A|M)?DP$"),
+ XVCVSPDP)>;
+
+ // Instructions of FX, LU or LS pipeline
+
+ def : InstRW<[P8_FX_NONE, P8_ISSUE_FX], (instrs TDI, TWI, TD, TW, MTCRF, MTCRF8, MTOCRF, MTOCRF8)>;
+ def : InstRW<[P8_FX_1C, P8_ISSUE_FX], (instregex "^RLWIMI(8)?$")>;
+ // TODO: Pipeline of logical instructions might be LS or FX
+ def : InstRW<[P8_FX_2C, P8_ISSUE_FX], (instrs
+ (instregex "^(N|X)?(EQV|AND|OR)(I)?(S|C)?(8)?(_rec)?$"),
+ (instregex "^EXTS(B|H|W)(8)?(_32)?(_64)?(_rec)?$"),
+ (instregex "^RL(D|W)(I)?(NM|C)(L|R)?(8)?(_32)?(_64)?(_rec)?$"),
+ (instregex "^S(L|R)(A)?(W|D)(I)?(8)?(_rec|_32)?$"),
+ (instregex "^(ADD|SUBF)(M|Z)?(C|E)?(4|8)?O(_rec)?$"),
+ (instregex "^(ADD|SUBF)(M|Z)?E(8)?_rec$"),
+ (instregex "^(ADD|SUBF|NEG)(4|8)?_rec$"),
+ NOP, ADDG6S, ADDG6S8, ADDZE, ADDZE8, ADDIC_rec, NEGO_rec, ADDC, ADDC8, SUBFC, SUBFC8,
+ ADDC_rec, ADDC8_rec, SUBFC_rec, SUBFC8_rec, COPY, NEG8O_rec,
+ RLDIMI, RLDIMI_rec, RLWIMI8_rec, RLWIMI_rec)>;
+
+ def : InstRW<[P8_FX_3C], (instregex "^(POP)?CNT(LZ)?(B|W|D)(8)?(_rec)?$")>;
+ def : InstRW<[P8_FX_5C, P8_ISSUE_FX], (instrs
+ (instregex "^MUL(H|L)(I|W|D)(8)?(U|O)?(_rec)?$"),
+ CMPDI,CMPWI,CMPD,CMPW,CMPLDI,CMPLWI,CMPLD,CMPLW,
+ ISEL, ISEL8, MTLR, MTLR8, MTCTR, MTCTR8, MTCTR8loop, MTCTRloop)>;
+
+ def : InstRW<[P8_FX_10C, P8_ISSUE_VSX], (instregex "^MFTB(8)?$")>;
+ def : InstRW<[P8_FX_15C, P8_ISSUE_FX], (instregex "^DIVW(U)?$")>;
+
+ def : InstRW<[P8_FX_23C, P8_ISSUE_FX], (instregex "^DIV(D|WE)(U)?$")>;
+ def : InstRW<[P8_FX_41C], (instrs
+ (instregex "^DIV(D|W)(E)?(U)?O(_rec)?$"),
+ (instregex "^DIV(D|W)(E)?(U)?_rec$"),
+ DIVDE, DIVDEU)>;
+
+ def : InstRW<[P8_LS_3C, P8_ISSUE_FX], (instrs MFSR, MFSRIN)>;
+
+ def : InstRW<[P8_LU_5C, P8_ISSUE_LD], (instrs
+ LFS, LFSX, LFD, LFDX, LFDXTLS, LFDXTLS_, LXVD2X, LXVW4X, LXVDSX, LVEBX, LVEHX, LVEWX,
+ LVX, LVXL, LXSDX, LFIWAX, LFIWZX, LFSXTLS, LFSXTLS_, LXVB16X, LXVD2X, LXSIWZX,
+ DFLOADf64, XFLOADf64, LIWZX)>;
+ def : InstRW<[P8_LS_FX_3C, P8_ISSUE_FXLD], (instrs LQ)>;
+ def : InstRW<[P8_LU_FX_5C, P8_ISSUE_LD], (instregex "^LF(D|S)U(X)?$")>;
+
+ def : InstRW<[P8_LS_FP_NONE, P8_ISSUE_ST], (instrs
+ STXSDX, STXVD2X, STXVW4X, STFIWX, STFS, STFSX, STFD, STFDX,
+ STFDEPX, STFDXTLS, STFDXTLS_, STFSXTLS, STFSXTLS_, STXSIWX, STXSSP, STXSSPX)>;
+
+ def : InstRW<[P8_LS_FP_FX_2C, P8_ISSUE_ST], (instrs STVEBX, STVEHX, STVEWX, STVX, STVXL)>;
+ def : InstRW<[P8_LS_FP_FX_3C, P8_ISSUE_ST], (instregex "^STF(D|S)U(X)?$")>;
+
+ def : InstRW<[P8_LS_LU_NONE, P8_ISSUE_ST], (instrs
+ (instregex "^ST(B|H|W|D)(U)?(X)?(8|TLS)?(_)?(32)?$"),
+ STBCIX, STBCX, STBEPX, STDBRX, STDCIX, STDCX, STHBRX, STHCIX, STHCX, STHEPX,
+ STMW, STSWI, STWBRX, STWCIX, STWCX, STWEPX)>;
+
+ def : InstRW<[P8_LU_or_LS_FX_3C, P8_ISSUE_FXLD],
+ (instregex "^L(B|H|W|D)(A|Z)?(U)?(X)?(8|TLS)?(_)?(32)?$")>;
+
+ def : InstRW<[P8_LU_or_LS_3C, P8_ISSUE_FXLD], (instrs
+ LBARX, LBARXL, LBEPX, LBZCIX, LDARX, LDARXL, LDBRX, LDCIX, LFDEPX, LHARX, LHARXL, LHBRX, LXSIWAX,
+ LHBRX8, LHEPX, LHZCIX, LMW, LSWI, LVSL, LVSR, LWARX, LWARXL, LWBRX, LWBRX8, LWEPX, LWZCIX)>;
+
+ def : InstRW<[P8_LU_or_LS_or_FX_2C, P8_ISSUE_FX], (instrs
+ (instregex "^ADDI(C)?(dtprel|tlsgd|toc)?(L)?(ADDR)?(32|8)?$"),
+ (instregex "^ADDIS(dtprel|tlsgd|toc|gotTprel)?(HA)?(32|8)?$"),
+ (instregex "^LI(S)?(8)?$"),
+ (instregex "^ADD(M)?(E)?(4|8)?(TLS)?(_)?$"),
+ (instregex "^SUBF(M|Z)?(E)?(IC)?(4|8)?$"),
+ (instregex "^NEG(8)?(O)?$"))>;
+
+ // Instructions of PM pipeline
+
+ def : InstRW<[P8_PM_2C, P8_ISSUE_VSX], (instrs
+ (instregex "^VPK(S|U)(H|W|D)(S|U)(M|S)$"),
+ (instregex "^VUPK(H|L)(P|S)(H|B|W|X)$"),
+ (instregex "^VSPLT(IS)?(B|H|W)(s)?$"),
+ (instregex "^(XX|V)MRG(E|O|H|L)(B|H|W)$"),
+ XXPERMDI, XXPERMDIs, XXSEL, XXSLDWI, XXSLDWIs, XXSPLTW, XXSPLTWs, VPERMXOR,
+ VPKPX, VPERM, VBPERMQ, VGBBD, VSEL, VSL, VSLDOI, VSLO, VSR, VSRO)>;
+
+ def : InstRW<[P8_XS_2C, P8_ISSUE_VSX], (instrs
+ (instregex "^V(ADD|SUB)(S|U)(B|H|W|D)(M|S)$"),
+ (instregex "^X(S|V)(MAX|MIN)(D|S)P$"),
+ (instregex "^V(S)?(R)?(L)?(A)?(B|D|H|W)$"),
+ (instregex "^VAVG(S|U)(B|H|W)$"),
+ (instregex "^VM(AX|IN)(S|U)(B|H|W|D)$"),
+ (instregex "^(XX|V)(L)?(N)?(X)?(AND|OR|EQV)(C)?$"),
+ (instregex "^(X)?VCMP(EQ|GT|GE|B)(F|S|U)?(B|H|W|D|P|S)(P)?(_rec)?$"),
+ (instregex "^VCLZ(B|H|W|D)$"),
+ (instregex "^VPOPCNT(B|H|W)$"),
+ XXLORf, XXLXORdpz, XXLXORspz, XXLXORz, VEQV, VMAXFP, VMINFP,
+ VSHASIGMAD, VSHASIGMAW, VSUBCUW, VADDCUW, MFVSCR, MTVSCR)>;
+
+ def : InstRW<[P8_XS_4C, P8_ISSUE_VSX], (instrs
+ (instregex "^V(ADD|SUB)(E)?(C)?UQ(M)?$"),
+ VPOPCNTD)>;
+
+ def : InstRW<[P8_XS_9C, P8_ISSUE_CR], (instrs
+ (instregex "^(F|XS)CMP(O|U)(D|S)(P)?$"),
+ (instregex "^(F|XS|XV)T(DIV|SQRT)((D|S)P)?$"))>;
+
+ // Instructions of VX pipeline
+
+ def : InstRW<[P8_VX_7C, P8_ISSUE_VSX], (instrs
+ (instregex "^V(M)?SUM(2|4)?(M|S|U)(B|H|W)(M|S)$"),
+ (instregex "^VMUL(E|O)?(S|U)(B|H|W)(M)?$"),
+ VMHADDSHS, VMHRADDSHS, VMLADDUHM)>;
+
+ // Instructions of BR pipeline
+
+ def : InstRW<[P8_BR_2C, P8_ISSUE_BR], (instrs
+ (instregex "^(g)?B(C)?(C)?(CTR)?(L)?(A)?(R)?(L)?(8)?(_LD|_LWZ)?(always|into_toc|at)?(_RM)?(n)?$"),
+ (instregex "^BD(N)?Z(L)?(R|A)?(L)?(m|p|8)?$"),
+ (instregex "^BL(R|A)?(8)?(_NOP)?(_TLS)?(_)?(RM)?$"))>;
+
+ // Instructions of DFP pipeline
+ // DFP operations also use float/vector/crypto issue ports.
+ def : InstRW<[P8_DFU_13C, P8_ISSUE_VSX], (instrs
+ (instregex "^DTST(D|S)(C|F|G)(Q)?$"),
+ (instregex "^D(Q|X)EX(Q)?(_rec)?$"),
+ (instregex "^D(ADD|SUB|IEX|QUA|RRND|RINTX|RINTN|CTDP|DEDPD|ENBCD)(_rec)?$"),
+ (instregex "^DSC(L|R)I(_rec)?$"),
+ BCDADD_rec, BCDSUB_rec, DCMPO, DCMPU, DTSTEX, DQUAI)>;
+
+ def : InstRW<[P8_DFU_15C, P8_ISSUE_VSX], (instrs
+ (instregex "^DRINT(N|X)Q(_rec)?$"),
+ DCMPOQ, DCMPUQ, DRRNDQ, DRRNDQ_rec, DIEXQ, DIEXQ_rec, DQUAIQ, DQUAIQ_rec,
+ DTSTEXQ, DDEDPDQ, DDEDPDQ_rec, DENBCDQ, DENBCDQ_rec, DSCLIQ, DSCLIQ_rec,
+ DSCRIQ, DSCRIQ_rec, DCTQPQ, DCTQPQ_rec)>;
+
+ def : InstRW<[P8_DFU_17C, P8_ISSUE_VSX], (instregex "^D(ADD|SUB|QUA)Q(_rec)?$")>;
+ def : InstRW<[P8_DFU_25C, P8_ISSUE_VSX], (instrs DRSP, DRSP_rec, DCTFIX, DCTFIX_rec)>;
+ def : InstRW<[P8_DFU_32C, P8_ISSUE_VSX], (instrs DCFFIX, DCFFIX_rec)>;
+ def : InstRW<[P8_DFU_34C, P8_ISSUE_VSX], (instrs DCFFIXQ, DCFFIXQ_rec)>;
+ def : InstRW<[P8_DFU_40C, P8_ISSUE_VSX], (instrs DMUL, DMUL_rec)>;
+ def : InstRW<[P8_DFU_90C, P8_ISSUE_VSX], (instrs DMULQ, DMULQ_rec)>;
+ def : InstRW<[P8_DFU_96C, P8_ISSUE_VSX], (instrs DDIV, DDIV_rec)>;
+ def : InstRW<[P8_DFU_172C, P8_ISSUE_VSX], (instrs DDIVQ, DDIVQ_rec)>;
+
+ // Direct move instructions
+
+ def : InstRW<[P8_DM_5C, P8_ISSUE_VSX], (instrs
+ MFVRD, MFVSRD, MFVRWZ, MFVSRWZ, MTVRD, MTVSRD, MTVRWA, MTVSRWA, MTVRWZ, MTVSRWZ)>;
+}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td
index b763191d980e..36befceef4ac 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td
@@ -227,17 +227,17 @@ let SchedModel = P9Model in {
}
def P9_DIV_16C_8 : SchedWriteRes<[DIV]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 16;
}
def P9_DIV_24C_8 : SchedWriteRes<[DIV]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 24;
}
def P9_DIV_40C_8 : SchedWriteRes<[DIV]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 40;
}
@@ -261,62 +261,62 @@ let SchedModel = P9Model in {
}
def P9_DP_22C_5 : SchedWriteRes<[DP]> {
- let ResourceCycles = [5];
+ let ReleaseAtCycles = [5];
let Latency = 22;
}
def P9_DPO_24C_8 : SchedWriteRes<[DPO]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 24;
}
def P9_DPE_24C_8 : SchedWriteRes<[DPE]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 24;
}
def P9_DP_26C_5 : SchedWriteRes<[DP]> {
- let ResourceCycles = [5];
+ let ReleaseAtCycles = [5];
let Latency = 22;
}
def P9_DPE_27C_10 : SchedWriteRes<[DP]> {
- let ResourceCycles = [10];
+ let ReleaseAtCycles = [10];
let Latency = 27;
}
def P9_DPO_27C_10 : SchedWriteRes<[DP]> {
- let ResourceCycles = [10];
+ let ReleaseAtCycles = [10];
let Latency = 27;
}
def P9_DP_33C_8 : SchedWriteRes<[DP]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 33;
}
def P9_DPE_33C_8 : SchedWriteRes<[DPE]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 33;
}
def P9_DPO_33C_8 : SchedWriteRes<[DPO]> {
- let ResourceCycles = [8];
+ let ReleaseAtCycles = [8];
let Latency = 33;
}
def P9_DP_36C_10 : SchedWriteRes<[DP]> {
- let ResourceCycles = [10];
+ let ReleaseAtCycles = [10];
let Latency = 36;
}
def P9_DPE_36C_10 : SchedWriteRes<[DP]> {
- let ResourceCycles = [10];
+ let ReleaseAtCycles = [10];
let Latency = 36;
}
def P9_DPO_36C_10 : SchedWriteRes<[DP]> {
- let ResourceCycles = [10];
+ let ReleaseAtCycles = [10];
let Latency = 36;
}
@@ -358,27 +358,27 @@ let SchedModel = P9Model in {
def P9_DFU_23C : SchedWriteRes<[DFU]> {
let Latency = 23;
- let ResourceCycles = [11];
+ let ReleaseAtCycles = [11];
}
def P9_DFU_24C : SchedWriteRes<[DFU]> {
let Latency = 24;
- let ResourceCycles = [12];
+ let ReleaseAtCycles = [12];
}
def P9_DFU_37C : SchedWriteRes<[DFU]> {
let Latency = 37;
- let ResourceCycles = [25];
+ let ReleaseAtCycles = [25];
}
def P9_DFU_58C : SchedWriteRes<[DFU]> {
let Latency = 58;
- let ResourceCycles = [44];
+ let ReleaseAtCycles = [44];
}
def P9_DFU_76C : SchedWriteRes<[DFU]> {
let Latency = 76;
- let ResourceCycles = [62];
+ let ReleaseAtCycles = [62];
}
// 2 or 5 cycle latencies for the branch unit.
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
index 49400eefe4a9..c9740818c9bf 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
@@ -123,6 +123,11 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,
// Determine endianness.
IsLittleEndian = TM.isLittleEndian();
+
+ if (HasAIXSmallLocalExecTLS && (!TargetTriple.isOSAIX() || !IsPPC64))
+ report_fatal_error(
+ "The aix-small-local-exec-tls attribute is only supported on AIX in "
+ "64-bit mode.\n", false);
}
bool PPCSubtarget::enableMachineScheduler() const { return true; }
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp
index 8120975c4fb2..81f078ab246e 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp
@@ -100,7 +100,7 @@ protected:
return true;
for (const MachineOperand &MO : MI.operands()) {
- if ((MO.getTargetFlags() & PPCII::MO_ACCESS_MASK) == PPCII::MO_TOC_LO)
+ if (MO.getTargetFlags() == PPCII::MO_TOC_LO)
return true;
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
index 3858d44e5099..d676fa86a10e 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -100,6 +100,11 @@ static cl::opt<bool>
cl::desc("Expand eligible cr-logical binary ops to branches"),
cl::init(true), cl::Hidden);
+static cl::opt<bool> MergeStringPool(
+ "ppc-merge-string-pool",
+ cl::desc("Merge all of the strings in a module into one pool"),
+ cl::init(true), cl::Hidden);
+
static cl::opt<bool> EnablePPCGenScalarMASSEntries(
"enable-ppc-gen-scalar-mass", cl::init(false),
cl::desc("Enable lowering math functions to their corresponding MASS "
@@ -137,6 +142,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTarget() {
initializeGlobalISel(PR);
initializePPCCTRLoopsPass(PR);
initializePPCDAGToDAGISelPass(PR);
+ initializePPCMergeStringPoolPass(PR);
}
static bool isLittleEndianTriple(const Triple &T) {
@@ -191,7 +197,7 @@ static std::string getDataLayoutString(const Triple &T) {
return Ret;
}
-static std::string computeFSAdditions(StringRef FS, CodeGenOpt::Level OL,
+static std::string computeFSAdditions(StringRef FS, CodeGenOptLevel OL,
const Triple &TT) {
std::string FullFS = std::string(FS);
@@ -203,14 +209,14 @@ static std::string computeFSAdditions(StringRef FS, CodeGenOpt::Level OL,
FullFS = "+64bit";
}
- if (OL >= CodeGenOpt::Default) {
+ if (OL >= CodeGenOptLevel::Default) {
if (!FullFS.empty())
FullFS = "+crbits," + FullFS;
else
FullFS = "+crbits";
}
- if (OL != CodeGenOpt::None) {
+ if (OL != CodeGenOptLevel::None) {
if (!FullFS.empty())
FullFS = "+invariant-function-descriptors," + FullFS;
else
@@ -236,9 +242,9 @@ static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT,
const TargetOptions &Options) {
- if (Options.MCOptions.getABIName().startswith("elfv1"))
+ if (Options.MCOptions.getABIName().starts_with("elfv1"))
return PPCTargetMachine::PPC_ABI_ELFv1;
- else if (Options.MCOptions.getABIName().startswith("elfv2"))
+ else if (Options.MCOptions.getABIName().starts_with("elfv2"))
return PPCTargetMachine::PPC_ABI_ELFv2;
assert(Options.MCOptions.getABIName().empty() &&
@@ -259,8 +265,9 @@ static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT,
static Reloc::Model getEffectiveRelocModel(const Triple &TT,
std::optional<Reloc::Model> RM) {
- assert((!TT.isOSAIX() || !RM || *RM == Reloc::PIC_) &&
- "Invalid relocation model for AIX.");
+ if (TT.isOSAIX() && RM && *RM != Reloc::PIC_)
+ report_fatal_error("invalid relocation model, AIX only supports PIC",
+ false);
if (RM)
return *RM;
@@ -339,7 +346,7 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT,
const TargetOptions &Options,
std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM,
- CodeGenOpt::Level OL, bool JIT)
+ CodeGenOptLevel OL, bool JIT)
: LLVMTargetMachine(T, getDataLayoutString(TT), TT, CPU,
computeFSAdditions(FS, OL, TT), Options,
getEffectiveRelocModel(TT, RM),
@@ -408,7 +415,7 @@ public:
: TargetPassConfig(TM, PM) {
// At any optimization level above -O0 we use the Machine Scheduler and not
// the default Post RA List Scheduler.
- if (TM.getOptLevel() != CodeGenOpt::None)
+ if (TM.getOptLevel() != CodeGenOptLevel::None)
substitutePass(&PostRASchedulerID, &PostMachineSchedulerID);
}
@@ -448,7 +455,7 @@ TargetPassConfig *PPCTargetMachine::createPassConfig(PassManagerBase &PM) {
}
void PPCPassConfig::addIRPasses() {
- if (TM->getOptLevel() != CodeGenOpt::None)
+ if (TM->getOptLevel() != CodeGenOptLevel::None)
addPass(createPPCBoolRetToIntPass());
addPass(createAtomicExpandPass());
@@ -457,7 +464,7 @@ void PPCPassConfig::addIRPasses() {
// Generate PowerPC target-specific entries for scalar math functions
// that are available in IBM MASS (scalar) library.
- if (TM->getOptLevel() == CodeGenOpt::Aggressive &&
+ if (TM->getOptLevel() == CodeGenOptLevel::Aggressive &&
EnablePPCGenScalarMASSEntries) {
TM->Options.PPCGenScalarMASSEntries = EnablePPCGenScalarMASSEntries;
addPass(createPPCGenScalarMASSEntriesPass());
@@ -467,7 +474,7 @@ void PPCPassConfig::addIRPasses() {
if (EnablePrefetch.getNumOccurrences() > 0)
addPass(createLoopDataPrefetchPass());
- if (TM->getOptLevel() >= CodeGenOpt::Default && EnableGEPOpt) {
+ if (TM->getOptLevel() >= CodeGenOptLevel::Default && EnableGEPOpt) {
// Call SeparateConstOffsetFromGEP pass to extract constants within indices
// and lower a GEP with multiple indices to either arithmetic operations or
// multiple GEPs with single index.
@@ -484,10 +491,13 @@ void PPCPassConfig::addIRPasses() {
}
bool PPCPassConfig::addPreISel() {
- if (!DisableInstrFormPrep && getOptLevel() != CodeGenOpt::None)
+ if (MergeStringPool && getOptLevel() != CodeGenOptLevel::None)
+ addPass(createPPCMergeStringPoolPass());
+
+ if (!DisableInstrFormPrep && getOptLevel() != CodeGenOptLevel::None)
addPass(createPPCLoopInstrFormPrepPass(getPPCTargetMachine()));
- if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None)
+ if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None)
addPass(createHardwareLoopsLegacyPass());
return false;
@@ -507,7 +517,7 @@ bool PPCPassConfig::addInstSelector() {
addPass(createPPCISelDag(getPPCTargetMachine(), getOptLevel()));
#ifndef NDEBUG
- if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None)
+ if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None)
addPass(createPPCCTRLoopsVerify());
#endif
@@ -518,12 +528,12 @@ bool PPCPassConfig::addInstSelector() {
void PPCPassConfig::addMachineSSAOptimization() {
// Run CTR loops pass before any cfg modification pass to prevent the
// canonical form of hardware loop from being destroied.
- if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None)
+ if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None)
addPass(createPPCCTRLoopsPass());
// PPCBranchCoalescingPass need to be done before machine sinking
// since it merges empty blocks.
- if (EnableBranchCoalescing && getOptLevel() != CodeGenOpt::None)
+ if (EnableBranchCoalescing && getOptLevel() != CodeGenOptLevel::None)
addPass(createPPCBranchCoalescingPass());
TargetPassConfig::addMachineSSAOptimization();
// For little endian, remove where possible the vector swap instructions
@@ -532,7 +542,7 @@ void PPCPassConfig::addMachineSSAOptimization() {
!DisableVSXSwapRemoval)
addPass(createPPCVSXSwapRemovalPass());
// Reduce the number of cr-logical ops.
- if (ReduceCRLogical && getOptLevel() != CodeGenOpt::None)
+ if (ReduceCRLogical && getOptLevel() != CodeGenOptLevel::None)
addPass(createPPCReduceCRLogicalsPass());
// Target-specific peephole cleanups performed after instruction
// selection.
@@ -543,7 +553,7 @@ void PPCPassConfig::addMachineSSAOptimization() {
}
void PPCPassConfig::addPreRegAlloc() {
- if (getOptLevel() != CodeGenOpt::None) {
+ if (getOptLevel() != CodeGenOptLevel::None) {
initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry());
insertPass(VSXFMAMutateEarly ? &RegisterCoalescerID : &MachineSchedulerID,
&PPCVSXFMAMutateID);
@@ -561,12 +571,12 @@ void PPCPassConfig::addPreRegAlloc() {
if (EnableExtraTOCRegDeps)
addPass(createPPCTOCRegDepsPass());
- if (getOptLevel() != CodeGenOpt::None)
+ if (getOptLevel() != CodeGenOptLevel::None)
addPass(&MachinePipelinerID);
}
void PPCPassConfig::addPreSched2() {
- if (getOptLevel() != CodeGenOpt::None)
+ if (getOptLevel() != CodeGenOptLevel::None)
addPass(&IfConverterID);
}
@@ -574,7 +584,7 @@ void PPCPassConfig::addPreEmitPass() {
addPass(createPPCPreEmitPeepholePass());
addPass(createPPCExpandISELPass());
- if (getOptLevel() != CodeGenOpt::None)
+ if (getOptLevel() != CodeGenOptLevel::None)
addPass(createPPCEarlyReturnPass());
}
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h
index 5d4571b7323a..56145a2eb39c 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h
@@ -39,7 +39,7 @@ public:
PPCTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
std::optional<Reloc::Model> RM,
- std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL,
+ std::optional<CodeModel::Model> CM, CodeGenOptLevel OL,
bool JIT);
~PPCTargetMachine() override;
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
index 8137b61f4982..062b53e24a0d 100644
--- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
@@ -18,7 +18,6 @@
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/KnownBits.h"
#include "llvm/Transforms/InstCombine/InstCombiner.h"
#include "llvm/Transforms/Utils/Local.h"
#include <optional>
@@ -27,6 +26,9 @@ using namespace llvm;
#define DEBUG_TYPE "ppctti"
+static cl::opt<bool> VecMaskCost("ppc-vec-mask-cost",
+cl::desc("add masking cost for i1 vectors"), cl::init(true), cl::Hidden);
+
static cl::opt<bool> DisablePPCConstHoist("disable-ppc-constant-hoisting",
cl::desc("disable constant hoisting on PPC"), cl::init(false), cl::Hidden);
@@ -73,16 +75,14 @@ PPCTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
if (getOrEnforceKnownAlignment(
II.getArgOperand(0), Align(16), IC.getDataLayout(), &II,
&IC.getAssumptionCache(), &IC.getDominatorTree()) >= 16) {
- Value *Ptr = IC.Builder.CreateBitCast(
- II.getArgOperand(0), PointerType::getUnqual(II.getType()));
+ Value *Ptr = II.getArgOperand(0);
return new LoadInst(II.getType(), Ptr, "", false, Align(16));
}
break;
case Intrinsic::ppc_vsx_lxvw4x:
case Intrinsic::ppc_vsx_lxvd2x: {
// Turn PPC VSX loads into normal loads.
- Value *Ptr = IC.Builder.CreateBitCast(II.getArgOperand(0),
- PointerType::getUnqual(II.getType()));
+ Value *Ptr = II.getArgOperand(0);
return new LoadInst(II.getType(), Ptr, Twine(""), false, Align(1));
}
case Intrinsic::ppc_altivec_stvx:
@@ -91,16 +91,14 @@ PPCTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
if (getOrEnforceKnownAlignment(
II.getArgOperand(1), Align(16), IC.getDataLayout(), &II,
&IC.getAssumptionCache(), &IC.getDominatorTree()) >= 16) {
- Type *OpPtrTy = PointerType::getUnqual(II.getArgOperand(0)->getType());
- Value *Ptr = IC.Builder.CreateBitCast(II.getArgOperand(1), OpPtrTy);
+ Value *Ptr = II.getArgOperand(1);
return new StoreInst(II.getArgOperand(0), Ptr, false, Align(16));
}
break;
case Intrinsic::ppc_vsx_stxvw4x:
case Intrinsic::ppc_vsx_stxvd2x: {
// Turn PPC VSX stores into normal stores.
- Type *OpPtrTy = PointerType::getUnqual(II.getArgOperand(0)->getType());
- Value *Ptr = IC.Builder.CreateBitCast(II.getArgOperand(1), OpPtrTy);
+ Value *Ptr = II.getArgOperand(1);
return new StoreInst(II.getArgOperand(0), Ptr, false, Align(1));
}
case Intrinsic::ppc_altivec_vperm:
@@ -700,6 +698,9 @@ InstructionCost PPCTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val,
return Cost;
} else if (Val->getScalarType()->isIntegerTy() && Index != -1U) {
+ unsigned EltSize = Val->getScalarSizeInBits();
+ // Computing on 1 bit values requires extra mask or compare operations.
+ unsigned MaskCost = VecMaskCost && EltSize == 1 ? 1 : 0;
if (ST->hasP9Altivec()) {
if (ISD == ISD::INSERT_VECTOR_ELT)
// A move-to VSR and a permute/insert. Assume vector operation cost
@@ -721,12 +722,15 @@ InstructionCost PPCTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val,
// We need a vector extract (or mfvsrld). Assume vector operation cost.
// The cost of the load constant for a vector extract is disregarded
// (invariant, easily schedulable).
- return CostFactor;
+ return CostFactor + MaskCost;
- } else if (ST->hasDirectMove())
+ } else if (ST->hasDirectMove()) {
// Assume permute has standard cost.
// Assume move-to/move-from VSR have 2x standard cost.
- return 3;
+ if (ISD == ISD::INSERT_VECTOR_ELT)
+ return 3;
+ return 3 + MaskCost;
+ }
}
// Estimated cost of a load-hit-store delay. This was obtained