mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-02 15:51:54 +00:00
ARM: handle post-indexed NEON ops where the offset isn't the access width.
Before, we assumed that any ConstantInt offset was precisely the access width, so we could use the "[rN]!" form. ISelLowering only ever created that kind, but further simplification during combining could lead to unexpected constants and incorrect codegen. Should fix PR32658. llvm-svn: 300878
This commit is contained in:
parent
3bbb757a10
commit
cc3adfc204
@ -1854,6 +1854,14 @@ static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
|
||||
return Opc; // If not one we handle, return it unchanged.
|
||||
}
|
||||
|
||||
/// Returns true if the given increment is a Constant known to be equal to the
|
||||
/// access size performed by a NEON load/store. This means the "[rN]!" form can
|
||||
/// be used.
|
||||
static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs) {
|
||||
auto C = dyn_cast<ConstantSDNode>(Inc);
|
||||
return C && C->getZExtValue() == VecTy.getSizeInBits() / 8 * NumVecs;
|
||||
}
|
||||
|
||||
void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
|
||||
const uint16_t *DOpcodes,
|
||||
const uint16_t *QOpcodes0,
|
||||
@ -1921,13 +1929,13 @@ void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
|
||||
SDValue Inc = N->getOperand(AddrOpIdx + 1);
|
||||
// FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
|
||||
// case entirely when the rest are updated to that form, too.
|
||||
if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
|
||||
bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
|
||||
if ((NumVecs <= 2) && !IsImmUpdate)
|
||||
Opc = getVLDSTRegisterUpdateOpcode(Opc);
|
||||
// FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
|
||||
// check for that explicitly too. Horribly hacky, but temporary.
|
||||
if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
|
||||
!isa<ConstantSDNode>(Inc.getNode()))
|
||||
Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
|
||||
if ((NumVecs > 2 && !isVLDfixed(Opc)) || !IsImmUpdate)
|
||||
Ops.push_back(IsImmUpdate ? Reg0 : Inc);
|
||||
}
|
||||
Ops.push_back(Pred);
|
||||
Ops.push_back(Reg0);
|
||||
@ -2075,11 +2083,12 @@ void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
|
||||
SDValue Inc = N->getOperand(AddrOpIdx + 1);
|
||||
// FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
|
||||
// case entirely when the rest are updated to that form, too.
|
||||
if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
|
||||
bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
|
||||
if (NumVecs <= 2 && !IsImmUpdate)
|
||||
Opc = getVLDSTRegisterUpdateOpcode(Opc);
|
||||
// FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
|
||||
// check for that explicitly too. Horribly hacky, but temporary.
|
||||
if (!isa<ConstantSDNode>(Inc.getNode()))
|
||||
if (!IsImmUpdate)
|
||||
Ops.push_back(Inc);
|
||||
else if (NumVecs > 2 && !isVSTfixed(Opc))
|
||||
Ops.push_back(Reg0);
|
||||
@ -2209,7 +2218,9 @@ void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
|
||||
Ops.push_back(Align);
|
||||
if (isUpdating) {
|
||||
SDValue Inc = N->getOperand(AddrOpIdx + 1);
|
||||
Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
|
||||
bool IsImmUpdate =
|
||||
isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
|
||||
Ops.push_back(IsImmUpdate ? Reg0 : Inc);
|
||||
}
|
||||
|
||||
SDValue SuperReg;
|
||||
@ -2313,9 +2324,11 @@ void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
|
||||
// fixed-stride update instructions don't have an explicit writeback
|
||||
// operand. It's implicit in the opcode itself.
|
||||
SDValue Inc = N->getOperand(2);
|
||||
if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
|
||||
bool IsImmUpdate =
|
||||
isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
|
||||
if (NumVecs <= 2 && !IsImmUpdate)
|
||||
Opc = getVLDSTRegisterUpdateOpcode(Opc);
|
||||
if (!isa<ConstantSDNode>(Inc.getNode()))
|
||||
if (!IsImmUpdate)
|
||||
Ops.push_back(Inc);
|
||||
// FIXME: VLD3 and VLD4 haven't been updated to that form yet.
|
||||
else if (NumVecs > 2)
|
||||
|
@ -10873,11 +10873,8 @@ static SDValue CombineBaseUpdate(SDNode *N,
|
||||
|
||||
// If the increment is a constant, it must match the memory ref size.
|
||||
SDValue Inc = User->getOperand(User->getOperand(0) == Addr ? 1 : 0);
|
||||
if (ConstantSDNode *CInc = dyn_cast<ConstantSDNode>(Inc.getNode())) {
|
||||
uint64_t IncVal = CInc->getZExtValue();
|
||||
if (IncVal != NumBytes)
|
||||
continue;
|
||||
} else if (NumBytes >= 3 * 16) {
|
||||
ConstantSDNode *CInc = dyn_cast<ConstantSDNode>(Inc.getNode());
|
||||
if (NumBytes >= 3 * 16 && (!CInc || CInc->getZExtValue() != NumBytes)) {
|
||||
// VLD3/4 and VST3/4 for 128-bit vectors are implemented with two
|
||||
// separate instructions that make it harder to use a non-constant update.
|
||||
continue;
|
||||
|
@ -7,31 +7,32 @@
|
||||
|
||||
define void @test1(<16 x float>* noalias sret %agg.result) nounwind ssp "no-realign-stack" {
|
||||
entry:
|
||||
; CHECK-LABEL: test1
|
||||
; CHECK: ldr r[[R1:[0-9]+]], [pc, r1]
|
||||
; CHECK: add r[[R2:[0-9]+]], r1, #48
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: mov r[[R2:[0-9]+]], r[[R1]]
|
||||
; CHECK: vld1.32 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r[[R1]], #32
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: mov r[[R1:[0-9]+]], sp
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: add r[[R2:[0-9]+]], r[[R1]], #32
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #48
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #32
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vst1.32 {{{d[0-9]+, d[0-9]+}}}, [r0:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r0:128]
|
||||
; CHECK-LABEL: test1:
|
||||
; CHECK: ldr r[[R1:[0-9]+]], [pc, r[[R1]]]
|
||||
; CHECK: mov r[[R2:[0-9]+]], r[[R1]]
|
||||
; CHECK: vld1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R2:[0-9]+]], r[[R1]], #48
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r[[R1]], #32
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: mov r[[R1:[0-9]+]], #32
|
||||
; CHECK: mov r[[R2:[0-9]+]], sp
|
||||
; CHECK: mov r[[R3:[0-9]+]], r[[R2]]
|
||||
; CHECK: vst1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128], r[[R1]]
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #48
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #32
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vst1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r0:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r0:128]
|
||||
%retval = alloca <16 x float>, align 16
|
||||
%0 = load <16 x float>, <16 x float>* @T3_retval, align 16
|
||||
store <16 x float> %0, <16 x float>* %retval
|
||||
@ -42,30 +43,32 @@ entry:
|
||||
|
||||
define void @test2(<16 x float>* noalias sret %agg.result) nounwind ssp {
|
||||
entry:
|
||||
; CHECK: ldr r[[R1:[0-9]+]], [pc, r1]
|
||||
; CHECK: add r[[R2:[0-9]+]], r[[R1]], #48
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: mov r[[R2:[0-9]+]], r[[R1]]
|
||||
; CHECK: vld1.32 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r[[R1]], #32
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: mov r[[R1:[0-9]+]], sp
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: orr r[[R2:[0-9]+]], r[[R1]], #32
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #48
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #32
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vst1.32 {{{d[0-9]+, d[0-9]+}}}, [r0:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+, d[0-9]+}}}, [r0:128]
|
||||
; CHECK-LABEL: test2:
|
||||
; CHECK: ldr r[[R1:[0-9]+]], [pc, r[[R1]]]
|
||||
; CHECK: mov r[[R2:[0-9]+]], r[[R1]]
|
||||
; CHECK: vld1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R2:[0-9]+]], r[[R1]], #48
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r[[R1]], #32
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: mov r[[R1:[0-9]+]], #32
|
||||
; CHECK: mov r[[R2:[0-9]+]], sp
|
||||
; CHECK: mov r[[R3:[0-9]+]], r[[R2]]
|
||||
; CHECK: vst1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128], r[[R1]]
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]
|
||||
; CHECK: vld1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R3]]:128]
|
||||
; CHECK: vld1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R2]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #48
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: add r[[R1:[0-9]+]], r0, #32
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r[[R1]]:128]
|
||||
; CHECK: vst1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r0:128]!
|
||||
; CHECK: vst1.64 {{{d[0-9]+}}, {{d[0-9]+}}}, [r0:128]
|
||||
|
||||
|
||||
%retval = alloca <16 x float>, align 16
|
||||
|
@ -30,10 +30,9 @@ entry:
|
||||
define void @t1(i8* nocapture %C) nounwind {
|
||||
entry:
|
||||
; CHECK-LABEL: t1:
|
||||
; CHECK: vld1.64 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
|
||||
; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
|
||||
; CHECK: adds r0, #15
|
||||
; CHECK: adds r1, #15
|
||||
; CHECK: movs [[INC:r[0-9]+]], #15
|
||||
; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1], [[INC]]
|
||||
; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0], [[INC]]
|
||||
; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
|
||||
; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
|
||||
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str1, i64 0, i64 0), i64 31, i32 1, i1 false)
|
||||
@ -43,13 +42,15 @@ entry:
|
||||
define void @t2(i8* nocapture %C) nounwind {
|
||||
entry:
|
||||
; CHECK-LABEL: t2:
|
||||
; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]!
|
||||
; CHECK: movs [[INC:r[0-9]+]], #32
|
||||
; CHECK: add.w r3, r0, #16
|
||||
; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0], [[INC]]
|
||||
; CHECK: movw [[REG2:r[0-9]+]], #16716
|
||||
; CHECK: movt [[REG2:r[0-9]+]], #72
|
||||
; CHECK: str [[REG2]], [r0, #32]
|
||||
; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]!
|
||||
; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]!
|
||||
; CHECK: str [[REG2]], [r0]
|
||||
; CHECK: vld1.64 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
|
||||
; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
|
||||
; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r3]
|
||||
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str2, i64 0, i64 0), i64 36, i32 1, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
@ -13,10 +13,10 @@ entry:
|
||||
define void @t2() nounwind ssp {
|
||||
entry:
|
||||
; CHECK-LABEL: t2:
|
||||
; CHECK: add.w r1, r0, #10
|
||||
; CHECK: vmov.i32 {{q[0-9]+}}, #0x0
|
||||
; CHECK: vst1.16 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
|
||||
; CHECK: vst1.64 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
|
||||
; CHECK: movs r1, #10
|
||||
; CHECK: vst1.64 {d{{[0-9]+}}, d{{[0-9]+}}}, [r2], r1
|
||||
; CHECK: vst1.16 {d{{[0-9]+}}, d{{[0-9]+}}}, [r2]
|
||||
%buf = alloca [26 x i8], align 1
|
||||
%0 = getelementptr inbounds [26 x i8], [26 x i8]* %buf, i32 0, i32 0
|
||||
call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 26, i32 1, i1 false)
|
||||
|
@ -253,11 +253,22 @@ define <4 x i32> @zextload_v8i8tov8i32_fake_update(<4 x i8>** %ptr) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: test_silly_load:
|
||||
; CHECK: ldr {{r[0-9]+}}, [r0, #24]
|
||||
; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0:128]!
|
||||
; CHECK: vldr d{{[0-9]+}}, [r0]
|
||||
; CHECK: vldr d{{[0-9]+}}, [r0, #16]
|
||||
; CHECK: movs r1, #24
|
||||
; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0:128], r1
|
||||
; CHECK: ldr {{r[0-9]+}}, [r0]
|
||||
|
||||
define void @test_silly_load(<28 x i8>* %addr) {
|
||||
load volatile <28 x i8>, <28 x i8>* %addr
|
||||
ret void
|
||||
}
|
||||
|
||||
define <4 x i32>* @test_vld1_immoffset(<4 x i32>* %ptr.in, <4 x i32>* %ptr.out) {
|
||||
; CHECK-LABEL: test_vld1_immoffset:
|
||||
; CHECK: movs [[INC:r[0-9]+]], #32
|
||||
; CHECK: vld1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r0], [[INC]]
|
||||
%val = load <4 x i32>, <4 x i32>* %ptr.in
|
||||
store <4 x i32> %val, <4 x i32>* %ptr.out
|
||||
%next = getelementptr <4 x i32>, <4 x i32>* %ptr.in, i32 2
|
||||
ret <4 x i32>* %next
|
||||
}
|
||||
|
@ -256,3 +256,13 @@ define void @truncstore_v4i32tov4i8_fake_update(<4 x i8>** %ptr, <4 x i32> %val)
|
||||
store <4 x i8>* %inc, <4 x i8>** %ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define <4 x i32>* @test_vst1_1reg(<4 x i32>* %ptr.in, <4 x i32>* %ptr.out) {
|
||||
; CHECK-LABEL: test_vst1_1reg:
|
||||
; CHECK: movs [[INC:r[0-9]+]], #32
|
||||
; CHECK: vst1.32 {{{d[0-9]+}}, {{d[0-9]+}}}, [r1], [[INC]]
|
||||
%val = load <4 x i32>, <4 x i32>* %ptr.in
|
||||
store <4 x i32> %val, <4 x i32>* %ptr.out
|
||||
%next = getelementptr <4 x i32>, <4 x i32>* %ptr.out, i32 2
|
||||
ret <4 x i32>* %next
|
||||
}
|
||||
|
@ -310,6 +310,23 @@ define <4 x i16> @vld2dupi16_update(i16** %ptr) nounwind {
|
||||
ret <4 x i16> %tmp5
|
||||
}
|
||||
|
||||
define <4 x i16> @vld2dupi16_odd_update(i16** %ptr) nounwind {
|
||||
;CHECK-LABEL: vld2dupi16_odd_update:
|
||||
;CHECK: mov [[INC:r[0-9]+]], #6
|
||||
;CHECK: vld2.16 {d16[], d17[]}, [r1], [[INC]]
|
||||
%A = load i16*, i16** %ptr
|
||||
%A2 = bitcast i16* %A to i8*
|
||||
%tmp0 = tail call %struct.__neon_int4x16x2_t @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* %A2, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
|
||||
%tmp1 = extractvalue %struct.__neon_int4x16x2_t %tmp0, 0
|
||||
%tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> zeroinitializer
|
||||
%tmp3 = extractvalue %struct.__neon_int4x16x2_t %tmp0, 1
|
||||
%tmp4 = shufflevector <4 x i16> %tmp3, <4 x i16> undef, <4 x i32> zeroinitializer
|
||||
%tmp5 = add <4 x i16> %tmp2, %tmp4
|
||||
%tmp6 = getelementptr i16, i16* %A, i32 3
|
||||
store i16* %tmp6, i16** %ptr
|
||||
ret <4 x i16> %tmp5
|
||||
}
|
||||
|
||||
define <2 x i32> @vld2dupi32(i8* %A) nounwind {
|
||||
;CHECK-LABEL: vld2dupi32:
|
||||
;Check the alignment value. Max for this instruction is 64 bits:
|
||||
|
@ -150,6 +150,22 @@ define <2 x i32> @vld2lanei32_update(i32** %ptr, <2 x i32>* %B) nounwind {
|
||||
ret <2 x i32> %tmp5
|
||||
}
|
||||
|
||||
define <2 x i32> @vld2lanei32_odd_update(i32** %ptr, <2 x i32>* %B) nounwind {
|
||||
;CHECK-LABEL: vld2lanei32_odd_update:
|
||||
;CHECK: mov [[INC:r[0-9]+]], #12
|
||||
;CHECK: vld2.32 {d16[1], d17[1]}, [{{r[0-9]+}}], [[INC]]
|
||||
%A = load i32*, i32** %ptr
|
||||
%tmp0 = bitcast i32* %A to i8*
|
||||
%tmp1 = load <2 x i32>, <2 x i32>* %B
|
||||
%tmp2 = call %struct.__neon_int32x2x2_t @llvm.arm.neon.vld2lane.v2i32.p0i8(i8* %tmp0, <2 x i32> %tmp1, <2 x i32> %tmp1, i32 1, i32 1)
|
||||
%tmp3 = extractvalue %struct.__neon_int32x2x2_t %tmp2, 0
|
||||
%tmp4 = extractvalue %struct.__neon_int32x2x2_t %tmp2, 1
|
||||
%tmp5 = add <2 x i32> %tmp3, %tmp4
|
||||
%tmp6 = getelementptr i32, i32* %A, i32 3
|
||||
store i32* %tmp6, i32** %ptr
|
||||
ret <2 x i32> %tmp5
|
||||
}
|
||||
|
||||
define <2 x float> @vld2lanef(float* %A, <2 x float>* %B) nounwind {
|
||||
;CHECK-LABEL: vld2lanef:
|
||||
;CHECK: vld2.32
|
||||
|
@ -198,7 +198,7 @@ for.end: ; preds = %for.body
|
||||
|
||||
; @testNeon is an important example of the nead for ivchains.
|
||||
;
|
||||
; Currently we have three extra add.w's that keep the store address
|
||||
; Currently we have two extra add.w's that keep the store address
|
||||
; live past the next increment because ISEL is unfortunately undoing
|
||||
; the store chain. ISEL also fails to convert all but one of the stores to
|
||||
; post-increment addressing. However, the loads should use
|
||||
@ -207,12 +207,10 @@ for.end: ; preds = %for.body
|
||||
;
|
||||
; A9: testNeon:
|
||||
; A9: %.lr.ph
|
||||
; A9: add.w r
|
||||
; A9-NOT: lsl.w
|
||||
; A9-NOT: {{ldr|str|adds|add r}}
|
||||
; A9: vst1.8 {{.*}} [r{{[0-9]+}}]!
|
||||
; A9-NOT: {{ldr|str|adds|add r}}
|
||||
; A9: add.w r
|
||||
; A9-NOT: {{ldr|str|adds|add r}}
|
||||
; A9: vst1.8 {{.*}} [r{{[0-9]+}}], r{{[0-9]+}}
|
||||
; A9: add.w r
|
||||
; A9-NOT: {{ldr|str|adds|add r}}
|
||||
; A9-NOT: add.w r
|
||||
|
Loading…
x
Reference in New Issue
Block a user