summaryrefslogtreecommitdiff
path: root/gnu/llvm
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2020-08-03 14:30:26 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2020-08-03 14:30:26 +0000
commit98796c6ed5bcaf7f6a1c132d15ed6d1abbb25c96 (patch)
treefb2fd7662d373eb37bf932200ab46cc79f0025a9 /gnu/llvm
parenteb93e80b081aeb1b8a4872c14050335dc72afa65 (diff)
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom tested by plenty
Diffstat (limited to 'gnu/llvm')
-rw-r--r--gnu/llvm/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp2203
1 files changed, 621 insertions, 1582 deletions
diff --git a/gnu/llvm/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/gnu/llvm/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index d80a33ff606..776ec52e260 100644
--- a/gnu/llvm/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/gnu/llvm/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -28,7 +28,6 @@
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -44,7 +43,6 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
-#include "llvm/IR/IntrinsicsPowerPC.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
@@ -68,8 +66,7 @@
using namespace llvm;
-#define DEBUG_TYPE "ppc-isel"
-#define PASS_NAME "PowerPC DAG->DAG Pattern Instruction Selection"
+#define DEBUG_TYPE "ppc-codegen"
STATISTIC(NumSextSetcc,
"Number of (sext(setcc)) nodes expanded into GPR sequence.");
@@ -141,34 +138,24 @@ namespace {
///
class PPCDAGToDAGISel : public SelectionDAGISel {
const PPCTargetMachine &TM;
- const PPCSubtarget *Subtarget = nullptr;
+ const PPCSubtarget *PPCSubTarget = nullptr;
const PPCTargetLowering *PPCLowering = nullptr;
unsigned GlobalBaseReg = 0;
public:
- static char ID;
-
- PPCDAGToDAGISel() = delete;
-
explicit PPCDAGToDAGISel(PPCTargetMachine &tm, CodeGenOpt::Level OptLevel)
- : SelectionDAGISel(ID, tm, OptLevel), TM(tm) {}
+ : SelectionDAGISel(tm, OptLevel), TM(tm) {}
bool runOnMachineFunction(MachineFunction &MF) override {
// Make sure we re-emit a set of the global base reg if necessary
GlobalBaseReg = 0;
- Subtarget = &MF.getSubtarget<PPCSubtarget>();
- PPCLowering = Subtarget->getTargetLowering();
- if (Subtarget->hasROPProtect()) {
- // Create a place on the stack for the ROP Protection Hash.
- // The ROP Protection Hash will always be 8 bytes and aligned to 8
- // bytes.
- MachineFrameInfo &MFI = MF.getFrameInfo();
- PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
- const int Result = MFI.CreateStackObject(8, Align(8), false);
- FI->setROPProtectionHashSaveIndex(Result);
- }
+ PPCSubTarget = &MF.getSubtarget<PPCSubtarget>();
+ PPCLowering = PPCSubTarget->getTargetLowering();
SelectionDAGISel::runOnMachineFunction(MF);
+ if (!PPCSubTarget->isSVR4ABI())
+ InsertVRSaveCode(MF);
+
return true;
}
@@ -194,7 +181,7 @@ namespace {
}
/// getSmallIPtrImm - Return a target constant of pointer type.
- inline SDValue getSmallIPtrImm(uint64_t Imm, const SDLoc &dl) {
+ inline SDValue getSmallIPtrImm(unsigned Imm, const SDLoc &dl) {
return CurDAG->getTargetConstant(
Imm, dl, PPCLowering->getPointerTy(CurDAG->getDataLayout()));
}
@@ -208,7 +195,7 @@ namespace {
/// base register. Return the virtual register that holds this value.
SDNode *getGlobalBaseReg();
- void selectFrameIndex(SDNode *SN, SDNode *N, uint64_t Offset = 0);
+ void selectFrameIndex(SDNode *SN, SDNode *N, unsigned Offset = 0);
// Select - Convert the specified operand from a target-independent to a
// target-specific node if it hasn't already been changed.
@@ -217,6 +204,7 @@ namespace {
bool tryBitfieldInsert(SDNode *N);
bool tryBitPermutation(SDNode *N);
bool tryIntCompareInGPR(SDNode *N);
+ bool tryAndWithMask(SDNode *N);
// tryTLSXFormLoad - Convert an ISD::LOAD fed by a PPCISD::ADD_TLS into
// an X-Form load instruction with the offset being a relocation coming from
@@ -229,7 +217,7 @@ namespace {
/// SelectCC - Select a comparison of the specified values with the
/// specified condition code, returning the CR# of the expression.
SDValue SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
- const SDLoc &dl, SDValue Chain = SDValue());
+ const SDLoc &dl);
/// SelectAddrImmOffs - Return true if the operand is valid for a preinc
/// immediate field. Note that the operand at this point is already the
@@ -244,61 +232,6 @@ namespace {
return false;
}
- /// SelectDSForm - Returns true if address N can be represented by the
- /// addressing mode of DSForm instructions (a base register, plus a signed
- /// 16-bit displacement that is a multiple of 4.
- bool SelectDSForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
- Align(4)) == PPC::AM_DSForm;
- }
-
- /// SelectDQForm - Returns true if address N can be represented by the
- /// addressing mode of DQForm instructions (a base register, plus a signed
- /// 16-bit displacement that is a multiple of 16.
- bool SelectDQForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
- Align(16)) == PPC::AM_DQForm;
- }
-
- /// SelectDForm - Returns true if address N can be represented by
- /// the addressing mode of DForm instructions (a base register, plus a
- /// signed 16-bit immediate.
- bool SelectDForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
- std::nullopt) == PPC::AM_DForm;
- }
-
- /// SelectPCRelForm - Returns true if address N can be represented by
- /// PC-Relative addressing mode.
- bool SelectPCRelForm(SDNode *Parent, SDValue N, SDValue &Disp,
- SDValue &Base) {
- return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
- std::nullopt) == PPC::AM_PCRel;
- }
-
- /// SelectPDForm - Returns true if address N can be represented by Prefixed
- /// DForm addressing mode (a base register, plus a signed 34-bit immediate.
- bool SelectPDForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
- std::nullopt) ==
- PPC::AM_PrefixDForm;
- }
-
- /// SelectXForm - Returns true if address N can be represented by the
- /// addressing mode of XForm instructions (an indexed [r+r] operation).
- bool SelectXForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
- std::nullopt) == PPC::AM_XForm;
- }
-
- /// SelectForceXForm - Given the specified address, force it to be
- /// represented as an indexed [r+r] operation (an XForm instruction).
- bool SelectForceXForm(SDNode *Parent, SDValue N, SDValue &Disp,
- SDValue &Base) {
- return PPCLowering->SelectForceXFormMode(N, Disp, Base, *CurDAG) ==
- PPC::AM_XForm;
- }
-
/// SelectAddrIdx - Given the specified address, check to see if it can be
/// represented as an indexed [r+r] operation.
/// This is for xform instructions whose associated displacement form is D.
@@ -306,8 +239,7 @@ namespace {
/// bit signed displacement.
/// Returns false if it can be represented by [r+imm], which are preferred.
bool SelectAddrIdx(SDValue N, SDValue &Base, SDValue &Index) {
- return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG,
- std::nullopt);
+ return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG, 0);
}
/// SelectAddrIdx4 - Given the specified address, check to see if it can be
@@ -317,8 +249,7 @@ namespace {
/// displacement must be a multiple of 4.
/// Returns false if it can be represented by [r+imm], which are preferred.
bool SelectAddrIdxX4(SDValue N, SDValue &Base, SDValue &Index) {
- return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG,
- Align(4));
+ return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG, 4);
}
/// SelectAddrIdx16 - Given the specified address, check to see if it can be
@@ -328,8 +259,7 @@ namespace {
/// displacement must be a multiple of 16.
/// Returns false if it can be represented by [r+imm], which are preferred.
bool SelectAddrIdxX16(SDValue N, SDValue &Base, SDValue &Index) {
- return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG,
- Align(16));
+ return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG, 16);
}
/// SelectAddrIdxOnly - Given the specified address, force it to be
@@ -337,37 +267,28 @@ namespace {
bool SelectAddrIdxOnly(SDValue N, SDValue &Base, SDValue &Index) {
return PPCLowering->SelectAddressRegRegOnly(N, Base, Index, *CurDAG);
}
-
+
/// SelectAddrImm - Returns true if the address N can be represented by
/// a base register plus a signed 16-bit displacement [r+imm].
/// The last parameter \p 0 means D form has no requirment for 16 bit signed
/// displacement.
bool SelectAddrImm(SDValue N, SDValue &Disp,
SDValue &Base) {
- return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG,
- std::nullopt);
+ return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG, 0);
}
/// SelectAddrImmX4 - Returns true if the address N can be represented by
/// a base register plus a signed 16-bit displacement that is a multiple of
/// 4 (last parameter). Suitable for use by STD and friends.
bool SelectAddrImmX4(SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG, Align(4));
+ return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG, 4);
}
/// SelectAddrImmX16 - Returns true if the address N can be represented by
/// a base register plus a signed 16-bit displacement that is a multiple of
/// 16(last parameter). Suitable for use by STXV and friends.
bool SelectAddrImmX16(SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG,
- Align(16));
- }
-
- /// SelectAddrImmX34 - Returns true if the address N can be represented by
- /// a base register plus a signed 34-bit displacement. Suitable for use by
- /// PSTXVP and friends.
- bool SelectAddrImmX34(SDValue N, SDValue &Disp, SDValue &Base) {
- return PPCLowering->SelectAddressRegImm34(N, Disp, Base, *CurDAG);
+ return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG, 16);
}
// Select an address into a single register.
@@ -376,10 +297,6 @@ namespace {
return true;
}
- bool SelectAddrPCRel(SDValue N, SDValue &Base) {
- return PPCLowering->SelectAddressPCRel(N, Base);
- }
-
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions. It is always correct to compute the value into
/// a register. The case of adding a (possibly relocatable) constant to a
@@ -400,7 +317,7 @@ namespace {
case InlineAsm::Constraint_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();
+ const TargetRegisterInfo *TRI = PPCSubTarget->getRegisterInfo();
const TargetRegisterClass *TRC = TRI->getPointerRegClass(*MF, /*Kind=*/1);
SDLoc dl(Op);
SDValue RC = CurDAG->getTargetConstant(TRC->getID(), dl, MVT::i32);
@@ -415,20 +332,17 @@ namespace {
return true;
}
+ void InsertVRSaveCode(MachineFunction &MF);
+
+ StringRef getPassName() const override {
+ return "PowerPC DAG->DAG Pattern Instruction Selection";
+ }
+
// Include the pieces autogenerated from the target description.
#include "PPCGenDAGISel.inc"
private:
bool trySETCC(SDNode *N);
- bool tryFoldSWTestBRCC(SDNode *N);
- bool trySelectLoopCountIntrinsic(SDNode *N);
- bool tryAsSingleRLDICL(SDNode *N);
- bool tryAsSingleRLDICR(SDNode *N);
- bool tryAsSingleRLWINM(SDNode *N);
- bool tryAsSingleRLWINM8(SDNode *N);
- bool tryAsSingleRLWIMI(SDNode *N);
- bool tryAsPairOfRLDICL(SDNode *N);
- bool tryAsSingleRLDIMI(SDNode *N);
void PeepholePPC64();
void PeepholePPC64ZExt();
@@ -446,16 +360,76 @@ private:
} // end anonymous namespace
-char PPCDAGToDAGISel::ID = 0;
+/// InsertVRSaveCode - Once the entire function has been instruction selected,
+/// all virtual registers are created and all machine instructions are built,
+/// check to see if we need to save/restore VRSAVE. If so, do it.
+void PPCDAGToDAGISel::InsertVRSaveCode(MachineFunction &Fn) {
+ // Check to see if this function uses vector registers, which means we have to
+ // save and restore the VRSAVE register and update it with the regs we use.
+ //
+ // In this case, there will be virtual registers of vector type created
+ // by the scheduler. Detect them now.
+ bool HasVectorVReg = false;
+ for (unsigned i = 0, e = RegInfo->getNumVirtRegs(); i != e; ++i) {
+ unsigned Reg = Register::index2VirtReg(i);
+ if (RegInfo->getRegClass(Reg) == &PPC::VRRCRegClass) {
+ HasVectorVReg = true;
+ break;
+ }
+ }
+ if (!HasVectorVReg) return; // nothing to do.
-INITIALIZE_PASS(PPCDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
+ // If we have a vector register, we want to emit code into the entry and exit
+ // blocks to save and restore the VRSAVE register. We do this here (instead
+ // of marking all vector instructions as clobbering VRSAVE) for two reasons:
+ //
+ // 1. This (trivially) reduces the load on the register allocator, by not
+ // having to represent the live range of the VRSAVE register.
+ // 2. This (more significantly) allows us to create a temporary virtual
+ // register to hold the saved VRSAVE value, allowing this temporary to be
+ // register allocated, instead of forcing it to be spilled to the stack.
+
+ // Create two vregs - one to hold the VRSAVE register that is live-in to the
+ // function and one for the value after having bits or'd into it.
+ Register InVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass);
+ Register UpdatedVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass);
+
+ const TargetInstrInfo &TII = *PPCSubTarget->getInstrInfo();
+ MachineBasicBlock &EntryBB = *Fn.begin();
+ DebugLoc dl;
+ // Emit the following code into the entry block:
+ // InVRSAVE = MFVRSAVE
+ // UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE
+ // MTVRSAVE UpdatedVRSAVE
+ MachineBasicBlock::iterator IP = EntryBB.begin(); // Insert Point
+ BuildMI(EntryBB, IP, dl, TII.get(PPC::MFVRSAVE), InVRSAVE);
+ BuildMI(EntryBB, IP, dl, TII.get(PPC::UPDATE_VRSAVE),
+ UpdatedVRSAVE).addReg(InVRSAVE);
+ BuildMI(EntryBB, IP, dl, TII.get(PPC::MTVRSAVE)).addReg(UpdatedVRSAVE);
+
+ // Find all return blocks, outputting a restore in each epilog.
+ for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
+ if (BB->isReturnBlock()) {
+ IP = BB->end(); --IP;
+
+ // Skip over all terminator instructions, which are part of the return
+ // sequence.
+ MachineBasicBlock::iterator I2 = IP;
+ while (I2 != BB->begin() && (--I2)->isTerminator())
+ IP = I2;
+
+ // Emit: MTVRSAVE InVRSave
+ BuildMI(*BB, IP, dl, TII.get(PPC::MTVRSAVE)).addReg(InVRSAVE);
+ }
+ }
+}
/// getGlobalBaseReg - Output the instructions required to put the
/// base address to use for accessing globals into a register.
///
SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {
if (!GlobalBaseReg) {
- const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
+ const TargetInstrInfo &TII = *PPCSubTarget->getInstrInfo();
// Insert the set of GlobalBaseReg into the first MBB of the function
MachineBasicBlock &FirstMBB = MF->front();
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
@@ -463,9 +437,9 @@ SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {
DebugLoc dl;
if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) == MVT::i32) {
- if (Subtarget->isTargetELF()) {
+ if (PPCSubTarget->isTargetELF()) {
GlobalBaseReg = PPC::R30;
- if (!Subtarget->isSecurePlt() &&
+ if (!PPCSubTarget->isSecurePlt() &&
M->getPICLevel() == PICLevel::SmallPIC) {
BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MoveGOTtoLR));
BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg);
@@ -506,58 +480,6 @@ SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {
.getNode();
}
-// Check if a SDValue has the toc-data attribute.
-static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) {
- GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Val);
- if (!GA)
- return false;
-
- const GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(GA->getGlobal());
- if (!GV)
- return false;
-
- if (!GV->hasAttribute("toc-data"))
- return false;
-
- // TODO: These asserts should be updated as more support for the toc data
- // transformation is added (struct support, etc.).
-
- assert(
- PointerSize >= GV->getAlign().valueOrOne().value() &&
- "GlobalVariables with an alignment requirement stricter than TOC entry "
- "size not supported by the toc data transformation.");
-
- Type *GVType = GV->getValueType();
-
- assert(GVType->isSized() && "A GlobalVariable's size must be known to be "
- "supported by the toc data transformation.");
-
- if (GVType->isVectorTy())
- report_fatal_error("A GlobalVariable of Vector type is not currently "
- "supported by the toc data transformation.");
-
- if (GVType->isArrayTy())
- report_fatal_error("A GlobalVariable of Array type is not currently "
- "supported by the toc data transformation.");
-
- if (GVType->isStructTy())
- report_fatal_error("A GlobalVariable of Struct type is not currently "
- "supported by the toc data transformation.");
-
- assert(GVType->getPrimitiveSizeInBits() <= PointerSize * 8 &&
- "A GlobalVariable with size larger than a TOC entry is not currently "
- "supported by the toc data transformation.");
-
- if (GV->hasLocalLinkage() || GV->hasPrivateLinkage())
- report_fatal_error("A GlobalVariable with private or local linkage is not "
- "currently supported by the toc data transformation.");
-
- assert(!GV->hasCommonLinkage() &&
- "Tentative definitions cannot have the mapping class XMC_TD.");
-
- return true;
-}
-
/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
/// operand. If so Imm will receive the 32-bit value.
static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
@@ -649,7 +571,7 @@ static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
&& isInt32Immediate(N->getOperand(1).getNode(), Imm);
}
-void PPCDAGToDAGISel::selectFrameIndex(SDNode *SN, SDNode *N, uint64_t Offset) {
+void PPCDAGToDAGISel::selectFrameIndex(SDNode *SN, SDNode *N, unsigned Offset) {
SDLoc dl(SN);
int FI = cast<FrameIndexSDNode>(N)->getIndex();
SDValue TFI = CurDAG->getTargetFrameIndex(FI, N->getValueType(0));
@@ -711,8 +633,6 @@ bool PPCDAGToDAGISel::tryTLSXFormStore(StoreSDNode *ST) {
SDValue Offset = ST->getOffset();
if (!Offset.isUndef())
return false;
- if (Base.getOperand(1).getOpcode() == PPCISD::TLS_LOCAL_EXEC_MAT_ADDR)
- return false;
SDLoc dl(ST);
EVT MemVT = ST->getMemoryVT();
@@ -756,8 +676,6 @@ bool PPCDAGToDAGISel::tryTLSXFormLoad(LoadSDNode *LD) {
SDValue Offset = LD->getOffset();
if (!Offset.isUndef())
return false;
- if (Base.getOperand(1).getOpcode() == PPCISD::TLS_LOCAL_EXEC_MAT_ADDR)
- return false;
SDLoc dl(LD);
EVT MemVT = LD->getMemoryVT();
@@ -867,6 +785,251 @@ bool PPCDAGToDAGISel::tryBitfieldInsert(SDNode *N) {
return false;
}
+// Predict the number of instructions that would be generated by calling
+// selectI64Imm(N).
+static unsigned selectI64ImmInstrCountDirect(int64_t Imm) {
+ // Assume no remaining bits.
+ unsigned Remainder = 0;
+ // Assume no shift required.
+ unsigned Shift = 0;
+
+ // If it can't be represented as a 32 bit value.
+ if (!isInt<32>(Imm)) {
+ Shift = countTrailingZeros<uint64_t>(Imm);
+ int64_t ImmSh = static_cast<uint64_t>(Imm) >> Shift;
+
+ // If the shifted value fits 32 bits.
+ if (isInt<32>(ImmSh)) {
+ // Go with the shifted value.
+ Imm = ImmSh;
+ } else {
+ // Still stuck with a 64 bit value.
+ Remainder = Imm;
+ Shift = 32;
+ Imm >>= 32;
+ }
+ }
+
+ // Intermediate operand.
+ unsigned Result = 0;
+
+ // Handle first 32 bits.
+ unsigned Lo = Imm & 0xFFFF;
+
+ // Simple value.
+ if (isInt<16>(Imm)) {
+ // Just the Lo bits.
+ ++Result;
+ } else if (Lo) {
+ // Handle the Hi bits and Lo bits.
+ Result += 2;
+ } else {
+ // Just the Hi bits.
+ ++Result;
+ }
+
+ // If no shift, we're done.
+ if (!Shift) return Result;
+
+ // If Hi word == Lo word,
+ // we can use rldimi to insert the Lo word into Hi word.
+ if ((unsigned)(Imm & 0xFFFFFFFF) == Remainder) {
+ ++Result;
+ return Result;
+ }
+
+ // Shift for next step if the upper 32-bits were not zero.
+ if (Imm)
+ ++Result;
+
+ // Add in the last bits as required.
+ if ((Remainder >> 16) & 0xFFFF)
+ ++Result;
+ if (Remainder & 0xFFFF)
+ ++Result;
+
+ return Result;
+}
+
+static uint64_t Rot64(uint64_t Imm, unsigned R) {
+ return (Imm << R) | (Imm >> (64 - R));
+}
+
+static unsigned selectI64ImmInstrCount(int64_t Imm) {
+ unsigned Count = selectI64ImmInstrCountDirect(Imm);
+
+ // If the instruction count is 1 or 2, we do not need further analysis
+ // since rotate + load constant requires at least 2 instructions.
+ if (Count <= 2)
+ return Count;
+
+ for (unsigned r = 1; r < 63; ++r) {
+ uint64_t RImm = Rot64(Imm, r);
+ unsigned RCount = selectI64ImmInstrCountDirect(RImm) + 1;
+ Count = std::min(Count, RCount);
+
+ // See comments in selectI64Imm for an explanation of the logic below.
+ unsigned LS = findLastSet(RImm);
+ if (LS != r-1)
+ continue;
+
+ uint64_t OnesMask = -(int64_t) (UINT64_C(1) << (LS+1));
+ uint64_t RImmWithOnes = RImm | OnesMask;
+
+ RCount = selectI64ImmInstrCountDirect(RImmWithOnes) + 1;
+ Count = std::min(Count, RCount);
+ }
+
+ return Count;
+}
+
+// Select a 64-bit constant. For cost-modeling purposes, selectI64ImmInstrCount
+// (above) needs to be kept in sync with this function.
+static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl,
+ int64_t Imm) {
+ // Assume no remaining bits.
+ unsigned Remainder = 0;
+ // Assume no shift required.
+ unsigned Shift = 0;
+
+ // If it can't be represented as a 32 bit value.
+ if (!isInt<32>(Imm)) {
+ Shift = countTrailingZeros<uint64_t>(Imm);
+ int64_t ImmSh = static_cast<uint64_t>(Imm) >> Shift;
+
+ // If the shifted value fits 32 bits.
+ if (isInt<32>(ImmSh)) {
+ // Go with the shifted value.
+ Imm = ImmSh;
+ } else {
+ // Still stuck with a 64 bit value.
+ Remainder = Imm;
+ Shift = 32;
+ Imm >>= 32;
+ }
+ }
+
+ // Intermediate operand.
+ SDNode *Result;
+
+ // Handle first 32 bits.
+ unsigned Lo = Imm & 0xFFFF;
+ unsigned Hi = (Imm >> 16) & 0xFFFF;
+
+ auto getI32Imm = [CurDAG, dl](unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
+ };
+
+ // Simple value.
+ if (isInt<16>(Imm)) {
+ uint64_t SextImm = SignExtend64(Lo, 16);
+ SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i64);
+ // Just the Lo bits.
+ Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, SDImm);
+ } else if (Lo) {
+ // Handle the Hi bits.
+ unsigned OpC = Hi ? PPC::LIS8 : PPC::LI8;
+ Result = CurDAG->getMachineNode(OpC, dl, MVT::i64, getI32Imm(Hi));
+ // And Lo bits.
+ Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64,
+ SDValue(Result, 0), getI32Imm(Lo));
+ } else {
+ // Just the Hi bits.
+ Result = CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(Hi));
+ }
+
+ // If no shift, we're done.
+ if (!Shift) return Result;
+
+ // If Hi word == Lo word,
+ // we can use rldimi to insert the Lo word into Hi word.
+ if ((unsigned)(Imm & 0xFFFFFFFF) == Remainder) {
+ SDValue Ops[] =
+ { SDValue(Result, 0), SDValue(Result, 0), getI32Imm(Shift), getI32Imm(0)};
+ return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
+ }
+
+ // Shift for next step if the upper 32-bits were not zero.
+ if (Imm) {
+ Result = CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64,
+ SDValue(Result, 0),
+ getI32Imm(Shift),
+ getI32Imm(63 - Shift));
+ }
+
+ // Add in the last bits as required.
+ if ((Hi = (Remainder >> 16) & 0xFFFF)) {
+ Result = CurDAG->getMachineNode(PPC::ORIS8, dl, MVT::i64,
+ SDValue(Result, 0), getI32Imm(Hi));
+ }
+ if ((Lo = Remainder & 0xFFFF)) {
+ Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64,
+ SDValue(Result, 0), getI32Imm(Lo));
+ }
+
+ return Result;
+}
+
+static SDNode *selectI64Imm(SelectionDAG *CurDAG, const SDLoc &dl,
+ int64_t Imm) {
+ unsigned Count = selectI64ImmInstrCountDirect(Imm);
+
+ // If the instruction count is 1 or 2, we do not need further analysis
+ // since rotate + load constant requires at least 2 instructions.
+ if (Count <= 2)
+ return selectI64ImmDirect(CurDAG, dl, Imm);
+
+ unsigned RMin = 0;
+
+ int64_t MatImm;
+ unsigned MaskEnd;
+
+ for (unsigned r = 1; r < 63; ++r) {
+ uint64_t RImm = Rot64(Imm, r);
+ unsigned RCount = selectI64ImmInstrCountDirect(RImm) + 1;
+ if (RCount < Count) {
+ Count = RCount;
+ RMin = r;
+ MatImm = RImm;
+ MaskEnd = 63;
+ }
+
+ // If the immediate to generate has many trailing zeros, it might be
+ // worthwhile to generate a rotated value with too many leading ones
+ // (because that's free with li/lis's sign-extension semantics), and then
+ // mask them off after rotation.
+
+ unsigned LS = findLastSet(RImm);
+ // We're adding (63-LS) higher-order ones, and we expect to mask them off
+ // after performing the inverse rotation by (64-r). So we need that:
+ // 63-LS == 64-r => LS == r-1
+ if (LS != r-1)
+ continue;
+
+ uint64_t OnesMask = -(int64_t) (UINT64_C(1) << (LS+1));
+ uint64_t RImmWithOnes = RImm | OnesMask;
+
+ RCount = selectI64ImmInstrCountDirect(RImmWithOnes) + 1;
+ if (RCount < Count) {
+ Count = RCount;
+ RMin = r;
+ MatImm = RImmWithOnes;
+ MaskEnd = LS;
+ }
+ }
+
+ if (!RMin)
+ return selectI64ImmDirect(CurDAG, dl, Imm);
+
+ auto getI32Imm = [CurDAG, dl](unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
+ };
+
+ SDValue Val = SDValue(selectI64ImmDirect(CurDAG, dl, MatImm), 0);
+ return CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Val,
+ getI32Imm(64 - RMin), getI32Imm(MaskEnd));
+}
+
static unsigned allUsesTruncate(SelectionDAG *CurDAG, SDNode *N) {
unsigned MaxTruncation = 0;
// Cannot use range-based for loop here as we need the actual use (i.e. we
@@ -923,421 +1086,6 @@ static unsigned allUsesTruncate(SelectionDAG *CurDAG, SDNode *N) {
return MaxTruncation;
}
-// For any 32 < Num < 64, check if the Imm contains at least Num consecutive
-// zeros and return the number of bits by the left of these consecutive zeros.
-static int findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) {
- unsigned HiTZ = countTrailingZeros<uint32_t>(Hi_32(Imm));
- unsigned LoLZ = countLeadingZeros<uint32_t>(Lo_32(Imm));
- if ((HiTZ + LoLZ) >= Num)
- return (32 + HiTZ);
- return 0;
-}
-
-// Direct materialization of 64-bit constants by enumerated patterns.
-static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl,
- uint64_t Imm, unsigned &InstCnt) {
- unsigned TZ = countTrailingZeros<uint64_t>(Imm);
- unsigned LZ = countLeadingZeros<uint64_t>(Imm);
- unsigned TO = countTrailingOnes<uint64_t>(Imm);
- unsigned LO = countLeadingOnes<uint64_t>(Imm);
- unsigned Hi32 = Hi_32(Imm);
- unsigned Lo32 = Lo_32(Imm);
- SDNode *Result = nullptr;
- unsigned Shift = 0;
-
- auto getI32Imm = [CurDAG, dl](unsigned Imm) {
- return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
- };
-
- // Following patterns use 1 instructions to materialize the Imm.
- InstCnt = 1;
- // 1-1) Patterns : {zeros}{15-bit valve}
- // {ones}{15-bit valve}
- if (isInt<16>(Imm)) {
- SDValue SDImm = CurDAG->getTargetConstant(Imm, dl, MVT::i64);
- return CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, SDImm);
- }
- // 1-2) Patterns : {zeros}{15-bit valve}{16 zeros}
- // {ones}{15-bit valve}{16 zeros}
- if (TZ > 15 && (LZ > 32 || LO > 32))
- return CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64,
- getI32Imm((Imm >> 16) & 0xffff));
-
- // Following patterns use 2 instructions to materialize the Imm.
- InstCnt = 2;
- assert(LZ < 64 && "Unexpected leading zeros here.");
- // Count of ones follwing the leading zeros.
- unsigned FO = countLeadingOnes<uint64_t>(Imm << LZ);
- // 2-1) Patterns : {zeros}{31-bit value}
- // {ones}{31-bit value}
- if (isInt<32>(Imm)) {
- uint64_t ImmHi16 = (Imm >> 16) & 0xffff;
- unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
- Result = CurDAG->getMachineNode(Opcode, dl, MVT::i64, getI32Imm(ImmHi16));
- return CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(Imm & 0xffff));
- }
- // 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros}
- // {zeros}{15-bit value}{zeros}
- // {zeros}{ones}{15-bit value}
- // {ones}{15-bit value}{zeros}
- // We can take advantage of LI's sign-extension semantics to generate leading
- // ones, and then use RLDIC to mask off the ones in both sides after rotation.
- if ((LZ + FO + TZ) > 48) {
- Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
- getI32Imm((Imm >> TZ) & 0xffff));
- return CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(TZ), getI32Imm(LZ));
- }
- // 2-3) Pattern : {zeros}{15-bit value}{ones}
- // Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value,
- // therefore we can take advantage of LI's sign-extension semantics, and then
- // mask them off after rotation.
- //
- // +--LZ--||-15-bit-||--TO--+ +-------------|--16-bit--+
- // |00000001bbbbbbbbb1111111| -> |00000000000001bbbbbbbbb1|
- // +------------------------+ +------------------------+
- // 63 0 63 0
- // Imm (Imm >> (48 - LZ) & 0xffff)
- // +----sext-----|--16-bit--+ +clear-|-----------------+
- // |11111111111111bbbbbbbbb1| -> |00000001bbbbbbbbb1111111|
- // +------------------------+ +------------------------+
- // 63 0 63 0
- // LI8: sext many leading zeros RLDICL: rotate left (48 - LZ), clear left LZ
- if ((LZ + TO) > 48) {
- // Since the immediates with (LZ > 32) have been handled by previous
- // patterns, here we have (LZ <= 32) to make sure we will not shift right
- // the Imm by a negative value.
- assert(LZ <= 32 && "Unexpected shift value.");
- Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
- getI32Imm((Imm >> (48 - LZ) & 0xffff)));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(48 - LZ), getI32Imm(LZ));
- }
- // 2-4) Patterns : {zeros}{ones}{15-bit value}{ones}
- // {ones}{15-bit value}{ones}
- // We can take advantage of LI's sign-extension semantics to generate leading
- // ones, and then use RLDICL to mask off the ones in left sides (if required)
- // after rotation.
- //
- // +-LZ-FO||-15-bit-||--TO--+ +-------------|--16-bit--+
- // |00011110bbbbbbbbb1111111| -> |000000000011110bbbbbbbbb|
- // +------------------------+ +------------------------+
- // 63 0 63 0
- // Imm (Imm >> TO) & 0xffff
- // +----sext-----|--16-bit--+ +LZ|---------------------+
- // |111111111111110bbbbbbbbb| -> |00011110bbbbbbbbb1111111|
- // +------------------------+ +------------------------+
- // 63 0 63 0
- // LI8: sext many leading zeros RLDICL: rotate left TO, clear left LZ
- if ((LZ + FO + TO) > 48) {
- Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
- getI32Imm((Imm >> TO) & 0xffff));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(TO), getI32Imm(LZ));
- }
- // 2-5) Pattern : {32 zeros}{****}{0}{15-bit value}
- // If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit
- // value, we can use LI for Lo16 without generating leading ones then add the
- // Hi16(in Lo32).
- if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {
- Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
- getI32Imm(Lo32 & 0xffff));
- return CurDAG->getMachineNode(PPC::ORIS8, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(Lo32 >> 16));
- }
- // 2-6) Patterns : {******}{49 zeros}{******}
- // {******}{49 ones}{******}
- // If the Imm contains 49 consecutive zeros/ones, it means that a total of 15
- // bits remain on both sides. Rotate right the Imm to construct an int<16>
- // value, use LI for int<16> value and then use RLDICL without mask to rotate
- // it back.
- //
- // 1) findContiguousZerosAtLeast(Imm, 49)
- // +------|--zeros-|------+ +---ones--||---15 bit--+
- // |bbbbbb0000000000aaaaaa| -> |0000000000aaaaaabbbbbb|
- // +----------------------+ +----------------------+
- // 63 0 63 0
- //
- // 2) findContiguousZerosAtLeast(~Imm, 49)
- // +------|--ones--|------+ +---ones--||---15 bit--+
- // |bbbbbb1111111111aaaaaa| -> |1111111111aaaaaabbbbbb|
- // +----------------------+ +----------------------+
- // 63 0 63 0
- if ((Shift = findContiguousZerosAtLeast(Imm, 49)) ||
- (Shift = findContiguousZerosAtLeast(~Imm, 49))) {
- uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
- Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
- getI32Imm(RotImm & 0xffff));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(Shift), getI32Imm(0));
- }
-
- // Following patterns use 3 instructions to materialize the Imm.
- InstCnt = 3;
- // 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros}
- // {zeros}{31-bit value}{zeros}
- // {zeros}{ones}{31-bit value}
- // {ones}{31-bit value}{zeros}
- // We can take advantage of LIS's sign-extension semantics to generate leading
- // ones, add the remaining bits with ORI, and then use RLDIC to mask off the
- // ones in both sides after rotation.
- if ((LZ + FO + TZ) > 32) {
- uint64_t ImmHi16 = (Imm >> (TZ + 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((Imm >> TZ) & 0xffff));
- return CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(TZ), getI32Imm(LZ));
- }
- // 3-2) Pattern : {zeros}{31-bit value}{ones}
- // Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits
- // value, therefore we can take advantage of LIS's sign-extension semantics,
- // add the remaining bits with ORI, and then mask them off after rotation.
- // This is similar to Pattern 2-3, please refer to the diagram there.
- if ((LZ + TO) > 32) {
- // Since the immediates with (LZ > 32) have been handled by previous
- // patterns, here we have (LZ <= 32) to make sure we will not shift right
- // the Imm by a negative value.
- assert(LZ <= 32 && "Unexpected shift value.");
- Result = CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64,
- getI32Imm((Imm >> (48 - LZ)) & 0xffff));
- Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm((Imm >> (32 - LZ)) & 0xffff));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(32 - LZ), getI32Imm(LZ));
- }
- // 3-3) Patterns : {zeros}{ones}{31-bit value}{ones}
- // {ones}{31-bit value}{ones}
- // We can take advantage of LIS's sign-extension semantics to generate leading
- // ones, add the remaining bits with ORI, and then use RLDICL to mask off the
- // ones in left sides (if required) after rotation.
- // This is similar to Pattern 2-4, please refer to the diagram there.
- if ((LZ + FO + TO) > 32) {
- Result = CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64,
- getI32Imm((Imm >> (TO + 16)) & 0xffff));
- Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm((Imm >> TO) & 0xffff));
- 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}{******}
- // {******}{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>
- // value, use LIS + ORI for int<32> value and then use RLDICL without mask to
- // rotate it back.
- // This is similar to Pattern 2-6, please refer to the diagram there.
- if ((Shift = findContiguousZerosAtLeast(Imm, 33)) ||
- (Shift = findContiguousZerosAtLeast(~Imm, 33))) {
- uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
- uint64_t ImmHi16 = (RotImm >> 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(RotImm & 0xffff));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(Shift), getI32Imm(0));
- }
-
- InstCnt = 0;
- return nullptr;
-}
-
-// Try to select instructions to generate a 64 bit immediate using prefix as
-// well as non prefix instructions. The function will return the SDNode
-// to materialize that constant or it will return nullptr if it does not
-// find one. The variable InstCnt is set to the number of instructions that
-// were selected.
-static SDNode *selectI64ImmDirectPrefix(SelectionDAG *CurDAG, const SDLoc &dl,
- uint64_t Imm, unsigned &InstCnt) {
- unsigned TZ = countTrailingZeros<uint64_t>(Imm);
- unsigned LZ = countLeadingZeros<uint64_t>(Imm);
- unsigned TO = countTrailingOnes<uint64_t>(Imm);
- unsigned FO = countLeadingOnes<uint64_t>(LZ == 64 ? 0 : (Imm << LZ));
- unsigned Hi32 = Hi_32(Imm);
- unsigned Lo32 = Lo_32(Imm);
-
- auto getI32Imm = [CurDAG, dl](unsigned Imm) {
- return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
- };
-
- auto getI64Imm = [CurDAG, dl](uint64_t Imm) {
- return CurDAG->getTargetConstant(Imm, dl, MVT::i64);
- };
-
- // Following patterns use 1 instruction to materialize Imm.
- InstCnt = 1;
-
- // The pli instruction can materialize up to 34 bits directly.
- // If a constant fits within 34-bits, emit the pli instruction here directly.
- if (isInt<34>(Imm))
- return CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
- CurDAG->getTargetConstant(Imm, dl, MVT::i64));
-
- // Require at least two instructions.
- InstCnt = 2;
- SDNode *Result = nullptr;
- // Patterns : {zeros}{ones}{33-bit value}{zeros}
- // {zeros}{33-bit value}{zeros}
- // {zeros}{ones}{33-bit value}
- // {ones}{33-bit value}{zeros}
- // We can take advantage of PLI's sign-extension semantics to generate leading
- // ones, and then use RLDIC to mask off the ones on both sides after rotation.
- if ((LZ + FO + TZ) > 30) {
- APInt SignedInt34 = APInt(34, (Imm >> TZ) & 0x3ffffffff);
- APInt Extended = SignedInt34.sext(64);
- Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
- getI64Imm(*Extended.getRawData()));
- return CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(TZ), getI32Imm(LZ));
- }
- // Pattern : {zeros}{33-bit value}{ones}
- // Shift right the Imm by (30 - LZ) bits to construct a negative 34 bit value,
- // therefore we can take advantage of PLI's sign-extension semantics, and then
- // mask them off after rotation.
- //
- // +--LZ--||-33-bit-||--TO--+ +-------------|--34-bit--+
- // |00000001bbbbbbbbb1111111| -> |00000000000001bbbbbbbbb1|
- // +------------------------+ +------------------------+
- // 63 0 63 0
- //
- // +----sext-----|--34-bit--+ +clear-|-----------------+
- // |11111111111111bbbbbbbbb1| -> |00000001bbbbbbbbb1111111|
- // +------------------------+ +------------------------+
- // 63 0 63 0
- if ((LZ + TO) > 30) {
- APInt SignedInt34 = APInt(34, (Imm >> (30 - LZ)) & 0x3ffffffff);
- APInt Extended = SignedInt34.sext(64);
- Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
- getI64Imm(*Extended.getRawData()));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(30 - LZ), getI32Imm(LZ));
- }
- // Patterns : {zeros}{ones}{33-bit value}{ones}
- // {ones}{33-bit value}{ones}
- // Similar to LI we can take advantage of PLI's sign-extension semantics to
- // generate leading ones, and then use RLDICL to mask off the ones in left
- // sides (if required) after rotation.
- if ((LZ + FO + TO) > 30) {
- APInt SignedInt34 = APInt(34, (Imm >> TO) & 0x3ffffffff);
- APInt Extended = SignedInt34.sext(64);
- Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
- getI64Imm(*Extended.getRawData()));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(TO), getI32Imm(LZ));
- }
- // Patterns : {******}{31 zeros}{******}
- // : {******}{31 ones}{******}
- // If Imm contains 31 consecutive zeros/ones then the remaining bit count
- // is 33. Rotate right the Imm to construct a int<33> value, we can use PLI
- // for the int<33> value and then use RLDICL without a mask to rotate it back.
- //
- // +------|--ones--|------+ +---ones--||---33 bit--+
- // |bbbbbb1111111111aaaaaa| -> |1111111111aaaaaabbbbbb|
- // +----------------------+ +----------------------+
- // 63 0 63 0
- for (unsigned Shift = 0; Shift < 63; ++Shift) {
- uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
- if (isInt<34>(RotImm)) {
- Result =
- CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(RotImm));
- return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
- SDValue(Result, 0), getI32Imm(Shift),
- getI32Imm(0));
- }
- }
-
- // Patterns : High word == Low word
- // This is basically a splat of a 32 bit immediate.
- if (Hi32 == Lo32) {
- Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(Hi32));
- SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32),
- getI32Imm(0)};
- return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
- }
-
- InstCnt = 3;
- // Catch-all
- // This pattern can form any 64 bit immediate in 3 instructions.
- SDNode *ResultHi =
- CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(Hi32));
- SDNode *ResultLo =
- CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(Lo32));
- SDValue Ops[] = {SDValue(ResultLo, 0), SDValue(ResultHi, 0), getI32Imm(32),
- getI32Imm(0)};
- return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
-}
-
-static SDNode *selectI64Imm(SelectionDAG *CurDAG, const SDLoc &dl, uint64_t Imm,
- unsigned *InstCnt = nullptr) {
- unsigned InstCntDirect = 0;
- // No more than 3 instructions are used if we can select the i64 immediate
- // directly.
- SDNode *Result = selectI64ImmDirect(CurDAG, dl, Imm, InstCntDirect);
-
- const PPCSubtarget &Subtarget =
- CurDAG->getMachineFunction().getSubtarget<PPCSubtarget>();
-
- // If we have prefixed instructions and there is a chance we can
- // materialize the constant with fewer prefixed instructions than
- // non-prefixed, try that.
- if (Subtarget.hasPrefixInstrs() && InstCntDirect != 1) {
- unsigned InstCntDirectP = 0;
- SDNode *ResultP = selectI64ImmDirectPrefix(CurDAG, dl, Imm, InstCntDirectP);
- // Use the prefix case in either of two cases:
- // 1) We have no result from the non-prefix case to use.
- // 2) The non-prefix case uses more instructions than the prefix case.
- // If the prefix and non-prefix cases use the same number of instructions
- // we will prefer the non-prefix case.
- if (ResultP && (!Result || InstCntDirectP < InstCntDirect)) {
- if (InstCnt)
- *InstCnt = InstCntDirectP;
- return ResultP;
- }
- }
-
- if (Result) {
- if (InstCnt)
- *InstCnt = InstCntDirect;
- return Result;
- }
- auto getI32Imm = [CurDAG, dl](unsigned Imm) {
- return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
- };
- // Handle the upper 32 bit value.
- Result =
- selectI64ImmDirect(CurDAG, dl, Imm & 0xffffffff00000000, InstCntDirect);
- // Add in the last bits as required.
- if (uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff) {
- Result = CurDAG->getMachineNode(PPC::ORIS8, dl, MVT::i64,
- SDValue(Result, 0), getI32Imm(Hi16));
- ++InstCntDirect;
- }
- if (uint32_t Lo16 = Lo_32(Imm) & 0xffff) {
- Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(Lo16));
- ++InstCntDirect;
- }
- if (InstCnt)
- *InstCnt = InstCntDirect;
- return Result;
-}
-
// Select a 64-bit constant.
static SDNode *selectI64Imm(SelectionDAG *CurDAG, SDNode *N) {
SDLoc dl(N);
@@ -1375,7 +1123,8 @@ class BitPermutationSelector {
ValueBit(SDValue V, unsigned I, Kind K = Variable)
: V(V), Idx(I), K(K) {}
- ValueBit(Kind K = Variable) : Idx(UINT32_MAX), K(K) {}
+ ValueBit(Kind K = Variable)
+ : V(SDValue(nullptr, 0)), Idx(UINT32_MAX), K(K) {}
bool isZero() const {
return K == ConstZero || K == VariableKnownToBeZero;
@@ -1489,7 +1238,6 @@ class BitPermutationSelector {
}
break;
case ISD::SHL:
- case PPCISD::SHL:
if (isa<ConstantSDNode>(V.getOperand(1))) {
unsigned ShiftAmt = V.getConstantOperandVal(1);
@@ -1505,7 +1253,6 @@ class BitPermutationSelector {
}
break;
case ISD::SRL:
- case PPCISD::SRL:
if (isa<ConstantSDNode>(V.getOperand(1))) {
unsigned ShiftAmt = V.getConstantOperandVal(1);
@@ -2385,14 +2132,11 @@ class BitPermutationSelector {
unsigned NumAndInsts = (unsigned) NeedsRotate +
(unsigned) (bool) Res;
- unsigned NumOfSelectInsts = 0;
- selectI64Imm(CurDAG, dl, Mask, &NumOfSelectInsts);
- assert(NumOfSelectInsts > 0 && "Failed to select an i64 constant.");
if (Use32BitInsts)
NumAndInsts += (unsigned) (ANDIMask != 0) + (unsigned) (ANDISMask != 0) +
(unsigned) (ANDIMask != 0 && ANDISMask != 0);
else
- NumAndInsts += NumOfSelectInsts + /* and */ 1;
+ NumAndInsts += selectI64ImmInstrCount(Mask) + /* and */ 1;
unsigned NumRLInsts = 0;
bool FirstBG = true;
@@ -2616,14 +2360,12 @@ class BitPermutationSelector {
Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
ExtendToInt64(ANDIVal, dl), ANDISVal), 0);
} else {
- unsigned NumOfSelectInsts = 0;
- SDValue MaskVal =
- SDValue(selectI64Imm(CurDAG, dl, Mask, &NumOfSelectInsts), 0);
- Res = SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
- ExtendToInt64(Res, dl), MaskVal),
- 0);
- if (InstCnt)
- *InstCnt += NumOfSelectInsts + /* and */ 1;
+ if (InstCnt) *InstCnt += selectI64ImmInstrCount(Mask) + /* and */ 1;
+
+ SDValue MaskVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0);
+ Res =
+ SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
+ ExtendToInt64(Res, dl), MaskVal), 0);
}
}
@@ -2654,7 +2396,7 @@ class BitPermutationSelector {
}
void eraseMatchingBitGroups(function_ref<bool(const BitGroup &)> F) {
- erase_if(BitGroups, F);
+ BitGroups.erase(remove_if(BitGroups, F), BitGroups.end());
}
SmallVector<ValueBit, 64> Bits;
@@ -2781,7 +2523,7 @@ public:
if (CmpInGPR == ICGPR_Sext || CmpInGPR == ICGPR_SextI32 ||
CmpInGPR == ICGPR_SextI64)
return nullptr;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SIGN_EXTEND:
if (CmpInGPR == ICGPR_Zext || CmpInGPR == ICGPR_ZextI32 ||
CmpInGPR == ICGPR_ZextI64)
@@ -3208,8 +2950,8 @@ IntegerCompareEliminator::get32BitZExtCompare(SDValue LHS, SDValue RHS,
// by swapping inputs and falling through.
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
- [[fallthrough]];
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
+ LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
if (CmpInGPR == ICGPR_NonExtIn)
@@ -3258,9 +3000,9 @@ IntegerCompareEliminator::get32BitZExtCompare(SDValue LHS, SDValue RHS,
// (%b < %a) by swapping inputs and falling through.
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
}
case ISD::SETLT: {
// (zext (setcc %a, %b, setlt)) -> (lshr (sub %a, %b), 63)
@@ -3295,7 +3037,7 @@ IntegerCompareEliminator::get32BitZExtCompare(SDValue LHS, SDValue RHS,
// (zext (setcc %a, %b, setuge)) -> (xor (lshr (sub %b, %a), 63), 1)
// (zext (setcc %a, %b, setule)) -> (xor (lshr (sub %a, %b), 63), 1)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULE: {
if (CmpInGPR == ICGPR_NonExtIn)
return SDValue();
@@ -3315,7 +3057,7 @@ IntegerCompareEliminator::get32BitZExtCompare(SDValue LHS, SDValue RHS,
// (zext (setcc %a, %b, setugt)) -> (lshr (sub %b, %a), 63)
// (zext (setcc %a, %b, setult)) -> (lshr (sub %a, %b), 63)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULT: {
if (CmpInGPR == ICGPR_NonExtIn)
return SDValue();
@@ -3392,8 +3134,8 @@ IntegerCompareEliminator::get32BitSExtCompare(SDValue LHS, SDValue RHS,
// by swapping inputs and falling through.
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
- [[fallthrough]];
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
+ LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
if (CmpInGPR == ICGPR_NonExtIn)
@@ -3437,9 +3179,9 @@ IntegerCompareEliminator::get32BitSExtCompare(SDValue LHS, SDValue RHS,
// (%b < %a) by swapping inputs and falling through.
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
}
case ISD::SETLT: {
// (sext (setcc %a, %b, setgt)) -> (ashr (sub %a, %b), 63)
@@ -3468,7 +3210,7 @@ IntegerCompareEliminator::get32BitSExtCompare(SDValue LHS, SDValue RHS,
// (sext (setcc %a, %b, setuge)) -> (add (lshr (sub %a, %b), 63), -1)
// (sext (setcc %a, %b, setule)) -> (add (lshr (sub %b, %a), 63), -1)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULE: {
if (CmpInGPR == ICGPR_NonExtIn)
return SDValue();
@@ -3488,7 +3230,7 @@ IntegerCompareEliminator::get32BitSExtCompare(SDValue LHS, SDValue RHS,
// (sext (setcc %a, %b, setugt)) -> (ashr (sub %b, %a), 63)
// (sext (setcc %a, %b, setugt)) -> (ashr (sub %a, %b), 63)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULT: {
if (CmpInGPR == ICGPR_NonExtIn)
return SDValue();
@@ -3550,8 +3292,8 @@ IntegerCompareEliminator::get64BitZExtCompare(SDValue LHS, SDValue RHS,
return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GEZExt);
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
- [[fallthrough]];
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
+ LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
// {subc.reg, subc.CA} = (subcarry %b, %a)
@@ -3592,9 +3334,9 @@ IntegerCompareEliminator::get64BitZExtCompare(SDValue LHS, SDValue RHS,
}
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
}
case ISD::SETLT: {
// {subc.reg, subc.CA} = (subcarry %a, %b)
@@ -3627,7 +3369,7 @@ IntegerCompareEliminator::get64BitZExtCompare(SDValue LHS, SDValue RHS,
// {subc.reg, subc.CA} = (subcarry %a, %b)
// (zext (setcc %a, %b, setuge)) -> (add (sube %b, %b, subc.CA), 1)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULE: {
// {subc.reg, subc.CA} = (subcarry %b, %a)
// (zext (setcc %a, %b, setule)) -> (add (sube %a, %a, subc.CA), 1)
@@ -3644,7 +3386,7 @@ IntegerCompareEliminator::get64BitZExtCompare(SDValue LHS, SDValue RHS,
// {subc.reg, subc.CA} = (subcarry %b, %a)
// (zext (setcc %a, %b, setugt)) -> -(sube %b, %b, subc.CA)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULT: {
// {subc.reg, subc.CA} = (subcarry %a, %b)
// (zext (setcc %a, %b, setult)) -> -(sube %a, %a, subc.CA)
@@ -3709,8 +3451,8 @@ IntegerCompareEliminator::get64BitSExtCompare(SDValue LHS, SDValue RHS,
return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GESExt);
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
- [[fallthrough]];
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
+ LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
// {subc.reg, subc.CA} = (subcarry %b, %a)
@@ -3752,9 +3494,9 @@ IntegerCompareEliminator::get64BitSExtCompare(SDValue LHS, SDValue RHS,
}
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isZero();
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
}
case ISD::SETLT: {
// {subc.reg, subc.CA} = (subcarry %a, %b)
@@ -3790,7 +3532,7 @@ IntegerCompareEliminator::get64BitSExtCompare(SDValue LHS, SDValue RHS,
// {subc.reg, subc.CA} = (subcarry %a, %b)
// (sext (setcc %a, %b, setuge)) -> ~(sube %b, %b, subc.CA)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULE: {
// {subc.reg, subc.CA} = (subcarry %b, %a)
// (sext (setcc %a, %b, setule)) -> ~(sube %a, %a, subc.CA)
@@ -3807,7 +3549,7 @@ IntegerCompareEliminator::get64BitSExtCompare(SDValue LHS, SDValue RHS,
// {subc.reg, subc.CA} = (subcarry %b, %a)
// (sext (setcc %a, %b, setugt)) -> (sube %b, %b, subc.CA)
std::swap(LHS, RHS);
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETULT: {
// {subc.reg, subc.CA} = (subcarry %a, %b)
// (sext (setcc %a, %b, setult)) -> (sube %a, %a, subc.CA)
@@ -3834,7 +3576,7 @@ static bool allUsesExtend(SDValue Compare, SelectionDAG *CurDAG) {
return true;
// We want the value in a GPR if it is being extended, used for a select, or
// used in logical operations.
- for (auto *CompareUse : Compare.getNode()->uses())
+ for (auto CompareUse : Compare.getNode()->uses())
if (CompareUse->getOpcode() != ISD::SIGN_EXTEND &&
CompareUse->getOpcode() != ISD::ZERO_EXTEND &&
CompareUse->getOpcode() != ISD::SELECT &&
@@ -3904,12 +3646,6 @@ bool PPCDAGToDAGISel::tryIntCompareInGPR(SDNode *N) {
if (TM.getOptLevel() == CodeGenOpt::None || !TM.isPPC64())
return false;
- // For POWER10, it is more profitable to use the set boolean extension
- // instructions rather than the integer compare elimination codegen.
- // Users can override this via the command line option, `--ppc-gpr-icmps`.
- if (!(CmpInGPR.getNumOccurrences() > 0) && Subtarget->isISA3_1())
- return false;
-
switch (N->getOpcode()) {
default: break;
case ISD::ZERO_EXTEND:
@@ -3937,19 +3673,9 @@ bool PPCDAGToDAGISel::tryBitPermutation(SDNode *N) {
switch (N->getOpcode()) {
default: break;
- case ISD::SRL:
- // If we are on P10, we have a pattern for 32-bit (srl (bswap r), 16) that
- // uses the BRH instruction.
- if (Subtarget->isISA3_1() && N->getValueType(0) == MVT::i32 &&
- N->getOperand(0).getOpcode() == ISD::BSWAP) {
- auto &OpRight = N->getOperand(1);
- ConstantSDNode *SRLConst = dyn_cast<ConstantSDNode>(OpRight);
- if (SRLConst && SRLConst->getSExtValue() == 16)
- return false;
- }
- LLVM_FALLTHROUGH;
case ISD::ROTL:
case ISD::SHL:
+ case ISD::SRL:
case ISD::AND:
case ISD::OR: {
BitPermutationSelector BPS(CurDAG);
@@ -3967,7 +3693,7 @@ bool PPCDAGToDAGISel::tryBitPermutation(SDNode *N) {
/// SelectCC - Select a comparison of the specified values with the specified
/// condition code, returning the CR# of the expression.
SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
- const SDLoc &dl, SDValue Chain) {
+ const SDLoc &dl) {
// Always select the LHS.
unsigned Opc;
@@ -4062,7 +3788,7 @@ SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
Opc = PPC::CMPD;
}
} else if (LHS.getValueType() == MVT::f32) {
- if (Subtarget->hasSPE()) {
+ if (PPCSubTarget->hasSPE()) {
switch (CC) {
default:
case ISD::SETEQ:
@@ -4089,7 +3815,7 @@ SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
} else
Opc = PPC::FCMPUS;
} else if (LHS.getValueType() == MVT::f64) {
- if (Subtarget->hasSPE()) {
+ if (PPCSubTarget->hasSPE()) {
switch (CC) {
default:
case ISD::SETEQ:
@@ -4114,18 +3840,13 @@ SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
break;
}
} else
- Opc = Subtarget->hasVSX() ? PPC::XSCMPUDP : PPC::FCMPUD;
+ Opc = PPCSubTarget->hasVSX() ? PPC::XSCMPUDP : PPC::FCMPUD;
} else {
assert(LHS.getValueType() == MVT::f128 && "Unknown vt!");
- assert(Subtarget->hasP9Vector() && "XSCMPUQP requires Power9 Vector");
+ assert(PPCSubTarget->hasVSX() && "__float128 requires VSX");
Opc = PPC::XSCMPUQP;
}
- if (Chain)
- return SDValue(
- CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::Other, LHS, RHS, Chain),
- 0);
- else
- return SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i32, LHS, RHS), 0);
+ return SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i32, LHS, RHS), 0);
}
static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC, const EVT &VT,
@@ -4151,10 +3872,10 @@ static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC, const EVT &VT,
return UseSPE ? PPC::PRED_GT : PPC::PRED_LT;
case ISD::SETULE:
case ISD::SETLE:
- return PPC::PRED_LE;
+ return UseSPE ? PPC::PRED_LE : PPC::PRED_LE;
case ISD::SETOGT:
case ISD::SETGT:
- return PPC::PRED_GT;
+ return UseSPE ? PPC::PRED_GT : PPC::PRED_GT;
case ISD::SETUGE:
case ISD::SETGE:
return UseSPE ? PPC::PRED_LE : PPC::PRED_GE;
@@ -4200,8 +3921,7 @@ static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool &Invert) {
// getVCmpInst: return the vector compare instruction for the specified
// vector type and condition code. Since this is for altivec specific code,
-// only support the altivec types (v16i8, v8i16, v4i32, v2i64, v1i128,
-// and v4f32).
+// only support the altivec types (v16i8, v8i16, v4i32, v2i64, and v4f32).
static unsigned int getVCmpInst(MVT VecVT, ISD::CondCode CC,
bool HasVSX, bool &Swap, bool &Negate) {
Swap = false;
@@ -4282,8 +4002,6 @@ static unsigned int getVCmpInst(MVT VecVT, ISD::CondCode CC,
return PPC::VCMPEQUW;
else if (VecVT == MVT::v2i64)
return PPC::VCMPEQUD;
- else if (VecVT == MVT::v1i128)
- return PPC::VCMPEQUQ;
break;
case ISD::SETGT:
if (VecVT == MVT::v16i8)
@@ -4294,8 +4012,6 @@ static unsigned int getVCmpInst(MVT VecVT, ISD::CondCode CC,
return PPC::VCMPGTSW;
else if (VecVT == MVT::v2i64)
return PPC::VCMPGTSD;
- else if (VecVT == MVT::v1i128)
- return PPC::VCMPGTSQ;
break;
case ISD::SETUGT:
if (VecVT == MVT::v16i8)
@@ -4306,8 +4022,6 @@ static unsigned int getVCmpInst(MVT VecVT, ISD::CondCode CC,
return PPC::VCMPGTUW;
else if (VecVT == MVT::v2i64)
return PPC::VCMPGTUD;
- else if (VecVT == MVT::v1i128)
- return PPC::VCMPGTUQ;
break;
default:
break;
@@ -4319,23 +4033,18 @@ static unsigned int getVCmpInst(MVT VecVT, ISD::CondCode CC,
bool PPCDAGToDAGISel::trySETCC(SDNode *N) {
SDLoc dl(N);
unsigned Imm;
- bool IsStrict = N->isStrictFPOpcode();
- ISD::CondCode CC =
- cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
EVT PtrVT =
CurDAG->getTargetLoweringInfo().getPointerTy(CurDAG->getDataLayout());
bool isPPC64 = (PtrVT == MVT::i64);
- SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
-
- SDValue LHS = N->getOperand(IsStrict ? 1 : 0);
- SDValue RHS = N->getOperand(IsStrict ? 2 : 1);
- if (!IsStrict && !Subtarget->useCRBits() && isInt32Immediate(RHS, Imm)) {
+ if (!PPCSubTarget->useCRBits() &&
+ isInt32Immediate(N->getOperand(1), Imm)) {
// We can codegen setcc op, imm very efficiently compared to a brcond.
// Check for those cases here.
// setcc op, 0
if (Imm == 0) {
- SDValue Op = LHS;
+ SDValue Op = N->getOperand(0);
switch (CC) {
default: break;
case ISD::SETEQ: {
@@ -4370,7 +4079,7 @@ bool PPCDAGToDAGISel::trySETCC(SDNode *N) {
}
}
} else if (Imm == ~0U) { // setcc op, -1
- SDValue Op = LHS;
+ SDValue Op = N->getOperand(0);
switch (CC) {
default: break;
case ISD::SETEQ:
@@ -4413,23 +4122,26 @@ bool PPCDAGToDAGISel::trySETCC(SDNode *N) {
}
}
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+
// Altivec Vector compare instructions do not set any CR register by default and
// vector compare operations return the same type as the operands.
- if (!IsStrict && LHS.getValueType().isVector()) {
- if (Subtarget->hasSPE())
+ if (LHS.getValueType().isVector()) {
+ if (PPCSubTarget->hasQPX() || PPCSubTarget->hasSPE())
return false;
EVT VecVT = LHS.getValueType();
bool Swap, Negate;
- unsigned int VCmpInst =
- getVCmpInst(VecVT.getSimpleVT(), CC, Subtarget->hasVSX(), Swap, Negate);
+ unsigned int VCmpInst = getVCmpInst(VecVT.getSimpleVT(), CC,
+ PPCSubTarget->hasVSX(), Swap, Negate);
if (Swap)
std::swap(LHS, RHS);
EVT ResVT = VecVT.changeVectorElementTypeToInteger();
if (Negate) {
SDValue VCmp(CurDAG->getMachineNode(VCmpInst, dl, ResVT, LHS, RHS), 0);
- CurDAG->SelectNodeTo(N, Subtarget->hasVSX() ? PPC::XXLNOR : PPC::VNOR,
+ CurDAG->SelectNodeTo(N, PPCSubTarget->hasVSX() ? PPC::XXLNOR : PPC::VNOR,
ResVT, VCmp, VCmp);
return true;
}
@@ -4438,26 +4150,24 @@ bool PPCDAGToDAGISel::trySETCC(SDNode *N) {
return true;
}
- if (Subtarget->useCRBits())
+ if (PPCSubTarget->useCRBits())
return false;
bool Inv;
unsigned Idx = getCRIdxForSetCC(CC, Inv);
- SDValue CCReg = SelectCC(LHS, RHS, CC, dl, Chain);
- if (IsStrict)
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 1), CCReg.getValue(1));
+ SDValue CCReg = SelectCC(LHS, RHS, CC, dl);
SDValue IntCR;
// SPE e*cmp* instructions only set the 'gt' bit, so hard-code that
// The correct compare instruction is already set by SelectCC()
- if (Subtarget->hasSPE() && LHS.getValueType().isFloatingPoint()) {
+ if (PPCSubTarget->hasSPE() && LHS.getValueType().isFloatingPoint()) {
Idx = 1;
}
// Force the ccreg into CR7.
SDValue CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32);
- SDValue InFlag; // Null incoming flag value.
+ SDValue InFlag(nullptr, 0); // Null incoming flag value.
CCReg = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, CR7Reg, CCReg,
InFlag).getValue(1);
@@ -4483,10 +4193,9 @@ bool PPCDAGToDAGISel::trySETCC(SDNode *N) {
bool PPCDAGToDAGISel::isOffsetMultipleOf(SDNode *N, unsigned Val) const {
LoadSDNode *LDN = dyn_cast<LoadSDNode>(N);
StoreSDNode *STN = dyn_cast<StoreSDNode>(N);
- MemIntrinsicSDNode *MIN = dyn_cast<MemIntrinsicSDNode>(N);
SDValue AddrOp;
- if (LDN || (MIN && MIN->getOpcode() == PPCISD::LD_SPLAT))
- AddrOp = N->getOperand(1);
+ if (LDN)
+ AddrOp = LDN->getOperand(1);
else if (STN)
AddrOp = STN->getOperand(2);
@@ -4500,7 +4209,7 @@ bool PPCDAGToDAGISel::isOffsetMultipleOf(SDNode *N, unsigned Val) const {
// because it is translated to r31 or r1 + slot + offset. We won't know the
// slot number until the stack frame is finalized.
const MachineFrameInfo &MFI = CurDAG->getMachineFunction().getFrameInfo();
- unsigned SlotAlign = MFI.getObjectAlign(FI->getIndex()).value();
+ unsigned SlotAlign = MFI.getObjectAlignment(FI->getIndex());
if ((SlotAlign % Val) != 0)
return false;
@@ -4532,10 +4241,13 @@ static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG,
SDValue TrueRes = N->getOperand(2);
SDValue FalseRes = N->getOperand(3);
ConstantSDNode *TrueConst = dyn_cast<ConstantSDNode>(TrueRes);
- if (!TrueConst || (N->getSimpleValueType(0) != MVT::i64 &&
- N->getSimpleValueType(0) != MVT::i32))
+ if (!TrueConst)
return false;
+ assert((N->getSimpleValueType(0) == MVT::i64 ||
+ N->getSimpleValueType(0) == MVT::i32) &&
+ "Expecting either i64 or i32 here.");
+
// We are looking for any of:
// (select_cc lhs, rhs, 1, (sext (setcc [lr]hs, [lr]hs, cc2)), cc1)
// (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, cc2)), cc1)
@@ -4549,10 +4261,8 @@ static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG,
(FalseRes.getOpcode() != ISD::SELECT_CC || CC != ISD::SETEQ)))
return false;
- SDValue SetOrSelCC = FalseRes.getOpcode() == ISD::SELECT_CC
- ? FalseRes
- : FalseRes.getOperand(0);
- bool InnerIsSel = SetOrSelCC.getOpcode() == ISD::SELECT_CC;
+ bool InnerIsSel = FalseRes.getOpcode() == ISD::SELECT_CC;
+ SDValue SetOrSelCC = InnerIsSel ? FalseRes : FalseRes.getOperand(0);
if (SetOrSelCC.getOpcode() != ISD::SETCC &&
SetOrSelCC.getOpcode() != ISD::SELECT_CC)
return false;
@@ -4623,7 +4333,7 @@ static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG,
if (!IsUnCmp && InnerCC != ISD::SETNE)
return false;
IsUnCmp = true;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETLT:
if (InnerCC == ISD::SETNE || (InnerCC == ISD::SETGT && !InnerSwapped) ||
(InnerCC == ISD::SETLT && InnerSwapped))
@@ -4642,7 +4352,7 @@ static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG,
if (!IsUnCmp && InnerCC != ISD::SETNE)
return false;
IsUnCmp = true;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case ISD::SETGT:
if (InnerCC == ISD::SETNE || (InnerCC == ISD::SETLT && !InnerSwapped) ||
(InnerCC == ISD::SETGT && InnerSwapped))
@@ -4661,378 +4371,140 @@ static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG,
return true;
}
-// Return true if it's a software square-root/divide operand.
-static bool isSWTestOp(SDValue N) {
- if (N.getOpcode() == PPCISD::FTSQRT)
- return true;
- if (N.getNumOperands() < 1 || !isa<ConstantSDNode>(N.getOperand(0)) ||
- N.getOpcode() != ISD::INTRINSIC_WO_CHAIN)
- return false;
- switch (N.getConstantOperandVal(0)) {
- case Intrinsic::ppc_vsx_xvtdivdp:
- case Intrinsic::ppc_vsx_xvtdivsp:
- case Intrinsic::ppc_vsx_xvtsqrtdp:
- case Intrinsic::ppc_vsx_xvtsqrtsp:
- return true;
- }
- return false;
-}
-
-bool PPCDAGToDAGISel::tryFoldSWTestBRCC(SDNode *N) {
- assert(N->getOpcode() == ISD::BR_CC && "ISD::BR_CC is expected.");
- // We are looking for following patterns, where `truncate to i1` actually has
- // the same semantic with `and 1`.
- // (br_cc seteq, (truncateToi1 SWTestOp), 0) -> (BCC PRED_NU, SWTestOp)
- // (br_cc seteq, (and SWTestOp, 2), 0) -> (BCC PRED_NE, SWTestOp)
- // (br_cc seteq, (and SWTestOp, 4), 0) -> (BCC PRED_LE, SWTestOp)
- // (br_cc seteq, (and SWTestOp, 8), 0) -> (BCC PRED_GE, SWTestOp)
- // (br_cc setne, (truncateToi1 SWTestOp), 0) -> (BCC PRED_UN, SWTestOp)
- // (br_cc setne, (and SWTestOp, 2), 0) -> (BCC PRED_EQ, SWTestOp)
- // (br_cc setne, (and SWTestOp, 4), 0) -> (BCC PRED_GT, SWTestOp)
- // (br_cc setne, (and SWTestOp, 8), 0) -> (BCC PRED_LT, SWTestOp)
- ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
- if (CC != ISD::SETEQ && CC != ISD::SETNE)
- return false;
-
- SDValue CmpRHS = N->getOperand(3);
- if (!isa<ConstantSDNode>(CmpRHS) ||
- cast<ConstantSDNode>(CmpRHS)->getSExtValue() != 0)
- return false;
-
- SDValue CmpLHS = N->getOperand(2);
- if (CmpLHS.getNumOperands() < 1 || !isSWTestOp(CmpLHS.getOperand(0)))
- return false;
-
- unsigned PCC = 0;
- bool IsCCNE = CC == ISD::SETNE;
- if (CmpLHS.getOpcode() == ISD::AND &&
- isa<ConstantSDNode>(CmpLHS.getOperand(1)))
- switch (CmpLHS.getConstantOperandVal(1)) {
- case 1:
- PCC = IsCCNE ? PPC::PRED_UN : PPC::PRED_NU;
- break;
- case 2:
- PCC = IsCCNE ? PPC::PRED_EQ : PPC::PRED_NE;
- break;
- case 4:
- PCC = IsCCNE ? PPC::PRED_GT : PPC::PRED_LE;
- break;
- case 8:
- PCC = IsCCNE ? PPC::PRED_LT : PPC::PRED_GE;
- break;
- default:
- return false;
- }
- else if (CmpLHS.getOpcode() == ISD::TRUNCATE &&
- CmpLHS.getValueType() == MVT::i1)
- PCC = IsCCNE ? PPC::PRED_UN : PPC::PRED_NU;
-
- if (PCC) {
- SDLoc dl(N);
- SDValue Ops[] = {getI32Imm(PCC, dl), CmpLHS.getOperand(0), N->getOperand(4),
- N->getOperand(0)};
- CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops);
- return true;
- }
- return false;
-}
-
-bool PPCDAGToDAGISel::trySelectLoopCountIntrinsic(SDNode *N) {
- // Sometimes the promoted value of the intrinsic is ANDed by some non-zero
- // value, for example when crbits is disabled. If so, select the
- // loop_decrement intrinsics now.
- ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
- SDValue LHS = N->getOperand(2), RHS = N->getOperand(3);
-
- if (LHS.getOpcode() != ISD::AND || !isa<ConstantSDNode>(LHS.getOperand(1)) ||
- isNullConstant(LHS.getOperand(1)))
- return false;
-
- if (LHS.getOperand(0).getOpcode() != ISD::INTRINSIC_W_CHAIN ||
- cast<ConstantSDNode>(LHS.getOperand(0).getOperand(1))->getZExtValue() !=
- Intrinsic::loop_decrement)
- return false;
-
- if (!isa<ConstantSDNode>(RHS))
- return false;
-
- assert((CC == ISD::SETEQ || CC == ISD::SETNE) &&
- "Counter decrement comparison is not EQ or NE");
-
- SDValue OldDecrement = LHS.getOperand(0);
- assert(OldDecrement.hasOneUse() && "loop decrement has more than one use!");
-
- SDLoc DecrementLoc(OldDecrement);
- SDValue ChainInput = OldDecrement.getOperand(0);
- SDValue DecrementOps[] = {Subtarget->isPPC64() ? getI64Imm(1, DecrementLoc)
- : getI32Imm(1, DecrementLoc)};
- unsigned DecrementOpcode =
- Subtarget->isPPC64() ? PPC::DecreaseCTR8loop : PPC::DecreaseCTRloop;
- SDNode *NewDecrement = CurDAG->getMachineNode(DecrementOpcode, DecrementLoc,
- MVT::i1, DecrementOps);
-
- unsigned Val = cast<ConstantSDNode>(RHS)->getZExtValue();
- bool IsBranchOnTrue = (CC == ISD::SETEQ && Val) || (CC == ISD::SETNE && !Val);
- unsigned Opcode = IsBranchOnTrue ? PPC::BC : PPC::BCn;
-
- ReplaceUses(LHS.getValue(0), LHS.getOperand(1));
- CurDAG->RemoveDeadNode(LHS.getNode());
-
- // Mark the old loop_decrement intrinsic as dead.
- ReplaceUses(OldDecrement.getValue(1), ChainInput);
- CurDAG->RemoveDeadNode(OldDecrement.getNode());
-
- SDValue Chain = CurDAG->getNode(ISD::TokenFactor, SDLoc(N), MVT::Other,
- ChainInput, N->getOperand(0));
-
- CurDAG->SelectNodeTo(N, Opcode, MVT::Other, SDValue(NewDecrement, 0),
- N->getOperand(4), Chain);
- return true;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLWINM(SDNode *N) {
- assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
- unsigned Imm;
- if (!isInt32Immediate(N->getOperand(1), Imm))
+bool PPCDAGToDAGISel::tryAndWithMask(SDNode *N) {
+ if (N->getOpcode() != ISD::AND)
return false;
SDLoc dl(N);
SDValue Val = N->getOperand(0);
- unsigned SH, MB, ME;
+ unsigned Imm, Imm2, SH, MB, ME;
+ uint64_t Imm64;
+
// If this is an and of a value rotated between 0 and 31 bits and then and'd
// with a mask, emit rlwinm
- if (isRotateAndMask(Val.getNode(), Imm, false, SH, MB, ME)) {
- Val = Val.getOperand(0);
- SDValue Ops[] = {Val, getI32Imm(SH, dl), getI32Imm(MB, dl),
- getI32Imm(ME, dl)};
+ if (isInt32Immediate(N->getOperand(1), Imm) &&
+ isRotateAndMask(N->getOperand(0).getNode(), Imm, false, SH, MB, ME)) {
+ SDValue Val = N->getOperand(0).getOperand(0);
+ SDValue Ops[] = { Val, getI32Imm(SH, dl), getI32Imm(MB, dl),
+ getI32Imm(ME, dl) };
CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
return true;
}
// If this is just a masked value where the input is not handled, and
// is not a rotate-left (handled by a pattern in the .td file), emit rlwinm
- if (isRunOfOnes(Imm, MB, ME) && Val.getOpcode() != ISD::ROTL) {
- SDValue Ops[] = {Val, getI32Imm(0, dl), getI32Imm(MB, dl),
- getI32Imm(ME, dl)};
- CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
- return true;
- }
-
- // AND X, 0 -> 0, not "rlwinm 32".
- if (Imm == 0) {
- ReplaceUses(SDValue(N, 0), N->getOperand(1));
- return true;
- }
-
- return false;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLWINM8(SDNode *N) {
- assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
- uint64_t Imm64;
- if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64))
- return false;
-
- unsigned MB, ME;
- if (isRunOfOnes64(Imm64, MB, ME) && MB >= 32 && MB <= ME) {
- // MB ME
- // +----------------------+
- // |xxxxxxxxxxx00011111000|
- // +----------------------+
- // 0 32 64
- // We can only do it if the MB is larger than 32 and MB <= ME
- // as RLWINM will replace the contents of [0 - 32) with [32 - 64) even
- // we didn't rotate it.
- SDLoc dl(N);
- SDValue Ops[] = {N->getOperand(0), getI64Imm(0, dl), getI64Imm(MB - 32, dl),
- getI64Imm(ME - 32, dl)};
- CurDAG->SelectNodeTo(N, PPC::RLWINM8, MVT::i64, Ops);
- return true;
- }
-
- return false;
-}
-
-bool PPCDAGToDAGISel::tryAsPairOfRLDICL(SDNode *N) {
- assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
- uint64_t Imm64;
- if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64))
- return false;
-
- // Do nothing if it is 16-bit imm as the pattern in the .td file handle
- // it well with "andi.".
- if (isUInt<16>(Imm64))
- return false;
-
- SDLoc Loc(N);
- SDValue Val = N->getOperand(0);
-
- // Optimized with two rldicl's as follows:
- // Add missing bits on left to the mask and check that the mask is a
- // wrapped run of ones, i.e.
- // Change pattern |0001111100000011111111|
- // to |1111111100000011111111|.
- unsigned NumOfLeadingZeros = countLeadingZeros(Imm64);
- if (NumOfLeadingZeros != 0)
- Imm64 |= maskLeadingOnes<uint64_t>(NumOfLeadingZeros);
-
- unsigned MB, ME;
- if (!isRunOfOnes64(Imm64, MB, ME))
- return false;
-
- // ME MB MB-ME+63
- // +----------------------+ +----------------------+
- // |1111111100000011111111| -> |0000001111111111111111|
- // +----------------------+ +----------------------+
- // 0 63 0 63
- // There are ME + 1 ones on the left and (MB - ME + 63) & 63 zeros in between.
- unsigned OnesOnLeft = ME + 1;
- unsigned ZerosInBetween = (MB - ME + 63) & 63;
- // Rotate left by OnesOnLeft (so leading ones are now trailing ones) and clear
- // on the left the bits that are already zeros in the mask.
- Val = SDValue(CurDAG->getMachineNode(PPC::RLDICL, Loc, MVT::i64, Val,
- getI64Imm(OnesOnLeft, Loc),
- getI64Imm(ZerosInBetween, Loc)),
- 0);
- // MB-ME+63 ME MB
- // +----------------------+ +----------------------+
- // |0000001111111111111111| -> |0001111100000011111111|
- // +----------------------+ +----------------------+
- // 0 63 0 63
- // Rotate back by 64 - OnesOnLeft to undo previous rotate. Then clear on the
- // left the number of ones we previously added.
- SDValue Ops[] = {Val, getI64Imm(64 - OnesOnLeft, Loc),
- getI64Imm(NumOfLeadingZeros, Loc)};
- CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops);
- return true;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLWIMI(SDNode *N) {
- assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
- unsigned Imm;
- if (!isInt32Immediate(N->getOperand(1), Imm))
- return false;
-
- SDValue Val = N->getOperand(0);
- unsigned Imm2;
- // ISD::OR doesn't get all the bitfield insertion fun.
- // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) might be a
- // bitfield insert.
- if (Val.getOpcode() != ISD::OR || !isInt32Immediate(Val.getOperand(1), Imm2))
- return false;
-
- // The idea here is to check whether this is equivalent to:
- // (c1 & m) | (x & ~m)
- // where m is a run-of-ones mask. The logic here is that, for each bit in
- // c1 and c2:
- // - if both are 1, then the output will be 1.
- // - if both are 0, then the output will be 0.
- // - if the bit in c1 is 0, and the bit in c2 is 1, then the output will
- // come from x.
- // - if the bit in c1 is 1, and the bit in c2 is 0, then the output will
- // be 0.
- // If that last condition is never the case, then we can form m from the
- // bits that are the same between c1 and c2.
- unsigned MB, ME;
- if (isRunOfOnes(~(Imm ^ Imm2), MB, ME) && !(~Imm & Imm2)) {
- SDLoc dl(N);
- SDValue Ops[] = {Val.getOperand(0), Val.getOperand(1), getI32Imm(0, dl),
- getI32Imm(MB, dl), getI32Imm(ME, dl)};
- ReplaceNode(N, CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops));
- return true;
- }
-
- return false;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLDICL(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;
-
- // If this is a 64-bit zero-extension mask, emit rldicl.
- unsigned MB = 64 - countTrailingOnes(Imm64);
- unsigned SH = 0;
- unsigned Imm;
- SDValue Val = N->getOperand(0);
- SDLoc dl(N);
+ if (isInt32Immediate(N->getOperand(1), Imm)) {
+ if (isRunOfOnes(Imm, MB, ME) &&
+ N->getOperand(0).getOpcode() != ISD::ROTL) {
+ SDValue Ops[] = { Val, getI32Imm(0, dl), getI32Imm(MB, dl),
+ getI32Imm(ME, dl) };
+ CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
+ return true;
+ }
+ // AND X, 0 -> 0, not "rlwinm 32".
+ if (Imm == 0) {
+ ReplaceUses(SDValue(N, 0), N->getOperand(1));
+ return true;
+ }
- if (Val.getOpcode() == ISD::ANY_EXTEND) {
- auto Op0 = Val.getOperand(0);
- if (Op0.getOpcode() == ISD::SRL &&
- isInt32Immediate(Op0.getOperand(1).getNode(), Imm) && Imm <= MB) {
+ // ISD::OR doesn't get all the bitfield insertion fun.
+ // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) might be a
+ // bitfield insert.
+ if (N->getOperand(0).getOpcode() == ISD::OR &&
+ isInt32Immediate(N->getOperand(0).getOperand(1), Imm2)) {
+ // The idea here is to check whether this is equivalent to:
+ // (c1 & m) | (x & ~m)
+ // where m is a run-of-ones mask. The logic here is that, for each bit in
+ // c1 and c2:
+ // - if both are 1, then the output will be 1.
+ // - if both are 0, then the output will be 0.
+ // - if the bit in c1 is 0, and the bit in c2 is 1, then the output will
+ // come from x.
+ // - if the bit in c1 is 1, and the bit in c2 is 0, then the output will
+ // be 0.
+ // If that last condition is never the case, then we can form m from the
+ // bits that are the same between c1 and c2.
+ unsigned MB, ME;
+ if (isRunOfOnes(~(Imm^Imm2), MB, ME) && !(~Imm & Imm2)) {
+ SDValue Ops[] = { N->getOperand(0).getOperand(0),
+ N->getOperand(0).getOperand(1),
+ getI32Imm(0, dl), getI32Imm(MB, dl),
+ getI32Imm(ME, dl) };
+ ReplaceNode(N, CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops));
+ return true;
+ }
+ }
+ } else if (isInt64Immediate(N->getOperand(1).getNode(), Imm64)) {
+ // If this is a 64-bit zero-extension mask, emit rldicl.
+ if (isMask_64(Imm64)) {
+ MB = 64 - countTrailingOnes(Imm64);
+ SH = 0;
+
+ if (Val.getOpcode() == ISD::ANY_EXTEND) {
+ auto Op0 = Val.getOperand(0);
+ if ( Op0.getOpcode() == ISD::SRL &&
+ isInt32Immediate(Op0.getOperand(1).getNode(), Imm) && Imm <= MB) {
+
+ auto ResultType = Val.getNode()->getValueType(0);
+ auto ImDef = CurDAG->getMachineNode(PPC::IMPLICIT_DEF, dl,
+ ResultType);
+ SDValue IDVal (ImDef, 0);
+
+ Val = SDValue(CurDAG->getMachineNode(PPC::INSERT_SUBREG, dl,
+ ResultType, IDVal, Op0.getOperand(0),
+ getI32Imm(1, dl)), 0);
+ SH = 64 - Imm;
+ }
+ }
- auto ResultType = Val.getNode()->getValueType(0);
- auto ImDef = CurDAG->getMachineNode(PPC::IMPLICIT_DEF, dl, ResultType);
- SDValue IDVal(ImDef, 0);
+ // If the operand is a logical right shift, we can fold it into this
+ // instruction: rldicl(rldicl(x, 64-n, n), 0, mb) -> rldicl(x, 64-n, mb)
+ // for n <= mb. The right shift is really a left rotate followed by a
+ // mask, and this mask is a more-restrictive sub-mask of the mask implied
+ // by the shift.
+ if (Val.getOpcode() == ISD::SRL &&
+ isInt32Immediate(Val.getOperand(1).getNode(), Imm) && Imm <= MB) {
+ assert(Imm < 64 && "Illegal shift amount");
+ Val = Val.getOperand(0);
+ SH = 64 - Imm;
+ }
- Val = SDValue(CurDAG->getMachineNode(PPC::INSERT_SUBREG, dl, ResultType,
- IDVal, Op0.getOperand(0),
- getI32Imm(1, dl)),
- 0);
- SH = 64 - Imm;
+ SDValue Ops[] = { Val, getI32Imm(SH, dl), getI32Imm(MB, dl) };
+ CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops);
+ return true;
+ } else if (isMask_64(~Imm64)) {
+ // If this is a negated 64-bit zero-extension mask,
+ // i.e. the immediate is a sequence of ones from most significant side
+ // and all zero for reminder, we should use rldicr.
+ MB = 63 - countTrailingOnes(~Imm64);
+ SH = 0;
+ SDValue Ops[] = { Val, getI32Imm(SH, dl), getI32Imm(MB, dl) };
+ CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, Ops);
+ return true;
}
- }
- // If the operand is a logical right shift, we can fold it into this
- // instruction: rldicl(rldicl(x, 64-n, n), 0, mb) -> rldicl(x, 64-n, mb)
- // for n <= mb. The right shift is really a left rotate followed by a
- // mask, and this mask is a more-restrictive sub-mask of the mask implied
- // by the shift.
- if (Val.getOpcode() == ISD::SRL &&
- isInt32Immediate(Val.getOperand(1).getNode(), Imm) && Imm <= MB) {
- assert(Imm < 64 && "Illegal shift amount");
- Val = Val.getOperand(0);
- SH = 64 - Imm;
+ // It is not 16-bit imm that means we need two instructions at least if
+ // using "and" instruction. Try to exploit it with rotate mask instructions.
+ if (isRunOfOnes64(Imm64, MB, ME)) {
+ if (MB >= 32 && MB <= ME) {
+ // MB ME
+ // +----------------------+
+ // |xxxxxxxxxxx00011111000|
+ // +----------------------+
+ // 0 32 64
+ // We can only do it if the MB is larger than 32 and MB <= ME
+ // as RLWINM will replace the content of [0 - 32) with [32 - 64) even
+ // we didn't rotate it.
+ SDValue Ops[] = { Val, getI64Imm(0, dl), getI64Imm(MB - 32, dl),
+ getI64Imm(ME - 32, dl) };
+ CurDAG->SelectNodeTo(N, PPC::RLWINM8, MVT::i64, Ops);
+ return true;
+ }
+ // TODO - handle it with rldicl + rldicl
+ }
}
- SDValue Ops[] = {Val, getI32Imm(SH, dl), getI32Imm(MB, dl)};
- CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops);
- return true;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLDICR(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;
-
- // If this is a negated 64-bit zero-extension mask,
- // i.e. the immediate is a sequence of ones from most significant side
- // and all zero for reminder, we should use rldicr.
- unsigned MB = 63 - countTrailingOnes(~Imm64);
- unsigned SH = 0;
- SDLoc dl(N);
- SDValue Ops[] = {N->getOperand(0), getI32Imm(SH, dl), getI32Imm(MB, dl)};
- CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, Ops);
- return true;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLDIMI(SDNode *N) {
- assert(N->getOpcode() == ISD::OR && "ISD::OR SDNode expected");
- uint64_t Imm64;
- unsigned MB, ME;
- SDValue N0 = N->getOperand(0);
-
- // We won't get fewer instructions if the imm is 32-bit integer.
- // rldimi requires the imm to have consecutive ones with both sides zero.
- // Also, make sure the first Op has only one use, otherwise this may increase
- // register pressure since rldimi is destructive.
- if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) ||
- isUInt<32>(Imm64) || !isRunOfOnes64(Imm64, MB, ME) || !N0.hasOneUse())
- return false;
-
- unsigned SH = 63 - ME;
- SDLoc Dl(N);
- // Use select64Imm for making LI instr instead of directly putting Imm64
- SDValue Ops[] = {
- N->getOperand(0),
- SDValue(selectI64Imm(CurDAG, getI64Imm(-1, Dl).getNode()), 0),
- getI32Imm(SH, Dl), getI32Imm(MB, Dl)};
- CurDAG->SelectNodeTo(N, PPC::RLDIMI, MVT::i64, Ops);
- return true;
+ return false;
}
// Select - Convert the specified operand from a target-independent to a
@@ -5069,214 +4541,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
}
break;
- case ISD::INTRINSIC_VOID: {
- auto IntrinsicID = N->getConstantOperandVal(1);
- if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
- IntrinsicID != Intrinsic::ppc_trapd &&
- IntrinsicID != Intrinsic::ppc_trap)
- break;
- unsigned Opcode = (IntrinsicID == Intrinsic::ppc_tdw ||
- IntrinsicID == Intrinsic::ppc_trapd)
- ? PPC::TDI
- : PPC::TWI;
- SmallVector<SDValue, 4> OpsWithMD;
- unsigned MDIndex;
- if (IntrinsicID == Intrinsic::ppc_tdw ||
- IntrinsicID == Intrinsic::ppc_tw) {
- SDValue Ops[] = {N->getOperand(4), N->getOperand(2), N->getOperand(3)};
- int16_t SImmOperand2;
- int16_t SImmOperand3;
- int16_t SImmOperand4;
- bool isOperand2IntS16Immediate =
- isIntS16Immediate(N->getOperand(2), SImmOperand2);
- bool isOperand3IntS16Immediate =
- isIntS16Immediate(N->getOperand(3), SImmOperand3);
- // We will emit PPC::TD or PPC::TW if the 2nd and 3rd operands are reg +
- // reg or imm + imm. The imm + imm form will be optimized to either an
- // unconditional trap or a nop in a later pass.
- if (isOperand2IntS16Immediate == isOperand3IntS16Immediate)
- Opcode = IntrinsicID == Intrinsic::ppc_tdw ? PPC::TD : PPC::TW;
- else if (isOperand3IntS16Immediate)
- // The 2nd and 3rd operands are reg + imm.
- Ops[2] = getI32Imm(int(SImmOperand3) & 0xFFFF, dl);
- else {
- // The 2nd and 3rd operands are imm + reg.
- bool isOperand4IntS16Immediate =
- isIntS16Immediate(N->getOperand(4), SImmOperand4);
- (void)isOperand4IntS16Immediate;
- assert(isOperand4IntS16Immediate &&
- "The 4th operand is not an Immediate");
- // We need to flip the condition immediate TO.
- int16_t TO = int(SImmOperand4) & 0x1F;
- // We swap the first and second bit of TO if they are not same.
- if ((TO & 0x1) != ((TO & 0x2) >> 1))
- TO = (TO & 0x1) ? TO + 1 : TO - 1;
- // We swap the fourth and fifth bit of TO if they are not same.
- if ((TO & 0x8) != ((TO & 0x10) >> 1))
- TO = (TO & 0x8) ? TO + 8 : TO - 8;
- Ops[0] = getI32Imm(TO, dl);
- Ops[1] = N->getOperand(3);
- Ops[2] = getI32Imm(int(SImmOperand2) & 0xFFFF, dl);
- }
- OpsWithMD = {Ops[0], Ops[1], Ops[2]};
- MDIndex = 5;
- } else {
- OpsWithMD = {getI32Imm(24, dl), N->getOperand(2), getI32Imm(0, dl)};
- MDIndex = 3;
- }
-
- if (N->getNumOperands() > MDIndex) {
- SDValue MDV = N->getOperand(MDIndex);
- const MDNode *MD = cast<MDNodeSDNode>(MDV)->getMD();
- assert(MD->getNumOperands() != 0 && "Empty MDNode in operands!");
- assert((isa<MDString>(MD->getOperand(0)) && cast<MDString>(
- MD->getOperand(0))->getString().equals("ppc-trap-reason"))
- && "Unsupported annotation data type!");
- for (unsigned i = 1; i < MD->getNumOperands(); i++) {
- assert(isa<MDString>(MD->getOperand(i)) &&
- "Invalid data type for annotation ppc-trap-reason!");
- OpsWithMD.push_back(
- getI32Imm(std::stoi(cast<MDString>(
- MD->getOperand(i))->getString().str()), dl));
- }
- }
- OpsWithMD.push_back(N->getOperand(0)); // chain
- CurDAG->SelectNodeTo(N, Opcode, MVT::Other, OpsWithMD);
- return;
- }
-
- case ISD::INTRINSIC_WO_CHAIN: {
- // We emit the PPC::FSELS instruction here because of type conflicts with
- // the comparison operand. The FSELS instruction is defined to use an 8-byte
- // comparison like the FSELD version. The fsels intrinsic takes a 4-byte
- // value for the comparison. When selecting through a .td file, a type
- // error is raised. Must check this first so we never break on the
- // !Subtarget->isISA3_1() check.
- auto IntID = N->getConstantOperandVal(0);
- if (IntID == Intrinsic::ppc_fsels) {
- SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3)};
- CurDAG->SelectNodeTo(N, PPC::FSELS, MVT::f32, Ops);
- return;
- }
-
- if (IntID == Intrinsic::ppc_bcdadd_p || IntID == Intrinsic::ppc_bcdsub_p) {
- auto Pred = N->getConstantOperandVal(1);
- unsigned Opcode =
- IntID == Intrinsic::ppc_bcdadd_p ? PPC::BCDADD_rec : PPC::BCDSUB_rec;
- unsigned SubReg = 0;
- unsigned ShiftVal = 0;
- bool Reverse = false;
- switch (Pred) {
- case 0:
- SubReg = PPC::sub_eq;
- ShiftVal = 1;
- break;
- case 1:
- SubReg = PPC::sub_eq;
- ShiftVal = 1;
- Reverse = true;
- break;
- case 2:
- SubReg = PPC::sub_lt;
- ShiftVal = 3;
- break;
- case 3:
- SubReg = PPC::sub_lt;
- ShiftVal = 3;
- Reverse = true;
- break;
- case 4:
- SubReg = PPC::sub_gt;
- ShiftVal = 2;
- break;
- case 5:
- SubReg = PPC::sub_gt;
- ShiftVal = 2;
- Reverse = true;
- break;
- case 6:
- SubReg = PPC::sub_un;
- break;
- case 7:
- SubReg = PPC::sub_un;
- Reverse = true;
- break;
- }
-
- EVT VTs[] = {MVT::v16i8, MVT::Glue};
- SDValue Ops[] = {N->getOperand(2), N->getOperand(3),
- CurDAG->getTargetConstant(0, dl, MVT::i32)};
- SDValue BCDOp = SDValue(CurDAG->getMachineNode(Opcode, dl, VTs, Ops), 0);
- SDValue CR6Reg = CurDAG->getRegister(PPC::CR6, MVT::i32);
- // On Power10, we can use SETBC[R]. On prior architectures, we have to use
- // MFOCRF and shift/negate the value.
- if (Subtarget->isISA3_1()) {
- SDValue SubRegIdx = CurDAG->getTargetConstant(SubReg, dl, MVT::i32);
- SDValue CRBit = SDValue(
- CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::i1,
- CR6Reg, SubRegIdx, BCDOp.getValue(1)),
- 0);
- CurDAG->SelectNodeTo(N, Reverse ? PPC::SETBCR : PPC::SETBC, MVT::i32,
- CRBit);
- } else {
- SDValue Move =
- SDValue(CurDAG->getMachineNode(PPC::MFOCRF, dl, MVT::i32, CR6Reg,
- BCDOp.getValue(1)),
- 0);
- SDValue Ops[] = {Move, getI32Imm((32 - (4 + ShiftVal)) & 31, dl),
- getI32Imm(31, dl), getI32Imm(31, dl)};
- if (!Reverse)
- CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
- else {
- SDValue Shift = SDValue(
- CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops), 0);
- CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Shift, getI32Imm(1, dl));
- }
- }
- return;
- }
-
- if (!Subtarget->isISA3_1())
- break;
- unsigned Opcode = 0;
- switch (IntID) {
- default:
- break;
- case Intrinsic::ppc_altivec_vstribr_p:
- Opcode = PPC::VSTRIBR_rec;
- break;
- case Intrinsic::ppc_altivec_vstribl_p:
- Opcode = PPC::VSTRIBL_rec;
- break;
- case Intrinsic::ppc_altivec_vstrihr_p:
- Opcode = PPC::VSTRIHR_rec;
- break;
- case Intrinsic::ppc_altivec_vstrihl_p:
- Opcode = PPC::VSTRIHL_rec;
- break;
- }
- if (!Opcode)
- break;
-
- // Generate the appropriate vector string isolate intrinsic to match.
- EVT VTs[] = {MVT::v16i8, MVT::Glue};
- SDValue VecStrOp =
- SDValue(CurDAG->getMachineNode(Opcode, dl, VTs, N->getOperand(2)), 0);
- // Vector string isolate instructions update the EQ bit of CR6.
- // Generate a SETBC instruction to extract the bit and place it in a GPR.
- SDValue SubRegIdx = CurDAG->getTargetConstant(PPC::sub_eq, dl, MVT::i32);
- SDValue CR6Reg = CurDAG->getRegister(PPC::CR6, MVT::i32);
- SDValue CRBit = SDValue(
- CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::i1,
- CR6Reg, SubRegIdx, VecStrOp.getValue(1)),
- 0);
- CurDAG->SelectNodeTo(N, PPC::SETBC, MVT::i32, CRBit);
- return;
- }
-
case ISD::SETCC:
- case ISD::STRICT_FSETCC:
- case ISD::STRICT_FSETCCS:
if (trySETCC(N))
return;
break;
@@ -5286,7 +4551,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
case PPCISD::ADDI_TLSGD_L_ADDR: {
const Module *Mod = MF->getFunction().getParent();
if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 ||
- !Subtarget->isSecurePlt() || !Subtarget->isTargetELF() ||
+ !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() ||
Mod->getPICLevel() == PICLevel::SmallPIC)
break;
// Attach global base pointer on GETtlsADDR32 node in order to
@@ -5295,8 +4560,8 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
} break;
case PPCISD::CALL: {
if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 ||
- !TM.isPositionIndependent() || !Subtarget->isSecurePlt() ||
- !Subtarget->isTargetELF())
+ !TM.isPositionIndependent() || !PPCSubTarget->isSecurePlt() ||
+ !PPCSubTarget->isTargetELF())
break;
SDValue Op = N->getOperand(1);
@@ -5360,7 +4625,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
case ISD::STORE: {
// Change TLS initial-exec D-form stores to X-form stores.
StoreSDNode *ST = cast<StoreSDNode>(N);
- if (EnableTLSOpt && Subtarget->isELFv2ABI() &&
+ if (EnableTLSOpt && PPCSubTarget->isELFv2ABI() &&
ST->getAddressingMode() != ISD::PRE_INC)
if (tryTLSXFormStore(ST))
return;
@@ -5374,7 +4639,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
// Normal loads are handled by code generated from the .td file.
if (LD->getAddressingMode() != ISD::PRE_INC) {
// Change TLS initial-exec D-form loads to X-form loads.
- if (EnableTLSOpt && Subtarget->isELFv2ABI())
+ if (EnableTLSOpt && PPCSubTarget->isELFv2ABI())
if (tryTLSXFormLoad(LD))
return;
break;
@@ -5428,6 +4693,8 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
assert((!isSExt || LoadedVT == MVT::i16) && "Invalid sext update load");
switch (LoadedVT.getSimpleVT().SimpleTy) {
default: llvm_unreachable("Invalid PPC load type!");
+ case MVT::v4f64: Opcode = PPC::QVLFDUX; break; // QPX
+ case MVT::v4f32: Opcode = PPC::QVLFSUX; break; // QPX
case MVT::f64: Opcode = PPC::LFDUX; break;
case MVT::f32: Opcode = PPC::LFSUX; break;
case MVT::i32: Opcode = PPC::LWZUX; break;
@@ -5463,8 +4730,7 @@ 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 (tryAndWithMask(N))
return;
// Other cases are autogenerated.
@@ -5482,20 +4748,15 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
// If this is equivalent to an add, then we can fold it with the
// FrameIndex calculation.
if ((LHSKnown.Zero.getZExtValue()|~(uint64_t)Imm) == ~0ULL) {
- selectFrameIndex(N, N->getOperand(0).getNode(), (int64_t)Imm);
+ selectFrameIndex(N, N->getOperand(0).getNode(), (int)Imm);
return;
}
}
- // If this is 'or' against an imm with consecutive ones and both sides zero,
- // try to emit rldimi
- if (tryAsSingleRLDIMI(N))
- return;
-
// OR with a 32-bit immediate can be handled by ori + oris
// without creating an immediate in a GPR.
uint64_t Imm64 = 0;
- bool IsPPC64 = Subtarget->isPPC64();
+ bool IsPPC64 = PPCSubTarget->isPPC64();
if (IsPPC64 && isInt64Immediate(N->getOperand(1), Imm64) &&
(Imm64 & ~0xFFFFFFFFuLL) == 0) {
// If ImmHi (ImmHi) is zero, only one ori (oris) is generated later.
@@ -5518,7 +4779,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
// XOR with a 32-bit immediate can be handled by xori + xoris
// without creating an immediate in a GPR.
uint64_t Imm64 = 0;
- bool IsPPC64 = Subtarget->isPPC64();
+ bool IsPPC64 = PPCSubTarget->isPPC64();
if (IsPPC64 && isInt64Immediate(N->getOperand(1), Imm64) &&
(Imm64 & ~0xFFFFFFFFuLL) == 0) {
// If ImmHi (ImmHi) is zero, only one xori (xoris) is generated later.
@@ -5540,7 +4801,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
int16_t Imm;
if (N->getOperand(0)->getOpcode() == ISD::FrameIndex &&
isIntS16Immediate(N->getOperand(1), Imm)) {
- selectFrameIndex(N, N->getOperand(0).getNode(), (int64_t)Imm);
+ selectFrameIndex(N, N->getOperand(0).getNode(), (int)Imm);
return;
}
@@ -5574,47 +4835,6 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
// Other cases are autogenerated.
break;
}
- case ISD::MUL: {
- SDValue Op1 = N->getOperand(1);
- if (Op1.getOpcode() != ISD::Constant ||
- (Op1.getValueType() != MVT::i64 && Op1.getValueType() != MVT::i32))
- break;
-
- // If the multiplier fits int16, we can handle it with mulli.
- int64_t Imm = cast<ConstantSDNode>(Op1)->getZExtValue();
- unsigned Shift = countTrailingZeros<uint64_t>(Imm);
- if (isInt<16>(Imm) || !Shift)
- break;
-
- // If the shifted value fits int16, we can do this transformation:
- // (mul X, c1 << c2) -> (rldicr (mulli X, c1) c2). We do this in ISEL due to
- // DAGCombiner prefers (shl (mul X, c1), c2) -> (mul X, c1 << c2).
- uint64_t ImmSh = Imm >> Shift;
- if (!isInt<16>(ImmSh))
- break;
-
- uint64_t SextImm = SignExtend64(ImmSh & 0xFFFF, 16);
- if (Op1.getValueType() == MVT::i64) {
- SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i64);
- SDNode *MulNode = CurDAG->getMachineNode(PPC::MULLI8, dl, MVT::i64,
- N->getOperand(0), SDImm);
-
- SDValue Ops[] = {SDValue(MulNode, 0), getI32Imm(Shift, dl),
- getI32Imm(63 - Shift, dl)};
- CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, Ops);
- return;
- } else {
- SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i32);
- SDNode *MulNode = CurDAG->getMachineNode(PPC::MULLI, dl, MVT::i32,
- N->getOperand(0), SDImm);
-
- SDValue Ops[] = {SDValue(MulNode, 0), getI32Imm(Shift, dl),
- getI32Imm(0, dl), getI32Imm(31 - Shift, dl)};
- CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
- return;
- }
- break;
- }
// FIXME: Remove this once the ANDI glue bug is fixed:
case PPCISD::ANDI_rec_1_EQ_BIT:
case PPCISD::ANDI_rec_1_GT_BIT: {
@@ -5646,10 +4866,11 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
bool isPPC64 = (PtrVT == MVT::i64);
// If this is a select of i1 operands, we'll pattern match it.
- if (Subtarget->useCRBits() && N->getOperand(0).getValueType() == MVT::i1)
+ if (PPCSubTarget->useCRBits() &&
+ N->getOperand(0).getValueType() == MVT::i1)
break;
- if (Subtarget->isISA3_0() && Subtarget->isPPC64()) {
+ if (PPCSubTarget->isISA3_0() && PPCSubTarget->isPPC64()) {
bool NeedSwapOps = false;
bool IsUnCmp = false;
if (mayUseP9Setb(N, CC, CurDAG, NeedSwapOps, IsUnCmp)) {
@@ -5679,8 +4900,8 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N->getOperand(2)))
if (ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N->getOperand(3)))
- if (N1C->isZero() && N3C->isZero() && N2C->getZExtValue() == 1ULL &&
- CC == ISD::SETNE &&
+ if (N1C->isNullValue() && N3C->isNullValue() &&
+ N2C->getZExtValue() == 1ULL && CC == ISD::SETNE &&
// FIXME: Implement this optzn for PPC64.
N->getValueType(0) == MVT::i32) {
SDNode *Tmp =
@@ -5724,7 +4945,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
}
unsigned BROpc =
- getPredicateForSetCC(CC, N->getOperand(0).getValueType(), Subtarget);
+ getPredicateForSetCC(CC, N->getOperand(0).getValueType(), PPCSubTarget);
unsigned SelectCCOp;
if (N->getValueType(0) == MVT::i32)
@@ -5732,23 +4953,29 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
else if (N->getValueType(0) == MVT::i64)
SelectCCOp = PPC::SELECT_CC_I8;
else if (N->getValueType(0) == MVT::f32) {
- if (Subtarget->hasP8Vector())
+ if (PPCSubTarget->hasP8Vector())
SelectCCOp = PPC::SELECT_CC_VSSRC;
- else if (Subtarget->hasSPE())
+ else if (PPCSubTarget->hasSPE())
SelectCCOp = PPC::SELECT_CC_SPE4;
else
SelectCCOp = PPC::SELECT_CC_F4;
} else if (N->getValueType(0) == MVT::f64) {
- if (Subtarget->hasVSX())
+ if (PPCSubTarget->hasVSX())
SelectCCOp = PPC::SELECT_CC_VSFRC;
- else if (Subtarget->hasSPE())
+ else if (PPCSubTarget->hasSPE())
SelectCCOp = PPC::SELECT_CC_SPE;
else
SelectCCOp = PPC::SELECT_CC_F8;
} else if (N->getValueType(0) == MVT::f128)
SelectCCOp = PPC::SELECT_CC_F16;
- else if (Subtarget->hasSPE())
+ else if (PPCSubTarget->hasSPE())
SelectCCOp = PPC::SELECT_CC_SPE;
+ else if (PPCSubTarget->hasQPX() && N->getValueType(0) == MVT::v4f64)
+ SelectCCOp = PPC::SELECT_CC_QFRC;
+ else if (PPCSubTarget->hasQPX() && N->getValueType(0) == MVT::v4f32)
+ SelectCCOp = PPC::SELECT_CC_QSRC;
+ else if (PPCSubTarget->hasQPX() && N->getValueType(0) == MVT::v4i1)
+ SelectCCOp = PPC::SELECT_CC_QBRC;
else if (N->getValueType(0) == MVT::v2f64 ||
N->getValueType(0) == MVT::v2i64)
SelectCCOp = PPC::SELECT_CC_VSRC;
@@ -5761,8 +4988,8 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
return;
}
case ISD::VECTOR_SHUFFLE:
- if (Subtarget->hasVSX() && (N->getValueType(0) == MVT::v2f64 ||
- N->getValueType(0) == MVT::v2i64)) {
+ if (PPCSubTarget->hasVSX() && (N->getValueType(0) == MVT::v2f64 ||
+ N->getValueType(0) == MVT::v2i64)) {
ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(N);
SDValue Op1 = N->getOperand(SVN->getMaskElt(0) < 2 ? 0 : 1),
@@ -5797,7 +5024,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
// For little endian, we must swap the input operands and adjust
// the mask elements (reverse and invert them).
- if (Subtarget->isLittleEndian()) {
+ if (PPCSubTarget->isLittleEndian()) {
std::swap(Op1, Op2);
unsigned tmp = DM[0];
DM[0] = 1 - DM[1];
@@ -5814,7 +5041,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
break;
case PPCISD::BDNZ:
case PPCISD::BDZ: {
- bool IsPPC64 = Subtarget->isPPC64();
+ bool IsPPC64 = PPCSubTarget->isPPC64();
SDValue Ops[] = { N->getOperand(1), N->getOperand(0) };
CurDAG->SelectNodeTo(N, N->getOpcode() == PPCISD::BDNZ
? (IsPPC64 ? PPC::BDNZ8 : PPC::BDNZ)
@@ -5840,13 +5067,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
return;
}
case ISD::BR_CC: {
- if (tryFoldSWTestBRCC(N))
- return;
- if (trySelectLoopCountIntrinsic(N))
- return;
ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
unsigned PCC =
- getPredicateForSetCC(CC, N->getOperand(2).getValueType(), Subtarget);
+ getPredicateForSetCC(CC, N->getOperand(2).getValueType(), PPCSubTarget);
if (N->getOperand(2).getValueType() == MVT::i1) {
unsigned Opc;
@@ -5899,9 +5122,11 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
return;
}
case PPCISD::TOC_ENTRY: {
- const bool isPPC64 = Subtarget->isPPC64();
- const bool isELFABI = Subtarget->isSVR4ABI();
- const bool isAIXABI = Subtarget->isAIXABI();
+ const bool isPPC64 = PPCSubTarget->isPPC64();
+ const bool isELFABI = PPCSubTarget->isSVR4ABI();
+ const bool isAIXABI = PPCSubTarget->isAIXABI();
+
+ assert(!PPCSubTarget->isDarwin() && "TOC is an ELF/XCOFF construct");
// PowerPC only support small, medium and large code model.
const CodeModel::Model CModel = TM.getCodeModel();
@@ -5911,57 +5136,36 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
if (isAIXABI && CModel == CodeModel::Medium)
report_fatal_error("Medium code model is not supported on AIX.");
- // For 64-bit ELF small code model, we allow SelectCodeCommon to handle
- // this, selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA. For AIX
- // small code model, we need to check for a toc-data attribute.
- if (isPPC64 && !isAIXABI && CModel == CodeModel::Small)
+ // For 64-bit small code model, we allow SelectCodeCommon to handle this,
+ // selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA.
+ if (isPPC64 && CModel == CodeModel::Small)
break;
- auto replaceWith = [this, &dl](unsigned OpCode, SDNode *TocEntry,
- EVT OperandTy) {
- SDValue GA = TocEntry->getOperand(0);
- SDValue TocBase = TocEntry->getOperand(1);
- SDNode *MN = CurDAG->getMachineNode(OpCode, dl, OperandTy, GA, TocBase);
- transferMemOperands(TocEntry, MN);
- ReplaceNode(TocEntry, MN);
- };
-
// Handle 32-bit small code model.
- if (!isPPC64 && CModel == CodeModel::Small) {
- // Transforms the ISD::TOC_ENTRY node to passed in Opcode, either
- // PPC::ADDItoc, or PPC::LWZtoc
+ if (!isPPC64) {
+ // Transforms the ISD::TOC_ENTRY node to a PPCISD::LWZtoc.
+ auto replaceWithLWZtoc = [this, &dl](SDNode *TocEntry) {
+ SDValue GA = TocEntry->getOperand(0);
+ SDValue TocBase = TocEntry->getOperand(1);
+ SDNode *MN = CurDAG->getMachineNode(PPC::LWZtoc, dl, MVT::i32, GA,
+ TocBase);
+ transferMemOperands(TocEntry, MN);
+ ReplaceNode(TocEntry, MN);
+ };
+
if (isELFABI) {
assert(TM.isPositionIndependent() &&
"32-bit ELF can only have TOC entries in position independent"
" code.");
// 32-bit ELF always uses a small code model toc access.
- replaceWith(PPC::LWZtoc, N, MVT::i32);
+ replaceWithLWZtoc(N);
return;
}
- assert(isAIXABI && "ELF ABI already handled");
-
- if (hasTocDataAttr(N->getOperand(0),
- CurDAG->getDataLayout().getPointerSize())) {
- replaceWith(PPC::ADDItoc, N, MVT::i32);
+ if (isAIXABI && CModel == CodeModel::Small) {
+ replaceWithLWZtoc(N);
return;
}
-
- replaceWith(PPC::LWZtoc, N, MVT::i32);
- return;
- }
-
- if (isPPC64 && CModel == CodeModel::Small) {
- assert(isAIXABI && "ELF ABI handled in common SelectCode");
-
- if (hasTocDataAttr(N->getOperand(0),
- CurDAG->getDataLayout().getPointerSize())) {
- replaceWith(PPC::ADDItoc8, N, MVT::i64);
- return;
- }
- // Break if it doesn't have toc data attribute. Proceed with common
- // SelectCode.
- break;
}
assert(CModel != CodeModel::Small && "All small code models handled.");
@@ -5973,7 +5177,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
// or 64-bit medium (ELF-only) or large (ELF and AIX) code model code. We
// generate two instructions as described below. The first source operand
// is a symbol reference. If it must be toc-referenced according to
- // Subtarget, we generate:
+ // PPCSubTarget, we generate:
// [32-bit AIX]
// LWZtocL(@sym, ADDIStocHA(%r2, @sym))
// [64-bit ELF/AIX]
@@ -6005,7 +5209,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
}
case PPCISD::PPC32_PICGOT:
// Generate a PIC-safe GOT reference.
- assert(Subtarget->is32BitELFABI() &&
+ assert(PPCSubTarget->is32BitELFABI() &&
"PPCISD::PPC32_PICGOT is only supported for 32-bit SVR4");
CurDAG->SelectNodeTo(N, PPC::PPC32PICGOT,
PPCLowering->getPointerTy(CurDAG->getDataLayout()),
@@ -6084,78 +5288,6 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
return;
}
}
- case PPCISD::LD_SPLAT: {
- // Here we want to handle splat load for type v16i8 and v8i16 when there is
- // no direct move, we don't need to use stack for this case. If target has
- // direct move, we should be able to get the best selection in the .td file.
- if (!Subtarget->hasAltivec() || Subtarget->hasDirectMove())
- break;
-
- EVT Type = N->getValueType(0);
- if (Type != MVT::v16i8 && Type != MVT::v8i16)
- break;
-
- // If the alignment for the load is 16 or bigger, we don't need the
- // permutated mask to get the required value. The value must be the 0
- // element in big endian target or 7/15 in little endian target in the
- // result vsx register of lvx instruction.
- // Select the instruction in the .td file.
- if (cast<MemIntrinsicSDNode>(N)->getAlign() >= Align(16) &&
- isOffsetMultipleOf(N, 16))
- break;
-
- SDValue ZeroReg =
- CurDAG->getRegister(Subtarget->isPPC64() ? PPC::ZERO8 : PPC::ZERO,
- Subtarget->isPPC64() ? MVT::i64 : MVT::i32);
- unsigned LIOpcode = Subtarget->isPPC64() ? PPC::LI8 : PPC::LI;
- // v16i8 LD_SPLAT addr
- // ======>
- // Mask = LVSR/LVSL 0, addr
- // LoadLow = LVX 0, addr
- // Perm = VPERM LoadLow, LoadLow, Mask
- // Splat = VSPLTB 15/0, Perm
- //
- // v8i16 LD_SPLAT addr
- // ======>
- // Mask = LVSR/LVSL 0, addr
- // LoadLow = LVX 0, addr
- // LoadHigh = LVX (LI, 1), addr
- // Perm = VPERM LoadLow, LoadHigh, Mask
- // Splat = VSPLTH 7/0, Perm
- unsigned SplatOp = (Type == MVT::v16i8) ? PPC::VSPLTB : PPC::VSPLTH;
- unsigned SplatElemIndex =
- Subtarget->isLittleEndian() ? ((Type == MVT::v16i8) ? 15 : 7) : 0;
-
- SDNode *Mask = CurDAG->getMachineNode(
- Subtarget->isLittleEndian() ? PPC::LVSR : PPC::LVSL, dl, Type, ZeroReg,
- N->getOperand(1));
-
- SDNode *LoadLow =
- CurDAG->getMachineNode(PPC::LVX, dl, MVT::v16i8, MVT::Other,
- {ZeroReg, N->getOperand(1), N->getOperand(0)});
-
- SDNode *LoadHigh = LoadLow;
- if (Type == MVT::v8i16) {
- LoadHigh = CurDAG->getMachineNode(
- PPC::LVX, dl, MVT::v16i8, MVT::Other,
- {SDValue(CurDAG->getMachineNode(
- LIOpcode, dl, MVT::i32,
- CurDAG->getTargetConstant(1, dl, MVT::i8)),
- 0),
- N->getOperand(1), SDValue(LoadLow, 1)});
- }
-
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 1), SDValue(LoadHigh, 1));
- transferMemOperands(N, LoadHigh);
-
- SDNode *Perm =
- CurDAG->getMachineNode(PPC::VPERM, dl, Type, SDValue(LoadLow, 0),
- SDValue(LoadHigh, 0), SDValue(Mask, 0));
- CurDAG->SelectNodeTo(N, SplatOp, Type,
- CurDAG->getTargetConstant(SplatElemIndex, dl, MVT::i8),
- SDValue(Perm, 0));
- return;
- }
}
SelectCode(N);
@@ -6174,7 +5306,7 @@ SDValue PPCDAGToDAGISel::combineToCMPB(SDNode *N) {
"Only OR nodes are supported for CMPB");
SDValue Res;
- if (!Subtarget->hasCMPB())
+ if (!PPCSubTarget->hasCMPB())
return Res;
if (N->getValueType(0) != MVT::i32 &&
@@ -6385,7 +5517,7 @@ SDValue PPCDAGToDAGISel::combineToCMPB(SDNode *N) {
// only one instruction (like a zero or one), then we should fold in those
// operations with the select.
void PPCDAGToDAGISel::foldBoolExts(SDValue &Res, SDNode *&N) {
- if (!Subtarget->useCRBits())
+ if (!PPCSubTarget->useCRBits())
return;
if (N->getOpcode() != ISD::ZERO_EXTEND &&
@@ -6417,7 +5549,8 @@ void PPCDAGToDAGISel::foldBoolExts(SDValue &Res, SDNode *&N) {
SDValue O1 = UserO1.getNode() == N ? Val : UserO1;
return CurDAG->FoldConstantArithmetic(User->getOpcode(), dl,
- User->getValueType(0), {O0, O1});
+ User->getValueType(0),
+ O0.getNode(), O1.getNode());
};
// FIXME: When the semantics of the interaction between select and undef
@@ -6499,20 +5632,16 @@ void PPCDAGToDAGISel::PostprocessISelDAG() {
// be folded with the isel so that we don't need to materialize a register
// containing zero.
bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
- for (const SDNode *User : N->uses()) {
+ for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
+ UI != UE; ++UI) {
+ SDNode *User = *UI;
if (!User->isMachineOpcode())
return false;
if (User->getMachineOpcode() != PPC::SELECT_I4 &&
User->getMachineOpcode() != PPC::SELECT_I8)
return false;
- SDNode *Op1 = User->getOperand(1).getNode();
SDNode *Op2 = User->getOperand(2).getNode();
- // If we have a degenerate select with two equal operands, swapping will
- // not do anything, and we may run into an infinite loop.
- if (Op1 == Op2)
- return false;
-
if (!Op2->isMachineOpcode())
return false;
@@ -6524,7 +5653,7 @@ bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
if (!C)
return false;
- if (!C->isZero())
+ if (!C->isNullValue())
return false;
}
@@ -6533,14 +5662,18 @@ bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
void PPCDAGToDAGISel::SwapAllSelectUsers(SDNode *N) {
SmallVector<SDNode *, 4> ToReplace;
- for (SDNode *User : N->uses()) {
+ for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
+ UI != UE; ++UI) {
+ SDNode *User = *UI;
assert((User->getMachineOpcode() == PPC::SELECT_I4 ||
User->getMachineOpcode() == PPC::SELECT_I8) &&
"Must have all select users");
ToReplace.push_back(User);
}
- for (SDNode *User : ToReplace) {
+ for (SmallVector<SDNode *, 4>::iterator UI = ToReplace.begin(),
+ UE = ToReplace.end(); UI != UE; ++UI) {
+ SDNode *User = *UI;
SDNode *ResNode =
CurDAG->getMachineNode(User->getMachineOpcode(), SDLoc(User),
User->getValueType(0), User->getOperand(0),
@@ -6589,12 +5722,11 @@ void PPCDAGToDAGISel::PeepholeCROps() {
Op2Set = true;
else if (Op.getMachineOpcode() == PPC::CRUNSET)
Op2Unset = true;
- else if ((Op.getMachineOpcode() == PPC::CRNOR &&
- Op.getOperand(0) == Op.getOperand(1)) ||
- Op.getMachineOpcode() == PPC::CRNOT)
+ else if (Op.getMachineOpcode() == PPC::CRNOR &&
+ Op.getOperand(0) == Op.getOperand(1))
Op2Not = true;
}
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
}
case PPC::BC:
case PPC::BCn:
@@ -6602,6 +5734,9 @@ void PPCDAGToDAGISel::PeepholeCROps() {
case PPC::SELECT_I8:
case PPC::SELECT_F4:
case PPC::SELECT_F8:
+ case PPC::SELECT_QFRC:
+ case PPC::SELECT_QSRC:
+ case PPC::SELECT_QBRC:
case PPC::SELECT_SPE:
case PPC::SELECT_SPE4:
case PPC::SELECT_VRRC:
@@ -6614,9 +5749,8 @@ void PPCDAGToDAGISel::PeepholeCROps() {
Op1Set = true;
else if (Op.getMachineOpcode() == PPC::CRUNSET)
Op1Unset = true;
- else if ((Op.getMachineOpcode() == PPC::CRNOR &&
- Op.getOperand(0) == Op.getOperand(1)) ||
- Op.getMachineOpcode() == PPC::CRNOT)
+ else if (Op.getMachineOpcode() == PPC::CRNOR &&
+ Op.getOperand(0) == Op.getOperand(1))
Op1Not = true;
}
}
@@ -6921,6 +6055,9 @@ void PPCDAGToDAGISel::PeepholeCROps() {
case PPC::SELECT_I8:
case PPC::SELECT_F4:
case PPC::SELECT_F8:
+ case PPC::SELECT_QFRC:
+ case PPC::SELECT_QSRC:
+ case PPC::SELECT_QBRC:
case PPC::SELECT_SPE:
case PPC::SELECT_SPE4:
case PPC::SELECT_VRRC:
@@ -7122,7 +6259,7 @@ static bool PeepholePPC64ZExtGather(SDValue Op32,
}
void PPCDAGToDAGISel::PeepholePPC64ZExt() {
- if (!Subtarget->isPPC64())
+ if (!PPCSubTarget->isPPC64())
return;
// When we zero-extend from i32 to i64, we use a pattern like this:
@@ -7290,106 +6427,11 @@ void PPCDAGToDAGISel::PeepholePPC64ZExt() {
CurDAG->RemoveDeadNodes();
}
-static bool isVSXSwap(SDValue N) {
- if (!N->isMachineOpcode())
- return false;
- unsigned Opc = N->getMachineOpcode();
-
- // Single-operand XXPERMDI or the regular XXPERMDI/XXSLDWI where the immediate
- // operand is 2.
- if (Opc == PPC::XXPERMDIs) {
- return isa<ConstantSDNode>(N->getOperand(1)) &&
- N->getConstantOperandVal(1) == 2;
- } else if (Opc == PPC::XXPERMDI || Opc == PPC::XXSLDWI) {
- return N->getOperand(0) == N->getOperand(1) &&
- isa<ConstantSDNode>(N->getOperand(2)) &&
- N->getConstantOperandVal(2) == 2;
- }
-
- return false;
-}
-
-// TODO: Make this complete and replace with a table-gen bit.
-static bool isLaneInsensitive(SDValue N) {
- if (!N->isMachineOpcode())
- return false;
- unsigned Opc = N->getMachineOpcode();
-
- switch (Opc) {
- default:
- return false;
- case PPC::VAVGSB:
- case PPC::VAVGUB:
- case PPC::VAVGSH:
- case PPC::VAVGUH:
- case PPC::VAVGSW:
- case PPC::VAVGUW:
- case PPC::VMAXFP:
- case PPC::VMAXSB:
- case PPC::VMAXUB:
- case PPC::VMAXSH:
- case PPC::VMAXUH:
- case PPC::VMAXSW:
- case PPC::VMAXUW:
- case PPC::VMINFP:
- case PPC::VMINSB:
- case PPC::VMINUB:
- case PPC::VMINSH:
- case PPC::VMINUH:
- case PPC::VMINSW:
- case PPC::VMINUW:
- case PPC::VADDFP:
- case PPC::VADDUBM:
- case PPC::VADDUHM:
- case PPC::VADDUWM:
- case PPC::VSUBFP:
- case PPC::VSUBUBM:
- case PPC::VSUBUHM:
- case PPC::VSUBUWM:
- case PPC::VAND:
- case PPC::VANDC:
- case PPC::VOR:
- case PPC::VORC:
- case PPC::VXOR:
- case PPC::VNOR:
- case PPC::VMULUWM:
- return true;
- }
-}
-
-// Try to simplify (xxswap (vec-op (xxswap) (xxswap))) where vec-op is
-// lane-insensitive.
-static void reduceVSXSwap(SDNode *N, SelectionDAG *DAG) {
- // Our desired xxswap might be source of COPY_TO_REGCLASS.
- // TODO: Can we put this a common method for DAG?
- auto SkipRCCopy = [](SDValue V) {
- while (V->isMachineOpcode() &&
- V->getMachineOpcode() == TargetOpcode::COPY_TO_REGCLASS) {
- // All values in the chain should have single use.
- if (V->use_empty() || !V->use_begin()->isOnlyUserOf(V.getNode()))
- return SDValue();
- V = V->getOperand(0);
- }
- return V.hasOneUse() ? V : SDValue();
- };
-
- SDValue VecOp = SkipRCCopy(N->getOperand(0));
- if (!VecOp || !isLaneInsensitive(VecOp))
- return;
-
- SDValue LHS = SkipRCCopy(VecOp.getOperand(0)),
- RHS = SkipRCCopy(VecOp.getOperand(1));
- if (!LHS || !RHS || !isVSXSwap(LHS) || !isVSXSwap(RHS))
+void PPCDAGToDAGISel::PeepholePPC64() {
+ // These optimizations are currently supported only for 64-bit SVR4.
+ if (PPCSubTarget->isDarwin() || !PPCSubTarget->isPPC64())
return;
- // These swaps may still have chain-uses here, count on dead code elimination
- // in following passes to remove them.
- DAG->ReplaceAllUsesOfValueWith(LHS, LHS.getOperand(0));
- DAG->ReplaceAllUsesOfValueWith(RHS, RHS.getOperand(0));
- DAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), N->getOperand(0));
-}
-
-void PPCDAGToDAGISel::PeepholePPC64() {
SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
while (Position != CurDAG->allnodes_begin()) {
@@ -7398,9 +6440,6 @@ void PPCDAGToDAGISel::PeepholePPC64() {
if (N->use_empty() || !N->isMachineOpcode())
continue;
- if (isVSXSwap(SDValue(N, 0)))
- reduceVSXSwap(N, CurDAG);
-
unsigned FirstOp;
unsigned StorageOpcode = N->getMachineOpcode();
bool RequiresMod4Offset = false;
@@ -7413,7 +6452,7 @@ void PPCDAGToDAGISel::PeepholePPC64() {
case PPC::DFLOADf64:
case PPC::DFLOADf32:
RequiresMod4Offset = true;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case PPC::LBZ:
case PPC::LBZ8:
case PPC::LFD:
@@ -7431,7 +6470,7 @@ void PPCDAGToDAGISel::PeepholePPC64() {
case PPC::DFSTOREf64:
case PPC::DFSTOREf32:
RequiresMod4Offset = true;
- [[fallthrough]];
+ LLVM_FALLTHROUGH;
case PPC::STB:
case PPC::STB8:
case PPC::STFD:
@@ -7505,8 +6544,7 @@ void PPCDAGToDAGISel::PeepholePPC64() {
int MaxDisplacement = 7;
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
const GlobalValue *GV = GA->getGlobal();
- Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
- MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement);
+ MaxDisplacement = std::min((int) GV->getAlignment() - 1, MaxDisplacement);
}
bool UpdateHBase = false;
@@ -7572,10 +6610,10 @@ void PPCDAGToDAGISel::PeepholePPC64() {
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
SDLoc dl(GA);
const GlobalValue *GV = GA->getGlobal();
- Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
// We can't perform this optimization for data whose alignment
// is insufficient for the instruction encoding.
- if (Alignment < 4 && (RequiresMod4Offset || (Offset % 4) != 0)) {
+ if (GV->getAlignment() < 4 &&
+ (RequiresMod4Offset || (Offset % 4) != 0)) {
LLVM_DEBUG(dbgs() << "Rejected this candidate for alignment.\n\n");
continue;
}
@@ -7583,7 +6621,8 @@ void PPCDAGToDAGISel::PeepholePPC64() {
} else if (ConstantPoolSDNode *CP =
dyn_cast<ConstantPoolSDNode>(ImmOpnd)) {
const Constant *C = CP->getConstVal();
- ImmOpnd = CurDAG->getTargetConstantPool(C, MVT::i64, CP->getAlign(),
+ ImmOpnd = CurDAG->getTargetConstantPool(C, MVT::i64,
+ CP->getAlignment(),
Offset, Flags);
}
}