ARM big endian function argument passing

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208316 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Christian Pirker 2014-05-08 14:06:24 +00:00
parent 958fcdc21b
commit c60a59cad3
9 changed files with 412 additions and 140 deletions

View File

@ -1293,6 +1293,8 @@ ARMTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
InFlag);
Chain = Hi.getValue(1);
InFlag = Hi.getValue(2);
if (!Subtarget->isLittle())
std::swap (Lo, Hi);
Val = DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
if (VA.getLocVT() == MVT::v2f64) {
@ -1308,6 +1310,8 @@ ARMTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, InFlag);
Chain = Hi.getValue(1);
InFlag = Hi.getValue(2);
if (!Subtarget->isLittle())
std::swap (Lo, Hi);
Val = DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Vec, Val,
DAG.getConstant(1, MVT::i32));
@ -1358,16 +1362,17 @@ void ARMTargetLowering::PassF64ArgInRegs(SDLoc dl, SelectionDAG &DAG,
SDValue fmrrd = DAG.getNode(ARMISD::VMOVRRD, dl,
DAG.getVTList(MVT::i32, MVT::i32), Arg);
RegsToPass.push_back(std::make_pair(VA.getLocReg(), fmrrd));
unsigned id = Subtarget->isLittle() ? 0 : 1;
RegsToPass.push_back(std::make_pair(VA.getLocReg(), fmrrd.getValue(id)));
if (NextVA.isRegLoc())
RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), fmrrd.getValue(1)));
RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), fmrrd.getValue(1-id)));
else {
assert(NextVA.isMemLoc());
if (!StackPtr.getNode())
StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy());
MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, fmrrd.getValue(1),
MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, fmrrd.getValue(1-id),
dl, DAG, NextVA,
Flags));
}
@ -2082,6 +2087,7 @@ ARMTargetLowering::LowerReturn(SDValue Chain,
SDValue Flag;
SmallVector<SDValue, 4> RetOps;
RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
bool isLittleEndian = Subtarget->isLittle();
// Copy the result values into the output registers.
for (unsigned i = 0, realRVLocIdx = 0;
@ -2108,12 +2114,15 @@ ARMTargetLowering::LowerReturn(SDValue Chain,
SDValue HalfGPRs = DAG.getNode(ARMISD::VMOVRRD, dl,
DAG.getVTList(MVT::i32, MVT::i32), Half);
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), HalfGPRs, Flag);
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
HalfGPRs.getValue(isLittleEndian ? 0 : 1),
Flag);
Flag = Chain.getValue(1);
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
VA = RVLocs[++i]; // skip ahead to next loc
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
HalfGPRs.getValue(1), Flag);
HalfGPRs.getValue(isLittleEndian ? 1 : 0),
Flag);
Flag = Chain.getValue(1);
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
VA = RVLocs[++i]; // skip ahead to next loc
@ -2126,11 +2135,14 @@ ARMTargetLowering::LowerReturn(SDValue Chain,
// available.
SDValue fmrrd = DAG.getNode(ARMISD::VMOVRRD, dl,
DAG.getVTList(MVT::i32, MVT::i32), Arg);
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd, Flag);
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
fmrrd.getValue(isLittleEndian ? 0 : 1),
Flag);
Flag = Chain.getValue(1);
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
VA = RVLocs[++i]; // skip ahead to next loc
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd.getValue(1),
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
fmrrd.getValue(isLittleEndian ? 1 : 0),
Flag);
} else
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Arg, Flag);
@ -2661,7 +2673,8 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA,
Reg = MF.addLiveIn(NextVA.getLocReg(), RC);
ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32);
}
if (!Subtarget->isLittle())
std::swap (ArgValue, ArgValue2);
return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
}
@ -8314,16 +8327,18 @@ static SDValue PerformSTORECombine(SDNode *N,
if (StVal.getNode()->getOpcode() == ARMISD::VMOVDRR &&
StVal.getNode()->hasOneUse()) {
SelectionDAG &DAG = DCI.DAG;
bool isBigEndian = DAG.getTargetLoweringInfo().isBigEndian();
SDLoc DL(St);
SDValue BasePtr = St->getBasePtr();
SDValue NewST1 = DAG.getStore(St->getChain(), DL,
StVal.getNode()->getOperand(0), BasePtr,
St->getPointerInfo(), St->isVolatile(),
StVal.getNode()->getOperand(isBigEndian ? 1 : 0 ),
BasePtr, St->getPointerInfo(), St->isVolatile(),
St->isNonTemporal(), St->getAlignment());
SDValue OffsetPtr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr,
DAG.getConstant(4, MVT::i32));
return DAG.getStore(NewST1.getValue(0), DL, StVal.getNode()->getOperand(1),
return DAG.getStore(NewST1.getValue(0), DL,
StVal.getNode()->getOperand(isBigEndian ? 0 : 1),
OffsetPtr, St->getPointerInfo(), St->isVolatile(),
St->isNonTemporal(),
std::min(4U, St->getAlignment() / 2));
@ -10539,6 +10554,8 @@ Value *ARMTargetLowering::emitLoadLinked(IRBuilder<> &Builder, Value *Addr,
Value *Lo = Builder.CreateExtractValue(LoHi, 0, "lo");
Value *Hi = Builder.CreateExtractValue(LoHi, 1, "hi");
if (!Subtarget->isLittle())
std::swap (Lo, Hi);
Lo = Builder.CreateZExt(Lo, ValTy, "lo64");
Hi = Builder.CreateZExt(Hi, ValTy, "hi64");
return Builder.CreateOr(
@ -10572,6 +10589,8 @@ Value *ARMTargetLowering::emitStoreConditional(IRBuilder<> &Builder, Value *Val,
Value *Lo = Builder.CreateTrunc(Val, Int32Ty, "lo");
Value *Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty, "hi");
if (!Subtarget->isLittle())
std::swap (Lo, Hi);
Addr = Builder.CreateBitCast(Addr, Type::getInt8PtrTy(M->getContext()));
return Builder.CreateCall3(Strex, Lo, Hi, Addr);
}

View File

@ -1,12 +1,16 @@
; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s
; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-THUMB
; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE
; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-LE
; RUN: llc < %s -mtriple=armebv7 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE
; RUN: llc < %s -mtriple=thumbebv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-BE
define i64 @test1(i64* %ptr, i64 %val) {
; CHECK-LABEL: test1:
; CHECK: dmb {{ish$}}
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
; CHECK: adds [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK: adc [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-LE: adds [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-LE: adc [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE: adds [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE: adc [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK: cmp
; CHECK: bne
@ -15,8 +19,10 @@ define i64 @test1(i64* %ptr, i64 %val) {
; CHECK-THUMB-LABEL: test1:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB: adds.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB: adc.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-LE: adds.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-LE: adc.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE: adds.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE: adc.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK-THUMB: cmp
; CHECK-THUMB: bne
@ -30,8 +36,10 @@ define i64 @test2(i64* %ptr, i64 %val) {
; CHECK-LABEL: test2:
; CHECK: dmb {{ish$}}
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
; CHECK: subs [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-LE: subs [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-LE: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE: subs [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE: sbc [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK: cmp
; CHECK: bne
@ -40,8 +48,10 @@ define i64 @test2(i64* %ptr, i64 %val) {
; CHECK-THUMB-LABEL: test2:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB: subs.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB: sbc.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-LE: subs.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-LE: sbc.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE: subs.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE: sbc.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK-THUMB: cmp
; CHECK-THUMB: bne
@ -55,8 +65,10 @@ define i64 @test3(i64* %ptr, i64 %val) {
; CHECK-LABEL: test3:
; CHECK: dmb {{ish$}}
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
; CHECK-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-LE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-LE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK: cmp
; CHECK: bne
@ -65,8 +77,10 @@ define i64 @test3(i64* %ptr, i64 %val) {
; CHECK-THUMB-LABEL: test3:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-LE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-LE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK-THUMB: cmp
; CHECK-THUMB: bne
@ -80,8 +94,10 @@ define i64 @test4(i64* %ptr, i64 %val) {
; CHECK-LABEL: test4:
; CHECK: dmb {{ish$}}
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
; CHECK-DAG: orr [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-DAG: orr [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-LE-DAG: orr [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-LE-DAG: orr [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE-DAG: orr [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE-DAG: orr [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK: cmp
; CHECK: bne
@ -90,8 +106,10 @@ define i64 @test4(i64* %ptr, i64 %val) {
; CHECK-THUMB-LABEL: test4:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB-DAG: orr.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-DAG: orr.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-LE-DAG: orr.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-LE-DAG: orr.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE-DAG: orr.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE-DAG: orr.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK-THUMB: cmp
; CHECK-THUMB: bne
@ -105,8 +123,10 @@ define i64 @test5(i64* %ptr, i64 %val) {
; CHECK-LABEL: test5:
; CHECK: dmb {{ish$}}
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
; CHECK-DAG: eor [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-DAG: eor [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-LE-DAG: eor [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK-LE-DAG: eor [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE-DAG: eor [[REG4:(r[0-9]?[13579])]], [[REG2]]
; CHECK-BE-DAG: eor [[REG3:(r[0-9]?[02468])]], [[REG1]]
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK: cmp
; CHECK: bne
@ -115,8 +135,10 @@ define i64 @test5(i64* %ptr, i64 %val) {
; CHECK-THUMB-LABEL: test5:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB-DAG: eor.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-DAG: eor.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-LE-DAG: eor.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-LE-DAG: eor.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE-DAG: eor.w [[REG4:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB-BE-DAG: eor.w [[REG3:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
; CHECK-THUMB: cmp
; CHECK-THUMB: bne
@ -151,8 +173,10 @@ define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
; CHECK-LABEL: test7:
; CHECK: dmb {{ish$}}
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
; CHECK-DAG: eor [[MISMATCH_LO:r[0-9]+]], [[REG1]], r1
; CHECK-DAG: eor [[MISMATCH_HI:r[0-9]+]], [[REG2]], r2
; CHECK-LE-DAG: eor [[MISMATCH_LO:r[0-9]+]], [[REG1]], r1
; CHECK-LE-DAG: eor [[MISMATCH_HI:r[0-9]+]], [[REG2]], r2
; CHECK-BE-DAG: eor [[MISMATCH_LO:r[0-9]+]], [[REG2]], r2
; CHECK-BE-DAG: eor [[MISMATCH_HI:r[0-9]+]], [[REG1]], r1
; CHECK: orrs {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
; CHECK: bne
; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
@ -163,8 +187,10 @@ define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
; CHECK-THUMB-LABEL: test7:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB-DAG: eor.w [[MISMATCH_LO:[a-z0-9]+]], [[REG1]], r2
; CHECK-THUMB-DAG: eor.w [[MISMATCH_HI:[a-z0-9]+]], [[REG2]], r3
; CHECK-THUMB-LE-DAG: eor.w [[MISMATCH_LO:[a-z0-9]+]], [[REG1]], r2
; CHECK-THUMB-LE-DAG: eor.w [[MISMATCH_HI:[a-z0-9]+]], [[REG2]], r3
; CHECK-THUMB-BE-DAG: eor.w [[MISMATCH_HI:[a-z0-9]+]], [[REG1]]
; CHECK-THUMB-BE-DAG: eor.w [[MISMATCH_LO:[a-z0-9]+]], [[REG2]]
; CHECK-THUMB: orrs [[MISMATCH_HI]], [[MISMATCH_LO]]
; CHECK-THUMB: bne
; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
@ -220,9 +246,11 @@ define i64 @test10(i64* %ptr, i64 %val) {
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
; CHECK: cmp [[REG1]], r1
; CHECK-LE: cmp [[REG1]], r1
; CHECK-BE: cmp [[REG2]], r2
; CHECK: movwls [[CARRY_LO]], #1
; CHECK: cmp [[REG2]], r2
; CHECK-LE: cmp [[REG2]], r2
; CHECK-BE: cmp [[REG1]], r1
; CHECK: movwle [[CARRY_HI]], #1
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK: cmp [[CARRY_HI]], #0
@ -237,11 +265,13 @@ define i64 @test10(i64* %ptr, i64 %val) {
; CHECK-THUMB-LABEL: test10:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+]], #0
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+]], #0
; CHECK-THUMB: cmp [[REG1]], r2
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+|lr]], #0
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+|lr]], #0
; CHECK-THUMB-LE: cmp [[REG1]], r2
; CHECK-THUMB-BE: cmp [[REG2]], r3
; CHECK-THUMB: movls.w [[CARRY_LO]], #1
; CHECK-THUMB: cmp [[REG2]], r3
; CHECK-THUMB-LE: cmp [[REG2]], r3
; CHECK-THUMB-BE: cmp [[REG1]], r2
; CHECK-THUMB: movle [[CARRY_HI]], #1
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
@ -265,9 +295,11 @@ define i64 @test11(i64* %ptr, i64 %val) {
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
; CHECK: cmp [[REG1]], r1
; CHECK-LE: cmp [[REG1]], r1
; CHECK-BE: cmp [[REG2]], r2
; CHECK: movwls [[CARRY_LO]], #1
; CHECK: cmp [[REG2]], r2
; CHECK-LE: cmp [[REG2]], r2
; CHECK-BE: cmp [[REG1]], r1
; CHECK: movwls [[CARRY_HI]], #1
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK: cmp [[CARRY_HI]], #0
@ -279,15 +311,16 @@ define i64 @test11(i64* %ptr, i64 %val) {
; CHECK: bne
; CHECK: dmb {{ish$}}
; CHECK-THUMB-LABEL: test11:
; CHECK-THUMB: dmb {{ish$}}
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+]], #0
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+]], #0
; CHECK-THUMB: cmp [[REG1]], r2
; CHECK-THUMB-LE: cmp [[REG1]], r2
; CHECK-THUMB-BE: cmp [[REG2]], r3
; CHECK-THUMB: movls.w [[CARRY_LO]], #1
; CHECK-THUMB: cmp [[REG2]], r3
; CHECK-THUMB-LE: cmp [[REG2]], r3
; CHECK-THUMB-BE: cmp [[REG1]], r2
; CHECK-THUMB: movls [[CARRY_HI]], #1
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
@ -311,9 +344,11 @@ define i64 @test12(i64* %ptr, i64 %val) {
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
; CHECK: cmp [[REG1]], r1
; CHECK-LE: cmp [[REG1]], r1
; CHECK-BE: cmp [[REG2]], r2
; CHECK: movwhi [[CARRY_LO]], #1
; CHECK: cmp [[REG2]], r2
; CHECK-LE: cmp [[REG2]], r2
; CHECK-BE: cmp [[REG1]], r1
; CHECK: movwgt [[CARRY_HI]], #1
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK: cmp [[CARRY_HI]], #0
@ -330,9 +365,11 @@ define i64 @test12(i64* %ptr, i64 %val) {
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+]], #0
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+]], #0
; CHECK-THUMB: cmp [[REG1]], r2
; CHECK-THUMB-LE: cmp [[REG1]], r2
; CHECK-THUMB-BE: cmp [[REG2]], r3
; CHECK-THUMB: movhi.w [[CARRY_LO]], #1
; CHECK-THUMB: cmp [[REG2]], r3
; CHECK-THUMB-LE: cmp [[REG2]], r3
; CHECK-THUMB-BE: cmp [[REG1]], r2
; CHECK-THUMB: movgt [[CARRY_HI]], #1
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
@ -356,9 +393,11 @@ define i64 @test13(i64* %ptr, i64 %val) {
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
; CHECK: cmp [[REG1]], r1
; CHECK-LE: cmp [[REG1]], r1
; CHECK-BE: cmp [[REG2]], r2
; CHECK: movwhi [[CARRY_LO]], #1
; CHECK: cmp [[REG2]], r2
; CHECK-LE: cmp [[REG2]], r2
; CHECK-BE: cmp [[REG1]], r1
; CHECK: movwhi [[CARRY_HI]], #1
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK: cmp [[CARRY_HI]], #0
@ -375,9 +414,11 @@ define i64 @test13(i64* %ptr, i64 %val) {
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+]], #0
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+]], #0
; CHECK-THUMB: cmp [[REG1]], r2
; CHECK-THUMB-LE: cmp [[REG1]], r2
; CHECK-THUMB-BE: cmp [[REG2]], r3
; CHECK-THUMB: movhi.w [[CARRY_LO]], #1
; CHECK-THUMB: cmp [[REG2]], r3
; CHECK-THUMB-LE: cmp [[REG2]], r3
; CHECK-THUMB-BE: cmp [[REG1]], r2
; CHECK-THUMB: movhi [[CARRY_HI]], #1
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3

View File

@ -1,5 +1,7 @@
; RUN: llc -mtriple=armv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
; RUN: llc -mtriple=thumbv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-THUMB
; RUN: llc -mtriple=armv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM-LE
; RUN: llc -mtriple=armebv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM-BE
; RUN: llc -mtriple=thumbv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-LE
; RUN: llc -mtriple=thumbebv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-BE
@var8 = global i8 0
@var16 = global i16 0
@ -87,8 +89,10 @@ define void @test_atomic_load_add_i64(i64 %offset) nounwind {
; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
; CHECK-NEXT: adds{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK-NEXT: adc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
; CHECK-LE-NEXT: adds{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK-LE-NEXT: adc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
; CHECK-BE-NEXT: adds{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-NEXT: adc{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@ -181,8 +185,10 @@ define void @test_atomic_load_sub_i64(i64 %offset) nounwind {
; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
; CHECK-NEXT: subs{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK-NEXT: sbc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
; CHECK-LE-NEXT: subs{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK-LE-NEXT: sbc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
; CHECK-BE-NEXT: subs{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-NEXT: sbc{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@ -275,8 +281,10 @@ define void @test_atomic_load_and_i64(i64 %offset) nounwind {
; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
; CHECK-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
; CHECK-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-LE-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK-LE-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@ -369,8 +377,10 @@ define void @test_atomic_load_or_i64(i64 %offset) nounwind {
; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
; CHECK-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
; CHECK-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-LE-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK-LE-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@ -463,8 +473,10 @@ define void @test_atomic_load_xor_i64(i64 %offset) nounwind {
; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
; CHECK-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
; CHECK-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-LE-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK-LE-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
; CHECK-BE-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@ -657,10 +669,14 @@ define void @test_atomic_load_min_i64(i64 %offset) nounwind {
; function there.
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
; CHECK-ARM: cmp [[OLD1]], r0
; CHECK-ARM: movwls [[LOCARRY]], #1
; CHECK-ARM: cmp [[OLD2]], r1
; CHECK-ARM: movwle [[HICARRY]], #1
; CHECK-ARM-LE: cmp [[OLD1]], r0
; CHECK-ARM-LE: movwls [[LOCARRY]], #1
; CHECK-ARM-LE: cmp [[OLD2]], r1
; CHECK-ARM-LE: movwle [[HICARRY]], #1
; CHECK-ARM-BE: cmp [[OLD2]], r1
; CHECK-ARM-BE: movwls [[LOCARRY]], #1
; CHECK-ARM-BE: cmp [[OLD1]], r0
; CHECK-ARM-BE: movwle [[HICARRY]], #1
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
; CHECK-ARM: cmp [[HICARRY]], #0
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
@ -771,10 +787,14 @@ define void @test_atomic_load_max_i64(i64 %offset) nounwind {
; function there.
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
; CHECK-ARM: cmp [[OLD1]], r0
; CHECK-ARM: movwhi [[LOCARRY]], #1
; CHECK-ARM: cmp [[OLD2]], r1
; CHECK-ARM: movwgt [[HICARRY]], #1
; CHECK-ARM-LE: cmp [[OLD1]], r0
; CHECK-ARM-LE: movwhi [[LOCARRY]], #1
; CHECK-ARM-LE: cmp [[OLD2]], r1
; CHECK-ARM-LE: movwgt [[HICARRY]], #1
; CHECK-ARM-BE: cmp [[OLD2]], r1
; CHECK-ARM-BE: movwhi [[LOCARRY]], #1
; CHECK-ARM-BE: cmp [[OLD1]], r0
; CHECK-ARM-BE: movwgt [[HICARRY]], #1
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
; CHECK-ARM: cmp [[HICARRY]], #0
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
@ -885,10 +905,14 @@ define void @test_atomic_load_umin_i64(i64 %offset) nounwind {
; function there.
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
; CHECK-ARM: cmp [[OLD1]], r0
; CHECK-ARM: movwls [[LOCARRY]], #1
; CHECK-ARM: cmp [[OLD2]], r1
; CHECK-ARM: movwls [[HICARRY]], #1
; CHECK-ARM-LE: cmp [[OLD1]], r0
; CHECK-ARM-LE: movwls [[LOCARRY]], #1
; CHECK-ARM-LE: cmp [[OLD2]], r1
; CHECK-ARM-LE: movwls [[HICARRY]], #1
; CHECK-ARM-BE: cmp [[OLD2]], r1
; CHECK-ARM-BE: movwls [[LOCARRY]], #1
; CHECK-ARM-BE: cmp [[OLD1]], r0
; CHECK-ARM-BE: movwls [[HICARRY]], #1
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
; CHECK-ARM: cmp [[HICARRY]], #0
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
@ -999,10 +1023,14 @@ define void @test_atomic_load_umax_i64(i64 %offset) nounwind {
; function there.
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
; CHECK-ARM: cmp [[OLD1]], r0
; CHECK-ARM: movwhi [[LOCARRY]], #1
; CHECK-ARM: cmp [[OLD2]], r1
; CHECK-ARM: movwhi [[HICARRY]], #1
; CHECK-ARM-LE: cmp [[OLD1]], r0
; CHECK-ARM-LE: movwhi [[LOCARRY]], #1
; CHECK-ARM-LE: cmp [[OLD2]], r1
; CHECK-ARM-LE: movwhi [[HICARRY]], #1
; CHECK-ARM-BE: cmp [[OLD2]], r1
; CHECK-ARM-BE: movwhi [[LOCARRY]], #1
; CHECK-ARM-BE: cmp [[OLD1]], r0
; CHECK-ARM-BE: movwhi [[HICARRY]], #1
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
; CHECK-ARM: cmp [[HICARRY]], #0
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
@ -1112,9 +1140,12 @@ define void @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
; CHECK: ldrexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
; CHECK-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
; CHECK-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
; CHECK: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
; CHECK-LE-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
; CHECK-LE-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
; CHECK-LE: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
; CHECK-BE-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
; CHECK-BE-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
; CHECK-BE: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_HI]], [[MISMATCH_LO]]
; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
; CHECK-NEXT: BB#2:
; As above, r2, r3 is a reasonable guess.
@ -1151,7 +1182,8 @@ define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
%val = load atomic i8* %addr monotonic, align 1
; CHECK-NOT: dmb
; CHECK-NOT: mcr
; CHECK: ldrb r0, [r0, r2]
; CHECK-LE: ldrb r0, [r0, r2]
; CHECK-BE: ldrb r0, [r1, r3]
; CHECK-NOT: dmb
; CHECK-NOT: mcr
@ -1218,7 +1250,8 @@ define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind
%val = load atomic i32* %addr monotonic, align 4
; CHECK-NOT: dmb
; CHECK-NOT: mcr
; CHECK: ldr r0, [r0, r2]
; CHECK-LE: ldr r0, [r0, r2]
; CHECK-BE: ldr r0, [r1, r3]
; CHECK-NOT: dmb
; CHECK-NOT: mcr
@ -1259,8 +1292,10 @@ define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val)
%addr = inttoptr i64 %addr_int to i8*
store atomic i8 %val, i8* %addr monotonic, align 1
; CHECK: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp]
; CHECK: strb [[VAL]], [r0, r2]
; CHECK-LE: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp]
; CHECK-LE: strb [[VAL]], [r0, r2]
; CHECK-BE: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp, #3]
; CHECK-BE: strb [[VAL]], [r1, r3]
ret void
}
@ -1328,7 +1363,8 @@ define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %va
; CHECK: ldr [[VAL:r[0-9]+]], [sp]
; CHECK-NOT: dmb
; CHECK-NOT: mcr
; CHECK: str [[VAL]], [r0, r2]
; CHECK-LE: str [[VAL]], [r0, r2]
; CHECK-BE: str [[VAL]], [r1, r3]
; CHECK-NOT: dmb
; CHECK-NOT: mcr

View File

@ -1,10 +1,13 @@
; RUN: llc < %s -mtriple=thumbv7s-apple-ios3.0.0 -mcpu=generic | FileCheck %s
; RUN: llc < %s -mtriple=thumbv7s-apple-ios3.0.0 -mcpu=generic | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-LE
; RUN: llc < %s -mtriple=thumbeb -mattr=v7,neon | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-BE
; PR15525
; CHECK-LABEL: test1:
; CHECK: ldr.w [[REG:r[0-9]+]], [sp]
; CHECK-NEXT: vmov {{d[0-9]+}}, r1, r2
; CHECK-NEXT: vmov {{d[0-9]+}}, r3, [[REG]]
; CHECK-LE-NEXT: vmov {{d[0-9]+}}, r1, r2
; CHECK-LE-NEXT: vmov {{d[0-9]+}}, r3, [[REG]]
; CHECK-BE-NEXT: vmov {{d[0-9]+}}, r2, r1
; CHECK-BE-NEXT: vmov {{d[0-9]+}}, [[REG]], r3
; CHECK-NEXT: vst1.8 {{{d[0-9]+}}, {{d[0-9]+}}}, [r0]
; CHECK-NEXT: bx lr
define void @test1(i8* %arg, [4 x i64] %vec.coerce) {

View File

@ -0,0 +1,124 @@
; RUN: llc -verify-machineinstrs < %s -march=arm -mattr=v7,neon | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LE %s
; RUN: llc -verify-machineinstrs < %s -march=armeb -mattr=v7,neon | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s
@var32 = global i32 0
@vardouble = global double 0.0
define void @arg_longint( i64 %val ) {
; CHECK-LABEL: arg_longint:
; CHECK-LE: str r0, [r1]
; CHECK-BE: str r1, [r0]
%tmp = trunc i64 %val to i32
store i32 %tmp, i32* @var32
ret void
}
define void @arg_double( double %val ) {
; CHECK-LABEL: arg_double:
; CHECK: strd r0, r1, [r2]
store double %val, double* @vardouble
ret void
}
define void @arg_v4i32(<4 x i32> %vec ) {
; CHECK-LABEL: arg_v4i32:
; CHECK-LE: vmov d17, r2, r3
; CHECK-LE: vmov d16, r0, r1
; CHECK-BE: vmov d17, r3, r2
; CHECK-BE: vmov d16, r1, r0
; CHECK: vst1.32 {d16[0]}, [r0:32]
%tmp = extractelement <4 x i32> %vec, i32 0
store i32 %tmp, i32* @var32
ret void
}
define void @arg_v2f64(<2 x double> %vec ) {
; CHECK-LABEL: arg_v2f64:
; CHECK: strd r0, r1, [r2]
%tmp = extractelement <2 x double> %vec, i32 0
store double %tmp, double* @vardouble
ret void
}
define i64 @return_longint() {
; CHECK-LABEL: return_longint:
; CHECK-LE: mov r0, #42
; CHECK-LE: mov r1, #0
; CHECK-BE: mov r0, #0
; CHECK-BE: mov r1, #42
ret i64 42
}
define double @return_double() {
; CHECK-LABEL: return_double:
; CHECK-LE: vmov r0, r1, d16
; CHECK-BE: vmov r1, r0, d16
ret double 1.0
}
define <4 x i32> @return_v4i32() {
; CHECK-LABEL: return_v4i32:
; CHECK-LE: vmov r0, r1, d16
; CHECK-LE: vmov r2, r3, d17
; CHECK-BE: vmov r1, r0, d16
; CHECK-BE: vmov r3, r2, d17
ret < 4 x i32> < i32 42, i32 43, i32 44, i32 45 >
}
define <2 x double> @return_v2f64() {
; CHECK-LABEL: return_v2f64:
; CHECK-LE: vmov r0, r1, d16
; CHECK-LE: vmov r2, r3, d17
; CHECK-BE: vmov r1, r0, d16
; CHECK-BE: vmov r3, r2, d17
ret <2 x double> < double 3.14, double 6.28 >
}
define void @caller_arg_longint() {
; CHECK-LABEL: caller_arg_longint:
; CHECK-LE: mov r0, #42
; CHECK-LE: mov r1, #0
; CHECK-BE: mov r0, #0
; CHECK-BE: mov r1, #42
call void @arg_longint( i64 42 )
ret void
}
define void @caller_arg_double() {
; CHECK-LABEL: caller_arg_double:
; CHECK-LE: vmov r0, r1, d16
; CHECK-BE: vmov r1, r0, d16
call void @arg_double( double 1.0 )
ret void
}
define void @caller_return_longint() {
; CHECK-LABEL: caller_return_longint:
; CHECK-LE: str r0, [r1]
; CHECK-BE: str r1, [r0]
%val = call i64 @return_longint()
%tmp = trunc i64 %val to i32
store i32 %tmp, i32* @var32
ret void
}
define void @caller_return_double() {
; CHECK-LABEL: caller_return_double:
; CHECK-LE: vmov d17, r0, r1
; CHECK-BE: vmov d17, r1, r0
%val = call double @return_double( )
%tmp = fadd double %val, 3.14
store double %tmp, double* @vardouble
ret void
}
define void @caller_return_v2f64() {
; CHECK-LABEL: caller_return_v2f64:
; CHECK: strd r0, r1, [r2]
%val = call <2 x double> @return_v2f64( )
%tmp = extractelement <2 x double> %val, i32 0
store double %tmp, double* @vardouble
ret void
}

View File

@ -1,5 +1,7 @@
; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s
; RUN: llc -mtriple=armv7-eabi %s -o - | FileCheck %s --check-prefix=CHECK-V7
; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s -check-prefix=CHECK --check-prefix=CHECK-LE
; RUN: llc -mtriple=armv7-eabi %s -o - | FileCheck %s --check-prefix=CHECK-V7-LE
; RUN: llc -mtriple=armeb-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE
; RUN: llc -mtriple=armebv7-eabi %s -o - | FileCheck %s -check-prefix=CHECK-V7-BE
; Check generated signed and unsigned multiply accumulate long.
define i64 @MACLongTest1(i32 %a, i32 %b, i64 %c) {
@ -53,13 +55,18 @@ define i64 @MACLongTest4(i32 %a, i32 %b, i32 %c) {
; function, both after the umlal. With it, *some* move has to happen
; before the umlal.
define i64 @MACLongTest5(i64 %c, i32 %a, i32 %b) {
; CHECK-V7-LABEL: MACLongTest5:
; CHECK-V7-LABEL: umlal r0, r1, r0, r0
; CHECK-V7-LE-LABEL: MACLongTest5:
; CHECK-V7-LE-LABEL: umlal r0, r1, r0, r0
; CHECK-V7-BE-LABEL: MACLongTest5:
; CHECK-V7-BE-LABEL: umlal r1, r0, r1, r1
; CHECK-LABEL: MACLongTest5:
; CHECK: mov [[RDLO:r[0-9]+]], r0
; CHECK: umlal [[RDLO]], r1, r0, r0
; CHECK: mov r0, [[RDLO]]
; CHECK-LE: mov [[RDLO:r[0-9]+]], r0
; CHECK-LE: umlal [[RDLO]], r1, r0, r0
; CHECK-LE: mov r0, [[RDLO]]
; CHECK-BE: mov [[RDLO:r[0-9]+]], r1
; CHECK-BE: umlal [[RDLO]], r0, r1, r1
; CHECK-BE: mov r1, [[RDLO]]
%conv.trunc = trunc i64 %c to i32
%conv = zext i32 %conv.trunc to i64

View File

@ -1,11 +1,16 @@
; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s
; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-LE
; RUN: llc -mtriple=armeb-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-BE
define i64 @f0(i64 %A, i64 %B) {
; CHECK-LABEL: f0:
; CHECK: lsrs r3, r3, #1
; CHECK-NEXT: rrx r2, r2
; CHECK-NEXT: subs r0, r0, r2
; CHECK-NEXT: sbc r1, r1, r3
; CHECK-LE: lsrs r3, r3, #1
; CHECK-LE-NEXT: rrx r2, r2
; CHECK-LE-NEXT: subs r0, r0, r2
; CHECK-LE-NEXT: sbc r1, r1, r3
; CHECK-BE: lsrs r2, r2, #1
; CHECK-BE-NEXT: rrx r3, r3
; CHECK-BE-NEXT: subs r1, r1, r3
; CHECK-BE-NEXT: sbc r0, r0, r2
%tmp = bitcast i64 %A to i64
%tmp2 = lshr i64 %B, 1
%tmp3 = sub i64 %tmp, %tmp2
@ -14,7 +19,8 @@ define i64 @f0(i64 %A, i64 %B) {
define i32 @f1(i64 %x, i64 %y) {
; CHECK-LABEL: f1:
; CHECK: lsl{{.*}}r2
; CHECK-LE: lsl{{.*}}r2
; CHECK-BE: lsl{{.*}}r3
%a = shl i64 %x, %y
%b = trunc i64 %a to i32
ret i32 %b
@ -22,12 +28,20 @@ define i32 @f1(i64 %x, i64 %y) {
define i32 @f2(i64 %x, i64 %y) {
; CHECK-LABEL: f2:
; CHECK: lsr{{.*}}r2
; CHECK-NEXT: rsb r3, r2, #32
; CHECK-NEXT: sub r2, r2, #32
; CHECK-NEXT: orr r0, r0, r1, lsl r3
; CHECK-NEXT: cmp r2, #0
; CHECK-NEXT: asrge r0, r1, r2
; CHECK-LE: lsr{{.*}}r2
; CHECK-LE-NEXT: rsb r3, r2, #32
; CHECK-LE-NEXT: sub r2, r2, #32
; CHECK-LE-NEXT: orr r0, r0, r1, lsl r3
; CHECK-LE-NEXT: cmp r2, #0
; CHECK-LE-NEXT: asrge r0, r1, r2
; CHECK-BE: lsr{{.*}}r3
; CHECK-BE-NEXT: rsb r2, r3, #32
; CHECK-BE-NEXT: orr r1, r1, r0, lsl r2
; CHECK-BE-NEXT: sub r2, r3, #32
; CHECK-BE-NEXT: cmp r2, #0
; CHECK-BE-NEXT: asrge r1, r0, r2
%a = ashr i64 %x, %y
%b = trunc i64 %a to i32
ret i32 %b
@ -35,12 +49,20 @@ define i32 @f2(i64 %x, i64 %y) {
define i32 @f3(i64 %x, i64 %y) {
; CHECK-LABEL: f3:
; CHECK: lsr{{.*}}r2
; CHECK-NEXT: rsb r3, r2, #32
; CHECK-NEXT: sub r2, r2, #32
; CHECK-NEXT: orr r0, r0, r1, lsl r3
; CHECK-NEXT: cmp r2, #0
; CHECK-NEXT: lsrge r0, r1, r2
; CHECK-LE: lsr{{.*}}r2
; CHECK-LE-NEXT: rsb r3, r2, #32
; CHECK-LE-NEXT: sub r2, r2, #32
; CHECK-LE-NEXT: orr r0, r0, r1, lsl r3
; CHECK-LE-NEXT: cmp r2, #0
; CHECK-LE-NEXT: lsrge r0, r1, r2
; CHECK-BE: lsr{{.*}}r3
; CHECK-BE-NEXT: rsb r2, r3, #32
; CHECK-BE-NEXT: orr r1, r1, r0, lsl r2
; CHECK-BE-NEXT: sub r2, r3, #32
; CHECK-BE-NEXT: cmp r2, #0
; CHECK-BE-NEXT: lsrge r1, r0, r2
%a = lshr i64 %x, %y
%b = trunc i64 %a to i32
ret i32 %b

View File

@ -1,10 +1,13 @@
; RUN: llc -mtriple=arm-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s
; RUN: llc -mtriple=arm-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-LE
; RUN: llc -mtriple=armeb-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-BE
; 171 = 0x000000ab
define i64 @f1(i64 %a) {
; CHECK: f1
; CHECK: subs r0, r0, #171
; CHECK: sbc r1, r1, #0
; CHECK-LE: subs r0, r0, #171
; CHECK-LE: sbc r1, r1, #0
; CHECK-BE: subs r1, r1, #171
; CHECK-BE: sbc r0, r0, #0
%tmp = sub i64 %a, 171
ret i64 %tmp
}
@ -12,8 +15,10 @@ define i64 @f1(i64 %a) {
; 66846720 = 0x03fc0000
define i64 @f2(i64 %a) {
; CHECK: f2
; CHECK: subs r0, r0, #66846720
; CHECK: sbc r1, r1, #0
; CHECK-LE: subs r0, r0, #66846720
; CHECK-LE: sbc r1, r1, #0
; CHECK-BE: subs r1, r1, #66846720
; CHECK-BE: sbc r0, r0, #0
%tmp = sub i64 %a, 66846720
ret i64 %tmp
}
@ -21,8 +26,10 @@ define i64 @f2(i64 %a) {
; 734439407618 = 0x000000ab00000002
define i64 @f3(i64 %a) {
; CHECK: f3
; CHECK: subs r0, r0, #2
; CHECK: sbc r1, r1, #171
; CHECK-LE: subs r0, r0, #2
; CHECK-LE: sbc r1, r1, #171
; CHECK-BE: subs r1, r1, #2
; CHECK-BE: sbc r0, r0, #171
%tmp = sub i64 %a, 734439407618
ret i64 %tmp
}

View File

@ -1,9 +1,12 @@
; RUN: llc -mtriple=arm-eabi -float-abi=soft -mattr=+neon %s -o - | FileCheck %s
; RUN: llc -mtriple=arm-eabi -float-abi=soft -mattr=+neon %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-LE
; RUN: llc -mtriple=armeb-eabi -float-abi=soft -mattr=+neon %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-BE
define <16 x i8> @vcombine8(<8 x i8>* %A, <8 x i8>* %B) nounwind {
; CHECK: vcombine8
; CHECK: vmov r0, r1, d16
; CHECK: vmov r2, r3, d17
; CHECK-LE: vmov r0, r1, d16
; CHECK-LE: vmov r2, r3, d17
; CHECK-BE: vmov r1, r0, d16
; CHECK-BE: vmov r3, r2, d17
%tmp1 = load <8 x i8>* %A
%tmp2 = load <8 x i8>* %B
%tmp3 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <16 x i32> <i32 0, i32 1, 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>
@ -12,8 +15,10 @@ define <16 x i8> @vcombine8(<8 x i8>* %A, <8 x i8>* %B) nounwind {
define <8 x i16> @vcombine16(<4 x i16>* %A, <4 x i16>* %B) nounwind {
; CHECK: vcombine16
; CHECK: vmov r0, r1, d16
; CHECK: vmov r2, r3, d17
; CHECK-LE: vmov r0, r1, d16
; CHECK-LE: vmov r2, r3, d17
; CHECK-BE: vmov r1, r0, d16
; CHECK-BE: vmov r3, r2, d17
%tmp1 = load <4 x i16>* %A
%tmp2 = load <4 x i16>* %B
%tmp3 = shufflevector <4 x i16> %tmp1, <4 x i16> %tmp2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@ -22,8 +27,10 @@ define <8 x i16> @vcombine16(<4 x i16>* %A, <4 x i16>* %B) nounwind {
define <4 x i32> @vcombine32(<2 x i32>* %A, <2 x i32>* %B) nounwind {
; CHECK: vcombine32
; CHECK: vmov r0, r1, d16
; CHECK: vmov r2, r3, d17
; CHECK-LE: vmov r0, r1, d16
; CHECK-LE: vmov r2, r3, d17
; CHECK-BE: vmov r1, r0, d16
; CHECK-BE: vmov r3, r2, d17
%tmp1 = load <2 x i32>* %A
%tmp2 = load <2 x i32>* %B
%tmp3 = shufflevector <2 x i32> %tmp1, <2 x i32> %tmp2, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@ -32,8 +39,10 @@ define <4 x i32> @vcombine32(<2 x i32>* %A, <2 x i32>* %B) nounwind {
define <4 x float> @vcombinefloat(<2 x float>* %A, <2 x float>* %B) nounwind {
; CHECK: vcombinefloat
; CHECK: vmov r0, r1, d16
; CHECK: vmov r2, r3, d17
; CHECK-LE: vmov r0, r1, d16
; CHECK-LE: vmov r2, r3, d17
; CHECK-BE: vmov r1, r0, d16
; CHECK-BE: vmov r3, r2, d17
%tmp1 = load <2 x float>* %A
%tmp2 = load <2 x float>* %B
%tmp3 = shufflevector <2 x float> %tmp1, <2 x float> %tmp2, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@ -42,8 +51,10 @@ define <4 x float> @vcombinefloat(<2 x float>* %A, <2 x float>* %B) nounwind {
define <2 x i64> @vcombine64(<1 x i64>* %A, <1 x i64>* %B) nounwind {
; CHECK: vcombine64
; CHECK: vmov r0, r1, d16
; CHECK: vmov r2, r3, d17
; CHECK-LE: vmov r0, r1, d16
; CHECK-LE: vmov r2, r3, d17
; CHECK-BE: vmov r1, r0, d16
; CHECK-BE: vmov r3, r2, d17
%tmp1 = load <1 x i64>* %A
%tmp2 = load <1 x i64>* %B
%tmp3 = shufflevector <1 x i64> %tmp1, <1 x i64> %tmp2, <2 x i32> <i32 0, i32 1>
@ -56,7 +67,8 @@ define <2 x i64> @vcombine64(<1 x i64>* %A, <1 x i64>* %B) nounwind {
define <4 x i16> @vget_low16(<8 x i16>* %A) nounwind {
; CHECK: vget_low16
; CHECK-NOT: vst
; CHECK: vmov r0, r1, d16
; CHECK-LE: vmov r0, r1, d16
; CHECK-BE: vmov r1, r0, d16
%tmp1 = load <8 x i16>* %A
%tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i16> %tmp2
@ -65,7 +77,8 @@ define <4 x i16> @vget_low16(<8 x i16>* %A) nounwind {
define <8 x i8> @vget_high8(<16 x i8>* %A) nounwind {
; CHECK: vget_high8
; CHECK-NOT: vst
; CHECK: vmov r0, r1, d17
; CHECK-LE: vmov r0, r1, d17
; CHECK-BE: vmov r1, r0, d17
%tmp1 = load <16 x i8>* %A
%tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
ret <8 x i8> %tmp2