1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[MIPS] For vectors, select add %x, C as sub %x, -C if it results in inline immediate

Summary:
As discussed in https://reviews.llvm.org/D62341#1515637,
for MIPS `add %x, -1` isn't optimal. Unlike X86 there
are no fastpaths to matearialize such `-1`/`1` vector constants,
and `sub %x, 1` results in better codegen,
so undo canonicalization

Reviewers: atanasyan, Petar.Avramovic, RKSimon

Reviewed By: atanasyan

Subscribers: sdardis, arichardson, hiraditya, jrtc27, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D66805

llvm-svn: 372254
This commit is contained in:
Roman Lebedev 2019-09-18 19:34:41 +00:00
parent 900862f032
commit 7beb057809
3 changed files with 61 additions and 8 deletions

View File

@ -217,6 +217,51 @@ bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
return false; return false;
} }
/// Convert vector addition with vector subtraction if that allows to encode
/// constant as an immediate and thus avoid extra 'ldi' instruction.
/// add X, <-1, -1...> --> sub X, <1, 1...>
bool MipsDAGToDAGISel::selectVecAddAsVecSubIfProfitable(SDNode *Node) {
assert(Node->getOpcode() == ISD::ADD && "Should only get 'add' here.");
EVT VT = Node->getValueType(0);
assert(VT.isVector() && "Should only be called for vectors.");
SDValue X = Node->getOperand(0);
SDValue C = Node->getOperand(1);
auto *BVN = dyn_cast<BuildVectorSDNode>(C);
if (!BVN)
return false;
APInt SplatValue, SplatUndef;
unsigned SplatBitSize;
bool HasAnyUndefs;
if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
8, !Subtarget->isLittle()))
return false;
auto IsInlineConstant = [](const APInt &Imm) { return Imm.isIntN(5); };
if (IsInlineConstant(SplatValue))
return false; // Can already be encoded as an immediate.
APInt NegSplatValue = 0 - SplatValue;
if (!IsInlineConstant(NegSplatValue))
return false; // Even if we negate it it won't help.
SDLoc DL(Node);
SDValue NegC = CurDAG->FoldConstantArithmetic(
ISD::SUB, DL, VT, CurDAG->getConstant(0, DL, VT).getNode(), C.getNode());
assert(NegC && "Constant-folding failed!");
SDValue NewNode = CurDAG->getNode(ISD::SUB, DL, VT, X, NegC);
ReplaceNode(Node, NewNode.getNode());
SelectCode(NewNode.getNode());
return true;
}
/// Select instructions not customized! Used for /// Select instructions not customized! Used for
/// expanded, promoted and normal instructions /// expanded, promoted and normal instructions
void MipsDAGToDAGISel::Select(SDNode *Node) { void MipsDAGToDAGISel::Select(SDNode *Node) {
@ -236,6 +281,12 @@ void MipsDAGToDAGISel::Select(SDNode *Node) {
switch(Opcode) { switch(Opcode) {
default: break; default: break;
case ISD::ADD:
if (Node->getSimpleValueType(0).isVector() &&
selectVecAddAsVecSubIfProfitable(Node))
return;
break;
// Get target GOT address. // Get target GOT address.
case ISD::GLOBAL_OFFSET_TABLE: case ISD::GLOBAL_OFFSET_TABLE:
ReplaceNode(Node, getGlobalBaseReg()); ReplaceNode(Node, getGlobalBaseReg());

View File

@ -125,6 +125,11 @@ private:
/// starting at bit zero. /// starting at bit zero.
virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const; virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const;
/// Convert vector addition with vector subtraction if that allows to encode
/// constant as an immediate and thus avoid extra 'ldi' instruction.
/// add X, <-1, -1...> --> sub X, <1, 1...>
bool selectVecAddAsVecSubIfProfitable(SDNode *Node);
void Select(SDNode *N) override; void Select(SDNode *N) override;
virtual bool trySelect(SDNode *Node) = 0; virtual bool trySelect(SDNode *Node) = 0;

View File

@ -194,8 +194,7 @@ define void @sub_v16i8_i_negated(<16 x i8>* %c, <16 x i8>* %a) nounwind {
; ALL-LABEL: sub_v16i8_i_negated: ; ALL-LABEL: sub_v16i8_i_negated:
; ALL: # %bb.0: ; ALL: # %bb.0:
; ALL-NEXT: ld.b $w0, 0($5) ; ALL-NEXT: ld.b $w0, 0($5)
; ALL-NEXT: ldi.b $w1, -1 ; ALL-NEXT: subvi.b $w0, $w0, 1
; ALL-NEXT: addv.b $w0, $w0, $w1
; ALL-NEXT: jr $ra ; ALL-NEXT: jr $ra
; ALL-NEXT: st.b $w0, 0($4) ; ALL-NEXT: st.b $w0, 0($4)
%1 = load <16 x i8>, <16 x i8>* %a %1 = load <16 x i8>, <16 x i8>* %a
@ -222,9 +221,8 @@ define void @sub_v8i16_i(<8 x i16>* %c, <8 x i16>* %a) nounwind {
define void @sub_v8i16_i_negated(<8 x i16>* %c, <8 x i16>* %a) nounwind { define void @sub_v8i16_i_negated(<8 x i16>* %c, <8 x i16>* %a) nounwind {
; ALL-LABEL: sub_v8i16_i_negated: ; ALL-LABEL: sub_v8i16_i_negated:
; ALL: # %bb.0: ; ALL: # %bb.0:
; ALL-NEXT: ldi.b $w0, -1 ; ALL-NEXT: ld.h $w0, 0($5)
; ALL-NEXT: ld.h $w1, 0($5) ; ALL-NEXT: subvi.h $w0, $w0, 1
; ALL-NEXT: addv.h $w0, $w1, $w0
; ALL-NEXT: jr $ra ; ALL-NEXT: jr $ra
; ALL-NEXT: st.h $w0, 0($4) ; ALL-NEXT: st.h $w0, 0($4)
%1 = load <8 x i16>, <8 x i16>* %a %1 = load <8 x i16>, <8 x i16>* %a
@ -250,9 +248,8 @@ define void @sub_v4i32_i(<4 x i32>* %c, <4 x i32>* %a) nounwind {
define void @sub_v4i32_i_negated(<4 x i32>* %c, <4 x i32>* %a) nounwind { define void @sub_v4i32_i_negated(<4 x i32>* %c, <4 x i32>* %a) nounwind {
; ALL-LABEL: sub_v4i32_i_negated: ; ALL-LABEL: sub_v4i32_i_negated:
; ALL: # %bb.0: ; ALL: # %bb.0:
; ALL-NEXT: ldi.b $w0, -1 ; ALL-NEXT: ld.w $w0, 0($5)
; ALL-NEXT: ld.w $w1, 0($5) ; ALL-NEXT: subvi.w $w0, $w0, 1
; ALL-NEXT: addv.w $w0, $w1, $w0
; ALL-NEXT: jr $ra ; ALL-NEXT: jr $ra
; ALL-NEXT: st.w $w0, 0($4) ; ALL-NEXT: st.w $w0, 0($4)
%1 = load <4 x i32>, <4 x i32>* %a %1 = load <4 x i32>, <4 x i32>* %a