Skip to content

Commit

Permalink
ARM big endian function argument passing
Browse files Browse the repository at this point in the history
llvm-svn: 208316
  • Loading branch information
Christian Pirker committed May 8, 2014
1 parent 6dc9c48 commit b572819
Showing 9 changed files with 412 additions and 140 deletions.
41 changes: 30 additions & 11 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
131 changes: 86 additions & 45 deletions llvm/test/CodeGen/ARM/atomic-64bit.ll
Original file line number Diff line number Diff line change
@@ -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
108 changes: 72 additions & 36 deletions llvm/test/CodeGen/ARM/atomic-ops-v8.ll
Original file line number Diff line number Diff line change
@@ -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

9 changes: 6 additions & 3 deletions llvm/test/CodeGen/ARM/dagcombine-concatvector.ll
Original file line number Diff line number Diff line change
@@ -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) {
124 changes: 124 additions & 0 deletions llvm/test/CodeGen/ARM/func-argpassing-endian.ll
Original file line number Diff line number Diff line change
@@ -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
}


21 changes: 14 additions & 7 deletions llvm/test/CodeGen/ARM/longMAC.ll
Original file line number Diff line number Diff line change
@@ -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
58 changes: 40 additions & 18 deletions llvm/test/CodeGen/ARM/long_shift.ll
Original file line number Diff line number Diff line change
@@ -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,33 +19,50 @@ 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
}

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
}

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
21 changes: 14 additions & 7 deletions llvm/test/CodeGen/ARM/sub.ll
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
; 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
}

; 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
}

; 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
}
39 changes: 26 additions & 13 deletions llvm/test/CodeGen/ARM/vcombine.ll
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit b572819

Please sign in to comment.