mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-02 02:14:23 +00:00
This patch teaches the DAGCombiner how to fold insert_subvector nodes
when the input is a concat_vectors and the insert replaces one of the concat halves: Lower half: fold (insert_subvector (concat_vectors X, Y), Z) -> (concat_vectors Z, Y) Upper half: fold (insert_subvector (concat_vectors X, Y), Z) -> (concat_vectors X, Z) This can be seen with the following IR: define <8 x float> @lower_half(<4 x float> %v1, <4 x float> %v2, <4 x float> %v3) { %1 = shufflevector <4 x float> %v1, <4 x float> %v2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> %2 = tail call <8 x float> @llvm.x86.avx.vinsertf128.ps.256(<8 x float> %1, <4 x float> %v3, i8 0) The vinsertf128 intrinsic is converted into an insert_subvector node in SelectionDAGBuilder.cpp. Using AVX, without the patch this generates two vinsertf128 instructions: vinsertf128 $1, %xmm1, %ymm0, %ymm0 vinsertf128 $0, %xmm2, %ymm0, %ymm0 With the patch this is optimized into: vinsertf128 $1, %xmm1, %ymm2, %ymm0 Patch by Robert Lougher. llvm-svn: 200506
This commit is contained in:
parent
2809d5d134
commit
0552af6547
@ -274,6 +274,7 @@ namespace {
|
||||
SDValue visitCONCAT_VECTORS(SDNode *N);
|
||||
SDValue visitEXTRACT_SUBVECTOR(SDNode *N);
|
||||
SDValue visitVECTOR_SHUFFLE(SDNode *N);
|
||||
SDValue visitINSERT_SUBVECTOR(SDNode *N);
|
||||
|
||||
SDValue XformToShuffleWithZero(SDNode *N);
|
||||
SDValue ReassociateOps(unsigned Opc, SDLoc DL, SDValue LHS, SDValue RHS);
|
||||
@ -1230,6 +1231,7 @@ SDValue DAGCombiner::visit(SDNode *N) {
|
||||
case ISD::CONCAT_VECTORS: return visitCONCAT_VECTORS(N);
|
||||
case ISD::EXTRACT_SUBVECTOR: return visitEXTRACT_SUBVECTOR(N);
|
||||
case ISD::VECTOR_SHUFFLE: return visitVECTOR_SHUFFLE(N);
|
||||
case ISD::INSERT_SUBVECTOR: return visitINSERT_SUBVECTOR(N);
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
@ -10433,6 +10435,33 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *N) {
|
||||
SDValue N0 = N->getOperand(0);
|
||||
SDValue N2 = N->getOperand(2);
|
||||
|
||||
// If the input vector is a concatenation, and the insert replaces
|
||||
// one of the halves, we can optimize into a single concat_vectors.
|
||||
if (N0.getOpcode() == ISD::CONCAT_VECTORS &&
|
||||
N0->getNumOperands() == 2 && N2.getOpcode() == ISD::Constant) {
|
||||
APInt InsIdx = cast<ConstantSDNode>(N2)->getAPIntValue();
|
||||
EVT VT = N->getValueType(0);
|
||||
|
||||
// Lower half: fold (insert_subvector (concat_vectors X, Y), Z) ->
|
||||
// (concat_vectors Z, Y)
|
||||
if (InsIdx == 0)
|
||||
return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT,
|
||||
N->getOperand(1), N0.getOperand(1));
|
||||
|
||||
// Upper half: fold (insert_subvector (concat_vectors X, Y), Z) ->
|
||||
// (concat_vectors X, Z)
|
||||
if (InsIdx == VT.getVectorNumElements()/2)
|
||||
return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT,
|
||||
N0.getOperand(0), N->getOperand(1));
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
/// XformToShuffleWithZero - Returns a vector_shuffle if it able to transform
|
||||
/// an AND to a vector_shuffle with the destination vector and a zero vector.
|
||||
/// e.g. AND V, <0xffffffff, 0, 0xffffffff, 0>. ==>
|
||||
|
28
test/CodeGen/X86/vec_shuf-insert.ll
Normal file
28
test/CodeGen/X86/vec_shuf-insert.ll
Normal file
@ -0,0 +1,28 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-linux -mcpu=corei7-avx | FileCheck %s
|
||||
|
||||
; These tests check that an insert_subvector which replaces one of the halves
|
||||
; of a concat_vectors is optimized into a single vinsertf128.
|
||||
|
||||
declare <8 x float> @llvm.x86.avx.vinsertf128.ps.256(<8 x float>, <4 x float>, i8)
|
||||
|
||||
define <8 x float> @lower_half(<4 x float> %v1, <4 x float> %v2, <4 x float> %v3) {
|
||||
%1 = shufflevector <4 x float> %v1, <4 x float> %v2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
||||
%2 = tail call <8 x float> @llvm.x86.avx.vinsertf128.ps.256(<8 x float> %1, <4 x float> %v3, i8 0)
|
||||
ret <8 x float> %2
|
||||
|
||||
; CHECK-LABEL: lower_half
|
||||
; CHECK-NOT: vinsertf128
|
||||
; CHECK: vinsertf128 $1, %xmm1, %ymm2, %ymm0
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
define <8 x float> @upper_half(<4 x float> %v1, <4 x float> %v2, <4 x float> %v3) {
|
||||
%1 = shufflevector <4 x float> %v1, <4 x float> %v2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
||||
%2 = tail call <8 x float> @llvm.x86.avx.vinsertf128.ps.256(<8 x float> %1, <4 x float> %v3, i8 1)
|
||||
ret <8 x float> %2
|
||||
|
||||
; CHECK-LABEL: upper_half
|
||||
; CHECK-NOT: vinsertf128
|
||||
; CHECK: vinsertf128 $1, %xmm2, %ymm0, %ymm0
|
||||
; CHECK-NEXT: ret
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user