[llvm] r371722 - AArch64: support arm64_32, an ILP32 slice for watchOS.
Tim Northover via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 12 03:22:24 PDT 2019
Author: tnorthover
Date: Thu Sep 12 03:22:23 2019
New Revision: 371722
URL: http://llvm.org/viewvc/llvm-project?rev=371722&view=rev
Log:
AArch64: support arm64_32, an ILP32 slice for watchOS.
This is the main CodeGen patch to support the arm64_32 watchOS ABI in LLVM.
FastISel is mostly disabled for now since it would generate incorrect code for
ILP32.
Added:
llvm/trunk/test/CodeGen/AArch64/arm64_32-addrs.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-atomics.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-fastisel.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-frame-pointers.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-gep-sink.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-memcpy.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-neon.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-null.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-pointer-extend.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-stack-pointers.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-tls.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32-va.ll
llvm/trunk/test/CodeGen/AArch64/arm64_32.ll
llvm/trunk/test/CodeGen/AArch64/jump-table-32.ll
llvm/trunk/test/MC/AArch64/arm64_32-compact-unwind.s
Modified:
llvm/trunk/include/llvm/CodeGen/CallingConvLower.h
llvm/trunk/include/llvm/Target/TargetCallingConv.td
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp
llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
llvm/trunk/lib/ExecutionEngine/Orc/LazyReexports.cpp
llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
llvm/trunk/lib/LTO/LTOModule.cpp
llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp
llvm/trunk/lib/MC/MCObjectFileInfo.cpp
llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp
llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp
llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp
llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h
llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td
llvm/trunk/lib/Target/AArch64/AArch64CollectLOH.cpp
llvm/trunk/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h
llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp
llvm/trunk/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp
llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h
llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp
llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
llvm/trunk/lib/Target/X86/X86FastISel.cpp
llvm/trunk/test/CodeGen/AArch64/arm64-aapcs.ll
llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-garbage-crash.ll
llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-str.ll
llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh.ll
llvm/trunk/test/CodeGen/AArch64/arm64-indexed-memory.ll
llvm/trunk/test/CodeGen/AArch64/arm64-stacksave.ll
llvm/trunk/test/CodeGen/AArch64/fastcc-reserved.ll
llvm/trunk/test/CodeGen/AArch64/fastcc.ll
llvm/trunk/test/CodeGen/AArch64/sibling-call.ll
llvm/trunk/test/CodeGen/AArch64/swift-return.ll
llvm/trunk/test/CodeGen/AArch64/swiftcc.ll
llvm/trunk/test/CodeGen/AArch64/swifterror.ll
llvm/trunk/test/CodeGen/AArch64/swiftself.ll
llvm/trunk/test/CodeGen/AArch64/tail-call.ll
llvm/trunk/test/CodeGen/AArch64/umulo-128-legalisation-lowering.ll
llvm/trunk/test/CodeGen/AArch64/win64_vararg.ll
llvm/trunk/utils/TableGen/CallingConvEmitter.cpp
Modified: llvm/trunk/include/llvm/CodeGen/CallingConvLower.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CallingConvLower.h?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/CallingConvLower.h (original)
+++ llvm/trunk/include/llvm/CodeGen/CallingConvLower.h Thu Sep 12 03:22:23 2019
@@ -44,6 +44,7 @@ public:
AExtUpper, // The value is in the upper bits of the location and should be
// extended with undefined upper bits when retrieved.
BCvt, // The value is bit-converted in the location.
+ Trunc, // The value is truncated in the location.
VExt, // The value is vector-widened in the location.
// FIXME: Not implemented yet. Code that uses AExt to mean
// vector-widen should be fixed to use VExt instead.
Modified: llvm/trunk/include/llvm/Target/TargetCallingConv.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetCallingConv.td?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetCallingConv.td (original)
+++ llvm/trunk/include/llvm/Target/TargetCallingConv.td Thu Sep 12 03:22:23 2019
@@ -152,6 +152,12 @@ class CCBitConvertToType<ValueType destT
ValueType DestTy = destTy;
}
+/// CCTruncToType - If applied, this truncates the specified current value to
+/// the specified type.
+class CCTruncToType<ValueType destTy> : CCAction {
+ ValueType DestTy = destTy;
+}
+
/// CCPassIndirect - If applied, this stores the value to stack and passes the pointer
/// as normal argument.
class CCPassIndirect<ValueType destTy> : CCAction {
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Thu Sep 12 03:22:23 2019
@@ -9867,6 +9867,10 @@ void SelectionDAGISel::LowerArguments(co
FuncInfo->setArgumentFrameIndex(&Arg, FI->getIndex());
}
+ // Analyses past this point are naive and don't expect an assertion.
+ if (Res.getOpcode() == ISD::AssertZext)
+ Res = Res.getOperand(0);
+
// Update the SwiftErrorVRegDefMap.
if (Res.getOpcode() == ISD::CopyFromReg && isSwiftErrorArg) {
unsigned Reg = cast<RegisterSDNode>(Res.getOperand(1))->getReg();
Modified: llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp Thu Sep 12 03:22:23 2019
@@ -167,6 +167,7 @@ void TargetLoweringBase::InitLibcalls(co
setLibcallName(RTLIB::BZERO, "__bzero");
break;
case Triple::aarch64:
+ case Triple::aarch64_32:
setLibcallName(RTLIB::BZERO, "bzero");
break;
default:
Modified: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Thu Sep 12 03:22:23 2019
@@ -155,6 +155,7 @@ void TargetLoweringObjectFileELF::Initia
break;
case Triple::aarch64:
case Triple::aarch64_be:
+ case Triple::aarch64_32:
// The small model guarantees static code/data size < 4GB, but not where it
// will be in memory. Most of these could end up >2GB away so even a signed
// pc-relative 32-bit address is insufficient, theoretically.
Modified: llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp Thu Sep 12 03:22:23 2019
@@ -120,7 +120,8 @@ createLocalCompileCallbackManager(const
return make_error<StringError>(
std::string("No callback manager available for ") + T.str(),
inconvertibleErrorCode());
- case Triple::aarch64: {
+ case Triple::aarch64:
+ case Triple::aarch64_32: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT;
return CCMgrT::Create(ES, ErrorHandlerAddress);
}
@@ -168,6 +169,7 @@ createLocalIndirectStubsManagerBuilder(c
};
case Triple::aarch64:
+ case Triple::aarch64_32:
return [](){
return std::make_unique<
orc::LocalIndirectStubsManager<orc::OrcAArch64>>();
Modified: llvm/trunk/lib/ExecutionEngine/Orc/LazyReexports.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/LazyReexports.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/LazyReexports.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/LazyReexports.cpp Thu Sep 12 03:22:23 2019
@@ -90,6 +90,7 @@ createLocalLazyCallThroughManager(const
inconvertibleErrorCode());
case Triple::aarch64:
+ case Triple::aarch64_32:
return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
ErrorHandlerAddr);
Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Thu Sep 12 03:22:23 2019
@@ -919,7 +919,8 @@ void RuntimeDyldImpl::addRelocationForSy
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
unsigned AbiVariant) {
- if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) {
+ if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be ||
+ Arch == Triple::aarch64_32) {
// This stub has to be able to access the full address space,
// since symbol lookup won't necessarily find a handy, in-range,
// PLT stub for functions which could be anywhere.
Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp Thu Sep 12 03:22:23 2019
@@ -357,6 +357,8 @@ RuntimeDyldMachO::create(Triple::ArchTyp
return std::make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);
case Triple::aarch64:
return std::make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
+ case Triple::aarch64_32:
+ return std::make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
case Triple::x86:
return std::make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);
case Triple::x86_64:
Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)
+++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Thu Sep 12 03:22:23 2019
@@ -365,7 +365,8 @@ bool LTOCodeGenerator::determineTarget()
MCpu = "core2";
else if (Triple.getArch() == llvm::Triple::x86)
MCpu = "yonah";
- else if (Triple.getArch() == llvm::Triple::aarch64)
+ else if (Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_32)
MCpu = "cyclone";
}
Modified: llvm/trunk/lib/LTO/LTOModule.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOModule.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTOModule.cpp (original)
+++ llvm/trunk/lib/LTO/LTOModule.cpp Thu Sep 12 03:22:23 2019
@@ -220,7 +220,8 @@ LTOModule::makeLTOModule(MemoryBufferRef
CPU = "core2";
else if (Triple.getArch() == llvm::Triple::x86)
CPU = "yonah";
- else if (Triple.getArch() == llvm::Triple::aarch64)
+ else if (Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_32)
CPU = "cyclone";
}
Modified: llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp (original)
+++ llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp Thu Sep 12 03:22:23 2019
@@ -489,7 +489,8 @@ static void initTMBuilder(TargetMachineB
TMBuilder.MCpu = "core2";
else if (TheTriple.getArch() == llvm::Triple::x86)
TMBuilder.MCpu = "yonah";
- else if (TheTriple.getArch() == llvm::Triple::aarch64)
+ else if (TheTriple.getArch() == llvm::Triple::aarch64 ||
+ TheTriple.getArch() == llvm::Triple::aarch64_32)
TMBuilder.MCpu = "cyclone";
}
TMBuilder.TheTriple = std::move(TheTriple);
Modified: llvm/trunk/lib/MC/MCObjectFileInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectFileInfo.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectFileInfo.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp Thu Sep 12 03:22:23 2019
@@ -28,7 +28,7 @@ static bool useCompactUnwind(const Tripl
return false;
// aarch64 always has it.
- if (T.getArch() == Triple::aarch64)
+ if (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32)
return true;
// armv7k always has it.
@@ -57,7 +57,8 @@ void MCObjectFileInfo::initMachOMCObject
MachO::S_ATTR_STRIP_STATIC_SYMS | MachO::S_ATTR_LIVE_SUPPORT,
SectionKind::getReadOnly());
- if (T.isOSDarwin() && T.getArch() == Triple::aarch64)
+ if (T.isOSDarwin() &&
+ (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32))
SupportsCompactUnwindWithoutEHFrame = true;
if (T.isWatchABI())
@@ -193,7 +194,7 @@ void MCObjectFileInfo::initMachOMCObject
if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)
CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_X86_64_MODE_DWARF
- else if (T.getArch() == Triple::aarch64)
+ else if (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32)
CompactUnwindDwarfEHFrameOnly = 0x03000000; // UNWIND_ARM64_MODE_DWARF
else if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_ARM_MODE_DWARF
Modified: llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp Thu Sep 12 03:22:23 2019
@@ -1203,4 +1203,6 @@ extern "C" void LLVMInitializeAArch64Asm
RegisterAsmPrinter<AArch64AsmPrinter> X(getTheAArch64leTarget());
RegisterAsmPrinter<AArch64AsmPrinter> Y(getTheAArch64beTarget());
RegisterAsmPrinter<AArch64AsmPrinter> Z(getTheARM64Target());
+ RegisterAsmPrinter<AArch64AsmPrinter> W(getTheARM64_32Target());
+ RegisterAsmPrinter<AArch64AsmPrinter> V(getTheAArch64_32Target());
}
Modified: llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp Thu Sep 12 03:22:23 2019
@@ -379,14 +379,16 @@ bool AArch64CallLowering::lowerFormalArg
return false;
if (F.isVarArg()) {
- if (!MF.getSubtarget<AArch64Subtarget>().isTargetDarwin()) {
- // FIXME: we need to reimplement saveVarArgsRegisters from
+ auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
+ if (!Subtarget.isTargetDarwin()) {
+ // FIXME: we need to reimplement saveVarArgsRegisters from
// AArch64ISelLowering.
return false;
}
- // We currently pass all varargs at 8-byte alignment.
- uint64_t StackOffset = alignTo(Handler.StackUsed, 8);
+ // We currently pass all varargs at 8-byte alignment, or 4 in ILP32.
+ uint64_t StackOffset =
+ alignTo(Handler.StackUsed, Subtarget.isTargetILP32() ? 4 : 8);
auto &MFI = MIRBuilder.getMF().getFrameInfo();
AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
Modified: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp Thu Sep 12 03:22:23 2019
@@ -79,10 +79,14 @@ static bool CC_AArch64_Custom_Stack_Bloc
static bool CC_AArch64_Custom_Block(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+ const AArch64Subtarget &Subtarget = static_cast<const AArch64Subtarget &>(
+ State.getMachineFunction().getSubtarget());
+ bool IsDarwinILP32 = Subtarget.isTargetILP32() && Subtarget.isTargetMachO();
+
// Try to allocate a contiguous block of registers, each of the correct
// size to hold one member.
ArrayRef<MCPhysReg> RegList;
- if (LocVT.SimpleTy == MVT::i64)
+ if (LocVT.SimpleTy == MVT::i64 || (IsDarwinILP32 && LocVT.SimpleTy == MVT::i32))
RegList = XRegList;
else if (LocVT.SimpleTy == MVT::f16)
RegList = HRegList;
@@ -107,8 +111,12 @@ static bool CC_AArch64_Custom_Block(unsi
if (!ArgFlags.isInConsecutiveRegsLast())
return true;
- unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
- if (RegResult) {
+ // [N x i32] arguments get packed into x-registers on Darwin's arm64_32
+ // because that's how the armv7k Clang front-end emits small structs.
+ unsigned EltsPerReg = (IsDarwinILP32 && LocVT.SimpleTy == MVT::i32) ? 2 : 1;
+ unsigned RegResult = State.AllocateRegBlock(
+ RegList, alignTo(PendingMembers.size(), EltsPerReg) / EltsPerReg);
+ if (RegResult && EltsPerReg == 1) {
for (auto &It : PendingMembers) {
It.convertToReg(RegResult);
State.addLoc(It);
@@ -116,14 +124,26 @@ static bool CC_AArch64_Custom_Block(unsi
}
PendingMembers.clear();
return true;
+ } else if (RegResult) {
+ assert(EltsPerReg == 2 && "unexpected ABI");
+ bool UseHigh = false;
+ CCValAssign::LocInfo Info;
+ for (auto &It : PendingMembers) {
+ Info = UseHigh ? CCValAssign::AExtUpper : CCValAssign::ZExt;
+ State.addLoc(CCValAssign::getReg(It.getValNo(), MVT::i32, RegResult,
+ MVT::i64, Info));
+ UseHigh = !UseHigh;
+ if (!UseHigh)
+ ++RegResult;
+ }
+ PendingMembers.clear();
+ return true;
}
// Mark all regs in the class as unavailable
for (auto Reg : RegList)
State.AllocateReg(Reg);
- const AArch64Subtarget &Subtarget = static_cast<const AArch64Subtarget &>(
- State.getMachineFunction().getSubtarget());
unsigned SlotAlign = Subtarget.isTargetDarwin() ? 1 : 8;
return finishStackBlock(PendingMembers, LocVT, ArgFlags, State, SlotAlign);
Modified: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h Thu Sep 12 03:22:23 2019
@@ -25,6 +25,9 @@ bool CC_AArch64_DarwinPCS_VarArg(unsigne
bool CC_AArch64_DarwinPCS(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State);
+bool CC_AArch64_DarwinPCS_ILP32_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT,
+ CCValAssign::LocInfo LocInfo,
+ ISD::ArgFlagsTy ArgFlags, CCState &State);
bool CC_AArch64_Win64_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State);
Modified: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td Thu Sep 12 03:22:23 2019
@@ -17,6 +17,10 @@ class CCIfAlign<string Align, CCAction A
class CCIfBigEndian<CCAction A> :
CCIf<"State.getMachineFunction().getDataLayout().isBigEndian()", A>;
+class CCIfILP32<CCAction A> :
+ CCIf<"State.getMachineFunction().getDataLayout().getPointerSize() == 4", A>;
+
+
//===----------------------------------------------------------------------===//
// ARM AAPCS64 Calling Convention
//===----------------------------------------------------------------------===//
@@ -123,6 +127,7 @@ def RetCC_AArch64_AAPCS : CallingConv<[
CCIfType<[v2f32], CCBitConvertToType<v2i32>>,
CCIfType<[v2f64, v4f32], CCBitConvertToType<v2i64>>,
+ CCIfConsecutiveRegs<CCCustom<"CC_AArch64_Custom_Block">>,
CCIfSwiftError<CCIfType<[i64], CCAssignToRegWithShadow<[X21], [W21]>>>,
// Big endian vectors must be passed as if they were 1-element vectors so that
@@ -221,6 +226,12 @@ def CC_AArch64_DarwinPCS : CallingConv<[
CCIf<"ValVT == MVT::i1 || ValVT == MVT::i8", CCAssignToStack<1, 1>>,
CCIf<"ValVT == MVT::i16 || ValVT == MVT::f16", CCAssignToStack<2, 2>>,
CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
+
+ // Re-demote pointers to 32-bits so we don't end up storing 64-bit
+ // values and clobbering neighbouring stack locations. Not very pretty.
+ CCIfPtr<CCIfILP32<CCTruncToType<i32>>>,
+ CCIfPtr<CCIfILP32<CCAssignToStack<4, 4>>>,
+
CCIfType<[i64, f64, v1f64, v2f32, v1i64, v2i32, v4i16, v8i8, v4f16],
CCAssignToStack<8, 8>>,
CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32, v2f64, v8f16],
@@ -248,6 +259,29 @@ def CC_AArch64_DarwinPCS_VarArg : Callin
CCAssignToStack<16, 16>>
]>;
+// In the ILP32 world, the minimum stack slot size is 4 bytes. Otherwise the
+// same as the normal Darwin VarArgs handling.
+let Entry = 1 in
+def CC_AArch64_DarwinPCS_ILP32_VarArg : CallingConv<[
+ CCIfType<[v2f32], CCBitConvertToType<v2i32>>,
+ CCIfType<[v2f64, v4f32, f128], CCBitConvertToType<v2i64>>,
+
+ // Handle all scalar types as either i32 or f32.
+ CCIfType<[i8, i16], CCPromoteToType<i32>>,
+ CCIfType<[f16], CCPromoteToType<f32>>,
+
+ // Everything is on the stack.
+ // i128 is split to two i64s, and its stack alignment is 16 bytes.
+ CCIfPtr<CCIfILP32<CCTruncToType<i32>>>,
+ CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
+ CCIfType<[i64], CCIfSplit<CCAssignToStack<8, 16>>>,
+ CCIfType<[i64, f64, v1i64, v2i32, v4i16, v8i8, v1f64, v2f32, v4f16],
+ CCAssignToStack<8, 8>>,
+ CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32, v2f64, v8f16],
+ CCAssignToStack<16, 16>>
+]>;
+
+
// The WebKit_JS calling convention only passes the first argument (the callee)
// in register and the remaining arguments on stack. We allow 32bit stack slots,
// so that WebKit can write partial values in the stack and define the other
Modified: llvm/trunk/lib/Target/AArch64/AArch64CollectLOH.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64CollectLOH.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64CollectLOH.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64CollectLOH.cpp Thu Sep 12 03:22:23 2019
@@ -103,6 +103,7 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
@@ -181,6 +182,7 @@ static bool canDefBePartOfLOH(const Mach
case AArch64::ADDXri:
return canAddBePartOfLOH(MI);
case AArch64::LDRXui:
+ case AArch64::LDRWui:
// Check immediate to see if the immediate is an address.
switch (MI.getOperand(2).getType()) {
default:
@@ -312,7 +314,8 @@ static void handleUse(const MachineInstr
Info.Type = MCLOH_AdrpAdd;
Info.IsCandidate = true;
Info.MI0 = &MI;
- } else if (MI.getOpcode() == AArch64::LDRXui &&
+ } else if ((MI.getOpcode() == AArch64::LDRXui ||
+ MI.getOpcode() == AArch64::LDRWui) &&
MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) {
Info.Type = MCLOH_AdrpLdrGot;
Info.IsCandidate = true;
@@ -357,7 +360,9 @@ static bool handleMiddleInst(const Machi
return true;
}
} else {
- assert(MI.getOpcode() == AArch64::LDRXui && "Expect LDRXui");
+ assert((MI.getOpcode() == AArch64::LDRXui ||
+ MI.getOpcode() == AArch64::LDRWui) &&
+ "Expect LDRXui or LDRWui");
assert((MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) &&
"Expected GOT relocation");
if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
@@ -474,13 +479,23 @@ static void handleNormalInst(const Machi
handleClobber(LOHInfos[Idx]);
}
// Handle uses.
+
+ SmallSet<int, 4> UsesSeen;
for (const MachineOperand &MO : MI.uses()) {
if (!MO.isReg() || !MO.readsReg())
continue;
int Idx = mapRegToGPRIndex(MO.getReg());
if (Idx < 0)
continue;
- handleUse(MI, MO, LOHInfos[Idx]);
+
+ // Multiple uses of the same register within a single instruction don't
+ // count as MultiUser or block optimization. This is especially important on
+ // arm64_32, where any memory operation is likely to be an explicit use of
+ // xN and an implicit use of wN (the base address register).
+ if (!UsesSeen.count(Idx)) {
+ handleUse(MI, MO, LOHInfos[Idx]);
+ UsesSeen.insert(Idx);
+ }
}
}
@@ -512,6 +527,7 @@ bool AArch64CollectLOH::runOnMachineFunc
switch (Opcode) {
case AArch64::ADDXri:
case AArch64::LDRXui:
+ case AArch64::LDRWui:
if (canDefBePartOfLOH(MI)) {
const MachineOperand &Def = MI.getOperand(0);
const MachineOperand &Op = MI.getOperand(1);
Modified: llvm/trunk/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp Thu Sep 12 03:22:23 2019
@@ -495,12 +495,26 @@ bool AArch64ExpandPseudo::expandMI(Machi
}
} else {
// Small codemodel expand into ADRP + LDR.
+ MachineFunction &MF = *MI.getParent()->getParent();
+ DebugLoc DL = MI.getDebugLoc();
MachineInstrBuilder MIB1 =
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
- MachineInstrBuilder MIB2 =
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRXui))
- .add(MI.getOperand(0))
- .addReg(DstReg);
+
+ MachineInstrBuilder MIB2;
+ if (MF.getSubtarget<AArch64Subtarget>().isTargetILP32()) {
+ auto TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
+ unsigned Reg32 = TRI->getSubReg(DstReg, AArch64::sub_32);
+ unsigned DstFlags = MI.getOperand(0).getTargetFlags();
+ MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRWui))
+ .addDef(Reg32, RegState::Dead)
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, DstFlags | RegState::Implicit);
+ } else {
+ unsigned DstReg = MI.getOperand(0).getReg();
+ MIB2 = BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
+ .add(MI.getOperand(0))
+ .addUse(DstReg, RegState::Kill);
+ }
if (MO1.isGlobal()) {
MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
Modified: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp Thu Sep 12 03:22:23 2019
@@ -474,12 +474,32 @@ unsigned AArch64FastISel::materializeGV(
ADRPReg)
.addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);
- ResultReg = createResultReg(&AArch64::GPR64RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::LDRXui),
+ unsigned LdrOpc;
+ if (Subtarget->isTargetILP32()) {
+ ResultReg = createResultReg(&AArch64::GPR32RegClass);
+ LdrOpc = AArch64::LDRWui;
+ } else {
+ ResultReg = createResultReg(&AArch64::GPR64RegClass);
+ LdrOpc = AArch64::LDRXui;
+ }
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(LdrOpc),
ResultReg)
- .addReg(ADRPReg)
- .addGlobalAddress(GV, 0,
- AArch64II::MO_PAGEOFF | AArch64II::MO_NC | OpFlags);
+ .addReg(ADRPReg)
+ .addGlobalAddress(GV, 0, AArch64II::MO_GOT | AArch64II::MO_PAGEOFF |
+ AArch64II::MO_NC | OpFlags);
+ if (!Subtarget->isTargetILP32())
+ return ResultReg;
+
+ // LDRWui produces a 32-bit register, but pointers in-register are 64-bits
+ // so we must extend the result on ILP32.
+ unsigned Result64 = createResultReg(&AArch64::GPR64RegClass);
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ TII.get(TargetOpcode::SUBREG_TO_REG))
+ .addDef(Result64)
+ .addImm(0)
+ .addReg(ResultReg, RegState::Kill)
+ .addImm(AArch64::sub_32);
+ return Result64;
} else {
// ADRP + ADDX
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
@@ -504,6 +524,15 @@ unsigned AArch64FastISel::fastMaterializ
if (!CEVT.isSimple())
return 0;
MVT VT = CEVT.getSimpleVT();
+ // arm64_32 has 32-bit pointers held in 64-bit registers. Because of that,
+ // 'null' pointers need to have a somewhat special treatment.
+ if (const auto *CPN = dyn_cast<ConstantPointerNull>(C)) {
+ (void)CPN;
+ assert(CPN->getType()->getPointerAddressSpace() == 0 &&
+ "Unexpected address space");
+ assert(VT == MVT::i64 && "Expected 64-bit pointers");
+ return materializeInt(ConstantInt::get(Type::getInt64Ty(*Context), 0), VT);
+ }
if (const auto *CI = dyn_cast<ConstantInt>(C))
return materializeInt(CI, VT);
@@ -946,6 +975,9 @@ bool AArch64FastISel::computeCallAddress
bool AArch64FastISel::isTypeLegal(Type *Ty, MVT &VT) {
EVT evt = TLI.getValueType(DL, Ty, true);
+ if (Subtarget->isTargetILP32() && Ty->isPointerTy())
+ return false;
+
// Only handle simple types.
if (evt == MVT::Other || !evt.isSimple())
return false;
@@ -988,6 +1020,9 @@ bool AArch64FastISel::isValueAvailable(c
}
bool AArch64FastISel::simplifyAddress(Address &Addr, MVT VT) {
+ if (Subtarget->isTargetILP32())
+ return false;
+
unsigned ScaleFactor = getImplicitScaleFactor(VT);
if (!ScaleFactor)
return false;
@@ -3165,6 +3200,11 @@ bool AArch64FastISel::fastLowerCall(Call
if (IsTailCall)
return false;
+ // FIXME: we could and should support this, but for now correctness at -O0 is
+ // more important.
+ if (Subtarget->isTargetILP32())
+ return false;
+
CodeModel::Model CM = TM.getCodeModel();
// Only support the small-addressing and large code models.
if (CM != CodeModel::Large && !Subtarget->useSmallAddressing())
@@ -3796,6 +3836,11 @@ bool AArch64FastISel::selectRet(const In
if (!FuncInfo.CanLowerReturn)
return false;
+ // FIXME: in principle it could. Mostly just a case of zero extending outgoing
+ // pointers.
+ if (Subtarget->isTargetILP32())
+ return false;
+
if (F.isVarArg())
return false;
Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Thu Sep 12 03:22:23 2019
@@ -23,6 +23,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
@@ -1053,6 +1054,14 @@ void AArch64TargetLowering::computeKnown
Known.One &= Known2.One;
break;
}
+ case AArch64ISD::LOADgot:
+ case AArch64ISD::ADDlow: {
+ if (!Subtarget->isTargetILP32())
+ break;
+ // In ILP32 mode all valid pointers are in the low 4GB of the address-space.
+ Known.Zero = APInt::getHighBitsSet(64, 32);
+ break;
+ }
case ISD::INTRINSIC_W_CHAIN: {
ConstantSDNode *CN = cast<ConstantSDNode>(Op->getOperand(1));
Intrinsic::ID IntID = static_cast<Intrinsic::ID>(CN->getZExtValue());
@@ -3071,8 +3080,11 @@ CCAssignFn *AArch64TargetLowering::CCAss
return CC_AArch64_Win64_VarArg;
if (!Subtarget->isTargetDarwin())
return CC_AArch64_AAPCS;
- return IsVarArg ? CC_AArch64_DarwinPCS_VarArg : CC_AArch64_DarwinPCS;
- case CallingConv::Win64:
+ if (!IsVarArg)
+ return CC_AArch64_DarwinPCS;
+ return Subtarget->isTargetILP32() ? CC_AArch64_DarwinPCS_ILP32_VarArg
+ : CC_AArch64_DarwinPCS_VarArg;
+ case CallingConv::Win64:
return IsVarArg ? CC_AArch64_Win64_VarArg : CC_AArch64_AAPCS;
case CallingConv::AArch64_VectorCall:
return CC_AArch64_AAPCS;
@@ -3095,6 +3107,7 @@ SDValue AArch64TargetLowering::LowerForm
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
+ DenseMap<unsigned, SDValue> CopiedRegs;
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
*DAG.getContext());
@@ -3151,11 +3164,10 @@ SDValue AArch64TargetLowering::LowerForm
continue;
}
+ SDValue ArgValue;
if (VA.isRegLoc()) {
// Arguments stored in registers.
EVT RegVT = VA.getLocVT();
-
- SDValue ArgValue;
const TargetRegisterClass *RC;
if (RegVT == MVT::i32)
@@ -3200,14 +3212,13 @@ SDValue AArch64TargetLowering::LowerForm
case CCValAssign::AExt:
case CCValAssign::SExt:
case CCValAssign::ZExt:
- // SelectionDAGBuilder will insert appropriate AssertZExt & AssertSExt
- // nodes after our lowering.
- assert(RegVT == Ins[i].VT && "incorrect register location selected");
+ break;
+ case CCValAssign::AExtUpper:
+ ArgValue = DAG.getNode(ISD::SRL, DL, RegVT, ArgValue,
+ DAG.getConstant(32, DL, RegVT));
+ ArgValue = DAG.getZExtOrTrunc(ArgValue, DL, VA.getValVT());
break;
}
-
- InVals.push_back(ArgValue);
-
} else { // VA.isRegLoc()
assert(VA.isMemLoc() && "CCValAssign is neither reg nor mem");
unsigned ArgOffset = VA.getLocMemOffset();
@@ -3222,7 +3233,6 @@ SDValue AArch64TargetLowering::LowerForm
// Create load nodes to retrieve arguments from the stack.
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
- SDValue ArgValue;
// For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
ISD::LoadExtType ExtType = ISD::NON_EXTLOAD;
@@ -3231,6 +3241,7 @@ SDValue AArch64TargetLowering::LowerForm
switch (VA.getLocInfo()) {
default:
break;
+ case CCValAssign::Trunc:
case CCValAssign::BCvt:
MemVT = VA.getLocVT();
break;
@@ -3254,8 +3265,11 @@ SDValue AArch64TargetLowering::LowerForm
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI),
MemVT);
- InVals.push_back(ArgValue);
}
+ if (Subtarget->isTargetILP32() && Ins[i].Flags.isPointer())
+ ArgValue = DAG.getNode(ISD::AssertZext, DL, ArgValue.getValueType(),
+ ArgValue, DAG.getValueType(MVT::i32));
+ InVals.push_back(ArgValue);
}
// varargs
@@ -3272,8 +3286,8 @@ SDValue AArch64TargetLowering::LowerForm
// This will point to the next argument passed via stack.
unsigned StackOffset = CCInfo.getNextStackOffset();
- // We currently pass all varargs at 8-byte alignment.
- StackOffset = ((StackOffset + 7) & ~7);
+ // We currently pass all varargs at 8-byte alignment, or 4 for ILP32
+ StackOffset = alignTo(StackOffset, Subtarget->isTargetILP32() ? 4 : 8);
FuncInfo->setVarArgsStackIndex(MFI.CreateFixedObject(4, StackOffset, true));
if (MFI.hasMustTailInVarArgFunc()) {
@@ -3436,6 +3450,7 @@ SDValue AArch64TargetLowering::LowerCall
: RetCC_AArch64_AAPCS;
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
+ DenseMap<unsigned, SDValue> CopiedRegs;
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
*DAG.getContext());
CCInfo.AnalyzeCallResult(Ins, RetCC);
@@ -3453,10 +3468,16 @@ SDValue AArch64TargetLowering::LowerCall
continue;
}
- SDValue Val =
- DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InFlag);
- Chain = Val.getValue(1);
- InFlag = Val.getValue(2);
+ // Avoid copying a physreg twice since RegAllocFast is incompetent and only
+ // allows one use of a physreg per block.
+ SDValue Val = CopiedRegs.lookup(VA.getLocReg());
+ if (!Val) {
+ Val =
+ DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InFlag);
+ Chain = Val.getValue(1);
+ InFlag = Val.getValue(2);
+ CopiedRegs[VA.getLocReg()] = Val;
+ }
switch (VA.getLocInfo()) {
default:
@@ -3466,6 +3487,15 @@ SDValue AArch64TargetLowering::LowerCall
case CCValAssign::BCvt:
Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
break;
+ case CCValAssign::AExtUpper:
+ Val = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Val,
+ DAG.getConstant(32, DL, VA.getLocVT()));
+ LLVM_FALLTHROUGH;
+ case CCValAssign::AExt:
+ LLVM_FALLTHROUGH;
+ case CCValAssign::ZExt:
+ Val = DAG.getZExtOrTrunc(Val, DL, VA.getValVT());
+ break;
}
InVals.push_back(Val);
@@ -3779,6 +3809,7 @@ AArch64TargetLowering::LowerCall(CallLow
getPointerTy(DAG.getDataLayout()));
SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
+ SmallSet<unsigned, 8> RegsUsed;
SmallVector<SDValue, 8> MemOpChains;
auto PtrVT = getPointerTy(DAG.getDataLayout());
@@ -3786,7 +3817,7 @@ AArch64TargetLowering::LowerCall(CallLow
const auto &Forwards = FuncInfo->getForwardedMustTailRegParms();
for (const auto &F : Forwards) {
SDValue Val = DAG.getCopyFromReg(Chain, DL, F.VReg, F.VT);
- RegsToPass.push_back(std::make_pair(unsigned(F.PReg), Val));
+ RegsToPass.emplace_back(F.PReg, Val);
}
}
@@ -3817,8 +3848,17 @@ AArch64TargetLowering::LowerCall(CallLow
}
Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
break;
+ case CCValAssign::AExtUpper:
+ assert(VA.getValVT() == MVT::i32 && "only expect 32 -> 64 upper bits");
+ Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
+ Arg = DAG.getNode(ISD::SHL, DL, VA.getLocVT(), Arg,
+ DAG.getConstant(32, DL, VA.getLocVT()));
+ break;
case CCValAssign::BCvt:
- Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
+ Arg = DAG.getBitcast(VA.getLocVT(), Arg);
+ break;
+ case CCValAssign::Trunc:
+ Arg = DAG.getZExtOrTrunc(Arg, DL, VA.getLocVT());
break;
case CCValAssign::FPExt:
Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
@@ -3838,7 +3878,22 @@ AArch64TargetLowering::LowerCall(CallLow
"unexpected use of 'returned'");
IsThisReturn = true;
}
- RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+ if (RegsUsed.count(VA.getLocReg())) {
+ // If this register has already been used then we're trying to pack
+ // parts of an [N x i32] into an X-register. The extension type will
+ // take care of putting the two halves in the right place but we have to
+ // combine them.
+ SDValue &Bits =
+ std::find_if(RegsToPass.begin(), RegsToPass.end(),
+ [=](const std::pair<unsigned, SDValue> &Elt) {
+ return Elt.first == VA.getLocReg();
+ })
+ ->second;
+ Bits = DAG.getNode(ISD::OR, DL, Bits.getValueType(), Bits, Arg);
+ } else {
+ RegsToPass.emplace_back(VA.getLocReg(), Arg);
+ RegsUsed.insert(VA.getLocReg());
+ }
} else {
assert(VA.isMemLoc());
@@ -4071,7 +4126,8 @@ AArch64TargetLowering::LowerReturn(SDVal
// Copy the result values into the output registers.
SDValue Flag;
- SmallVector<SDValue, 4> RetOps(1, Chain);
+ SmallVector<std::pair<unsigned, SDValue>, 4> RetVals;
+ SmallSet<unsigned, 4> RegsUsed;
for (unsigned i = 0, realRVLocIdx = 0; i != RVLocs.size();
++i, ++realRVLocIdx) {
CCValAssign &VA = RVLocs[i];
@@ -4093,11 +4149,38 @@ AArch64TargetLowering::LowerReturn(SDVal
case CCValAssign::BCvt:
Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
break;
+ case CCValAssign::AExt:
+ case CCValAssign::ZExt:
+ Arg = DAG.getZExtOrTrunc(Arg, DL, VA.getLocVT());
+ break;
+ case CCValAssign::AExtUpper:
+ assert(VA.getValVT() == MVT::i32 && "only expect 32 -> 64 upper bits");
+ Arg = DAG.getZExtOrTrunc(Arg, DL, VA.getLocVT());
+ Arg = DAG.getNode(ISD::SHL, DL, VA.getLocVT(), Arg,
+ DAG.getConstant(32, DL, VA.getLocVT()));
+ break;
}
- Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Flag);
+ if (RegsUsed.count(VA.getLocReg())) {
+ SDValue &Bits =
+ std::find_if(RetVals.begin(), RetVals.end(),
+ [=](const std::pair<unsigned, SDValue> &Elt) {
+ return Elt.first == VA.getLocReg();
+ })
+ ->second;
+ Bits = DAG.getNode(ISD::OR, DL, Bits.getValueType(), Bits, Arg);
+ } else {
+ RetVals.emplace_back(VA.getLocReg(), Arg);
+ RegsUsed.insert(VA.getLocReg());
+ }
+ }
+
+ SmallVector<SDValue, 4> RetOps(1, Chain);
+ for (auto &RetVal : RetVals) {
+ Chain = DAG.getCopyToReg(Chain, DL, RetVal.first, RetVal.second, Flag);
Flag = Chain.getValue(1);
- RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
+ RetOps.push_back(
+ DAG.getRegister(RetVal.first, RetVal.second.getValueType()));
}
// Windows AArch64 ABIs require that for returning structs by value we copy
@@ -4291,6 +4374,7 @@ AArch64TargetLowering::LowerDarwinGlobal
SDLoc DL(Op);
MVT PtrVT = getPointerTy(DAG.getDataLayout());
+ MVT PtrMemVT = getPointerMemTy(DAG.getDataLayout());
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
SDValue TLVPAddr =
@@ -4301,12 +4385,15 @@ AArch64TargetLowering::LowerDarwinGlobal
// to obtain the address of the variable.
SDValue Chain = DAG.getEntryNode();
SDValue FuncTLVGet = DAG.getLoad(
- MVT::i64, DL, Chain, DescAddr,
+ PtrMemVT, DL, Chain, DescAddr,
MachinePointerInfo::getGOT(DAG.getMachineFunction()),
- /* Alignment = */ 8,
+ /* Alignment = */ PtrMemVT.getSizeInBits() / 8,
MachineMemOperand::MOInvariant | MachineMemOperand::MODereferenceable);
Chain = FuncTLVGet.getValue(1);
+ // Extend loaded pointer if necessary (i.e. if ILP32) to DAG pointer.
+ FuncTLVGet = DAG.getZExtOrTrunc(FuncTLVGet, DL, PtrVT);
+
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
MFI.setAdjustsStack(true);
@@ -5182,6 +5269,7 @@ SDValue AArch64TargetLowering::LowerDarw
SDLoc DL(Op);
SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsStackIndex(),
getPointerTy(DAG.getDataLayout()));
+ FR = DAG.getZExtOrTrunc(FR, DL, getPointerMemTy(DAG.getDataLayout()));
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
return DAG.getStore(Op.getOperand(0), DL, FR, Op.getOperand(1),
MachinePointerInfo(SV));
@@ -5288,15 +5376,15 @@ SDValue AArch64TargetLowering::LowerVACO
// AAPCS has three pointers and two ints (= 32 bytes), Darwin has single
// pointer.
SDLoc DL(Op);
- unsigned VaListSize =
- Subtarget->isTargetDarwin() || Subtarget->isTargetWindows() ? 8 : 32;
+ unsigned PtrSize = Subtarget->isTargetILP32() ? 4 : 8;
+ unsigned VaListSize = (Subtarget->isTargetDarwin() ||
+ Subtarget->isTargetWindows()) ? PtrSize : 32;
const Value *DestSV = cast<SrcValueSDNode>(Op.getOperand(3))->getValue();
const Value *SrcSV = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
- return DAG.getMemcpy(Op.getOperand(0), DL, Op.getOperand(1),
- Op.getOperand(2),
- DAG.getConstant(VaListSize, DL, MVT::i32),
- 8, false, false, false, MachinePointerInfo(DestSV),
+ return DAG.getMemcpy(Op.getOperand(0), DL, Op.getOperand(1), Op.getOperand(2),
+ DAG.getConstant(VaListSize, DL, MVT::i32), PtrSize,
+ false, false, false, MachinePointerInfo(DestSV),
MachinePointerInfo(SrcSV));
}
@@ -5310,12 +5398,15 @@ SDValue AArch64TargetLowering::LowerVAAR
SDValue Chain = Op.getOperand(0);
SDValue Addr = Op.getOperand(1);
unsigned Align = Op.getConstantOperandVal(3);
+ unsigned MinSlotSize = Subtarget->isTargetILP32() ? 4 : 8;
auto PtrVT = getPointerTy(DAG.getDataLayout());
-
- SDValue VAList = DAG.getLoad(PtrVT, DL, Chain, Addr, MachinePointerInfo(V));
+ auto PtrMemVT = getPointerMemTy(DAG.getDataLayout());
+ SDValue VAList =
+ DAG.getLoad(PtrMemVT, DL, Chain, Addr, MachinePointerInfo(V));
Chain = VAList.getValue(1);
+ VAList = DAG.getZExtOrTrunc(VAList, DL, PtrVT);
- if (Align > 8) {
+ if (Align > MinSlotSize) {
assert(((Align & (Align - 1)) == 0) && "Expected Align to be a power of 2");
VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
DAG.getConstant(Align - 1, DL, PtrVT));
@@ -5324,14 +5415,14 @@ SDValue AArch64TargetLowering::LowerVAAR
}
Type *ArgTy = VT.getTypeForEVT(*DAG.getContext());
- uint64_t ArgSize = DAG.getDataLayout().getTypeAllocSize(ArgTy);
+ unsigned ArgSize = DAG.getDataLayout().getTypeAllocSize(ArgTy);
// Scalar integer and FP values smaller than 64 bits are implicitly extended
// up to 64 bits. At the very least, we have to increase the striding of the
// vaargs list to match this, and for FP values we need to introduce
// FP_ROUND nodes as well.
if (VT.isInteger() && !VT.isVector())
- ArgSize = 8;
+ ArgSize = std::max(ArgSize, MinSlotSize);
bool NeedFPTrunc = false;
if (VT.isFloatingPoint() && !VT.isVector() && VT != MVT::f64) {
ArgSize = 8;
@@ -5341,6 +5432,8 @@ SDValue AArch64TargetLowering::LowerVAAR
// Increment the pointer, VAList, to the next vaarg
SDValue VANext = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
DAG.getConstant(ArgSize, DL, PtrVT));
+ VANext = DAG.getZExtOrTrunc(VANext, DL, PtrMemVT);
+
// Store the incremented VAList to the legalized pointer
SDValue APStore =
DAG.getStore(Chain, DL, VANext, Addr, MachinePointerInfo(V));
@@ -5370,10 +5463,15 @@ SDValue AArch64TargetLowering::LowerFRAM
SDLoc DL(Op);
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
SDValue FrameAddr =
- DAG.getCopyFromReg(DAG.getEntryNode(), DL, AArch64::FP, VT);
+ DAG.getCopyFromReg(DAG.getEntryNode(), DL, AArch64::FP, MVT::i64);
while (Depth--)
FrameAddr = DAG.getLoad(VT, DL, DAG.getEntryNode(), FrameAddr,
MachinePointerInfo());
+
+ if (Subtarget->isTargetILP32())
+ FrameAddr = DAG.getNode(ISD::AssertZext, DL, MVT::i64, FrameAddr,
+ DAG.getValueType(VT));
+
return FrameAddr;
}
Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h Thu Sep 12 03:22:23 2019
@@ -261,6 +261,14 @@ public:
const SelectionDAG &DAG,
unsigned Depth = 0) const override;
+ MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const override {
+ // Returning i64 unconditionally here (i.e. even for ILP32) means that the
+ // *DAG* representation of pointers will always be 64-bits. They will be
+ // truncated and extended when transferred to memory, but the 64-bit DAG
+ // allows us to use AArch64's addressing modes much more easily.
+ return MVT::getIntegerVT(64);
+ }
+
bool targetShrinkDemandedConstant(SDValue Op, const APInt &Demanded,
TargetLoweringOpt &TLO) const override;
Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp Thu Sep 12 03:22:23 2019
@@ -1471,6 +1471,8 @@ bool AArch64InstrInfo::expandPostRAPseud
return false;
MachineBasicBlock &MBB = *MI.getParent();
+ auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
+ auto TRI = Subtarget.getRegisterInfo();
DebugLoc DL = MI.getDebugLoc();
if (MI.getOpcode() == AArch64::CATCHRET) {
@@ -1506,11 +1508,22 @@ bool AArch64InstrInfo::expandPostRAPseud
if ((OpFlags & AArch64II::MO_GOT) != 0) {
BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
.addGlobalAddress(GV, 0, OpFlags);
- BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
- .addReg(Reg, RegState::Kill)
- .addImm(0)
- .addMemOperand(*MI.memoperands_begin());
+ if (Subtarget.isTargetILP32()) {
+ unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
+ BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
+ .addDef(Reg32, RegState::Dead)
+ .addUse(Reg, RegState::Kill)
+ .addImm(0)
+ .addMemOperand(*MI.memoperands_begin())
+ .addDef(Reg, RegState::Implicit);
+ } else {
+ BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
+ .addReg(Reg, RegState::Kill)
+ .addImm(0)
+ .addMemOperand(*MI.memoperands_begin());
+ }
} else if (TM.getCodeModel() == CodeModel::Large) {
+ assert(!Subtarget.isTargetILP32() && "how can large exist in ILP32?");
BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
.addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
.addImm(0);
@@ -1537,10 +1550,20 @@ bool AArch64InstrInfo::expandPostRAPseud
BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
.addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
- BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
- .addReg(Reg, RegState::Kill)
- .addGlobalAddress(GV, 0, LoFlags)
- .addMemOperand(*MI.memoperands_begin());
+ if (Subtarget.isTargetILP32()) {
+ unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
+ BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
+ .addDef(Reg32, RegState::Dead)
+ .addUse(Reg, RegState::Kill)
+ .addGlobalAddress(GV, 0, LoFlags)
+ .addMemOperand(*MI.memoperands_begin())
+ .addDef(Reg, RegState::Implicit);
+ } else {
+ BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
+ .addReg(Reg, RegState::Kill)
+ .addGlobalAddress(GV, 0, LoFlags)
+ .addMemOperand(*MI.memoperands_begin());
+ }
}
MBB.erase(MI);
Modified: llvm/trunk/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp Thu Sep 12 03:22:23 2019
@@ -32,7 +32,7 @@ SDValue AArch64SelectionDAGInfo::EmitTar
const AArch64TargetLowering &TLI = *STI.getTargetLowering();
EVT IntPtr = TLI.getPointerTy(DAG.getDataLayout());
- Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
+ Type *IntPtrTy = Type::getInt8PtrTy(*DAG.getContext());
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
Entry.Node = Dst;
Modified: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h Thu Sep 12 03:22:23 2019
@@ -411,6 +411,8 @@ public:
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
+ bool isTargetILP32() const { return TargetTriple.isArch32Bit(); }
+
bool useAA() const override { return UseAA; }
bool hasVH() const { return HasVH; }
@@ -437,6 +439,12 @@ public:
bool hasFMI() const { return HasFMI; }
bool hasRCPC_IMMO() const { return HasRCPC_IMMO; }
+ bool addrSinkUsingGEPs() const override {
+ // Keeping GEPs inbounds is important for exploiting AArch64
+ // addressing-modes in ILP32 mode.
+ return useAA() || isTargetILP32();
+ }
+
bool useSmallAddressing() const {
switch (TLInfo.getTargetMachine().getCodeModel()) {
case CodeModel::Kernel:
Modified: llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp Thu Sep 12 03:22:23 2019
@@ -157,6 +157,8 @@ extern "C" void LLVMInitializeAArch64Tar
RegisterTargetMachine<AArch64leTargetMachine> X(getTheAArch64leTarget());
RegisterTargetMachine<AArch64beTargetMachine> Y(getTheAArch64beTarget());
RegisterTargetMachine<AArch64leTargetMachine> Z(getTheARM64Target());
+ RegisterTargetMachine<AArch64leTargetMachine> W(getTheARM64_32Target());
+ RegisterTargetMachine<AArch64leTargetMachine> V(getTheAArch64_32Target());
auto PR = PassRegistry::getPassRegistry();
initializeGlobalISel(*PR);
initializeAArch64A53Fix835769Pass(*PR);
@@ -201,8 +203,11 @@ static std::string computeDataLayout(con
bool LittleEndian) {
if (Options.getABIName() == "ilp32")
return "e-m:e-p:32:32-i8:8-i16:16-i64:64-S128";
- if (TT.isOSBinFormatMachO())
+ if (TT.isOSBinFormatMachO()) {
+ if (TT.getArch() == Triple::aarch64_32)
+ return "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128";
return "e-m:o-i64:64-i128:128-n32:64-S128";
+ }
if (TT.isOSBinFormatCOFF())
return "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128";
if (LittleEndian)
@@ -279,7 +284,8 @@ AArch64TargetMachine::AArch64TargetMachi
}
// Enable GlobalISel at or below EnableGlobalISelAt0.
- if (getOptLevel() <= EnableGlobalISelAtO) {
+ if (getOptLevel() <= EnableGlobalISelAtO &&
+ TT.getArch() != Triple::aarch64_32) {
setGlobalISel(true);
setGlobalISelAbort(GlobalISelAbortMode::Disable);
}
Modified: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp Thu Sep 12 03:22:23 2019
@@ -30,7 +30,7 @@ static cl::opt<AsmWriterVariantTy> AsmWr
cl::values(clEnumValN(Generic, "generic", "Emit generic NEON assembly"),
clEnumValN(Apple, "apple", "Emit Apple-style NEON assembly")));
-AArch64MCAsmInfoDarwin::AArch64MCAsmInfoDarwin() {
+AArch64MCAsmInfoDarwin::AArch64MCAsmInfoDarwin(bool IsILP32) {
// We prefer NEON instructions to be printed in the short, Apple-specific
// form when targeting Darwin.
AssemblerDialect = AsmWriterVariant == Default ? Apple : AsmWriterVariant;
@@ -39,7 +39,8 @@ AArch64MCAsmInfoDarwin::AArch64MCAsmInfo
PrivateLabelPrefix = "L";
SeparatorString = "%%";
CommentString = ";";
- CodePointerSize = CalleeSaveStackSlotSize = 8;
+ CalleeSaveStackSlotSize = 8;
+ CodePointerSize = IsILP32 ? 4 : 8;
AlignmentIsInBytes = false;
UsesELFSectionDirectiveForBSS = true;
Modified: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h (original)
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h Thu Sep 12 03:22:23 2019
@@ -23,7 +23,7 @@ class Target;
class Triple;
struct AArch64MCAsmInfoDarwin : public MCAsmInfoDarwin {
- explicit AArch64MCAsmInfoDarwin();
+ explicit AArch64MCAsmInfoDarwin(bool IsILP32);
const MCExpr *
getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding,
MCStreamer &Streamer) const override;
Modified: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp Thu Sep 12 03:22:23 2019
@@ -241,7 +241,7 @@ static MCAsmInfo *createAArch64MCAsmInfo
const Triple &TheTriple) {
MCAsmInfo *MAI;
if (TheTriple.isOSBinFormatMachO())
- MAI = new AArch64MCAsmInfoDarwin();
+ MAI = new AArch64MCAsmInfoDarwin(TheTriple.getArch() == Triple::aarch64_32);
else if (TheTriple.isWindowsMSVCEnvironment())
MAI = new AArch64MCAsmInfoMicrosoftCOFF();
else if (TheTriple.isOSBinFormatCOFF())
Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Thu Sep 12 03:22:23 2019
@@ -3387,6 +3387,7 @@ bool X86FastISel::fastLowerCall(CallLowe
case CCValAssign::SExtUpper:
case CCValAssign::ZExtUpper:
case CCValAssign::FPExt:
+ case CCValAssign::Trunc:
llvm_unreachable("Unexpected loc info!");
case CCValAssign::Indirect:
// FIXME: Indirect doesn't need extending, but fast-isel doesn't fully
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-aapcs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-aapcs.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-aapcs.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-aapcs.ll Thu Sep 12 03:22:23 2019
@@ -25,7 +25,7 @@ define [2 x i64] @test_i64x2_align(i32,
@var64 = global i64 0, align 8
; Check stack slots are 64-bit at all times.
-define void @test_stack_slots([8 x i32], i1 %bool, i8 %char, i16 %short,
+define void @test_stack_slots([8 x i64], i1 %bool, i8 %char, i16 %short,
i32 %int, i64 %long) {
; CHECK-LABEL: test_stack_slots:
; CHECK-DAG: ldr w[[ext1:[0-9]+]], [sp, #24]
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-garbage-crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-garbage-crash.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-garbage-crash.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-garbage-crash.ll Thu Sep 12 03:22:23 2019
@@ -1,4 +1,5 @@
; RUN: llc -o - %s -mtriple=arm64-apple-ios -O3 -aarch64-enable-collect-loh | FileCheck %s
+; RUN: llc -o - %s -mtriple=arm64_32-apple-watchos -O3 -aarch64-enable-collect-loh | FileCheck %s
; Check that the LOH analysis does not crash when the analysed chained
; contains instructions that are filtered out.
;
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-str.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-str.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-str.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh-str.ll Thu Sep 12 03:22:23 2019
@@ -1,4 +1,5 @@
; RUN: llc -o - %s -mtriple=arm64-apple-ios -O2 | FileCheck %s
+; RUN: llc -o - %s -mtriple=arm64_32-apple-ios -O2 | FileCheck %s
; Test case for <rdar://problem/15942912>.
; AdrpAddStr cannot be used when the store uses same
; register as address and value. Indeed, the related
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-collect-loh.ll Thu Sep 12 03:22:23 2019
@@ -1,4 +1,5 @@
; RUN: llc -o - %s -mtriple=arm64-apple-ios -O2 | FileCheck %s
+; RUN: llc -o - %s -mtriple=arm64_32-apple-watchos -O2 | FileCheck %s
; RUN: llc -o - %s -mtriple=arm64-linux-gnu -O2 | FileCheck %s --check-prefix=CHECK-ELF
; CHECK-ELF-NOT: .loh
@@ -60,9 +61,9 @@ if.end4:
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define i32 @getC() {
@@ -76,9 +77,9 @@ define i32 @getC() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldrsw x0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldrsw x0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define i64 @getSExtC() {
@@ -94,10 +95,10 @@ define i64 @getSExtC() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
-; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
+; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], [x[[LDRGOT_REG]]]
; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
-; CHECK-NEXT: str [[ADD]], {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str [[ADD]], [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
define void @getSeveralC(i32 %t) {
@@ -114,9 +115,9 @@ entry:
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: str w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define void @setC(i32 %t) {
@@ -142,7 +143,7 @@ entry:
; CHECK-NEXT: ret
; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
define i32 @getInternalCPlus4() {
- %addr = getelementptr i32, i32* @InternalC, i32 4
+ %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
%res = load i32, i32* %addr, align 4
ret i32 %res
}
@@ -159,7 +160,7 @@ define i32 @getInternalCPlus4() {
; CHECK-NEXT: ret
; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
define i64 @getSExtInternalCPlus4() {
- %addr = getelementptr i32, i32* @InternalC, i32 4
+ %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
%res = load i32, i32* %addr, align 4
%sextres = sext i32 %res to i64
ret i64 %sextres
@@ -180,7 +181,7 @@ define i64 @getSExtInternalCPlus4() {
; CHECK: .loh AdrpAdd [[ADRP_LABEL]], [[ADDGOT_LABEL]]
define void @getSeveralInternalCPlus4(i32 %t) {
entry:
- %addr = getelementptr i32, i32* @InternalC, i32 4
+ %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
%tmp = load i32, i32* %addr, align 4
%add = add nsw i32 %tmp, %t
store i32 %add, i32* %addr, align 4
@@ -200,7 +201,7 @@ entry:
; CHECK: .loh AdrpAddStr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
define void @setInternalCPlus4(i32 %t) {
entry:
- %addr = getelementptr i32, i32* @InternalC, i32 4
+ %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
store i32 %t, i32* %addr, align 4
ret void
}
@@ -276,8 +277,8 @@ entry:
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
-; CHECK-NEXT: ldrb w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
+; CHECK-NEXT: ldrb w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
define i8 @getD() {
@@ -289,9 +290,9 @@ define i8 @getD() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: strb w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: strb w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setD(i8 %t) {
@@ -305,9 +306,9 @@ define void @setD(i8 %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldrsb w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldrsb w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define i32 @getSExtD() {
@@ -322,9 +323,9 @@ define i32 @getSExtD() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldrsb x0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldrsb x0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define i64 @getSExt64D() {
@@ -341,8 +342,8 @@ define i64 @getSExt64D() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
-; CHECK-NEXT: ldrh w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
+; CHECK-NEXT: ldrh w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
define i16 @getE() {
@@ -356,9 +357,9 @@ define i16 @getE() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldrsh w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldrsh w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define i32 @getSExtE() {
@@ -371,9 +372,9 @@ define i32 @getSExtE() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: strh w0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: strh w0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setE(i16 %t) {
@@ -387,9 +388,9 @@ define void @setE(i16 %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldrsh x0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldrsh x0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define i64 @getSExt64E() {
@@ -406,9 +407,9 @@ define i64 @getSExt64E() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _F at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr x0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr x0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define i64 @getF() {
@@ -420,9 +421,9 @@ define i64 @getF() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _F at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: str x0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str x0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setF(i64 %t) {
@@ -438,9 +439,9 @@ define void @setF(i64 %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _G at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr s0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr s0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define float @getG() {
@@ -452,9 +453,9 @@ define float @getG() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _G at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: str s0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str s0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setG(float %t) {
@@ -470,9 +471,9 @@ define void @setG(float %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _H at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr h0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr h0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define half @getH() {
@@ -484,9 +485,9 @@ define half @getH() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _H at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: str h0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str h0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setH(half %t) {
@@ -502,9 +503,9 @@ define void @setH(half %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _I at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr d0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define double @getI() {
@@ -516,9 +517,9 @@ define double @getI() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _I at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str d0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setI(double %t) {
@@ -534,9 +535,9 @@ define void @setI(double %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _J at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr d0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define <2 x i32> @getJ() {
@@ -548,9 +549,9 @@ define <2 x i32> @getJ() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _J at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str d0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setJ(<2 x i32> %t) {
@@ -566,9 +567,9 @@ define void @setJ(<2 x i32> %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _K at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr q0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr q0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define <4 x i32> @getK() {
@@ -580,9 +581,9 @@ define <4 x i32> @getK() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _K at GOTPAGEOFF]
; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: str q0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: str q0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
define void @setK(<4 x i32> %t) {
@@ -598,9 +599,9 @@ define void @setK(<4 x i32> %t) {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _L at GOTPAGEOFF]
; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr b0, {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: ldr b0, [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
define <1 x i8> @getL() {
@@ -612,11 +613,11 @@ define <1 x i8> @getL() {
; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L at GOTPAGE
; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
-; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L at GOTPAGEOFF]
+; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _L at GOTPAGEOFF]
; CHECK-NEXT: ; kill
; Ultimately we should generate str b0, but right now, we match the vector
; variant which does not allow to fold the immediate into the store.
-; CHECK-NEXT: st1.b { v0 }[0], {{\[}}[[LDRGOT_REG]]]
+; CHECK-NEXT: st1.b { v0 }[0], [x[[LDRGOT_REG]]]
; CHECK-NEXT: ret
; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
define void @setL(<1 x i8> %t) {
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-indexed-memory.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-indexed-memory.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-indexed-memory.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-indexed-memory.ll Thu Sep 12 03:22:23 2019
@@ -1,4 +1,5 @@
; RUN: llc < %s -mtriple=arm64-eabi -aarch64-redzone | FileCheck %s
+; RUN: llc < %s -mtriple=arm64_32-apple-ios -aarch64-redzone | FileCheck %s
define i64* @store64(i64* %ptr, i64 %index, i64 %spacing) {
; CHECK-LABEL: store64:
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-stacksave.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-stacksave.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-stacksave.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-stacksave.ll Thu Sep 12 03:22:23 2019
@@ -1,6 +1,6 @@
-; RUN: llc < %s -verify-coalescing
+; RUN: llc -mtriple=arm64-apple-macosx10.8.0 < %s -verify-coalescing
+; RUN: llc -mtriple=arm64_32-apple-ios9.0 < %s -verify-coalescing
; <rdar://problem/11522048>
-target triple = "arm64-apple-macosx10.8.0"
; Verify that we can handle spilling the stack pointer without attempting
; spilling it directly.
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-addrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-addrs.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-addrs.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-addrs.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,44 @@
+; RUN: llc -mtriple=arm64_32-apple-ios %s -o - | FileCheck %s
+
+; If %base < 96 then the sum will not wrap (in an unsigned sense), but "ldr w0,
+; [x0, #-96]" would.
+define i32 @test_valid_wrap(i32 %base) {
+; CHECK-LABEL: test_valid_wrap:
+; CHECK: sub w[[ADDR:[0-9]+]], w0, #96
+; CHECK: ldr w0, [x[[ADDR]]]
+
+ %newaddr = add nuw i32 %base, -96
+ %ptr = inttoptr i32 %newaddr to i32*
+ %val = load i32, i32* %ptr
+ ret i32 %val
+}
+
+define i8 @test_valid_wrap_optimizable(i8* %base) {
+; CHECK-LABEL: test_valid_wrap_optimizable:
+; CHECK: ldurb w0, [x0, #-96]
+
+ %newaddr = getelementptr inbounds i8, i8* %base, i32 -96
+ %val = load i8, i8* %newaddr
+ ret i8 %val
+}
+
+define i8 @test_valid_wrap_optimizable1(i8* %base, i32 %offset) {
+; CHECK-LABEL: test_valid_wrap_optimizable1:
+; CHECK: ldrb w0, [x0, w1, sxtw]
+
+ %newaddr = getelementptr inbounds i8, i8* %base, i32 %offset
+ %val = load i8, i8* %newaddr
+ ret i8 %val
+}
+
+;
+define i8 @test_valid_wrap_optimizable2(i8* %base, i32 %offset) {
+; CHECK-LABEL: test_valid_wrap_optimizable2:
+; CHECK: sxtw x[[OFFSET:[0-9]+]], w1
+; CHECK: mov w[[BASE:[0-9]+]], #-100
+; CHECK: ldrb w0, [x[[OFFSET]], x[[BASE]]]
+
+ %newaddr = getelementptr inbounds i8, i8* inttoptr(i32 -100 to i8*), i32 %offset
+ %val = load i8, i8* %newaddr
+ ret i8 %val
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-atomics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-atomics.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-atomics.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-atomics.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,261 @@
+; RUN: llc -mtriple=arm64_32-apple-ios7.0 -o - %s | FileCheck %s
+
+define i8 @test_load_8(i8* %addr) {
+; CHECK-LABAL: test_load_8:
+; CHECK: ldarb w0, [x0]
+ %val = load atomic i8, i8* %addr seq_cst, align 1
+ ret i8 %val
+}
+
+define i16 @test_load_16(i16* %addr) {
+; CHECK-LABAL: test_load_16:
+; CHECK: ldarh w0, [x0]
+ %val = load atomic i16, i16* %addr acquire, align 2
+ ret i16 %val
+}
+
+define i32 @test_load_32(i32* %addr) {
+; CHECK-LABAL: test_load_32:
+; CHECK: ldar w0, [x0]
+ %val = load atomic i32, i32* %addr seq_cst, align 4
+ ret i32 %val
+}
+
+define i64 @test_load_64(i64* %addr) {
+; CHECK-LABAL: test_load_64:
+; CHECK: ldar x0, [x0]
+ %val = load atomic i64, i64* %addr seq_cst, align 8
+ ret i64 %val
+}
+
+define i8* @test_load_ptr(i8** %addr) {
+; CHECK-LABAL: test_load_ptr:
+; CHECK: ldar w0, [x0]
+ %val = load atomic i8*, i8** %addr seq_cst, align 8
+ ret i8* %val
+}
+
+define void @test_store_8(i8* %addr) {
+; CHECK-LABAL: test_store_8:
+; CHECK: stlrb wzr, [x0]
+ store atomic i8 0, i8* %addr seq_cst, align 1
+ ret void
+}
+
+define void @test_store_16(i16* %addr) {
+; CHECK-LABAL: test_store_16:
+; CHECK: stlrh wzr, [x0]
+ store atomic i16 0, i16* %addr seq_cst, align 2
+ ret void
+}
+
+define void @test_store_32(i32* %addr) {
+; CHECK-LABAL: test_store_32:
+; CHECK: stlr wzr, [x0]
+ store atomic i32 0, i32* %addr seq_cst, align 4
+ ret void
+}
+
+define void @test_store_64(i64* %addr) {
+; CHECK-LABAL: test_store_64:
+; CHECK: stlr xzr, [x0]
+ store atomic i64 0, i64* %addr seq_cst, align 8
+ ret void
+}
+
+define void @test_store_ptr(i8** %addr) {
+; CHECK-LABAL: test_store_ptr:
+; CHECK: stlr wzr, [x0]
+ store atomic i8* null, i8** %addr seq_cst, align 8
+ ret void
+}
+
+declare i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
+declare i64 @llvm.aarch64.ldxr.p0i16(i16* %addr)
+declare i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
+declare i64 @llvm.aarch64.ldxr.p0i64(i64* %addr)
+
+define i8 @test_ldxr_8(i8* %addr) {
+; CHECK-LABEL: test_ldxr_8:
+; CHECK: ldxrb w0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
+ %val8 = trunc i64 %val to i8
+ ret i8 %val8
+}
+
+define i16 @test_ldxr_16(i16* %addr) {
+; CHECK-LABEL: test_ldxr_16:
+; CHECK: ldxrh w0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr)
+ %val16 = trunc i64 %val to i16
+ ret i16 %val16
+}
+
+define i32 @test_ldxr_32(i32* %addr) {
+; CHECK-LABEL: test_ldxr_32:
+; CHECK: ldxr w0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
+ %val32 = trunc i64 %val to i32
+ ret i32 %val32
+}
+
+define i64 @test_ldxr_64(i64* %addr) {
+; CHECK-LABEL: test_ldxr_64:
+; CHECK: ldxr x0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr)
+ ret i64 %val
+}
+
+declare i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
+declare i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr)
+declare i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr)
+declare i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr)
+
+define i8 @test_ldaxr_8(i8* %addr) {
+; CHECK-LABEL: test_ldaxr_8:
+; CHECK: ldaxrb w0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
+ %val8 = trunc i64 %val to i8
+ ret i8 %val8
+}
+
+define i16 @test_ldaxr_16(i16* %addr) {
+; CHECK-LABEL: test_ldaxr_16:
+; CHECK: ldaxrh w0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr)
+ %val16 = trunc i64 %val to i16
+ ret i16 %val16
+}
+
+define i32 @test_ldaxr_32(i32* %addr) {
+; CHECK-LABEL: test_ldaxr_32:
+; CHECK: ldaxr w0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr)
+ %val32 = trunc i64 %val to i32
+ ret i32 %val32
+}
+
+define i64 @test_ldaxr_64(i64* %addr) {
+; CHECK-LABEL: test_ldaxr_64:
+; CHECK: ldaxr x0, [x0]
+
+ %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr)
+ ret i64 %val
+}
+
+declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*)
+declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*)
+declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*)
+declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*)
+
+define i32 @test_stxr_8(i8* %addr, i8 %val) {
+; CHECK-LABEL: test_stxr_8:
+; CHECK: stxrb [[TMP:w[0-9]+]], w1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %extval = zext i8 %val to i64
+ %success = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr)
+ ret i32 %success
+}
+
+define i32 @test_stxr_16(i16* %addr, i16 %val) {
+; CHECK-LABEL: test_stxr_16:
+; CHECK: stxrh [[TMP:w[0-9]+]], w1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %extval = zext i16 %val to i64
+ %success = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr)
+ ret i32 %success
+}
+
+define i32 @test_stxr_32(i32* %addr, i32 %val) {
+; CHECK-LABEL: test_stxr_32:
+; CHECK: stxr [[TMP:w[0-9]+]], w1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %extval = zext i32 %val to i64
+ %success = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr)
+ ret i32 %success
+}
+
+define i32 @test_stxr_64(i64* %addr, i64 %val) {
+; CHECK-LABEL: test_stxr_64:
+; CHECK: stxr [[TMP:w[0-9]+]], x1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %success = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr)
+ ret i32 %success
+}
+
+declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*)
+declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*)
+declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*)
+declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*)
+
+define i32 @test_stlxr_8(i8* %addr, i8 %val) {
+; CHECK-LABEL: test_stlxr_8:
+; CHECK: stlxrb [[TMP:w[0-9]+]], w1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %extval = zext i8 %val to i64
+ %success = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr)
+ ret i32 %success
+}
+
+define i32 @test_stlxr_16(i16* %addr, i16 %val) {
+; CHECK-LABEL: test_stlxr_16:
+; CHECK: stlxrh [[TMP:w[0-9]+]], w1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %extval = zext i16 %val to i64
+ %success = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr)
+ ret i32 %success
+}
+
+define i32 @test_stlxr_32(i32* %addr, i32 %val) {
+; CHECK-LABEL: test_stlxr_32:
+; CHECK: stlxr [[TMP:w[0-9]+]], w1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %extval = zext i32 %val to i64
+ %success = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr)
+ ret i32 %success
+}
+
+define i32 @test_stlxr_64(i64* %addr, i64 %val) {
+; CHECK-LABEL: test_stlxr_64:
+; CHECK: stlxr [[TMP:w[0-9]+]], x1, [x0]
+; CHECK: mov w0, [[TMP]]
+
+ %success = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr)
+ ret i32 %success
+}
+
+define {i8*, i1} @test_cmpxchg_ptr(i8** %addr, i8* %cmp, i8* %new) {
+; CHECK-LABEL: test_cmpxchg_ptr:
+; CHECK: [[LOOP:LBB[0-9]+_[0-9]+]]:
+; CHECK: ldaxr [[OLD:w[0-9]+]], [x0]
+; CHECK: cmp [[OLD]], w1
+; CHECK: b.ne [[DONE:LBB[0-9]+_[0-9]+]]
+; CHECK: stlxr [[SUCCESS:w[0-9]+]], w2, [x0]
+; CHECK: cbnz [[SUCCESS]], [[LOOP]]
+
+; CHECK: mov w1, #1
+; CHECK: mov w0, [[OLD]]
+; CHECK: ret
+
+; CHECK: [[DONE]]:
+; CHECK: clrex
+; CHECK: mov w1, wzr
+; CHECK: mov w0, [[OLD]]
+; CHECK: ret
+ %res = cmpxchg i8** %addr, i8* %cmp, i8* %new acq_rel acquire
+ ret {i8*, i1} %res
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-fastisel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-fastisel.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-fastisel.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-fastisel.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,28 @@
+; RUN: llc -mtriple=arm64_32-apple-ios -O0 -fast-isel %s -o - | FileCheck %s
+ at var = global i8* null
+
+define void @test_store_release_ptr() {
+; CHECK-LABEL: test_store_release_ptr
+; CHECK: mov [[ZERO:w[0-9]+]], wzr
+; CHECK: stlr [[ZERO]]
+ store atomic i8* null, i8** @var release, align 4
+ br label %next
+
+next:
+ ret void
+}
+
+declare [2 x i32] @callee()
+
+define void @test_struct_return(i32* %addr) {
+; CHECK-LABEL: test_struct_return:
+; CHECK: bl _callee
+; CHECK-DAG: lsr [[HI:x[0-9]+]], x0, #32
+; CHECK-DAG: str w0
+ %res = call [2 x i32] @callee()
+ %res.0 = extractvalue [2 x i32] %res, 0
+ store i32 %res.0, i32* %addr
+ %res.1 = extractvalue [2 x i32] %res, 1
+ store i32 %res.1, i32* %addr
+ ret void
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-frame-pointers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-frame-pointers.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-frame-pointers.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-frame-pointers.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,26 @@
+; RUN: llc -mtriple=arm64_32-apple-ios8.0 %s -o - | FileCheck %s
+
+; We're provoking LocalStackSlotAllocation to create some shared frame bases
+; here: it wants multiple <fi#N> using instructions that can be satisfied by a
+; single base, but not within the addressing-mode.
+;
+; When that happens it's important that we don't mix our pointer sizes
+; (e.g. try to create an ldr from a w-register base).
+define i8 @test_register_wrangling() {
+; CHECK-LABEL: test_register_wrangling:
+; CHECK: add [[TMP:x[0-9]+]], sp,
+; CHECK: add x[[BASE:[0-9]+]], [[TMP]],
+; CHECK: ldrb {{w[0-9]+}}, [x[[BASE]], #1]
+; CHECK: ldrb {{w[0-9]+}}, [x[[BASE]]]
+
+ %var1 = alloca i8, i32 4100
+ %var3 = alloca i8
+ %dummy = alloca i8, i32 4100
+
+ %var1p1 = getelementptr i8, i8* %var1, i32 1
+ %val1 = load i8, i8* %var1
+ %val2 = load i8, i8* %var3
+
+ %sum = add i8 %val1, %val2
+ ret i8 %sum
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-gep-sink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-gep-sink.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-gep-sink.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-gep-sink.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,61 @@
+; RUN: opt -codegenprepare -mtriple=arm64_32-apple-ios %s -S -o - | FileCheck %s
+
+define void @test_simple_sink(i1* %base, i64 %offset) {
+; CHECK-LABEL: @test_simple_sink
+; CHECK: next:
+; CHECK: [[BASE8:%.*]] = bitcast i1* %base to i8*
+; CHECK: [[ADDR8:%.*]] = getelementptr i8, i8* [[BASE8]], i64 %offset
+; CHECK: [[ADDR:%.*]] = bitcast i8* [[ADDR8]] to i1*
+; CHECK: load volatile i1, i1* [[ADDR]]
+ %addr = getelementptr i1, i1* %base, i64 %offset
+ %tst = load i1, i1* %addr
+ br i1 %tst, label %next, label %end
+
+next:
+ load volatile i1, i1* %addr
+ ret void
+
+end:
+ ret void
+}
+
+define void @test_inbounds_sink(i1* %base, i64 %offset) {
+; CHECK-LABEL: @test_inbounds_sink
+; CHECK: next:
+; CHECK: [[BASE8:%.*]] = bitcast i1* %base to i8*
+; CHECK: [[ADDR8:%.*]] = getelementptr inbounds i8, i8* [[BASE8]], i64 %offset
+; CHECK: [[ADDR:%.*]] = bitcast i8* [[ADDR8]] to i1*
+; CHECK: load volatile i1, i1* [[ADDR]]
+ %addr = getelementptr inbounds i1, i1* %base, i64 %offset
+ %tst = load i1, i1* %addr
+ br i1 %tst, label %next, label %end
+
+next:
+ load volatile i1, i1* %addr
+ ret void
+
+end:
+ ret void
+}
+
+; No address derived via an add can be guaranteed inbounds
+define void @test_add_sink(i1* %base, i64 %offset) {
+; CHECK-LABEL: @test_add_sink
+; CHECK: next:
+; CHECK: [[BASE8:%.*]] = bitcast i1* %base to i8*
+; CHECK: [[ADDR8:%.*]] = getelementptr i8, i8* [[BASE8]], i64 %offset
+; CHECK: [[ADDR:%.*]] = bitcast i8* [[ADDR8]] to i1*
+; CHECK: load volatile i1, i1* [[ADDR]]
+ %base64 = ptrtoint i1* %base to i64
+ %addr64 = add nsw nuw i64 %base64, %offset
+ %addr = inttoptr i64 %addr64 to i1*
+ %tst = load i1, i1* %addr
+ br i1 %tst, label %next, label %end
+
+next:
+ load volatile i1, i1* %addr
+ ret void
+
+end:
+ ret void
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-memcpy.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-memcpy.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-memcpy.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-memcpy.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,66 @@
+; RUN: llc -mtriple=arm64_32-apple-ios9.0 -o - %s | FileCheck %s
+
+define i64 @test_memcpy(i64* %addr, i8* %src, i1 %tst) minsize {
+; CHECK-LABEL: test_memcpy:
+; CHECK: ldr [[VAL64:x[0-9]+]], [x0]
+; [...]
+; CHECK: and x0, [[VAL64]], #0xffffffff
+; CHECK: bl _memcpy
+
+ %val64 = load i64, i64* %addr
+ br i1 %tst, label %true, label %false
+
+true:
+ ret i64 %val64
+
+false:
+ %val32 = trunc i64 %val64 to i32
+ %val.ptr = inttoptr i32 %val32 to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i32(i8* %val.ptr, i8* %src, i32 128, i32 0, i1 1)
+ ret i64 undef
+}
+
+define i64 @test_memmove(i64* %addr, i8* %src, i1 %tst) minsize {
+; CHECK-LABEL: test_memmove:
+; CHECK: ldr [[VAL64:x[0-9]+]], [x0]
+; [...]
+; CHECK: and x0, [[VAL64]], #0xffffffff
+; CHECK: bl _memmove
+
+ %val64 = load i64, i64* %addr
+ br i1 %tst, label %true, label %false
+
+true:
+ ret i64 %val64
+
+false:
+ %val32 = trunc i64 %val64 to i32
+ %val.ptr = inttoptr i32 %val32 to i8*
+ call void @llvm.memmove.p0i8.p0i8.i32(i8* %val.ptr, i8* %src, i32 128, i32 0, i1 1)
+ ret i64 undef
+}
+
+define i64 @test_memset(i64* %addr, i8* %src, i1 %tst) minsize {
+; CHECK-LABEL: test_memset:
+; CHECK: ldr [[VAL64:x[0-9]+]], [x0]
+; [...]
+; CHECK: and x0, [[VAL64]], #0xffffffff
+; CHECK: bl _memset
+
+ %val64 = load i64, i64* %addr
+ br i1 %tst, label %true, label %false
+
+true:
+ ret i64 %val64
+
+false:
+ %val32 = trunc i64 %val64 to i32
+ %val.ptr = inttoptr i32 %val32 to i8*
+ call void @llvm.memset.p0i8.i32(i8* %val.ptr, i8 42, i32 256, i32 0, i1 1)
+ ret i64 undef
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
+declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
+declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1)
+
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-neon.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-neon.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-neon.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-neon.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,198 @@
+; RUN: llc -mtriple=arm64_32-apple-ios7.0 -mcpu=cyclone %s -o - | FileCheck %s
+
+define <2 x double> @test_insert_elt(<2 x double> %vec, double %val) {
+; CHECK-LABEL: test_insert_elt:
+; CHECK: mov.d v0[0], v1[0]
+ %res = insertelement <2 x double> %vec, double %val, i32 0
+ ret <2 x double> %res
+}
+
+define void @test_split_16B(<4 x float> %val, <4 x float>* %addr) {
+; CHECK-LABEL: test_split_16B:
+; CHECK: str q0, [x0]
+ store <4 x float> %val, <4 x float>* %addr, align 8
+ ret void
+}
+
+define void @test_split_16B_splat(<4 x i32>, <4 x i32>* %addr) {
+; CHECK-LABEL: test_split_16B_splat:
+; CHECK: str {{q[0-9]+}}
+
+ %vec.tmp0 = insertelement <4 x i32> undef, i32 42, i32 0
+ %vec.tmp1 = insertelement <4 x i32> %vec.tmp0, i32 42, i32 1
+ %vec.tmp2 = insertelement <4 x i32> %vec.tmp1, i32 42, i32 2
+ %vec = insertelement <4 x i32> %vec.tmp2, i32 42, i32 3
+
+ store <4 x i32> %vec, <4 x i32>* %addr, align 8
+ ret void
+}
+
+
+%vec = type <2 x double>
+
+declare {%vec, %vec} @llvm.aarch64.neon.ld2r.v2f64.p0i8(i8*)
+define {%vec, %vec} @test_neon_load(i8* %addr) {
+; CHECK-LABEL: test_neon_load:
+; CHECK: ld2r.2d { v0, v1 }, [x0]
+ %res = call {%vec, %vec} @llvm.aarch64.neon.ld2r.v2f64.p0i8(i8* %addr)
+ ret {%vec, %vec} %res
+}
+
+declare {%vec, %vec} @llvm.aarch64.neon.ld2lane.v2f64.p0i8(%vec, %vec, i64, i8*)
+define {%vec, %vec} @test_neon_load_lane(i8* %addr, %vec %in1, %vec %in2) {
+; CHECK-LABEL: test_neon_load_lane:
+; CHECK: ld2.d { v0, v1 }[0], [x0]
+ %res = call {%vec, %vec} @llvm.aarch64.neon.ld2lane.v2f64.p0i8(%vec %in1, %vec %in2, i64 0, i8* %addr)
+ ret {%vec, %vec} %res
+}
+
+declare void @llvm.aarch64.neon.st2.v2f64.p0i8(%vec, %vec, i8*)
+define void @test_neon_store(i8* %addr, %vec %in1, %vec %in2) {
+; CHECK-LABEL: test_neon_store:
+; CHECK: st2.2d { v0, v1 }, [x0]
+ call void @llvm.aarch64.neon.st2.v2f64.p0i8(%vec %in1, %vec %in2, i8* %addr)
+ ret void
+}
+
+declare void @llvm.aarch64.neon.st2lane.v2f64.p0i8(%vec, %vec, i64, i8*)
+define void @test_neon_store_lane(i8* %addr, %vec %in1, %vec %in2) {
+; CHECK-LABEL: test_neon_store_lane:
+; CHECK: st2.d { v0, v1 }[1], [x0]
+ call void @llvm.aarch64.neon.st2lane.v2f64.p0i8(%vec %in1, %vec %in2, i64 1, i8* %addr)
+ ret void
+}
+
+declare {%vec, %vec} @llvm.aarch64.neon.ld2.v2f64.p0i8(i8*)
+define {{%vec, %vec}, i8*} @test_neon_load_post(i8* %addr, i32 %offset) {
+; CHECK-LABEL: test_neon_load_post:
+; CHECK-DAG: sxtw [[OFFSET:x[0-9]+]], w1
+; CHECK: ld2.2d { v0, v1 }, [x0], [[OFFSET]]
+
+ %vecs = call {%vec, %vec} @llvm.aarch64.neon.ld2.v2f64.p0i8(i8* %addr)
+
+ %addr.new = getelementptr inbounds i8, i8* %addr, i32 %offset
+
+ %res.tmp = insertvalue {{%vec, %vec}, i8*} undef, {%vec, %vec} %vecs, 0
+ %res = insertvalue {{%vec, %vec}, i8*} %res.tmp, i8* %addr.new, 1
+ ret {{%vec, %vec}, i8*} %res
+}
+
+define {{%vec, %vec}, i8*} @test_neon_load_post_lane(i8* %addr, i32 %offset, %vec %in1, %vec %in2) {
+; CHECK-LABEL: test_neon_load_post_lane:
+; CHECK-DAG: sxtw [[OFFSET:x[0-9]+]], w1
+; CHECK: ld2.d { v0, v1 }[1], [x0], [[OFFSET]]
+
+ %vecs = call {%vec, %vec} @llvm.aarch64.neon.ld2lane.v2f64.p0i8(%vec %in1, %vec %in2, i64 1, i8* %addr)
+
+ %addr.new = getelementptr inbounds i8, i8* %addr, i32 %offset
+
+ %res.tmp = insertvalue {{%vec, %vec}, i8*} undef, {%vec, %vec} %vecs, 0
+ %res = insertvalue {{%vec, %vec}, i8*} %res.tmp, i8* %addr.new, 1
+ ret {{%vec, %vec}, i8*} %res
+}
+
+define i8* @test_neon_store_post(i8* %addr, i32 %offset, %vec %in1, %vec %in2) {
+; CHECK-LABEL: test_neon_store_post:
+; CHECK-DAG: sxtw [[OFFSET:x[0-9]+]], w1
+; CHECK: st2.2d { v0, v1 }, [x0], [[OFFSET]]
+
+ call void @llvm.aarch64.neon.st2.v2f64.p0i8(%vec %in1, %vec %in2, i8* %addr)
+
+ %addr.new = getelementptr inbounds i8, i8* %addr, i32 %offset
+
+ ret i8* %addr.new
+}
+
+define i8* @test_neon_store_post_lane(i8* %addr, i32 %offset, %vec %in1, %vec %in2) {
+; CHECK-LABEL: test_neon_store_post_lane:
+; CHECK: sxtw [[OFFSET:x[0-9]+]], w1
+; CHECK: st2.d { v0, v1 }[0], [x0], [[OFFSET]]
+
+ call void @llvm.aarch64.neon.st2lane.v2f64.p0i8(%vec %in1, %vec %in2, i64 0, i8* %addr)
+
+ %addr.new = getelementptr inbounds i8, i8* %addr, i32 %offset
+
+ ret i8* %addr.new
+}
+
+; ld1 is slightly different because it goes via ISelLowering of normal IR ops
+; rather than an intrinsic.
+define {%vec, double*} @test_neon_ld1_post_lane(double* %addr, i32 %offset, %vec %in) {
+; CHECK-LABEL: test_neon_ld1_post_lane:
+; CHECK: sbfiz [[OFFSET:x[0-9]+]], x1, #3, #32
+; CHECK: ld1.d { v0 }[0], [x0], [[OFFSET]]
+
+ %loaded = load double, double* %addr, align 8
+ %newvec = insertelement %vec %in, double %loaded, i32 0
+
+ %addr.new = getelementptr inbounds double, double* %addr, i32 %offset
+
+ %res.tmp = insertvalue {%vec, double*} undef, %vec %newvec, 0
+ %res = insertvalue {%vec, double*} %res.tmp, double* %addr.new, 1
+
+ ret {%vec, double*} %res
+}
+
+define {{%vec, %vec}, i8*} @test_neon_load_post_exact(i8* %addr) {
+; CHECK-LABEL: test_neon_load_post_exact:
+; CHECK: ld2.2d { v0, v1 }, [x0], #32
+
+ %vecs = call {%vec, %vec} @llvm.aarch64.neon.ld2.v2f64.p0i8(i8* %addr)
+
+ %addr.new = getelementptr inbounds i8, i8* %addr, i32 32
+
+ %res.tmp = insertvalue {{%vec, %vec}, i8*} undef, {%vec, %vec} %vecs, 0
+ %res = insertvalue {{%vec, %vec}, i8*} %res.tmp, i8* %addr.new, 1
+ ret {{%vec, %vec}, i8*} %res
+}
+
+define {%vec, double*} @test_neon_ld1_post_lane_exact(double* %addr, %vec %in) {
+; CHECK-LABEL: test_neon_ld1_post_lane_exact:
+; CHECK: ld1.d { v0 }[0], [x0], #8
+
+ %loaded = load double, double* %addr, align 8
+ %newvec = insertelement %vec %in, double %loaded, i32 0
+
+ %addr.new = getelementptr inbounds double, double* %addr, i32 1
+
+ %res.tmp = insertvalue {%vec, double*} undef, %vec %newvec, 0
+ %res = insertvalue {%vec, double*} %res.tmp, double* %addr.new, 1
+
+ ret {%vec, double*} %res
+}
+
+; As in the general load/store case, this GEP has defined semantics when the
+; address wraps. We cannot use post-indexed addressing.
+define {%vec, double*} @test_neon_ld1_notpost_lane_exact(double* %addr, %vec %in) {
+; CHECK-LABEL: test_neon_ld1_notpost_lane_exact:
+; CHECK-NOT: ld1.d { {{v[0-9]+}} }[0], [{{x[0-9]+|sp}}], #8
+; CHECK: add w0, w0, #8
+; CHECK: ret
+
+ %loaded = load double, double* %addr, align 8
+ %newvec = insertelement %vec %in, double %loaded, i32 0
+
+ %addr.new = getelementptr double, double* %addr, i32 1
+
+ %res.tmp = insertvalue {%vec, double*} undef, %vec %newvec, 0
+ %res = insertvalue {%vec, double*} %res.tmp, double* %addr.new, 1
+
+ ret {%vec, double*} %res
+}
+
+define {%vec, double*} @test_neon_ld1_notpost_lane(double* %addr, i32 %offset, %vec %in) {
+; CHECK-LABEL: test_neon_ld1_notpost_lane:
+; CHECK-NOT: ld1.d { {{v[0-9]+}} }[0], [{{x[0-9]+|sp}}], {{x[0-9]+|sp}}
+; CHECK: add w0, w0, w1, lsl #3
+; CHECK: ret
+
+ %loaded = load double, double* %addr, align 8
+ %newvec = insertelement %vec %in, double %loaded, i32 0
+
+ %addr.new = getelementptr double, double* %addr, i32 %offset
+
+ %res.tmp = insertvalue {%vec, double*} undef, %vec %newvec, 0
+ %res = insertvalue {%vec, double*} %res.tmp, double* %addr.new, 1
+
+ ret {%vec, double*} %res
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-null.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-null.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-null.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-null.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,28 @@
+; RUN: llc -fast-isel=true -global-isel=false -O0 -mtriple=arm64_32-apple-ios %s -o - | FileCheck %s
+; RUN: llc -fast-isel=false -global-isel=false -O0 -mtriple=arm64_32-apple-ios %s -o - | FileCheck %s
+
+define void @test_store(i8** %p) {
+; CHECK-LABEL: test_store:
+; CHECK: mov [[R1:w[0-9]+]], wzr
+; CHECK: str [[R1]], [x0]
+
+ store i8* null, i8** %p
+ ret void
+}
+
+define void @test_phi(i8** %p) {
+; CHECK-LABEL: test_phi:
+; CHECK: mov [[R1:x[0-9]+]], xzr
+; CHECK: str [[R1]], [sp]
+; CHECK: b [[BB:LBB[0-9_]+]]
+; CHECK: [[BB]]:
+; CHECK: ldr x0, [sp]
+; CHECK: str w0, [x{{.*}}]
+
+bb0:
+ br label %bb1
+bb1:
+ %tmp0 = phi i8* [ null, %bb0 ]
+ store i8* %tmp0, i8** %p
+ ret void
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-pointer-extend.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-pointer-extend.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-pointer-extend.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-pointer-extend.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,49 @@
+; RUN: llc -mtriple=arm64_32-apple-ios7.0 %s -o - | FileCheck %s
+
+define void @pass_pointer(i64 %in) {
+; CHECK-LABEL: pass_pointer:
+; CHECK: and x0, x0, #0xffffffff
+; CHECK: bl _take_pointer
+
+ %in32 = trunc i64 %in to i32
+ %ptr = inttoptr i32 %in32 to i8*
+ call i64 @take_pointer(i8* %ptr)
+ ret void
+}
+
+define i64 @take_pointer(i8* %ptr) nounwind {
+; CHECK-LABEL: take_pointer:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: ret
+
+ %val = ptrtoint i8* %ptr to i32
+ %res = zext i32 %val to i64
+ ret i64 %res
+}
+
+define i32 @callee_ptr_stack_slot([8 x i64], i8*, i32 %val) {
+; CHECK-LABEL: callee_ptr_stack_slot:
+; CHECK: ldr w0, [sp, #4]
+
+ ret i32 %val
+}
+
+define void @caller_ptr_stack_slot(i8* %ptr) {
+; CHECK-LABEL: caller_ptr_stack_slot:
+; CHECK-DAG: mov [[VAL:w[0-9]]], #42
+; CHECK: stp w0, [[VAL]], [sp]
+
+ call i32 @callee_ptr_stack_slot([8 x i64] undef, i8* %ptr, i32 42)
+ ret void
+}
+
+define i8* @return_ptr(i64 %in, i64 %r) {
+; CHECK-LABEL: return_ptr:
+; CHECK: sdiv [[VAL64:x[0-9]+]], x0, x1
+; CHECK: and x0, [[VAL64]], #0xffffffff
+
+ %sum = sdiv i64 %in, %r
+ %sum32 = trunc i64 %sum to i32
+ %res = inttoptr i32 %sum32 to i8*
+ ret i8* %res
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-stack-pointers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-stack-pointers.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-stack-pointers.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-stack-pointers.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,13 @@
+; RUN: llc -mtriple=arm64_32-apple-ios9.0 -o - %s | FileCheck %s
+
+declare void @callee([8 x i64], i8*, i8*)
+
+; Make sure we don't accidentally store X0 or XZR, which might well
+; clobber other arguments or data.
+define void @test_stack_ptr_32bits(i8* %in) {
+; CHECK-LABEL: test_stack_ptr_32bits:
+; CHECK-DAG: stp wzr, w0, [sp]
+
+ call void @callee([8 x i64] undef, i8* null, i8* %in)
+ ret void
+}
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-tls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-tls.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-tls.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-tls.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,22 @@
+; RUN: llc -mtriple=arm64_32-apple-ios %s -o - | FileCheck %s
+
+define i32 @test_thread_local() {
+; CHECK-LABEL: test_thread_local:
+; CHECK: adrp x[[TMP:[0-9]+]], _var at TLVPPAGE
+; CHECK: ldr w0, [x[[TMP]], _var at TLVPPAGEOFF]
+; CHECK: ldr w[[DEST:[0-9]+]], [x0]
+; CHECK: blr x[[DEST]]
+
+ %val = load i32, i32* @var
+ ret i32 %val
+}
+
+ at var = thread_local global i32 zeroinitializer
+
+; CHECK: .tbss _var$tlv$init, 4, 2
+
+; CHECK-LABEL: __DATA,__thread_vars
+; CHECK: _var:
+; CHECK: .long __tlv_bootstrap
+; CHECK: .long 0
+; CHECK: .long _var$tlv$init
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32-va.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32-va.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32-va.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32-va.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,56 @@
+; RUN: llc -mtriple=arm64_32-apple-ios %s -o - | FileCheck %s
+
+define void @test_va_copy(i8* %dst, i8* %src) {
+; CHECK-LABEL: test_va_copy:
+; CHECK: ldr [[PTR:w[0-9]+]], [x1]
+; CHECK: str [[PTR]], [x0]
+
+ call void @llvm.va_copy(i8* %dst, i8* %src)
+ ret void
+}
+
+define void @test_va_start(i32, ...) {
+; CHECK-LABEL: test_va_start
+; CHECK: add x[[LIST:[0-9]+]], sp, #16
+; CHECK: str w[[LIST]],
+ %slot = alloca i8*, align 4
+ %list = bitcast i8** %slot to i8*
+ call void @llvm.va_start(i8* %list)
+ ret void
+}
+
+define void @test_va_start_odd([8 x i64], i32, ...) {
+; CHECK-LABEL: test_va_start_odd:
+; CHECK: add x[[LIST:[0-9]+]], sp, #20
+; CHECK: str w[[LIST]],
+ %slot = alloca i8*, align 4
+ %list = bitcast i8** %slot to i8*
+ call void @llvm.va_start(i8* %list)
+ ret void
+}
+
+define i8* @test_va_arg(i8** %list) {
+; CHECK-LABEL: test_va_arg:
+; CHECK: ldr w[[LOC:[0-9]+]], [x0]
+; CHECK: add [[NEXTLOC:w[0-9]+]], w[[LOC]], #4
+; CHECK: str [[NEXTLOC]], [x0]
+; CHECK: ldr w0, [x[[LOC]]]
+ %res = va_arg i8** %list, i8*
+ ret i8* %res
+}
+
+define i8* @really_test_va_arg(i8** %list, i1 %tst) {
+; CHECK-LABEL: really_test_va_arg:
+; CHECK: ldr w[[LOC:[0-9]+]], [x0]
+; CHECK: add [[NEXTLOC:w[0-9]+]], w[[LOC]], #4
+; CHECK: str [[NEXTLOC]], [x0]
+; CHECK: ldr w[[VAARG:[0-9]+]], [x[[LOC]]]
+; CHECK: csel x0, x[[VAARG]], xzr
+ %tmp = va_arg i8** %list, i8*
+ %res = select i1 %tst, i8* %tmp, i8* null
+ ret i8* %res
+}
+
+declare void @llvm.va_start(i8*)
+
+declare void @llvm.va_copy(i8*, i8*)
Added: llvm/trunk/test/CodeGen/AArch64/arm64_32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64_32.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64_32.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/arm64_32.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,715 @@
+; RUN: llc -mtriple=arm64_32-apple-ios7.0 %s -filetype=obj -o - -disable-post-ra -frame-pointer=all | \
+; RUN: llvm-objdump -private-headers - | \
+; RUN: FileCheck %s --check-prefix=CHECK-MACHO
+; RUN: llc -mtriple=arm64_32-apple-ios7.0 %s -o - -aarch64-enable-atomic-cfg-tidy=0 -disable-post-ra -frame-pointer=all | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT
+; RUN: llc -mtriple=arm64_32-apple-ios7.0 %s -o - -fast-isel -aarch64-enable-atomic-cfg-tidy=0 -disable-post-ra -frame-pointer=all | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-FAST
+
+; CHECK-MACHO: Mach header
+; CHECK-MACHO: MH_MAGIC ARM64_32 V8
+
+ at var64 = global i64 zeroinitializer, align 8
+ at var32 = global i32 zeroinitializer, align 4
+
+ at var_got = external global i8
+
+define i32* @test_global_addr() {
+; CHECK-LABEL: test_global_addr:
+; CHECK: adrp [[PAGE:x[0-9]+]], _var32 at PAGE
+; CHECK: add x0, [[PAGE]], _var32 at PAGEOFF
+ ret i32* @var32
+}
+
+; ADRP is necessarily 64-bit. The important point to check is that, however that
+; gets truncated to 32-bits, it's free. No need to zero out higher bits of that
+; register.
+define i64 @test_global_addr_extension() {
+; CHECK-LABEL: test_global_addr_extension:
+; CHECK: adrp [[PAGE:x[0-9]+]], _var32 at PAGE
+; CHECK: add x0, [[PAGE]], _var32 at PAGEOFF
+; CHECK-NOT: and
+; CHECK: ret
+
+ ret i64 ptrtoint(i32* @var32 to i64)
+}
+
+define i32 @test_global_value() {
+; CHECK-LABEL: test_global_value:
+; CHECK: adrp x[[PAGE:[0-9]+]], _var32 at PAGE
+; CHECK: ldr w0, [x[[PAGE]], _var32 at PAGEOFF]
+ %val = load i32, i32* @var32, align 4
+ ret i32 %val
+}
+
+; Because the addition may wrap, it is not safe to use "ldr w0, [xN, #32]" here.
+define i32 @test_unsafe_indexed_add() {
+; CHECK-LABEL: test_unsafe_indexed_add:
+; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32 at PAGEOFF
+; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #32
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = ptrtoint i32* @var32 to i32
+ %addr_plus_32 = add i32 %addr_int, 32
+ %addr = inttoptr i32 %addr_plus_32 to i32*
+ %val = load i32, i32* %addr, align 4
+ ret i32 %val
+}
+
+; Since we've promised there is no unsigned overflow, @var32 must be at least
+; 32-bytes below 2^32, and we can use the load this time.
+define i32 @test_safe_indexed_add() {
+; CHECK-LABEL: test_safe_indexed_add:
+; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32 at PAGEOFF
+; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #32
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = ptrtoint i32* @var32 to i64
+ %addr_plus_32 = add nuw i64 %addr_int, 32
+ %addr = inttoptr i64 %addr_plus_32 to i32*
+ %val = load i32, i32* %addr, align 4
+ ret i32 %val
+}
+
+define i32 @test_safe_indexed_or(i32 %in) {
+; CHECK-LABEL: test_safe_indexed_or:
+; CHECK: and [[TMP:w[0-9]+]], {{w[0-9]+}}, #0xfffffff0
+; CHECK: orr w[[ADDR:[0-9]+]], [[TMP]], #0x4
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = and i32 %in, -16
+ %addr_plus_4 = or i32 %addr_int, 4
+ %addr = inttoptr i32 %addr_plus_4 to i32*
+ %val = load i32, i32* %addr, align 4
+ ret i32 %val
+}
+
+
+; Promising nsw is not sufficient because the addressing mode basically
+; calculates "zext(base) + zext(offset)" and nsw only guarantees
+; "sext(base) + sext(offset) == base + offset".
+define i32 @test_unsafe_nsw_indexed_add() {
+; CHECK-LABEL: test_unsafe_nsw_indexed_add:
+; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32 at PAGEOFF
+; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #32
+; CHECK-NOT: ubfx
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = ptrtoint i32* @var32 to i32
+ %addr_plus_32 = add nsw i32 %addr_int, 32
+ %addr = inttoptr i32 %addr_plus_32 to i32*
+ %val = load i32, i32* %addr, align 4
+ ret i32 %val
+}
+
+; Because the addition may wrap, it is not safe to use "ldr w0, [xN, #32]" here.
+define i32 @test_unsafe_unscaled_add() {
+; CHECK-LABEL: test_unsafe_unscaled_add:
+; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32 at PAGEOFF
+; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = ptrtoint i32* @var32 to i32
+ %addr_plus_3 = add i32 %addr_int, 3
+ %addr = inttoptr i32 %addr_plus_3 to i32*
+ %val = load i32, i32* %addr, align 1
+ ret i32 %val
+}
+
+; Since we've promised there is no unsigned overflow, @var32 must be at least
+; 32-bytes below 2^32, and we can use the load this time.
+define i32 @test_safe_unscaled_add() {
+; CHECK-LABEL: test_safe_unscaled_add:
+; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32 at PAGEOFF
+; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = ptrtoint i32* @var32 to i32
+ %addr_plus_3 = add nuw i32 %addr_int, 3
+ %addr = inttoptr i32 %addr_plus_3 to i32*
+ %val = load i32, i32* %addr, align 1
+ ret i32 %val
+}
+
+; Promising nsw is not sufficient because the addressing mode basically
+; calculates "zext(base) + zext(offset)" and nsw only guarantees
+; "sext(base) + sext(offset) == base + offset".
+define i32 @test_unsafe_nsw_unscaled_add() {
+; CHECK-LABEL: test_unsafe_nsw_unscaled_add:
+; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32 at PAGEOFF
+; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3
+; CHECK-NOT: ubfx
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = ptrtoint i32* @var32 to i32
+ %addr_plus_3 = add nsw i32 %addr_int, 3
+ %addr = inttoptr i32 %addr_plus_3 to i32*
+ %val = load i32, i32* %addr, align 1
+ ret i32 %val
+}
+
+; Because the addition may wrap, it is not safe to use "ldur w0, [xN, #-3]"
+; here.
+define i32 @test_unsafe_negative_unscaled_add() {
+; CHECK-LABEL: test_unsafe_negative_unscaled_add:
+; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32 at PAGEOFF
+; CHECK: sub w[[ADDR:[0-9]+]], w[[VAR32]], #3
+; CHECK: ldr w0, [x[[ADDR]]]
+ %addr_int = ptrtoint i32* @var32 to i32
+ %addr_minus_3 = add i32 %addr_int, -3
+ %addr = inttoptr i32 %addr_minus_3 to i32*
+ %val = load i32, i32* %addr, align 1
+ ret i32 %val
+}
+
+define i8* @test_got_addr() {
+; CHECK-LABEL: test_got_addr:
+; CHECK: adrp x[[PAGE:[0-9]+]], _var_got at GOTPAGE
+; CHECK: ldr w0, [x[[PAGE]], _var_got at GOTPAGEOFF]
+ ret i8* @var_got
+}
+
+define float @test_va_arg_f32(i8** %list) {
+; CHECK-LABEL: test_va_arg_f32:
+
+; CHECK: ldr w[[START:[0-9]+]], [x0]
+; CHECK: add [[AFTER:w[0-9]+]], w[[START]], #8
+; CHECK: str [[AFTER]], [x0]
+
+ ; Floating point arguments get promoted to double as per C99.
+; CHECK: ldr [[DBL:d[0-9]+]], [x[[START]]]
+; CHECK: fcvt s0, [[DBL]]
+ %res = va_arg i8** %list, float
+ ret float %res
+}
+
+; Interesting point is that the slot is 4 bytes.
+define i8 @test_va_arg_i8(i8** %list) {
+; CHECK-LABEL: test_va_arg_i8:
+
+; CHECK: ldr w[[START:[0-9]+]], [x0]
+; CHECK: add [[AFTER:w[0-9]+]], w[[START]], #4
+; CHECK: str [[AFTER]], [x0]
+
+ ; i8 gets promoted to int (again, as per C99).
+; CHECK: ldr w0, [x[[START]]]
+
+ %res = va_arg i8** %list, i8
+ ret i8 %res
+}
+
+; Interesting point is that the slot needs aligning (again, min size is 4
+; bytes).
+define i64 @test_va_arg_i64(i64** %list) {
+; CHECK-LABEL: test_va_arg_i64:
+
+ ; Update the list for the next user (minimum slot size is 4, but the actual
+ ; argument is 8 which had better be reflected!)
+; CHECK: ldr w[[UNALIGNED_START:[0-9]+]], [x0]
+; CHECK: add [[ALIGN_TMP:x[0-9]+]], x[[UNALIGNED_START]], #7
+; CHECK: and x[[START:[0-9]+]], [[ALIGN_TMP]], #0x1fffffff8
+; CHECK: add w[[AFTER:[0-9]+]], w[[START]], #8
+; CHECK: str w[[AFTER]], [x0]
+
+; CHECK: ldr x0, [x[[START]]]
+
+ %res = va_arg i64** %list, i64
+ ret i64 %res
+}
+
+declare void @bar(...)
+define void @test_va_call(i8 %l, i8 %r, float %in, i8* %ptr) {
+; CHECK-LABEL: test_va_call:
+; CHECK: add [[SUM:w[0-9]+]], {{w[0-9]+}}, w1
+
+; CHECK-DAG: str w2, [sp, #32]
+; CHECK-DAG: str xzr, [sp, #24]
+; CHECK-DAG: str s0, [sp, #16]
+; CHECK-DAG: str xzr, [sp, #8]
+; CHECK-DAG: str [[SUM]], [sp]
+
+ ; Add them to ensure real promotion occurs.
+ %sum = add i8 %l, %r
+ call void(...) @bar(i8 %sum, i64 0, float %in, double 0.0, i8* %ptr)
+ ret void
+}
+
+declare i8* @llvm.frameaddress(i32)
+
+define i8* @test_frameaddr() {
+; CHECK-LABEL: test_frameaddr:
+; CHECK: ldr {{w0|x0}}, [x29]
+ %val = call i8* @llvm.frameaddress(i32 1)
+ ret i8* %val
+}
+
+declare i8* @llvm.returnaddress(i32)
+
+define i8* @test_toplevel_returnaddr() {
+; CHECK-LABEL: test_toplevel_returnaddr:
+; CHECK: mov x0, x30
+ %val = call i8* @llvm.returnaddress(i32 0)
+ ret i8* %val
+}
+
+define i8* @test_deep_returnaddr() {
+; CHECK-LABEL: test_deep_returnaddr:
+; CHECK: ldr x[[FRAME_REC:[0-9]+]], [x29]
+; CHECK: ldr x0, [x[[FRAME_REC]], #8]
+ %val = call i8* @llvm.returnaddress(i32 1)
+ ret i8* %val
+}
+
+define void @test_indirect_call(void()* %func) {
+; CHECK-LABEL: test_indirect_call:
+; CHECK: blr x0
+ call void() %func()
+ ret void
+}
+
+; Safe to use the unextended address here
+define void @test_indirect_safe_call(i32* %weird_funcs) {
+; CHECK-LABEL: test_indirect_safe_call:
+; CHECK: add w[[ADDR32:[0-9]+]], w0, #4
+; CHECK-OPT-NOT: ubfx
+; CHECK: blr x[[ADDR32]]
+ %addr = getelementptr i32, i32* %weird_funcs, i32 1
+ %func = bitcast i32* %addr to void()*
+ call void() %func()
+ ret void
+}
+
+declare void @simple()
+define void @test_simple_tail_call() {
+; CHECK-LABEL: test_simple_tail_call:
+; CHECK: b _simple
+ tail call void @simple()
+ ret void
+}
+
+define void @test_indirect_tail_call(void()* %func) {
+; CHECK-LABEL: test_indirect_tail_call:
+; CHECK: br x0
+ tail call void() %func()
+ ret void
+}
+
+; Safe to use the unextended address here
+define void @test_indirect_safe_tail_call(i32* %weird_funcs) {
+; CHECK-LABEL: test_indirect_safe_tail_call:
+; CHECK: add w[[ADDR32:[0-9]+]], w0, #4
+; CHECK-OPT-NOT: ubfx
+; CHECK-OPT: br x[[ADDR32]]
+ %addr = getelementptr i32, i32* %weird_funcs, i32 1
+ %func = bitcast i32* %addr to void()*
+ tail call void() %func()
+ ret void
+}
+
+; For the "armv7k" slice, Clang will be emitting some small structs as [N x
+; i32]. For ABI compatibility with arm64_32 these need to be passed in *X*
+; registers (e.g. [2 x i32] would be packed into a single register).
+
+define i32 @test_in_smallstruct_low([3 x i32] %in) {
+; CHECK-LABEL: test_in_smallstruct_low:
+; CHECK: mov x0, x1
+ %val = extractvalue [3 x i32] %in, 2
+ ret i32 %val
+}
+
+define i32 @test_in_smallstruct_high([3 x i32] %in) {
+; CHECK-LABEL: test_in_smallstruct_high:
+; CHECK: lsr x0, x0, #32
+ %val = extractvalue [3 x i32] %in, 1
+ ret i32 %val
+}
+
+; The 64-bit DarwinPCS ABI has the quirk that structs on the stack are always
+; 64-bit aligned. This must not happen for arm64_32 since othwerwise va_arg will
+; be incompatible with the armv7k ABI.
+define i32 @test_in_smallstruct_stack([8 x i64], i32, [3 x i32] %in) {
+; CHECK-LABEL: test_in_smallstruct_stack:
+; CHECK: ldr w0, [sp, #4]
+ %val = extractvalue [3 x i32] %in, 0
+ ret i32 %val
+}
+
+define [2 x i32] @test_ret_smallstruct([3 x i32] %in) {
+; CHECK-LABEL: test_ret_smallstruct:
+; CHECK: mov x0, #1
+; CHECK: movk x0, #2, lsl #32
+
+ ret [2 x i32] [i32 1, i32 2]
+}
+
+declare void @smallstruct_callee([4 x i32])
+define void @test_call_smallstruct() {
+; CHECK-LABEL: test_call_smallstruct:
+; CHECK: mov x0, #1
+; CHECK: movk x0, #2, lsl #32
+; CHECK: mov x1, #3
+; CHECK: movk x1, #4, lsl #32
+; CHECK: bl _smallstruct_callee
+
+ call void @smallstruct_callee([4 x i32] [i32 1, i32 2, i32 3, i32 4])
+ ret void
+}
+
+declare void @smallstruct_callee_stack([8 x i64], i32, [2 x i32])
+define void @test_call_smallstruct_stack() {
+; CHECK-LABEL: test_call_smallstruct_stack:
+; CHECK: mov [[VAL:x[0-9]+]], #1
+; CHECK: movk [[VAL]], #2, lsl #32
+; CHECK: stur [[VAL]], [sp, #4]
+
+ call void @smallstruct_callee_stack([8 x i64] undef, i32 undef, [2 x i32] [i32 1, i32 2])
+ ret void
+}
+
+declare [3 x i32] @returns_smallstruct()
+define i32 @test_use_smallstruct_low() {
+; CHECK-LABEL: test_use_smallstruct_low:
+; CHECK: bl _returns_smallstruct
+; CHECK: mov x0, x1
+
+ %struct = call [3 x i32] @returns_smallstruct()
+ %val = extractvalue [3 x i32] %struct, 2
+ ret i32 %val
+}
+
+define i32 @test_use_smallstruct_high() {
+; CHECK-LABEL: test_use_smallstruct_high:
+; CHECK: bl _returns_smallstruct
+; CHECK: lsr x0, x0, #32
+
+ %struct = call [3 x i32] @returns_smallstruct()
+ %val = extractvalue [3 x i32] %struct, 1
+ ret i32 %val
+}
+
+; If a small struct can't be allocated to x0-x7, the remaining registers should
+; be marked as unavailable and subsequent GPR arguments should also be on the
+; stack. Obviously the struct itself should be passed entirely on the stack.
+define i32 @test_smallstruct_padding([7 x i64], [4 x i32] %struct, i32 %in) {
+; CHECK-LABEL: test_smallstruct_padding:
+; CHECK-DAG: ldr [[IN:w[0-9]+]], [sp, #16]
+; CHECK-DAG: ldr [[LHS:w[0-9]+]], [sp]
+; CHECK: add w0, [[LHS]], [[IN]]
+ %lhs = extractvalue [4 x i32] %struct, 0
+ %sum = add i32 %lhs, %in
+ ret i32 %sum
+}
+
+declare void @take_small_smallstruct(i64, [1 x i32])
+define void @test_small_smallstruct() {
+; CHECK-LABEL: test_small_smallstruct:
+; CHECK-DAG: mov w0, #1
+; CHECK-DAG: mov w1, #2
+; CHECK: bl _take_small_smallstruct
+ call void @take_small_smallstruct(i64 1, [1 x i32] [i32 2])
+ ret void
+}
+
+define void @test_bare_frameaddr(i8** %addr) {
+; CHECK-LABEL: test_bare_frameaddr:
+; CHECK: add x[[LOCAL:[0-9]+]], sp, #{{[0-9]+}}
+; CHECK: str w[[LOCAL]],
+
+ %ptr = alloca i8
+ store i8* %ptr, i8** %addr, align 4
+ ret void
+}
+
+define void @test_sret_use([8 x i64]* sret %out) {
+; CHECK-LABEL: test_sret_use:
+; CHECK: str xzr, [x8]
+ %addr = getelementptr [8 x i64], [8 x i64]* %out, i32 0, i32 0
+ store i64 0, i64* %addr
+ ret void
+}
+
+define i64 @test_sret_call() {
+; CHECK-LABEL: test_sret_call:
+; CHECK: mov x8, sp
+; CHECK: bl _test_sret_use
+ %arr = alloca [8 x i64]
+ call void @test_sret_use([8 x i64]* sret %arr)
+
+ %addr = getelementptr [8 x i64], [8 x i64]* %arr, i32 0, i32 0
+ %val = load i64, i64* %addr
+ ret i64 %val
+}
+
+define double @test_constpool() {
+; CHECK-LABEL: test_constpool:
+; CHECK: adrp x[[PAGE:[0-9]+]], [[POOL:lCPI[0-9]+_[0-9]+]]@PAGE
+; CHECK: ldr d0, [x[[PAGE]], [[POOL]]@PAGEOFF]
+ ret double 1.0e-6
+}
+
+define i8* @test_blockaddress() {
+; CHECK-LABEL: test_blockaddress:
+; CHECK: [[BLOCK:Ltmp[0-9]+]]:
+; CHECK: adrp [[PAGE:x[0-9]+]], [[BLOCK]]@PAGE
+; CHECK: add x0, [[PAGE]], [[BLOCK]]@PAGEOFF
+ br label %dest
+dest:
+ ret i8* blockaddress(@test_blockaddress, %dest)
+}
+
+define i8* @test_indirectbr(i8* %dest) {
+; CHECK-LABEL: test_indirectbr:
+; CHECK: br x0
+ indirectbr i8* %dest, [label %true, label %false]
+
+true:
+ ret i8* blockaddress(@test_indirectbr, %true)
+false:
+ ret i8* blockaddress(@test_indirectbr, %false)
+}
+
+; ISelDAGToDAG tries to fold an offset FI load (in this case var+4) into the
+; actual load instruction. This needs to be done slightly carefully since we
+; claim the FI in the process -- it doesn't need extending.
+define float @test_frameindex_offset_load() {
+; CHECK-LABEL: test_frameindex_offset_load:
+; CHECK: ldr s0, [sp, #4]
+ %arr = alloca float, i32 4, align 8
+ %addr = getelementptr inbounds float, float* %arr, i32 1
+
+ %val = load float, float* %addr, align 4
+ ret float %val
+}
+
+define void @test_unaligned_frameindex_offset_store() {
+; CHECK-LABEL: test_unaligned_frameindex_offset_store:
+; CHECK: mov x[[TMP:[0-9]+]], sp
+; CHECK: orr w[[ADDR:[0-9]+]], w[[TMP]], #0x2
+; CHECK: mov [[VAL:w[0-9]+]], #42
+; CHECK: str [[VAL]], [x[[ADDR]]]
+ %arr = alloca [4 x i32]
+
+ %addr.int = ptrtoint [4 x i32]* %arr to i32
+ %addr.nextint = add nuw i32 %addr.int, 2
+ %addr.next = inttoptr i32 %addr.nextint to i32*
+ store i32 42, i32* %addr.next
+ ret void
+}
+
+
+define {i64, i64*} @test_pre_idx(i64* %addr) {
+; CHECK-LABEL: test_pre_idx:
+
+; CHECK: add w[[ADDR:[0-9]+]], w0, #8
+; CHECK: ldr x0, [x[[ADDR]]]
+ %addr.int = ptrtoint i64* %addr to i32
+ %addr.next.int = add nuw i32 %addr.int, 8
+ %addr.next = inttoptr i32 %addr.next.int to i64*
+ %val = load i64, i64* %addr.next
+
+ %tmp = insertvalue {i64, i64*} undef, i64 %val, 0
+ %res = insertvalue {i64, i64*} %tmp, i64* %addr.next, 1
+
+ ret {i64, i64*} %res
+}
+
+; Forming a post-indexed load is invalid here since the GEP needs to work when
+; %addr wraps round to 0.
+define {i64, i64*} @test_invalid_pre_idx(i64* %addr) {
+; CHECK-LABEL: test_invalid_pre_idx:
+; CHECK: add w1, w0, #8
+; CHECK: ldr x0, [x1]
+ %addr.next = getelementptr i64, i64* %addr, i32 1
+ %val = load i64, i64* %addr.next
+
+ %tmp = insertvalue {i64, i64*} undef, i64 %val, 0
+ %res = insertvalue {i64, i64*} %tmp, i64* %addr.next, 1
+
+ ret {i64, i64*} %res
+}
+
+declare void @callee([8 x i32]*)
+define void @test_stack_guard() ssp {
+; CHECK-LABEL: test_stack_guard:
+; CHECK: adrp x[[GUARD_GOTPAGE:[0-9]+]], ___stack_chk_guard at GOTPAGE
+; CHECK: ldr w[[GUARD_ADDR:[0-9]+]], [x[[GUARD_GOTPAGE]], ___stack_chk_guard at GOTPAGEOFF]
+; CHECK: ldr [[GUARD_VAL:w[0-9]+]], [x[[GUARD_ADDR]]]
+; CHECK: stur [[GUARD_VAL]], [x29, #[[GUARD_OFFSET:-[0-9]+]]]
+
+; CHECK: add x0, sp, #{{[0-9]+}}
+; CHECK: bl _callee
+
+; CHECK-OPT: adrp x[[GUARD_GOTPAGE:[0-9]+]], ___stack_chk_guard at GOTPAGE
+; CHECK-OPT: ldr w[[GUARD_ADDR:[0-9]+]], [x[[GUARD_GOTPAGE]], ___stack_chk_guard at GOTPAGEOFF]
+; CHECK-OPT: ldr [[GUARD_VAL:w[0-9]+]], [x[[GUARD_ADDR]]]
+; CHECK-OPT: ldur [[NEW_VAL:w[0-9]+]], [x29, #[[GUARD_OFFSET]]]
+; CHECK-OPT: cmp [[GUARD_VAL]], [[NEW_VAL]]
+; CHECK-OPT: b.ne [[FAIL:LBB[0-9]+_[0-9]+]]
+
+; CHECK-OPT: [[FAIL]]:
+; CHECK-OPT-NEXT: bl ___stack_chk_fail
+ %arr = alloca [8 x i32]
+ call void @callee([8 x i32]* %arr)
+ ret void
+}
+
+declare i32 @__gxx_personality_v0(...)
+declare void @eat_landingpad_args(i32, i8*, i32)
+ at _ZTI8Whatever = external global i8
+define void @test_landingpad_marshalling() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-LABEL: test_landingpad_marshalling:
+; CHECK-OPT: mov x2, x1
+; CHECK-OPT: mov x1, x0
+; CHECK: bl _eat_landingpad_args
+ invoke void @callee([8 x i32]* undef) to label %done unwind label %lpad
+
+lpad: ; preds = %entry
+ %exc = landingpad { i8*, i32 }
+ catch i8* @_ZTI8Whatever
+ %pointer = extractvalue { i8*, i32 } %exc, 0
+ %selector = extractvalue { i8*, i32 } %exc, 1
+ call void @eat_landingpad_args(i32 undef, i8* %pointer, i32 %selector)
+ ret void
+
+done:
+ ret void
+}
+
+define void @test_dynamic_stackalloc() {
+; CHECK-LABEL: test_dynamic_stackalloc:
+; CHECK: sub [[REG:x[0-9]+]], sp, #32
+; CHECK: mov sp, [[REG]]
+; CHECK-OPT-NOT: ubfx
+; CHECK: bl _callee
+ br label %next
+
+next:
+ %val = alloca [8 x i32]
+ call void @callee([8 x i32]* %val)
+ ret void
+}
+
+define void @test_asm_memory(i32* %base.addr) {
+; CHECK-LABEL: test_asm_memory:
+; CHECK: add w[[ADDR:[0-9]+]], w0, #4
+; CHECK: str wzr, [x[[ADDR]]
+ %addr = getelementptr i32, i32* %base.addr, i32 1
+ call void asm sideeffect "str wzr, $0", "*m"(i32* %addr)
+ ret void
+}
+
+define void @test_unsafe_asm_memory(i64 %val) {
+; CHECK-LABEL: test_unsafe_asm_memory:
+; CHECK: and x[[ADDR:[0-9]+]], x0, #0xffffffff
+; CHECK: str wzr, [x[[ADDR]]]
+ %addr_int = trunc i64 %val to i32
+ %addr = inttoptr i32 %addr_int to i32*
+ call void asm sideeffect "str wzr, $0", "*m"(i32* %addr)
+ ret void
+}
+
+define [9 x i8*] @test_demoted_return(i8* %in) {
+; CHECK-LABEL: test_demoted_return:
+; CHECK: str w0, [x8, #32]
+ %res = insertvalue [9 x i8*] undef, i8* %in, 8
+ ret [9 x i8*] %res
+}
+
+define i8* @test_inttoptr(i64 %in) {
+; CHECK-LABEL: test_inttoptr:
+; CHECK: and x0, x0, #0xffffffff
+ %res = inttoptr i64 %in to i8*
+ ret i8* %res
+}
+
+declare i32 @llvm.get.dynamic.area.offset.i32()
+define i32 @test_dynamic_area() {
+; CHECK-LABEL: test_dynamic_area:
+; CHECK: mov w0, wzr
+ %res = call i32 @llvm.get.dynamic.area.offset.i32()
+ ret i32 %res
+}
+
+define void @test_pointer_vec_store(<2 x i8*>* %addr) {
+; CHECK-LABEL: test_pointer_vec_store:
+; CHECK: str xzr, [x0]
+; CHECK-NOT: str
+; CHECK-NOT: stp
+
+ store <2 x i8*> zeroinitializer, <2 x i8*>* %addr, align 16
+ ret void
+}
+
+define <2 x i8*> @test_pointer_vec_load(<2 x i8*>* %addr) {
+; CHECK-LABEL: test_pointer_vec_load:
+; CHECK: ldr d[[TMP:[0-9]+]], [x0]
+; CHECK: ushll.2d v0, v[[TMP]], #0
+ %val = load <2 x i8*>, <2 x i8*>* %addr, align 16
+ ret <2 x i8*> %val
+}
+
+define void @test_inline_asm_mem_pointer(i32* %in) {
+; CHECK-LABEL: test_inline_asm_mem_pointer:
+; CHECK: str w0,
+ tail call void asm sideeffect "ldr x0, $0", "rm"(i32* %in)
+ ret void
+}
+
+
+define void @test_struct_hi(i32 %hi) nounwind {
+; CHECK-LABEL: test_struct_hi:
+; CHECK: mov w[[IN:[0-9]+]], w0
+; CHECK: bl _get_int
+; CHECK-NEXT: bfi x0, x[[IN]], #32, #32
+; CHECK-NEXT: bl _take_pair
+ %val.64 = call i64 @get_int()
+ %val.32 = trunc i64 %val.64 to i32
+
+ %pair.0 = insertvalue [2 x i32] undef, i32 %val.32, 0
+ %pair.1 = insertvalue [2 x i32] %pair.0, i32 %hi, 1
+ call void @take_pair([2 x i32] %pair.1)
+
+ ret void
+}
+declare void @take_pair([2 x i32])
+declare i64 @get_int()
+
+define i1 @test_icmp_ptr(i8* %in) {
+; CHECK-LABEL: test_icmp_ptr
+; CHECK: ubfx x0, x0, #31, #1
+ %res = icmp slt i8* %in, null
+ ret i1 %res
+}
+
+define void @test_multiple_icmp_ptr(i8* %l, i8* %r) {
+; CHECK-LABEL: test_multiple_icmp_ptr:
+; CHECK: tbnz w0, #31, [[FALSEBB:LBB[0-9]+_[0-9]+]]
+; CHECK: tbnz w1, #31, [[FALSEBB]]
+ %tst1 = icmp sgt i8* %l, inttoptr (i32 -1 to i8*)
+ %tst2 = icmp sgt i8* %r, inttoptr (i32 -1 to i8*)
+ %tst = and i1 %tst1, %tst2
+ br i1 %tst, label %true, label %false
+
+true:
+ call void(...) @bar()
+ ret void
+
+false:
+ ret void
+}
+
+define { [18 x i8] }* @test_gep_nonpow2({ [18 x i8] }* %a0, i32 %a1) {
+; CHECK-LABEL: test_gep_nonpow2:
+; CHECK: mov w[[SIZE:[0-9]+]], #18
+; CHECK-NEXT: smaddl x0, w1, w[[SIZE]], x0
+; CHECK-NEXT: ret
+ %tmp0 = getelementptr inbounds { [18 x i8] }, { [18 x i8] }* %a0, i32 %a1
+ ret { [18 x i8] }* %tmp0
+}
+
+define void @test_bzero(i64 %in) {
+; CHECK-LABEL: test_bzero:
+; CHECK-DAG: lsr x1, x0, #32
+; CHECK-DAG: and x0, x0, #0xffffffff
+; CHECK: bl _bzero
+
+ %ptr.i32 = trunc i64 %in to i32
+ %size.64 = lshr i64 %in, 32
+ %size = trunc i64 %size.64 to i32
+ %ptr = inttoptr i32 %ptr.i32 to i8*
+ tail call void @llvm.memset.p0i8.i32(i8* align 4 %ptr, i8 0, i32 %size, i1 false)
+ ret void
+}
+
+declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1)
Modified: llvm/trunk/test/CodeGen/AArch64/fastcc-reserved.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/fastcc-reserved.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/fastcc-reserved.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/fastcc-reserved.ll Thu Sep 12 03:22:23 2019
@@ -4,7 +4,7 @@
; call-frame is not reserved (hence disable-fp-elim), but where
; callee-pop can occur (hence tailcallopt).
-declare fastcc void @will_pop([8 x i32], i32 %val)
+declare fastcc void @will_pop([8 x i64], i32 %val)
define fastcc void @foo(i32 %in) {
; CHECK-LABEL: foo:
@@ -18,7 +18,7 @@ define fastcc void @foo(i32 %in) {
; Reserve space for call-frame:
; CHECK: str w{{[0-9]+}}, [sp, #-16]!
- call fastcc void @will_pop([8 x i32] undef, i32 42)
+ call fastcc void @will_pop([8 x i64] undef, i32 42)
; CHECK: bl will_pop
; Since @will_pop is fastcc with tailcallopt, it will put the stack
@@ -31,7 +31,7 @@ define fastcc void @foo(i32 %in) {
ret void
}
-declare void @wont_pop([8 x i32], i32 %val)
+declare void @wont_pop([8 x i64], i32 %val)
define void @foo1(i32 %in) {
; CHECK-LABEL: foo1:
@@ -44,7 +44,7 @@ define void @foo1(i32 %in) {
; Reserve space for call-frame
; CHECK: str w{{[0-9]+}}, [sp, #-16]!
- call void @wont_pop([8 x i32] undef, i32 42)
+ call void @wont_pop([8 x i64] undef, i32 42)
; CHECK: bl wont_pop
; This time we *do* need to unreserve the call-frame
Modified: llvm/trunk/test/CodeGen/AArch64/fastcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/fastcc.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/fastcc.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/fastcc.ll Thu Sep 12 03:22:23 2019
@@ -18,7 +18,7 @@ define fastcc void @func_stack0() {
; CHECK-TAIL: str w{{[0-9]+}}, [sp]
- call fastcc void @func_stack8([8 x i32] undef, i32 42)
+ call fastcc void @func_stack8([8 x i64] undef, i32 42)
; CHECK: bl func_stack8
; CHECK-NOT: sub sp, sp,
; CHECK-NOT: [sp, #{{[-0-9]+}}]!
@@ -28,7 +28,7 @@ define fastcc void @func_stack0() {
; CHECK-TAIL: stp xzr, xzr, [sp, #-16]!
- call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9)
+ call fastcc void @func_stack32([8 x i64] undef, i128 0, i128 9)
; CHECK: bl func_stack32
; CHECK-NOT: sub sp, sp,
@@ -56,7 +56,7 @@ define fastcc void @func_stack0() {
; CHECK-TAIL-NEXT: ret
}
-define fastcc void @func_stack8([8 x i32], i32 %stacked) {
+define fastcc void @func_stack8([8 x i64], i32 %stacked) {
; CHECK-LABEL: func_stack8:
; CHECK: sub sp, sp, #48
; CHECK: stp x29, x30, [sp, #32]
@@ -71,7 +71,7 @@ define fastcc void @func_stack8([8 x i32
; CHECK-TAIL: str w{{[0-9]+}}, [sp]
- call fastcc void @func_stack8([8 x i32] undef, i32 42)
+ call fastcc void @func_stack8([8 x i64] undef, i32 42)
; CHECK: bl func_stack8
; CHECK-NOT: sub sp, sp,
; CHECK-NOT: [sp, #{{[-0-9]+}}]!
@@ -82,7 +82,7 @@ define fastcc void @func_stack8([8 x i32
; CHECK-TAIL: stp xzr, xzr, [sp, #-16]!
- call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9)
+ call fastcc void @func_stack32([8 x i64] undef, i128 0, i128 9)
; CHECK: bl func_stack32
; CHECK-NOT: sub sp, sp,
@@ -109,7 +109,7 @@ define fastcc void @func_stack8([8 x i32
; CHECK-TAIL-NEXT: ret
}
-define fastcc void @func_stack32([8 x i32], i128 %stacked0, i128 %stacked1) {
+define fastcc void @func_stack32([8 x i64], i128 %stacked0, i128 %stacked1) {
; CHECK-LABEL: func_stack32:
; CHECK: add x29, sp, #32
@@ -117,7 +117,7 @@ define fastcc void @func_stack32([8 x i3
; CHECK-TAIL: add x29, sp, #32
- call fastcc void @func_stack8([8 x i32] undef, i32 42)
+ call fastcc void @func_stack8([8 x i64] undef, i32 42)
; CHECK: bl func_stack8
; CHECK-NOT: sub sp, sp,
; CHECK-NOT: [sp, #{{[-0-9]+}}]!
@@ -127,7 +127,7 @@ define fastcc void @func_stack32([8 x i3
; CHECK-TAIL: stp xzr, xzr, [sp, #-16]!
- call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9)
+ call fastcc void @func_stack32([8 x i64] undef, i128 0, i128 9)
; CHECK: bl func_stack32
; CHECK-NOT: sub sp, sp,
@@ -155,7 +155,7 @@ define fastcc void @func_stack32([8 x i3
}
; Check that arg stack pop is done after callee-save restore when no frame pointer is used.
-define fastcc void @func_stack32_leaf([8 x i32], i128 %stacked0, i128 %stacked1) {
+define fastcc void @func_stack32_leaf([8 x i64], i128 %stacked0, i128 %stacked1) {
; CHECK-LABEL: func_stack32_leaf:
; CHECK: str x20, [sp, #-16]!
; CHECK: nop
@@ -186,7 +186,7 @@ define fastcc void @func_stack32_leaf([8
}
; Check that arg stack pop is done after callee-save restore when no frame pointer is used.
-define fastcc void @func_stack32_leaf_local([8 x i32], i128 %stacked0, i128 %stacked1) {
+define fastcc void @func_stack32_leaf_local([8 x i64], i128 %stacked0, i128 %stacked1) {
; CHECK-LABEL: func_stack32_leaf_local:
; CHECK: sub sp, sp, #32
; CHECK-NEXT: str x20, [sp, #16]
@@ -222,7 +222,7 @@ define fastcc void @func_stack32_leaf_lo
}
; Check that arg stack pop is done after callee-save restore when no frame pointer is used.
-define fastcc void @func_stack32_leaf_local_nocs([8 x i32], i128 %stacked0, i128 %stacked1) {
+define fastcc void @func_stack32_leaf_local_nocs([8 x i64], i128 %stacked0, i128 %stacked1) {
; CHECK-LABEL: func_stack32_leaf_local_nocs:
; CHECK: sub sp, sp, #16
; CHECK: add sp, sp, #16
Added: llvm/trunk/test/CodeGen/AArch64/jump-table-32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/jump-table-32.ll?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/jump-table-32.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/jump-table-32.ll Thu Sep 12 03:22:23 2019
@@ -0,0 +1,42 @@
+; RUN: llc -verify-machineinstrs -o - %s -mtriple=arm64_32-apple-ios7.0 -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
+
+define i32 @test_jumptable(i32 %in) {
+; CHECK: test_jumptable
+
+ switch i32 %in, label %def [
+ i32 0, label %lbl1
+ i32 1, label %lbl2
+ i32 2, label %lbl3
+ i32 4, label %lbl4
+ ]
+; CHECK: adrp [[JTPAGE:x[0-9]+]], LJTI0_0 at PAGE
+; CHECK: mov w[[INDEX:[0-9]+]], w0
+; CHECK: add x[[JT:[0-9]+]], [[JTPAGE]], LJTI0_0 at PAGEOFF
+; CHECK: adr [[BASE_BLOCK:x[0-9]+]], LBB0_2
+; CHECK: ldrb w[[OFFSET:[0-9]+]], [x[[JT]], x[[INDEX]]]
+; CHECK: add [[DEST:x[0-9]+]], [[BASE_BLOCK]], x[[OFFSET]], lsl #2
+; CHECK: br [[DEST]]
+
+def:
+ ret i32 0
+
+lbl1:
+ ret i32 1
+
+lbl2:
+ ret i32 2
+
+lbl3:
+ ret i32 4
+
+lbl4:
+ ret i32 8
+
+}
+
+; CHECK: LJTI0_0:
+; CHECK-NEXT: .byte
+; CHECK-NEXT: .byte
+; CHECK-NEXT: .byte
+; CHECK-NEXT: .byte
+; CHECK-NEXT: .byte
Modified: llvm/trunk/test/CodeGen/AArch64/sibling-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/sibling-call.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/sibling-call.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/sibling-call.ll Thu Sep 12 03:22:23 2019
@@ -1,8 +1,8 @@
; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-ldst-opt=0 | FileCheck %s
declare void @callee_stack0()
-declare void @callee_stack8([8 x i32], i64)
-declare void @callee_stack16([8 x i32], i64, i64)
+declare void @callee_stack8([8 x i64], i64)
+declare void @callee_stack16([8 x i64], i64, i64)
define void @caller_to0_from0() nounwind {
; CHECK-LABEL: caller_to0_from0:
@@ -12,7 +12,7 @@ define void @caller_to0_from0() nounwind
; CHECK-NEXT: b callee_stack0
}
-define void @caller_to0_from8([8 x i32], i64) nounwind{
+define void @caller_to0_from8([8 x i64], i64) nounwind{
; CHECK-LABEL: caller_to0_from8:
; CHECK-NEXT: // %bb.
@@ -26,51 +26,51 @@ define void @caller_to8_from0() {
; Caller isn't going to clean up any extra stack we allocate, so it
; can't be a tail call.
- tail call void @callee_stack8([8 x i32] undef, i64 42)
+ tail call void @callee_stack8([8 x i64] undef, i64 42)
ret void
; CHECK: bl callee_stack8
}
-define void @caller_to8_from8([8 x i32], i64 %a) {
+define void @caller_to8_from8([8 x i64], i64 %a) {
; CHECK-LABEL: caller_to8_from8:
; CHECK-NOT: sub sp, sp,
; This should reuse our stack area for the 42
- tail call void @callee_stack8([8 x i32] undef, i64 42)
+ tail call void @callee_stack8([8 x i64] undef, i64 42)
ret void
; CHECK: str {{x[0-9]+}}, [sp]
; CHECK-NEXT: b callee_stack8
}
-define void @caller_to16_from8([8 x i32], i64 %a) {
+define void @caller_to16_from8([8 x i64], i64 %a) {
; CHECK-LABEL: caller_to16_from8:
; Shouldn't be a tail call: we can't use SP+8 because our caller might
; have something there. This may sound obvious but implementation does
; some funky aligning.
- tail call void @callee_stack16([8 x i32] undef, i64 undef, i64 undef)
+ tail call void @callee_stack16([8 x i64] undef, i64 undef, i64 undef)
; CHECK: bl callee_stack16
ret void
}
-define void @caller_to8_from24([8 x i32], i64 %a, i64 %b, i64 %c) {
+define void @caller_to8_from24([8 x i64], i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: caller_to8_from24:
; CHECK-NOT: sub sp, sp
; Reuse our area, putting "42" at incoming sp
- tail call void @callee_stack8([8 x i32] undef, i64 42)
+ tail call void @callee_stack8([8 x i64] undef, i64 42)
ret void
; CHECK: str {{x[0-9]+}}, [sp]
; CHECK-NEXT: b callee_stack8
}
-define void @caller_to16_from16([8 x i32], i64 %a, i64 %b) {
+define void @caller_to16_from16([8 x i64], i64 %a, i64 %b) {
; CHECK-LABEL: caller_to16_from16:
; CHECK-NOT: sub sp, sp,
; Here we want to make sure that both loads happen before the stores:
; otherwise either %a or %b will be wrongly clobbered.
- tail call void @callee_stack16([8 x i32] undef, i64 %b, i64 %a)
+ tail call void @callee_stack16([8 x i64] undef, i64 %b, i64 %a)
ret void
; CHECK: ldr [[VAL0:x[0-9]+]],
Modified: llvm/trunk/test/CodeGen/AArch64/swift-return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/swift-return.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/swift-return.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/swift-return.ll Thu Sep 12 03:22:23 2019
@@ -1,5 +1,7 @@
; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s
; RUN: llc -O0 -fast-isel -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s --check-prefix=CHECK-O0
+; RUN: llc -verify-machineinstrs -mtriple=arm64_32-apple-ios -o - %s | FileCheck %s
+; RUN: llc -O0 -fast-isel -verify-machineinstrs -mtriple=arm64_32-apple-ios -o - %s | FileCheck %s --check-prefix=CHECK-O0
; CHECK-LABEL: test1
; CHECK: bl _gen
@@ -8,7 +10,7 @@
; CHECK-O0-LABEL: test1
; CHECK-O0: bl _gen
; CHECK-O0: sxth [[TMP:w.*]], w0
-; CHECK-O0: add w8, [[TMP]], w1, sxtb
+; CHECK-O0: add {{w[0-9]+}}, [[TMP]], w1, sxtb
define i16 @test1(i32) {
entry:
%call = call swiftcc { i16, i8 } @gen(i32 %0)
Modified: llvm/trunk/test/CodeGen/AArch64/swiftcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/swiftcc.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/swiftcc.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/swiftcc.ll Thu Sep 12 03:22:23 2019
@@ -1,5 +1,7 @@
; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s
; RUN: llc -O0 -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=arm64_32-apple-ios -o - %s | FileCheck %s
+; RUN: llc -O0 -verify-machineinstrs -mtriple=arm64_32-apple-ios -o - %s | FileCheck %s
; CHECK: t1
; CHECK: fadd s0, s0, s1
Modified: llvm/trunk/test/CodeGen/AArch64/swifterror.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/swifterror.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/swifterror.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/swifterror.ll Thu Sep 12 03:22:23 2019
@@ -1,5 +1,7 @@
-; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -enable-shrink-wrap=false < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-APPLE %s
-; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -O0 -fast-isel < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-O0 %s
+; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -enable-shrink-wrap=false < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-APPLE --check-prefix=CHECK-APPLE-AARCH64 %s
+; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -O0 -fast-isel < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-O0 --check-prefix=CHECK-O0-AARCH64 %s
+; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -enable-shrink-wrap=false < %s -mtriple=arm64_32-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-APPLE --check-prefix=CHECK-APPLE-ARM64_32 %s
+; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -O0 -fast-isel < %s -mtriple=arm64_32-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-O0 --check-prefix=CHECK-O0-ARM64_32 %s
declare i8* @malloc(i64)
declare void @free(i8*)
@@ -40,7 +42,8 @@ define float @caller(i8* %error_ref) {
; CHECK-APPLE: mov x21, xzr
; CHECK-APPLE: bl {{.*}}foo
; CHECK-APPLE: mov x0, x21
-; CHECK-APPLE: cbnz x21
+; CHECK-APPLE-AARCH64: cbnz x21
+; CHECK-APPLE-ARM64_32: cbnz w0
; Access part of the error object and save it to error_ref
; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x0, #8]
; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
@@ -50,7 +53,8 @@ define float @caller(i8* %error_ref) {
; CHECK-O0: mov x21
; CHECK-O0: bl {{.*}}foo
; CHECK-O0: mov [[ID:x[0-9]+]], x21
-; CHECK-O0: cbnz x21
+; CHECK-O0-AARCH64: cbnz x21
+; CHECK-O0-ARM64_32: cmp x21, #0
entry:
%error_ptr_ref = alloca swifterror %swift_error*
store %swift_error* null, %swift_error** %error_ptr_ref
@@ -76,7 +80,8 @@ define float @caller2(i8* %error_ref) {
; CHECK-APPLE: fmov [[CMP:s[0-9]+]], #1.0
; CHECK-APPLE: mov x21, xzr
; CHECK-APPLE: bl {{.*}}foo
-; CHECK-APPLE: cbnz x21
+; CHECK-APPLE-AARCH64: cbnz x21
+; CHECK-APPLE-ARM64_32: cbnz w21
; CHECK-APPLE: fcmp s0, [[CMP]]
; CHECK-APPLE: b.le
; Access part of the error object and save it to error_ref
@@ -89,7 +94,8 @@ define float @caller2(i8* %error_ref) {
; CHECK-O0: mov x21
; CHECK-O0: bl {{.*}}foo
; CHECK-O0: mov [[ID:x[0-9]+]], x21
-; CHECK-O0: cbnz x21
+; CHECK-O0-AARCH64: cbnz x21
+; CHECK-O0-ARM64_32: cmp x21, #0
entry:
%error_ptr_ref = alloca swifterror %swift_error*
br label %bb_loop
@@ -171,29 +177,52 @@ define float @foo_loop(%swift_error** sw
; CHECK-APPLE: mov x21, x0
; CHECK-APPLE: ret
-; CHECK-O0-LABEL: foo_loop:
+; CHECK-O0-AARCH64-LABEL: foo_loop:
; spill x21
-; CHECK-O0: str x21, [sp, [[SLOT:#[0-9]+]]]
-; CHECK-O0: b [[BB1:[A-Za-z0-9_]*]]
-; CHECK-O0: [[BB1]]:
-; CHECK-O0: ldr x0, [sp, [[SLOT]]]
-; CHECK-O0: str x0, [sp, [[SLOT2:#[0-9]+]]]
-; CHECK-O0: cbz {{.*}}, [[BB2:[A-Za-z0-9_]*]]
-; CHECK-O0: mov w{{.*}}, #16
-; CHECK-O0: malloc
-; CHECK-O0: mov [[ID:x[0-9]+]], x0
-; CHECK-O0: strb w{{.*}}, [{{.*}}[[ID]], #8]
+; CHECK-O0-AARCH64: str x21, [sp, [[SLOT:#[0-9]+]]]
+; CHECK-O0-AARCH64: b [[BB1:[A-Za-z0-9_]*]]
+; CHECK-O0-AARCH64: [[BB1]]:
+; CHECK-O0-AARCH64: ldr x0, [sp, [[SLOT]]]
+; CHECK-O0-AARCH64: str x0, [sp, [[SLOT2:#[0-9]+]]]
+; CHECK-O0-AARCH64: cbz {{.*}}, [[BB2:[A-Za-z0-9_]*]]
+; CHECK-O0-AARCH64: mov w{{.*}}, #16
+; CHECK-O0-AARCH64: malloc
+; CHECK-O0-AARCH64: mov [[ID:x[0-9]+]], x0
+; CHECK-O0-AARCH64: strb w{{.*}}, [{{.*}}[[ID]], #8]
; spill x0
-; CHECK-O0: str x0, [sp, [[SLOT2]]]
-; CHECK-O0:[[BB2]]:
-; CHECK-O0: ldr x0, [sp, [[SLOT2]]]
-; CHECK-O0: fcmp
-; CHECK-O0: str x0, [sp]
-; CHECK-O0: b.le [[BB1]]
+; CHECK-O0-AARCH64: str x0, [sp, [[SLOT2]]]
+; CHECK-O0-AARCH64:[[BB2]]:
+; CHECK-O0-AARCH64: ldr x0, [sp, [[SLOT2]]]
+; CHECK-O0-AARCH64: fcmp
+; CHECK-O0-AARCH64: str x0, [sp]
+; CHECK-O0-AARCH64: b.le [[BB1]]
; reload from stack
-; CHECK-O0: ldr [[ID3:x[0-9]+]], [sp]
-; CHECK-O0: mov x21, [[ID3]]
-; CHECK-O0: ret
+; CHECK-O0-AARCH64: ldr [[ID3:x[0-9]+]], [sp]
+; CHECK-O0-AARCH64: mov x21, [[ID3]]
+; CHECK-O0-AARCH64: ret
+
+; CHECK-O0-ARM64_32-LABEL: foo_loop:
+; spill x21
+; CHECK-O0-ARM64_32: str x21, [sp, [[SLOT:#[0-9]+]]]
+; CHECK-O0-ARM64_32: b [[BB1:[A-Za-z0-9_]*]]
+; CHECK-O0-ARM64_32: [[BB1]]:
+; CHECK-O0-ARM64_32: ldr x0, [sp, [[SLOT]]]
+; CHECK-O0-ARM64_32: str x0, [sp, [[SLOT2:#[0-9]+]]]
+; CHECK-O0-ARM64_32: cbz {{.*}}, [[BB2:[A-Za-z0-9_]*]]
+; CHECK-O0-ARM64_32: mov w{{.*}}, #16
+; CHECK-O0-ARM64_32: malloc
+; CHECK-O0-ARM64_32: mov {{.*}}, x0
+; CHECK-O0-ARM64_32: strb w{{.*}},
+; CHECK-O0-ARM64_32:[[BB2]]:
+; CHECK-O0-ARM64_32: ldr x0, [sp, [[SLOT2]]]
+; CHECK-O0-ARM64_32: fcmp
+; CHECK-O0-ARM64_32: str x0, [sp[[OFFSET:.*]]]
+; CHECK-O0-ARM64_32: b.le [[BB1]]
+; reload from stack
+; CHECK-O0-ARM64_32: ldr [[ID3:x[0-9]+]], [sp[[OFFSET]]]
+; CHECK-O0-ARM64_32: mov x21, [[ID3]]
+; CHECK-O0-ARM64_32: ret
+
entry:
br label %bb_loop
@@ -261,7 +290,8 @@ define float @caller3(i8* %error_ref) {
; CHECK-APPLE: mov x21, xzr
; CHECK-APPLE: bl {{.*}}foo_sret
; CHECK-APPLE: mov x0, x21
-; CHECK-APPLE: cbnz x21
+; CHECK-APPLE-AARCH64: cbnz x21
+; CHECK-APPLE-ARM64_32: cbnz w0
; Access part of the error object and save it to error_ref
; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x0, #8]
; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
@@ -273,7 +303,8 @@ define float @caller3(i8* %error_ref) {
; CHECK-O0: mov x21
; CHECK-O0: bl {{.*}}foo_sret
; CHECK-O0: mov [[ID2:x[0-9]+]], x21
-; CHECK-O0: cbnz x21
+; CHECK-O0-AARCH64: cbnz x21
+; CHECK-O0-ARM64_32: cmp x21, #0
; Access part of the error object and save it to error_ref
; reload from stack
; CHECK-O0: ldrb [[CODE:w[0-9]+]]
@@ -306,20 +337,22 @@ define float @foo_vararg(%swift_error**
; CHECK-APPLE-LABEL: foo_vararg:
; CHECK-APPLE: mov w0, #16
; CHECK-APPLE: malloc
-; CHECK-APPLE-DAG: mov [[ID:w[0-9]+]], #1
-; CHECK-APPLE-DAG: add [[ARGS:x[0-9]+]], [[TMP:x[0-9]+]], #16
-; CHECK-APPLE-DAG: strb [[ID]], [x0, #8]
; First vararg
-; CHECK-APPLE-DAG: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #16]
+; CHECK-APPLE-AARCH64: ldr {{w[0-9]+}}, [{{.*}}[[TMP:x[0-9]+]], #16]
+; CHECK-APPLE-AARCH64: mov [[ID:w[0-9]+]], #1
+; CHECK-APPLE-AARCH64: add [[ARGS:x[0-9]+]], [[TMP]], #16
+; CHECK-APPLE-AARCH64: strb [[ID]], [x0, #8]
; Second vararg
-; CHECK-APPLE-DAG: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #24]
-; CHECK-APPLE-DAG: add {{x[0-9]+}}, {{x[0-9]+}}, #16
+; CHECK-APPLE-AARCH64: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #24]
; Third vararg
-; CHECK-APPLE-DAG: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #32]
+; CHECK-APPLE-AARCH64: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #32]
+
+; CHECK-APPLE-ARM64_32: mov [[ID:w[0-9]+]], #1
+; CHECK-APPLE-ARM64_32: add [[ARGS:x[0-9]+]], [[TMP:x[0-9]+]], #16
+; CHECK-APPLE-ARM64_32: strb [[ID]], [x0, #8]
+
-; CHECK-APPLE: mov x21, x0
-; CHECK-APPLE-NOT: x21
entry:
%call = call i8* @malloc(i64 16)
%call.0 = bitcast i8* %call to %swift_error*
@@ -347,18 +380,18 @@ entry:
define float @caller4(i8* %error_ref) {
; CHECK-APPLE-LABEL: caller4:
-; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
-; CHECK-APPLE: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #8]
-; CHECK-APPLE: str {{x[0-9]+}}, [sp]
-
-; CHECK-APPLE: mov x21, xzr
-; CHECK-APPLE: bl {{.*}}foo_vararg
-; CHECK-APPLE: mov x0, x21
-; CHECK-APPLE: cbnz x21
+; CHECK-APPLE-AARCH64: mov [[ID:x[0-9]+]], x0
+; CHECK-APPLE-AARCH64: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #8]
+; CHECK-APPLE-AARCH64: str {{x[0-9]+}}, [sp]
+
+; CHECK-APPLE-AARCH64: mov x21, xzr
+; CHECK-APPLE-AARCH64: bl {{.*}}foo_vararg
+; CHECK-APPLE-AARCH64: mov x0, x21
+; CHECK-APPLE-AARCH64: cbnz x21
; Access part of the error object and save it to error_ref
-; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x0, #8]
-; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
-; CHECK-APPLE: bl {{.*}}free
+; CHECK-APPLE-AARCH64: ldrb [[CODE:w[0-9]+]], [x0, #8]
+; CHECK-APPLE-AARCH64: strb [[CODE]], [{{.*}}[[ID]]]
+; CHECK-APPLE-AARCH64: bl {{.*}}free
entry:
%error_ptr_ref = alloca swifterror %swift_error*
store %swift_error* null, %swift_error** %error_ptr_ref
Modified: llvm/trunk/test/CodeGen/AArch64/swiftself.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/swiftself.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/swiftself.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/swiftself.ll Thu Sep 12 03:22:23 2019
@@ -1,6 +1,7 @@
-; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTAARCH64 %s
; RUN: llc -O0 -fast-isel -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s
-; RUN: llc -verify-machineinstrs -mtriple=aarch64-unknown-linux-gnu -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64-unknown-linux-gnu -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTAARCH64 %s
+; RUN: llc -verify-machineinstrs -mtriple=arm64_32-apple-ios -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTARM64_32 %s
; Parameter with swiftself should be allocated to x20.
; CHECK-LABEL: swiftself_param:
@@ -48,8 +49,9 @@ define void @swiftself_passthrough(i8* s
; We can use a tail call if the callee swiftself is the same as the caller one.
; This should also work with fast-isel.
; CHECK-LABEL: swiftself_tail:
-; CHECK: b {{_?}}swiftself_param
-; CHECK-NOT: ret
+; OPTAARCH64: b {{_?}}swiftself_param
+; OPTAARCH64-NOT: ret
+; OPTARM64_32: bl {{_?}}swiftself_param
define i8* @swiftself_tail(i8* swiftself %addr0) {
call void asm sideeffect "", "~{x20}"()
%res = tail call i8* @swiftself_param(i8* swiftself %addr0)
@@ -71,12 +73,19 @@ define i8* @swiftself_notail(i8* swiftse
; we normally would. We marked the first parameter with swiftself which means it
; will no longer be passed in x0.
declare swiftcc i8* @thisreturn_attribute(i8* returned swiftself)
-; OPT-LABEL: swiftself_nothisreturn:
-; OPT-DAG: ldr x20, [x20]
-; OPT-DAG: mov [[CSREG:x[1-9].*]], x8
-; OPT: bl {{_?}}thisreturn_attribute
-; OPT: str x0, {{\[}}[[CSREG]]
-; OPT: ret
+; OPTAARCH64-LABEL: swiftself_nothisreturn:
+; OPTAARCH64-DAG: ldr x20, [x20]
+; OPTAARCH64-DAG: mov [[CSREG:x[1-9].*]], x8
+; OPTAARCH64: bl {{_?}}thisreturn_attribute
+; OPTAARCH64: str x0, {{\[}}[[CSREG]]
+; OPTAARCH64: ret
+
+; OPTARM64_32-LABEL: swiftself_nothisreturn:
+; OPTARM64_32-DAG: ldr w20, [x20]
+; OPTARM64_32-DAG: mov [[CSREG:x[1-9].*]], x8
+; OPTARM64_32: bl {{_?}}thisreturn_attribute
+; OPTARM64_32: str w0, {{\[}}[[CSREG]]
+; OPTARM64_32: ret
define hidden swiftcc void @swiftself_nothisreturn(i8** noalias nocapture sret, i8** noalias nocapture readonly swiftself) {
entry:
%2 = load i8*, i8** %1, align 8
Modified: llvm/trunk/test/CodeGen/AArch64/tail-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/tail-call.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/tail-call.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/tail-call.ll Thu Sep 12 03:22:23 2019
@@ -2,8 +2,8 @@
; RUN: llc -global-isel -global-isel-abort=2 -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -tailcallopt | FileCheck %s --check-prefixes=GISEL,COMMON
declare fastcc void @callee_stack0()
-declare fastcc void @callee_stack8([8 x i32], i64)
-declare fastcc void @callee_stack16([8 x i32], i64, i64)
+declare fastcc void @callee_stack8([8 x i64], i64)
+declare fastcc void @callee_stack16([8 x i64], i64, i64)
declare extern_weak fastcc void @callee_weak()
define fastcc void @caller_to0_from0() nounwind {
@@ -16,7 +16,7 @@ define fastcc void @caller_to0_from0() n
; COMMON-NEXT: b callee_stack0
}
-define fastcc void @caller_to0_from8([8 x i32], i64) {
+define fastcc void @caller_to0_from8([8 x i64], i64) {
; COMMON-LABEL: caller_to0_from8:
tail call fastcc void @callee_stack0()
@@ -32,33 +32,33 @@ define fastcc void @caller_to8_from0() {
; Key point is that the "42" should go #16 below incoming stack
; pointer (we didn't have arg space to reuse).
- tail call fastcc void @callee_stack8([8 x i32] undef, i64 42)
+ tail call fastcc void @callee_stack8([8 x i64] undef, i64 42)
ret void
; COMMON: str {{x[0-9]+}}, [sp, #16]!
; COMMON-NEXT: b callee_stack8
}
-define fastcc void @caller_to8_from8([8 x i32], i64 %a) {
+define fastcc void @caller_to8_from8([8 x i64], i64 %a) {
; COMMON-LABEL: caller_to8_from8:
; COMMON: sub sp, sp, #16
; Key point is that the "%a" should go where at SP on entry.
- tail call fastcc void @callee_stack8([8 x i32] undef, i64 42)
+ tail call fastcc void @callee_stack8([8 x i64] undef, i64 42)
ret void
; COMMON: str {{x[0-9]+}}, [sp, #16]!
; COMMON-NEXT: b callee_stack8
}
-define fastcc void @caller_to16_from8([8 x i32], i64 %a) {
+define fastcc void @caller_to16_from8([8 x i64], i64 %a) {
; COMMON-LABEL: caller_to16_from8:
; COMMON: sub sp, sp, #16
; Important point is that the call reuses the "dead" argument space
; above %a on the stack. If it tries to go below incoming-SP then the
; callee will not deallocate the space, even in fastcc.
- tail call fastcc void @callee_stack16([8 x i32] undef, i64 42, i64 2)
+ tail call fastcc void @callee_stack16([8 x i64] undef, i64 42, i64 2)
; COMMON: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16]!
; COMMON-NEXT: b callee_stack16
@@ -66,12 +66,12 @@ define fastcc void @caller_to16_from8([8
}
-define fastcc void @caller_to8_from24([8 x i32], i64 %a, i64 %b, i64 %c) {
+define fastcc void @caller_to8_from24([8 x i64], i64 %a, i64 %b, i64 %c) {
; COMMON-LABEL: caller_to8_from24:
; COMMON: sub sp, sp, #16
; Key point is that the "%a" should go where at #16 above SP on entry.
- tail call fastcc void @callee_stack8([8 x i32] undef, i64 42)
+ tail call fastcc void @callee_stack8([8 x i64] undef, i64 42)
ret void
; COMMON: str {{x[0-9]+}}, [sp, #32]!
@@ -79,13 +79,13 @@ define fastcc void @caller_to8_from24([8
}
-define fastcc void @caller_to16_from16([8 x i32], i64 %a, i64 %b) {
+define fastcc void @caller_to16_from16([8 x i64], i64 %a, i64 %b) {
; COMMON-LABEL: caller_to16_from16:
; COMMON: sub sp, sp, #16
; Here we want to make sure that both loads happen before the stores:
; otherwise either %a or %b will be wrongly clobbered.
- tail call fastcc void @callee_stack16([8 x i32] undef, i64 %b, i64 %a)
+ tail call fastcc void @callee_stack16([8 x i64] undef, i64 %b, i64 %a)
ret void
; COMMON: ldp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16]
Modified: llvm/trunk/test/CodeGen/AArch64/umulo-128-legalisation-lowering.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/umulo-128-legalisation-lowering.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/umulo-128-legalisation-lowering.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/umulo-128-legalisation-lowering.ll Thu Sep 12 03:22:23 2019
@@ -27,8 +27,8 @@ define { i128, i8 } @muloti_test(i128 %l
; AARCH-NEXT: orr w10, w10, w11
; AARCH-NEXT: orr w9, w10, w9
; AARCH-NEXT: mul x0, x0, x2
-; AARCH-NEXT: mov x1, x8
-; AARCH-NEXT: mov w2, w9
+; AARCH-DAG: mov x1, x8
+; AARCH-DAG: mov w2, w9
; AARCH-NEXT: ret
start:
%0 = tail call { i128, i1 } @llvm.umul.with.overflow.i128(i128 %l, i128 %r) #2
Modified: llvm/trunk/test/CodeGen/AArch64/win64_vararg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/win64_vararg.ll?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/win64_vararg.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/win64_vararg.ll Thu Sep 12 03:22:23 2019
@@ -261,11 +261,11 @@ define i32 @snprintf(i8*, i64, i8*, ...)
; CHECK-DAG: mov w6, w3
; CHECK-DAG: mov [[REG1:w[0-9]+]], w2
; CHECK: mov w2, w1
-; CHECK: str w4, [sp]
; CHECK: fmov x1, d0
; CHECK: fmov x3, d1
; CHECK: fmov x5, d2
; CHECK: fmov x7, d3
+; CHECK: str w4, [sp]
; CHECK: mov w4, [[REG1]]
; CHECK: str x30, [sp, #16]
; CHECK: str d4, [sp, #8]
Added: llvm/trunk/test/MC/AArch64/arm64_32-compact-unwind.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/arm64_32-compact-unwind.s?rev=371722&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/arm64_32-compact-unwind.s (added)
+++ llvm/trunk/test/MC/AArch64/arm64_32-compact-unwind.s Thu Sep 12 03:22:23 2019
@@ -0,0 +1,15 @@
+; RUN: llvm-mc -triple=arm64_32-ios7.0 -filetype=obj %s -o %t
+; RUN: llvm-objdump -s %t | FileCheck %s
+
+; The compact unwind format in ILP32 mode is pretty much the same, except
+; references to addresses (function, personality, LSDA) are pointer-sized.
+
+; CHECK: Contents of section __compact_unwind:
+; CHECK-NEXT: 0004 00000000 04000000 00000002 00000000
+; CHECK-NEXT: 0014 00000000
+ .globl _test_compact_unwind
+ .align 2
+_test_compact_unwind:
+ .cfi_startproc
+ ret
+ .cfi_endproc
Modified: llvm/trunk/utils/TableGen/CallingConvEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CallingConvEmitter.cpp?rev=371722&r1=371721&r2=371722&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CallingConvEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/CallingConvEmitter.cpp Thu Sep 12 03:22:23 2019
@@ -264,6 +264,10 @@ void CallingConvEmitter::EmitAction(Reco
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
+ } else if (Action->isSubClassOf("CCTruncToType")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
+ O << IndentStr << "LocInfo = CCValAssign::Trunc;\n";
} else if (Action->isSubClassOf("CCPassIndirect")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
More information about the llvm-commits
mailing list