summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp157
1 files changed, 137 insertions, 20 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 606aae66196c..0abdf81d0908 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -262,6 +262,21 @@ namespace {
None) == 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,
+ None) == 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,
+ None) == 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) {
@@ -3186,7 +3201,7 @@ 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->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
@@ -3236,7 +3251,7 @@ 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->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
LLVM_FALLTHROUGH;
}
@@ -3370,7 +3385,7 @@ 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->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
@@ -3415,7 +3430,7 @@ 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->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
LLVM_FALLTHROUGH;
}
@@ -3528,7 +3543,7 @@ 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->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
@@ -3570,7 +3585,7 @@ IntegerCompareEliminator::get64BitZExtCompare(SDValue LHS, SDValue RHS,
}
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
LLVM_FALLTHROUGH;
}
@@ -3687,7 +3702,7 @@ 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->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
LLVM_FALLTHROUGH;
}
case ISD::SETLE: {
@@ -3730,7 +3745,7 @@ IntegerCompareEliminator::get64BitSExtCompare(SDValue LHS, SDValue RHS,
}
std::swap(LHS, RHS);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- IsRHSZero = RHSConst && RHSConst->isNullValue();
+ IsRHSZero = RHSConst && RHSConst->isZero();
IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
LLVM_FALLTHROUGH;
}
@@ -4982,6 +4997,51 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
}
break;
+ case ISD::INTRINSIC_VOID: {
+ auto IntrinsicID = N->getConstantOperandVal(1);
+ if (IntrinsicID == Intrinsic::ppc_tdw || IntrinsicID == Intrinsic::ppc_tw) {
+ unsigned Opcode = IntrinsicID == Intrinsic::ppc_tdw ? PPC::TDI : PPC::TWI;
+ 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);
+ }
+ CurDAG->SelectNodeTo(N, Opcode, MVT::Other, Ops);
+ return;
+ }
+ break;
+ }
+
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
@@ -5423,8 +5483,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->isNullValue() && N3C->isNullValue() &&
- N2C->getZExtValue() == 1ULL && CC == ISD::SETNE &&
+ if (N1C->isZero() && N3C->isZero() && N2C->getZExtValue() == 1ULL &&
+ CC == ISD::SETNE &&
// FIXME: Implement this optzn for PPC64.
N->getValueType(0) == MVT::i32) {
SDNode *Tmp =
@@ -5810,6 +5870,69 @@ 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;
+
+ 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);
@@ -6153,9 +6276,7 @@ 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 (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
- UI != UE; ++UI) {
- SDNode *User = *UI;
+ for (const SDNode *User : N->uses()) {
if (!User->isMachineOpcode())
return false;
if (User->getMachineOpcode() != PPC::SELECT_I4 &&
@@ -6180,7 +6301,7 @@ bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
if (!C)
return false;
- if (!C->isNullValue())
+ if (!C->isZero())
return false;
}
@@ -6189,18 +6310,14 @@ bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
void PPCDAGToDAGISel::SwapAllSelectUsers(SDNode *N) {
SmallVector<SDNode *, 4> ToReplace;
- for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
- UI != UE; ++UI) {
- SDNode *User = *UI;
+ for (SDNode *User : N->uses()) {
assert((User->getMachineOpcode() == PPC::SELECT_I4 ||
User->getMachineOpcode() == PPC::SELECT_I8) &&
"Must have all select users");
ToReplace.push_back(User);
}
- for (SmallVector<SDNode *, 4>::iterator UI = ToReplace.begin(),
- UE = ToReplace.end(); UI != UE; ++UI) {
- SDNode *User = *UI;
+ for (SDNode *User : ToReplace) {
SDNode *ResNode =
CurDAG->getMachineNode(User->getMachineOpcode(), SDLoc(User),
User->getValueType(0), User->getOperand(0),