mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 20:29:53 +00:00
Vext Lowering was missing opportunities
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167318 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5c87b732f2
commit
43934aee71
@ -1601,8 +1601,8 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
CallOpc = ARMISD::CALL_NOLINK;
|
||||
else if (doesNotRet && isDirect && !isARMFunc &&
|
||||
Subtarget->hasRAS() && !Subtarget->isThumb1Only() &&
|
||||
// Emit regular call when code size is the priority
|
||||
!HasMinSizeAttr)
|
||||
// Emit regular call when code size is the priority
|
||||
!HasMinSizeAttr)
|
||||
// "mov lr, pc; b _foo" to avoid confusing the RSP
|
||||
CallOpc = ARMISD::CALL_NOLINK;
|
||||
else
|
||||
@ -1611,8 +1611,8 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
if (!isDirect && !Subtarget->hasV5TOps()) {
|
||||
CallOpc = ARMISD::CALL_NOLINK;
|
||||
} else if (doesNotRet && isDirect && Subtarget->hasRAS() &&
|
||||
// Emit regular call when code size is the priority
|
||||
!HasMinSizeAttr)
|
||||
// Emit regular call when code size is the priority
|
||||
!HasMinSizeAttr)
|
||||
// "mov lr, pc; b _foo" to avoid confusing the RSP
|
||||
CallOpc = ARMISD::CALL_NOLINK;
|
||||
else
|
||||
@ -3929,6 +3929,36 @@ SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG,
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// check if an VEXT instruction can handle the shuffle mask when the
|
||||
// vector sources of the shuffle are the same.
|
||||
static bool isSingletonVEXTMask(ArrayRef<int> M, EVT VT, unsigned &Imm) {
|
||||
unsigned NumElts = VT.getVectorNumElements();
|
||||
|
||||
// Assume that the first shuffle index is not UNDEF. Fail if it is.
|
||||
if (M[0] < 0)
|
||||
return false;
|
||||
|
||||
Imm = M[0];
|
||||
|
||||
// If this is a VEXT shuffle, the immediate value is the index of the first
|
||||
// element. The other shuffle indices must be the successive elements after
|
||||
// the first one.
|
||||
unsigned ExpectedElt = Imm;
|
||||
for (unsigned i = 1; i < NumElts; ++i) {
|
||||
// Increment the expected index. If it wraps around, just follow it
|
||||
// back to index zero and keep going.
|
||||
++ExpectedElt;
|
||||
if (ExpectedElt == NumElts)
|
||||
ExpectedElt = 0;
|
||||
|
||||
if (M[i] < 0) continue; // ignore UNDEF indices
|
||||
if (ExpectedElt != static_cast<unsigned>(M[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool isVEXTMask(ArrayRef<int> M, EVT VT,
|
||||
bool &ReverseVEXT, unsigned &Imm) {
|
||||
@ -4688,6 +4718,12 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
|
||||
if (isVREVMask(ShuffleMask, VT, 16))
|
||||
return DAG.getNode(ARMISD::VREV16, dl, VT, V1);
|
||||
|
||||
if (V2->getOpcode() == ISD::UNDEF &&
|
||||
isSingletonVEXTMask(ShuffleMask, VT, Imm)) {
|
||||
return DAG.getNode(ARMISD::VEXT, dl, VT, V1, V1,
|
||||
DAG.getConstant(Imm, MVT::i32));
|
||||
}
|
||||
|
||||
// Check for Neon shuffles that modify both input vectors in place.
|
||||
// If both results are used, i.e., if there are two shuffles with the same
|
||||
// source operands and with masks corresponding to both results of one of
|
||||
|
@ -74,6 +74,39 @@ define <16 x i8> @test_vextRq_undef(<16 x i8>* %A, <16 x i8>* %B) nounwind {
|
||||
ret <16 x i8> %tmp3
|
||||
}
|
||||
|
||||
define <16 x i8> @test_vextq_undef_op2(<16 x i8> %a) nounwind {
|
||||
;CHECK: test_vextq_undef_op2:
|
||||
;CHECK: vext
|
||||
entry:
|
||||
%tmp1 = shufflevector <16 x i8> %a, <16 x i8> undef, <16 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1>
|
||||
ret <16 x i8> %tmp1
|
||||
}
|
||||
|
||||
define <8 x i8> @test_vextd_undef_op2(<8 x i8> %a) nounwind {
|
||||
;CHECK: test_vextd_undef_op2:
|
||||
;CHECK: vext
|
||||
entry:
|
||||
%tmp1 = shufflevector <8 x i8> %a, <8 x i8> undef, <8 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1>
|
||||
ret <8 x i8> %tmp1
|
||||
}
|
||||
|
||||
|
||||
define <16 x i8> @test_vextq_undef_op2_undef(<16 x i8> %a) nounwind {
|
||||
;CHECK: test_vextq_undef_op2_undef:
|
||||
;CHECK: vext
|
||||
entry:
|
||||
%tmp1 = shufflevector <16 x i8> %a, <16 x i8> undef, <16 x i32> <i32 2, i32 3, i32 4, i32 undef, i32 undef, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1>
|
||||
ret <16 x i8> %tmp1
|
||||
}
|
||||
|
||||
define <8 x i8> @test_vextd_undef_op2_undef(<8 x i8> %a) nounwind {
|
||||
;CHECK: test_vextd_undef_op2_undef:
|
||||
;CHECK: vext
|
||||
entry:
|
||||
%tmp1 = shufflevector <8 x i8> %a, <8 x i8> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 6, i32 7, i32 undef, i32 1>
|
||||
ret <8 x i8> %tmp1
|
||||
}
|
||||
|
||||
; Tests for ReconstructShuffle function. Indices have to be carefully
|
||||
; chosen to reach lowering phase as a BUILD_VECTOR.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user