diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2019-07-03 09:41:35 +0000 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2019-07-03 09:41:35 +0000 |
commit | c4b83a6054bb4f4fd35a61b1a3cbcc7588e3a1af (patch) | |
tree | ecbb592d65d6469a85cf5743f6792e3725508366 /llvm/lib | |
parent | ac407a7b4a9b0aca70a62cce52e43ad3c5a2686b (diff) | |
download | llvm-c4b83a6054bb4f4fd35a61b1a3cbcc7588e3a1af.zip llvm-c4b83a6054bb4f4fd35a61b1a3cbcc7588e3a1af.tar.gz llvm-c4b83a6054bb4f4fd35a61b1a3cbcc7588e3a1af.tar.bz2 |
[Codegen][X86][AArch64][ARM][PowerPC] Inc-of-add vs sub-of-not (PR42457)
Summary:
This is the backend part of [[ https://bugs.llvm.org/show_bug.cgi?id=42457 | PR42457 ]].
In middle-end, we'd want to prefer the form with two adds - D63992,
but as this diff shows, not every target will prefer that pattern.
Out of 4 targets for which i added tests all seem to be ok with inc-of-add for scalars,
but only X86 prefer that same pattern for vectors.
Here i'm adding a new TLI hook, always defaulting to the inc-of-add,
but adding AArch64,ARM,PowerPC overrides to prefer inc-of-add only for scalars.
Reviewers: spatel, RKSimon, efriedma, t.p.northover, hfinkel
Reviewed By: efriedma
Subscribers: nemanjai, javed.absar, kristof.beyls, kbarton, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64090
llvm-svn: 365010
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64ISelLowering.h | 2 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.h | 3 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.h | 2 |
7 files changed, 56 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 2bfc397..3bd4fe2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2424,6 +2424,17 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { if (Xor) return DAG.getNode(ISD::SUB, DL, VT, A, Xor.getOperand(0)); } + + // Look for: + // add (add x, y), 1 + // And if the target does not like this form then turn into: + // sub y, (xor x, -1) + if (!TLI.preferIncOfAddToSubOfNot(VT) && N0.hasOneUse() && + N0.getOpcode() == ISD::ADD) { + SDValue Not = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(0), + DAG.getAllOnesConstant(DL, VT)); + return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(1), Not); + } } // (x - y) + -1 -> add (xor y, -1), x @@ -2584,6 +2595,17 @@ SDValue DAGCombiner::visitADDLikeCommutative(SDValue N0, SDValue N1, if (SDValue V = foldAddSubMasked1(true, N0, N1, DAG, DL)) return V; + // Look for: + // add (add x, 1), y + // And if the target does not like this form then turn into: + // sub y, (xor x, -1) + if (!TLI.preferIncOfAddToSubOfNot(VT) && N0.hasOneUse() && + N0.getOpcode() == ISD::ADD && isOneOrOneSplat(N0.getOperand(1))) { + SDValue Not = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(0), + DAG.getAllOnesConstant(DL, VT)); + return DAG.getNode(ISD::SUB, DL, VT, N1, Not); + } + // Hoist one-use subtraction by non-opaque constant: // (x - C) + y -> (x + y) - C // This is necessary because SUB(X,C) -> ADD(X,-C) doesn't work for vectors. @@ -3108,6 +3130,15 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { return DAG.getNode(ISD::ADD, DL, VT, Xor, N0.getOperand(0)); } + // Look for: + // sub y, (xor x, -1) + // And if the target does not like this form then turn into: + // add (add x, y), 1 + if (TLI.preferIncOfAddToSubOfNot(VT) && N1.hasOneUse() && isBitwiseNot(N1)) { + SDValue Add = DAG.getNode(ISD::ADD, DL, VT, N0, N1.getOperand(0)); + return DAG.getNode(ISD::ADD, DL, VT, Add, DAG.getConstant(1, DL, VT)); + } + // Hoist one-use addition by non-opaque constant: // (x + C) - y -> (x - y) + C if (N0.hasOneUse() && N0.getOpcode() == ISD::ADD && diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 515da93c..11ee1a5 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -12039,6 +12039,11 @@ bool AArch64TargetLowering::isIntDivCheap(EVT VT, AttributeList Attr) const { return OptSize && !VT.isVector(); } +bool AArch64TargetLowering::preferIncOfAddToSubOfNot(EVT VT) const { + // We want inc-of-add for scalars and sub-of-not for vectors. + return VT.isScalarInteger(); +} + bool AArch64TargetLowering::enableAggressiveFMAFusion(EVT VT) const { return Subtarget->hasAggressiveFMA() && VT.isFloatingPoint(); } diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index 94793c6..754caaf 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -497,6 +497,8 @@ public: return VTIsOk(XVT) && VTIsOk(KeptBitsVT); } + bool preferIncOfAddToSubOfNot(EVT VT) const override; + bool hasBitPreservingFPLogic(EVT VT) const override { // FIXME: Is this always true? It should be true for vectors at least. return VT == MVT::f32 || VT == MVT::f64; diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index efa97b4..c1668dc 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -10736,6 +10736,15 @@ bool ARMTargetLowering::shouldFoldConstantShiftPairToMask( return false; } +bool ARMTargetLowering::preferIncOfAddToSubOfNot(EVT VT) const { + if (!Subtarget->hasNEON()) { + if (Subtarget->isThumb1Only()) + return VT.getScalarSizeInBits() <= 32; + return true; + } + return VT.isScalarInteger(); +} + static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST) { diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h index d188ad2..906e10d 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.h +++ b/llvm/lib/Target/ARM/ARMISelLowering.h @@ -608,6 +608,9 @@ class VectorType; bool shouldFoldConstantShiftPairToMask(const SDNode *N, CombineLevel Level) const override; + + bool preferIncOfAddToSubOfNot(EVT VT) const override; + protected: std::pair<const TargetRegisterClass *, uint8_t> findRepresentativeClass(const TargetRegisterInfo *TRI, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index b1ff161a..aad7ef6 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1279,6 +1279,10 @@ bool PPCTargetLowering::hasSPE() const { return Subtarget.hasSPE(); } +bool PPCTargetLowering::preferIncOfAddToSubOfNot(EVT VT) const { + return VT.isScalarInteger(); +} + const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((PPCISD::NodeType)Opcode) { case PPCISD::FIRST_NUMBER: break; diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index 2c0ac80..73c6dcd 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -634,6 +634,8 @@ namespace llvm { return true; } + bool preferIncOfAddToSubOfNot(EVT VT) const override; + bool convertSetCCLogicToBitwiseLogic(EVT VT) const override { return VT.isScalarInteger(); } |