llvm.org GIT mirror llvm / 3d765ce
[AArch64] Add Tiny Code Model for AArch64 This adds the plumbing for the Tiny code model for the AArch64 backend. This, instead of loading addresses through the normal ADRP;ADD pair used in the Small model, uses a single ADR. The 21 bit range of an ADR means that the code and its statically defined symbols need to be within 1MB of each other. This makes it mostly interesting for embedded applications where we want to fit as much as we can in as small a space as possible. Differential Revision: https://reviews.llvm.org/D49673 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@340397 91177308-0d34-0410-b5e6-96231b3b80d8 David Green 1 year, 1 month ago
34 changed file(s) with 797 addition(s) and 54 deletion(s). Raw diff Collapse all Expand all
6161 const (
6262 CodeModelDefault CodeModel = C.LLVMCodeModelDefault
6363 CodeModelJITDefault CodeModel = C.LLVMCodeModelJITDefault
64 CodeModelTiny CodeModel = C.LLVMCodeModelTiny
6465 CodeModelSmall CodeModel = C.LLVMCodeModelSmall
6566 CodeModelKernel CodeModel = C.LLVMCodeModelKernel
6667 CodeModelMedium CodeModel = C.LLVMCodeModelMedium
124124 .. code-block:: text
125125
126126 default: Target default code model
127 tiny: Tiny code model
127128 small: Small code model
128129 kernel: Kernel code model
129130 medium: Medium code model
7373
7474 static cl::opt CMModel(
7575 "code-model", cl::desc("Choose code model"),
76 cl::values(clEnumValN(CodeModel::Small, "small", "Small code model"),
76 cl::values(clEnumValN(CodeModel::Tiny, "tiny", "Tiny code model"),
77 clEnumValN(CodeModel::Small, "small", "Small code model"),
7778 clEnumValN(CodeModel::Kernel, "kernel", "Kernel code model"),
7879 clEnumValN(CodeModel::Medium, "medium", "Medium code model"),
7980 clEnumValN(CodeModel::Large, "large", "Large code model")));
2424 // Code model types.
2525 namespace CodeModel {
2626 // Sync changes with CodeGenCWrappers.h.
27 enum Model { Small, Kernel, Medium, Large };
27 enum Model { Tiny, Small, Kernel, Medium, Large };
2828 }
2929
3030 namespace PICLevel {
3030 LLVM_FALLTHROUGH;
3131 case LLVMCodeModelDefault:
3232 return None;
33 case LLVMCodeModelTiny:
34 return CodeModel::Tiny;
3335 case LLVMCodeModelSmall:
3436 return CodeModel::Small;
3537 case LLVMCodeModelKernel:
4446
4547 inline LLVMCodeModel wrap(CodeModel::Model Model) {
4648 switch (Model) {
49 case CodeModel::Tiny:
50 return LLVMCodeModelTiny;
4751 case CodeModel::Small:
4852 return LLVMCodeModelSmall;
4953 case CodeModel::Kernel:
4444 typedef enum {
4545 LLVMCodeModelDefault,
4646 LLVMCodeModelJITDefault,
47 LLVMCodeModelTiny,
4748 LLVMCodeModelSmall,
4849 LLVMCodeModelKernel,
4950 LLVMCodeModelMedium,
834834 }
835835
836836 case AArch64::LOADgot: {
837 // Expand into ADRP + LDR.
837 MachineFunction *MF = MBB.getParent();
838838 unsigned DstReg = MI.getOperand(0).getReg();
839839 const MachineOperand &MO1 = MI.getOperand(1);
840840 unsigned Flags = MO1.getTargetFlags();
841 MachineInstrBuilder MIB1 =
842 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
843 MachineInstrBuilder MIB2 =
844 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRXui))
845 .add(MI.getOperand(0))
846 .addReg(DstReg);
847
848 if (MO1.isGlobal()) {
849 MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
850 MIB2.addGlobalAddress(MO1.getGlobal(), 0,
851 Flags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
852 } else if (MO1.isSymbol()) {
853 MIB1.addExternalSymbol(MO1.getSymbolName(), Flags | AArch64II::MO_PAGE);
854 MIB2.addExternalSymbol(MO1.getSymbolName(),
855 Flags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
841
842 if (MF->getTarget().getCodeModel() == CodeModel::Tiny) {
843 // Tiny codemodel expand to LDR
844 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
845 TII->get(AArch64::LDRXl), DstReg);
846
847 if (MO1.isGlobal()) {
848 MIB.addGlobalAddress(MO1.getGlobal(), 0, Flags);
849 } else if (MO1.isSymbol()) {
850 MIB.addExternalSymbol(MO1.getSymbolName(), Flags);
851 } else {
852 assert(MO1.isCPI() &&
853 "Only expect globals, externalsymbols, or constant pools");
854 MIB.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(), Flags);
855 }
856856 } else {
857 assert(MO1.isCPI() &&
858 "Only expect globals, externalsymbols, or constant pools");
859 MIB1.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
860 Flags | AArch64II::MO_PAGE);
861 MIB2.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
862 Flags | AArch64II::MO_PAGEOFF |
863 AArch64II::MO_NC);
857 // Small codemodel expand into ADRP + LDR.
858 MachineInstrBuilder MIB1 =
859 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
860 MachineInstrBuilder MIB2 =
861 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRXui))
862 .add(MI.getOperand(0))
863 .addReg(DstReg);
864
865 if (MO1.isGlobal()) {
866 MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
867 MIB2.addGlobalAddress(MO1.getGlobal(), 0,
868 Flags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
869 } else if (MO1.isSymbol()) {
870 MIB1.addExternalSymbol(MO1.getSymbolName(), Flags | AArch64II::MO_PAGE);
871 MIB2.addExternalSymbol(MO1.getSymbolName(), Flags |
872 AArch64II::MO_PAGEOFF |
873 AArch64II::MO_NC);
874 } else {
875 assert(MO1.isCPI() &&
876 "Only expect globals, externalsymbols, or constant pools");
877 MIB1.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
878 Flags | AArch64II::MO_PAGE);
879 MIB2.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
880 Flags | AArch64II::MO_PAGEOFF |
881 AArch64II::MO_NC);
882 }
883
884 transferImpOps(MI, MIB1, MIB2);
864885 }
865
866 transferImpOps(MI, MIB1, MIB2);
867886 MI.eraseFromParent();
868887 return true;
869888 }
685685 .setMIFlags(MachineInstr::FrameSetup);
686686
687687 switch (MF.getTarget().getCodeModel()) {
688 case CodeModel::Tiny:
688689 case CodeModel::Small:
689690 case CodeModel::Medium:
690691 case CodeModel::Kernel:
10851085 case AArch64ISD::FIRST_NUMBER: break;
10861086 case AArch64ISD::CALL: return "AArch64ISD::CALL";
10871087 case AArch64ISD::ADRP: return "AArch64ISD::ADRP";
1088 case AArch64ISD::ADR: return "AArch64ISD::ADR";
10881089 case AArch64ISD::ADDlow: return "AArch64ISD::ADDlow";
10891090 case AArch64ISD::LOADgot: return "AArch64ISD::LOADgot";
10901091 case AArch64ISD::RET_FLAG: return "AArch64ISD::RET_FLAG";
39113912 return DAG.getNode(AArch64ISD::ADDlow, DL, Ty, ADRP, Lo);
39123913 }
39133914
3915 // (adr sym)
3916 template
3917 SDValue AArch64TargetLowering::getAddrTiny(NodeTy *N, SelectionDAG &DAG,
3918 unsigned Flags) const {
3919 LLVM_DEBUG(dbgs() << "AArch64TargetLowering::getAddrTiny\n");
3920 SDLoc DL(N);
3921 EVT Ty = getPointerTy(DAG.getDataLayout());
3922 SDValue Sym = getTargetNode(N, Ty, DAG, Flags);
3923 return DAG.getNode(AArch64ISD::ADR, DL, Ty, Sym);
3924 }
3925
39143926 SDValue AArch64TargetLowering::LowerGlobalAddress(SDValue Op,
39153927 SelectionDAG &DAG) const {
39163928 GlobalAddressSDNode *GN = cast(Op);
39253937 assert(cast(Op)->getOffset() == 0 &&
39263938 "unexpected offset in global node");
39273939
3928 // This also catches the large code model case for Darwin.
3940 // This also catches the large code model case for Darwin, and tiny code
3941 // model with got relocations.
39293942 if ((OpFlags & AArch64II::MO_GOT) != 0) {
39303943 return getGOT(GN, DAG, TargetFlags);
39313944 }
39333946 SDValue Result;
39343947 if (getTargetMachine().getCodeModel() == CodeModel::Large) {
39353948 Result = getAddrLarge(GN, DAG, TargetFlags);
3949 } else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
3950 Result = getAddrTiny(GN, DAG, TargetFlags);
39363951 } else {
39373952 Result = getAddr(GN, DAG, TargetFlags);
39383953 }
40544069 AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
40554070 SelectionDAG &DAG) const {
40564071 assert(Subtarget->isTargetELF() && "This function expects an ELF target");
4057 assert(Subtarget->useSmallAddressing() &&
4058 "ELF TLS only supported in small memory model");
4072 if (getTargetMachine().getCodeModel() == CodeModel::Large)
4073 report_fatal_error("ELF TLS only supported in small memory model");
40594074 // Different choices can be made for the maximum size of the TLS area for a
40604075 // module. For the small address model, the default TLS size is 16MiB and the
40614076 // maximum TLS size is 4GiB.
40624077 // FIXME: add -mtls-size command line option and make it control the 16MiB
40634078 // vs. 4GiB code sequence generation.
4079 // FIXME: add tiny codemodel support. We currently generate the same code as
4080 // small, which may be larger than needed.
40644081 const GlobalAddressSDNode *GA = cast(Op);
40654082
40664083 TLSModel::Model Model = getTargetMachine().getTLSModel(GA->getGlobal());
47784795 if (getTargetMachine().getCodeModel() == CodeModel::Large &&
47794796 !Subtarget->isTargetMachO()) {
47804797 return getAddrLarge(JT, DAG);
4798 } else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
4799 return getAddrTiny(JT, DAG);
47814800 }
47824801 return getAddr(JT, DAG);
47834802 }
47924811 return getGOT(CP, DAG);
47934812 }
47944813 return getAddrLarge(CP, DAG);
4814 } else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
4815 return getAddrTiny(CP, DAG);
47954816 } else {
47964817 return getAddr(CP, DAG);
47974818 }
48034824 if (getTargetMachine().getCodeModel() == CodeModel::Large &&
48044825 !Subtarget->isTargetMachO()) {
48054826 return getAddrLarge(BA, DAG);
4806 } else {
4807 return getAddr(BA, DAG);
4808 }
4827 } else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
4828 return getAddrTiny(BA, DAG);
4829 }
4830 return getAddr(BA, DAG);
48094831 }
48104832
48114833 SDValue AArch64TargetLowering::LowerDarwin_VASTART(SDValue Op,
3434 // offset of a variable into X0, using the TLSDesc model.
3535 TLSDESC_CALLSEQ,
3636 ADRP, // Page address of a TargetGlobalAddress operand.
37 ADR, // ADR
3738 ADDlow, // Add the low 12 bits of a TargetGlobalAddress operand.
3839 LOADgot, // Load from automatically generated descriptor (e.g. Global
3940 // Offset Table, TLS record).
586587 SDValue getAddrLarge(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const;
587588 template
588589 SDValue getAddr(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const;
590 template
591 SDValue getAddrTiny(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const;
589592 SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
590593 SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
591594 SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
16311631 .addReg(Reg, RegState::Kill)
16321632 .addImm(0)
16331633 .addMemOperand(*MI.memoperands_begin());
1634 } else if (TM.getCodeModel() == CodeModel::Tiny) {
1635 BuildMI(MBB, MI, DL, get(AArch64::ADR), Reg)
1636 .addGlobalAddress(GV, 0, OpFlags);
16341637 } else {
16351638 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
16361639 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
175175
176176 // Node definitions.
177177 def AArch64adrp : SDNode<"AArch64ISD::ADRP", SDTIntUnaryOp, []>;
178 def AArch64adr : SDNode<"AArch64ISD::ADR", SDTIntUnaryOp, []>;
178179 def AArch64addlow : SDNode<"AArch64ISD::ADDlow", SDTIntBinOp, []>;
179180 def AArch64LOADgot : SDNode<"AArch64ISD::LOADgot", SDTIntUnaryOp>;
180181 def AArch64callseq_start : SDNode<"ISD::CALLSEQ_START",
13841385 //===----------------------------------------------------------------------===//
13851386 let isReMaterializable = 1 in {
13861387 let hasSideEffects = 0, mayStore = 0, mayLoad = 0 in {
1387 def ADR : ADRI<0, "adr", adrlabel, []>;
1388 def ADR : ADRI<0, "adr", adrlabel,
1389 [(set GPR64:$Xd, (AArch64adr tglobaladdr:$label))]>;
13881390 } // hasSideEffects = 0
13891391
13901392 def ADRP : ADRI<1, "adrp", adrplabel,
13921394 } // isReMaterializable = 1
13931395
13941396 // page address of a constant pool entry, block address
1397 def : Pat<(AArch64adr tconstpool:$cp), (ADR tconstpool:$cp)>;
1398 def : Pat<(AArch64adr tblockaddress:$cp), (ADR tblockaddress:$cp)>;
1399 def : Pat<(AArch64adr texternalsym:$sym), (ADR texternalsym:$sym)>;
1400 def : Pat<(AArch64adr tjumptable:$sym), (ADR tjumptable:$sym)>;
13951401 def : Pat<(AArch64adrp tconstpool:$cp), (ADRP tconstpool:$cp)>;
13961402 def : Pat<(AArch64adrp tblockaddress:$cp), (ADRP tblockaddress:$cp)>;
13971403 def : Pat<(AArch64adrp texternalsym:$sym), (ADRP texternalsym:$sym)>;
982982 materializeLargeCMVal(I, GV, OpFlags);
983983 I.eraseFromParent();
984984 return true;
985 } else if (TM.getCodeModel() == CodeModel::Tiny) {
986 I.setDesc(TII.get(AArch64::ADR));
987 I.getOperand(1).setTargetFlags(OpFlags);
985988 } else {
986989 I.setDesc(TII.get(AArch64::MOVaddr));
987990 I.getOperand(1).setTargetFlags(OpFlags | AArch64II::MO_PAGE);
203203
204204 // The small code model's direct accesses use ADRP, which cannot
205205 // necessarily produce the value 0 (if the code is above 4GB).
206 if (useSmallAddressing() && GV->hasExternalWeakLinkage())
206 // Same for the tiny code model, where we have a pc relative LDR.
207 if ((useSmallAddressing() || TM.getCodeModel() == CodeModel::Tiny) &&
208 GV->hasExternalWeakLinkage())
207209 return AArch64II::MO_GOT | Flags;
208210
209211 return Flags;
209209 Optional CM,
210210 bool JIT) {
211211 if (CM) {
212 if (*CM != CodeModel::Small && *CM != CodeModel::Large) {
212 if (*CM != CodeModel::Small && *CM != CodeModel::Tiny &&
213 *CM != CodeModel::Large) {
213214 if (!TT.isOSFuchsia())
214215 report_fatal_error(
215 "Only small and large code models are allowed on AArch64");
216 else if (CM != CodeModel::Kernel)
217 report_fatal_error(
218 "Only small, kernel, and large code models are allowed on AArch64");
219 }
216 "Only small, tiny and large code models are allowed on AArch64");
217 else if (*CM != CodeModel::Kernel)
218 report_fatal_error("Only small, tiny, kernel, and large code models "
219 "are allowed on AArch64");
220 } else if (*CM == CodeModel::Tiny && !TT.isOSBinFormatELF())
221 report_fatal_error("tiny code model is only supported on ELF");
220222 return *CM;
221223 }
222224 // The default MCJIT memory managers make no guarantees about where they can
24522452 SMLoc S = getLoc();
24532453 const MCExpr *Expr;
24542454
2455 const AsmToken &Tok = getParser().getTok();
2456 if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
2457 if (getParser().parseExpression(Expr))
2455 // Leave anything with a bracket to the default for SVE
2456 if (getParser().getTok().is(AsmToken::LBrac))
2457 return MatchOperand_NoMatch;
2458
2459 if (getParser().getTok().is(AsmToken::Hash))
2460 getParser().Lex(); // Eat hash token.
2461
2462 if (parseSymbolicImmVal(Expr))
2463 return MatchOperand_ParseFail;
2464
2465 AArch64MCExpr::VariantKind ELFRefKind;
2466 MCSymbolRefExpr::VariantKind DarwinRefKind;
2467 int64_t Addend;
2468 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2469 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2470 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2471 // No modifier was specified at all; this is the syntax for an ELF basic
2472 // ADR relocation (unfortunately).
2473 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2474 } else {
2475 Error(S, "unexpected adr label");
24582476 return MatchOperand_ParseFail;
2459
2460 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2461 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2462
2463 return MatchOperand_Success;
2464 }
2465 return MatchOperand_NoMatch;
2477 }
2478 }
2479
2480 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2481 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2482 return MatchOperand_Success;
24662483 }
24672484
24682485 /// tryParseFPImm - A floating point immediate expression operand.
99 #include "AArch64.h"
1010 #include "AArch64RegisterInfo.h"
1111 #include "MCTargetDesc/AArch64FixupKinds.h"
12 #include "MCTargetDesc/AArch64MCExpr.h"
1213 #include "llvm/ADT/Triple.h"
1314 #include "llvm/BinaryFormat/MachO.h"
1415 #include "llvm/MC/MCAsmBackend.h"
375376 // to the linker -- a relocation!
376377 if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21)
377378 return true;
379
380 AArch64MCExpr::VariantKind RefKind =
381 static_cast(Target.getRefKind());
382 AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
383 // LDR GOT relocations need a relocation
384 if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_ldr_pcrel_imm19 &&
385 SymLoc == AArch64MCExpr::VK_GOT)
386 return true;
378387 return false;
379388 }
380389
137137 } else
138138 return ELF::R_AARCH64_PREL64;
139139 case AArch64::fixup_aarch64_pcrel_adr_imm21:
140 assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
140 if (SymLoc != AArch64MCExpr::VK_ABS)
141 Ctx.reportError(Fixup.getLoc(),
142 "invalid symbol kind for ADR relocation");
141143 return R_CLS(ADR_PREL_LO21);
142144 case AArch64::fixup_aarch64_pcrel_adrp_imm21:
143145 if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
6161 case VK_TLSDESC_LO12: return ":tlsdesc_lo12:";
6262 case VK_ABS_PAGE: return "";
6363 case VK_ABS_PAGE_NC: return ":pg_hi21_nc:";
64 case VK_GOT: return ":got:";
6465 case VK_GOT_PAGE: return ":got:";
6566 case VK_GOT_LO12: return ":got_lo12:";
67 case VK_GOTTPREL: return ":gottprel:";
6668 case VK_GOTTPREL_PAGE: return ":gottprel:";
6769 case VK_GOTTPREL_LO12_NC: return ":gottprel_lo12:";
6870 case VK_GOTTPREL_G1: return ":gottprel_g1:";
525525 .setMIFlags(MachineInstr::FrameSetup);
526526
527527 switch (TM.getCodeModel()) {
528 case CodeModel::Tiny:
529 llvm_unreachable("Tiny code model not available on ARM.");
528530 case CodeModel::Small:
529531 case CodeModel::Medium:
530532 case CodeModel::Kernel:
92069206 // IP.
92079207
92089208 switch (TM.getCodeModel()) {
9209 case CodeModel::Tiny:
9210 llvm_unreachable("Tiny code model not available on ARM.");
92099211 case CodeModel::Small:
92109212 case CodeModel::Medium:
92119213 case CodeModel::Kernel:
7676 if (isTargetELF()) {
7777 switch (TM.getCodeModel()) {
7878 // 64-bit small code model is simple: All rip-relative.
79 case CodeModel::Tiny:
80 llvm_unreachable("Tiny codesize model not supported on X86");
7981 case CodeModel::Small:
8082 case CodeModel::Kernel:
8183 return X86II::MO_NO_FLAG;
0 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
1 # RUN: llc -mtriple=aarch64-none-eabi -code-model=tiny -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s
2 --- |
3 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
4
5 @foo1 = common global [1073741824 x i32] zeroinitializer, align 4
6 @foo2 = common global [1073741824 x i32] zeroinitializer, align 4
7
8 define i32 @gv_tiny() {
9 entry:
10 %retval = alloca i32, align 4
11 store i32 0, i32* %retval, align 4
12 %0 = load i32, i32* getelementptr inbounds ([1073741824 x i32], [1073741824 x i32]* @foo1, i64 0, i64 0), align 4
13 %1 = load i32, i32* getelementptr inbounds ([1073741824 x i32], [1073741824 x i32]* @foo2, i64 0, i64 0), align 4
14 %add = add nsw i32 %0, %1
15 ret i32 %add
16 }
17
18 ...
19 ---
20 name: gv_tiny
21 legalized: true
22 regBankSelected: true
23 stack:
24 - { id: 0, name: retval, type: default, offset: 0, size: 4, alignment: 4,
25 stack-id: 0, callee-saved-register: '', callee-saved-restored: true,
26 debug-info-variable: '', debug-info-expression: '',
27 debug-info-location: '' }
28 constants:
29 body: |
30 bb.1:
31 ; CHECK-LABEL: name: gv_tiny
32 ; CHECK: [[ADR:%[0-9]+]]:gpr64 = ADR @foo1
33 ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY [[ADR]]
34 ; CHECK: [[ADR1:%[0-9]+]]:gpr64 = ADR @foo2
35 ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY [[ADR1]]
36 ; CHECK: STRWui $wzr, %stack.0.retval, 0 :: (store 4 into %ir.retval)
37 ; CHECK: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load 4 from `i32* getelementptr inbounds ([1073741824 x i32], [1073741824 x i32]* @foo1, i64 0, i64 0)`)
38 ; CHECK: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY1]], 0 :: (load 4 from `i32* getelementptr inbounds ([1073741824 x i32], [1073741824 x i32]* @foo2, i64 0, i64 0)`)
39 ; CHECK: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[LDRWui]], [[LDRWui1]]
40 ; CHECK: $w0 = COPY [[ADDWrr]]
41 ; CHECK: RET_ReallyLR implicit $w0
42 %1:gpr(s32) = G_CONSTANT i32 0
43 %4:gpr(p0) = G_GLOBAL_VALUE @foo1
44 %3:gpr(p0) = COPY %4(p0)
45 %7:gpr(p0) = G_GLOBAL_VALUE @foo2
46 %6:gpr(p0) = COPY %7(p0)
47 %0:gpr(p0) = G_FRAME_INDEX %stack.0.retval
48 G_STORE %1(s32), %0(p0) :: (store 4 into %ir.retval)
49 %2:gpr(s32) = G_LOAD %3(p0) :: (load 4 from `i32* getelementptr inbounds ([1073741824 x i32], [1073741824 x i32]* @foo1, i64 0, i64 0)`)
50 %5:gpr(s32) = G_LOAD %6(p0) :: (load 4 from `i32* getelementptr inbounds ([1073741824 x i32], [1073741824 x i32]* @foo2, i64 0, i64 0)`)
51 %8:gpr(s32) = G_ADD %2, %5
52 $w0 = COPY %8(s32)
53 RET_ReallyLR implicit $w0
54
55 ...
11 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s
22 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-NOLD %s
33 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-NOLD-RELOC %s
4 ; FIXME: We currently produce "small" code for the tiny model
5 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -code-model=tiny -verify-machineinstrs < %s | FileCheck %s
6 ; FIXME: We currently error for the large code model
7 ; RUN: not llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -code-model=large -verify-machineinstrs < %s 2>&1 | FileCheck %s --check-prefix=CHECK-LARGE
8
9 ; CHECK-LARGE: ELF TLS only supported in small memory model
410
511 @general_dynamic_var = external thread_local global i32
612
0 ; RUN: llc -mtriple=arm64-none-linux-gnu -verify-machineinstrs -show-mc-encoding < %s | FileCheck %s
11 ; RUN: llc -mtriple=arm64-none-linux-gnu -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s
2 ; RUN: llc -mtriple=arm64-none-linux-gnu -verify-machineinstrs -show-mc-encoding -code-model=tiny < %s | FileCheck %s --check-prefix=CHECK-TINY
3 ; RUN: llc -mtriple=arm64-none-linux-gnu -filetype=obj < %s -code-model=tiny | llvm-objdump -r - | FileCheck --check-prefix=CHECK-TINY-RELOC %s
4 ; FIXME: We currently error for the large code model
5 ; RUN: not llc -mtriple=arm64-none-linux-gnu -verify-machineinstrs -show-mc-encoding -code-model=large < %s 2>&1 | FileCheck %s --check-prefix=CHECK-LARGE
6
7 ; CHECK-LARGE: ELF TLS only supported in small memory model
28
39 @initial_exec_var = external thread_local(initialexec) global i32
410
1319
1420 ; CHECK-RELOC: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
1521 ; CHECK-RELOC: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
22
23 ; CHECK-TINY: ldr x[[TP_OFFSET:[0-9]+]], :gottprel:initial_exec_var
24 ; CHECK-TINY: mrs x[[TP:[0-9]+]], TPIDR_EL0
25 ; CHECK-TINY: ldr w0, [x[[TP]], x[[TP_OFFSET]]]
26
27 ; CHECK-TINY-RELOC: R_AARCH64_TLSIE_LD_GOTTPREL_PREL19
1628
1729 ret i32 %val
1830 }
2941 ; CHECK-RELOC: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
3042 ; CHECK-RELOC: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
3143
44 ; CHECK-TINY: ldr x[[TP_OFFSET:[0-9]+]], :gottprel:initial_exec_var
45 ; CHECK-TINY: mrs [[TP:x[0-9]+]], TPIDR_EL0
46 ; CHECK-TINY: add x0, [[TP]], x[[TP_OFFSET]]
47
48 ; CHECK-TINY-RELOC: R_AARCH64_TLSIE_LD_GOTTPREL_PREL19
49
3250 }
3351
3452 @local_exec_var = thread_local(localexec) global i32 0
4462
4563 ; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_HI12
4664 ; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
65
66 ; CHECK-TINY: mrs x[[R1:[0-9]+]], TPIDR_EL0
67 ; CHECK-TINY: add x[[R2:[0-9]+]], x[[R1]], :tprel_hi12:local_exec_var
68 ; CHECK-TINY: add x[[R3:[0-9]+]], x[[R2]], :tprel_lo12_nc:local_exec_var
69 ; CHECK-TINY: ldr w0, [x[[R3]]]
70
71 ; CHECK-TINY-RELOC: R_AARCH64_TLSLE_ADD_TPREL_HI12
72 ; CHECK-TINY-RELOC: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
4773 ret i32 %val
4874 }
4975
5884
5985 ; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_HI12
6086 ; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
87
88 ; CHECK-TINY: mrs x[[R1:[0-9]+]], TPIDR_EL0
89 ; CHECK-TINY: add x[[R2:[0-9]+]], x[[R1]], :tprel_hi12:local_exec_var
90 ; CHECK-TINY: add x0, x[[R2]], :tprel_lo12_nc:local_exec_var
91 ; CHECK-TINY: ret
92
93 ; CHECK-TINY-RELOC: R_AARCH64_TLSLE_ADD_TPREL_HI12
94 ; CHECK-TINY-RELOC: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
6195 }
0 ; RUN: llc -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck %s
11 ; RUN: llc -code-model=large -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-LARGE %s
2 ; RUN: llc -code-model=tiny -mtriple=aarch64-none-none-eabi -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-TINY %s
23
34 @addr = global i8* null
45
2122 ; CHECK-LARGE: ldr [[NEWDEST:x[0-9]+]]
2223 ; CHECK-LARGE: br [[NEWDEST]]
2324
25 ; CHECK-TINY: adr [[DEST:x[0-9]+]], {{.Ltmp[0-9]+}}
26 ; CHECK-TINY: str [[DEST]],
27 ; CHECK-TINY: ldr [[NEWDEST:x[0-9]+]]
28 ; CHECK-TINY: br [[NEWDEST]]
29
2430 block:
2531 ret void
2632 }
0 ; RUN: llc -mtriple=aarch64-none-eabi -code-model=tiny < %s | FileCheck %s
1
2 @var8 = global i8 0
3 @var16 = global i16 0
4 @var32 = global i32 0
5 @var64 = global i64 0
6
7 define i8* @global_addr() {
8 ; CHECK-LABEL: global_addr:
9 ret i8* @var8
10 ; The adr calculation should end up returned directly in x0.
11 ; CHECK: adr x0, var8
12 ; CHECK-NEXT: ret
13 }
14
15 define i8 @global_i8() {
16 ; CHECK-LABEL: global_i8:
17 %val = load i8, i8* @var8
18 ret i8 %val
19 ; CHECK: adr x[[ADDR_REG:[0-9]+]], var8
20 ; CHECK: ldrb w0, [x[[ADDR_REG]]]
21 }
22
23 define i16 @global_i16() {
24 ; CHECK-LABEL: global_i16:
25 %val = load i16, i16* @var16
26 ret i16 %val
27 ; CHECK: adr x[[ADDR_REG:[0-9]+]], var16
28 ; CHECK: ldrh w0, [x[[ADDR_REG]]]
29 }
30
31 define i32 @global_i32() {
32 ; CHECK-LABEL: global_i32:
33 %val = load i32, i32* @var32
34 ret i32 %val
35 ; CHECK: adr x[[ADDR_REG:[0-9]+]], var32
36 ; CHECK: ldr w0, [x[[ADDR_REG]]]
37 }
38
39 define i64 @global_i64() {
40 ; CHECK-LABEL: global_i64:
41 %val = load i64, i64* @var64
42 ret i64 %val
43 ; CHECK: adr x[[ADDR_REG:[0-9]+]], var64
44 ; CHECK: ldr x0, [x[[ADDR_REG]]]
45 }
46
47 define <2 x i64> @constpool() {
48 ; CHECK-LABEL: constpool:
49 ret <2 x i64>
50
51 ; CHECK: adr x[[ADDR_REG:[0-9]+]], {{.LCPI[0-9]+_[0-9]+}}
52 ; CHECK: ldr q0, [x[[ADDR_REG]]]
53 }
0 ; RUN: llc -mtriple=aarch64-none-linux-gnu -relocation-model=pic -o - %s | FileCheck %s
11 ; RUN: llc -mtriple=aarch64-none-linux-gnu -relocation-model=static -o - < %s | FileCheck %s
22 ; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=large -o - %s | FileCheck --check-prefix=CHECK-LARGE %s
3 ; RUN: llc -mtriple=aarch64-none-none-eabi -code-model=tiny -o - %s | FileCheck --check-prefix=CHECK-TINY %s
34
45 declare extern_weak i32 @var()
56
1920 ; CHECK-LARGE: movk x0, #:abs_g1_nc:var
2021 ; CHECK-LARGE: movk x0, #:abs_g2_nc:var
2122 ; CHECK-LARGE: movk x0, #:abs_g3:var
23
24 ; In the tiny codemodel we us a got relocated LDR.
25 ; CHECK-TINY: ldr x0, :got:var
2226 }
2327
2428
4044 ; CHECK-LARGE: movk [[ADDR]], #:abs_g1_nc:arr_var
4145 ; CHECK-LARGE: movk [[ADDR]], #:abs_g2_nc:arr_var
4246 ; CHECK-LARGE: movk [[ADDR]], #:abs_g3:arr_var
47
48 ; CHECK-TINY: ldr [[BASE:x[0-9]+]], :got:arr_var
49 ; CHECK-TINY: add x0, [[BASE]], #20
4350 }
4451
4552 @defined_weak_var = internal unnamed_addr global i32 0
5461 ; CHECK-LARGE: movk x0, #:abs_g1_nc:defined_weak_var
5562 ; CHECK-LARGE: movk x0, #:abs_g2_nc:defined_weak_var
5663 ; CHECK-LARGE: movk x0, #:abs_g3:defined_weak_var
64
65 ; CHECK-TINY: adr x0, defined_weak_var
5766 }
0 ; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs < %s | FileCheck %s
11 ; RUN: llc -mtriple=aarch64-apple-darwin -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix=LARGE
22 ; RUN: llc -mtriple=aarch64-apple-darwin -code-model=large -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s --check-prefix=LARGE
3 ; RUN: llc -mtriple=aarch64-none-eabi -code-model=tiny -verify-machineinstrs < %s | FileCheck %s --check-prefix=TINY
34
45 @varf32 = global float 0.0
56 @varf64 = global double 0.0
67
78 define void @check_float() {
89 ; CHECK-LABEL: check_float:
10 ; TINY-LABEL: check_float:
911
1012 %val = load float, float* @varf32
1113 %newval1 = fadd float %val, 8.5
1214 store volatile float %newval1, float* @varf32
13 ; CHECK-DAG: fmov [[EIGHT5:s[0-9]+]], #8.5
15 ; CHECK-DAG: fmov {{s[0-9]+}}, #8.5
16 ; TINY-DAG: fmov {{s[0-9]+}}, #8.5
1417
1518 %newval2 = fadd float %val, 128.0
1619 store volatile float %newval2, float* @varf32
17 ; CHECK-DAG: ldr [[HARD:s[0-9]+]], [{{x[0-9]+}}, {{#?}}:lo12:.LCPI0_0
20 ; CHECK-DAG: ldr {{s[0-9]+}}, [{{x[0-9]+}}, {{#?}}:lo12:.LCPI0_0
21 ; TINY-DAG: ldr {{s[0-9]+}}, [{{x[0-9]+}}]
1822
1923 ; CHECK: ret
24 ; TINY: ret
2025 ret void
2126 }
2227
2328 define void @check_double() {
2429 ; CHECK-LABEL: check_double:
30 ; TINY-LABEL: check_double:
2531
2632 %val = load double, double* @varf64
2733 %newval1 = fadd double %val, 8.5
2834 store volatile double %newval1, double* @varf64
2935 ; CHECK-DAG: fmov {{d[0-9]+}}, #8.5
36 ; TINY-DAG: fmov {{d[0-9]+}}, #8.5
3037
3138 %newval2 = fadd double %val, 128.0
3239 store volatile double %newval2, double* @varf64
3340 ; CHECK-DAG: ldr {{d[0-9]+}}, [{{x[0-9]+}}, {{#?}}:lo12:.LCPI1_0
41 ; TINY-DAG: ldr {{d[0-9]+}}, [{{x[0-9]+}}]
3442
3543 ; CHECK: ret
44 ; TINY: ret
3645 ret void
3746 }
3847
4049 ; LARGE: mov [[REG:w[0-9]+]], #4059
4150 ; LARGE-NEXT: movk [[REG]], #16457, lsl #16
4251 ; LARGE-NEXT: fmov s0, [[REG]]
52 ; TINY-LABEL: check_float2
53 ; TINY: adr x[[REG:[0-9]+]], .LCPI2_0
54 ; TINY-NEXT: ldr s0, [x[[REG]]]
4355 define float @check_float2() {
4456 ret float 3.14159274101257324218750
4557 }
5062 ; LARGE-NEXT: movk [[REG]], #8699, lsl #32
5163 ; LARGE-NEXT: movk [[REG]], #16393, lsl #48
5264 ; LARGE-NEXT: fmov d0, [[REG]]
65 ; TINY-LABEL: check_double2
66 ; TINY: adr x[[REG:[0-9]+]], .LCPI3_0
67 ; TINY-NEXT: ldr d0, [x[[REG]]]
5368 define double @check_double2() {
5469 ret double 3.1415926535897931159979634685441851615905761718750
5570 }
0 ; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
11 ; RUN: llc -code-model=large -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck --check-prefix=CHECK-LARGE %s
22 ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs -relocation-model=pic -aarch64-enable-atomic-cfg-tidy=0 -o - %s | FileCheck --check-prefix=CHECK-PIC %s
3 ; RUN: llc -code-model=tiny -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck --check-prefix=CHECK-TINY %s
34
45 define i32 @test_jumptable(i32 %in) {
56 ; CHECK: test_jumptable
2728 ; CHECK-PIC: ldrsw [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #2]
2829 ; CHECK-PIC: add [[TABLE:x[0-9]+]], [[DEST]], x[[JT]]
2930 ; CHECK-PIC: br [[TABLE]]
31
32 ; CHECK-TINY: adr x[[JT:[0-9]+]], .LJTI0_0
33 ; CHECK-TINY: ldr [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #3]
34 ; CHECK-TINY: br [[DEST]]
3035
3136 def:
3237 ret i32 0
0 ; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -mcpu=cyclone | FileCheck %s
11 ; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -code-model=large -mcpu=cyclone | FileCheck --check-prefix=CHECK-LARGE %s
2 ; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-none-none-eabi -code-model=tiny -mcpu=cyclone | FileCheck --check-prefix=CHECK-TINY %s
23 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -mattr=-fp-armv8 | FileCheck --check-prefix=CHECK-NOFP %s
34 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -code-model=large -mattr=-fp-armv8 | FileCheck --check-prefix=CHECK-NOFP-LARGE %s
5 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-none-eabi -code-model=tiny -mattr=-fp-armv8 | FileCheck --check-prefix=CHECK-NOFP-TINY %s
46
57 @varfloat = global float 0.0
68 @vardouble = global double 0.0
1315 ; CHECK: adrp x[[LITBASE:[0-9]+]], [[CURLIT:.LCPI[0-9]+_[0-9]+]]
1416 ; CHECK: ldr [[LIT128:s[0-9]+]], [x[[LITBASE]], {{#?}}:lo12:[[CURLIT]]]
1517 ; CHECK-NOFP-NOT: ldr {{s[0-9]+}},
18
19 ; CHECK-TINY: adr x[[LITBASE:[0-9]+]], [[CURLIT:.LCPI[0-9]+_[0-9]+]]
20 ; CHECK-TINY: ldr [[LIT128:s[0-9]+]], [x[[LITBASE]]]
21 ; CHECK-NOFP-TINY-NOT: ldr {{s[0-9]+}},
1622
1723 ; CHECK-LARGE: movz x[[LITADDR:[0-9]+]], #:abs_g0_nc:[[CURLIT:.LCPI[0-9]+_[0-9]+]]
1824 ; CHECK-LARGE: movk x[[LITADDR]], #:abs_g1_nc:[[CURLIT]]
3238 ; CHECK-NOFP-NOT: ldr {{d[0-9]+}},
3339 ; CHECK-NOFP-NOT: fadd
3440
41 ; CHECK-TINY: adr x[[LITBASE:[0-9]+]], [[CURLIT:.LCPI[0-9]+_[0-9]+]]
42 ; CHECK-TINY: ldr [[LIT129:d[0-9]+]], [x[[LITBASE]]]
43 ; CHECK-NOFP-TINY-NOT: ldr {{d[0-9]+}},
44 ; CHECK-NOFP-TINY-NOT: fadd
45
3546 ; CHECK-LARGE: movz x[[LITADDR:[0-9]+]], #:abs_g0_nc:[[CURLIT:.LCPI[0-9]+_[0-9]+]]
3647 ; CHECK-LARGE: movk x[[LITADDR]], #:abs_g1_nc:[[CURLIT]]
3748 ; CHECK-LARGE: movk x[[LITADDR]], #:abs_g2_nc:[[CURLIT]]
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny < %s | FileCheck %s
2 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny -fast-isel < %s | FileCheck %s
3 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny -global-isel < %s | FileCheck %s --check-prefix=CHECK-GLOBISEL
4 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK-PIC
5 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny -relocation-model=pic -fast-isel < %s | FileCheck %s --check-prefix=CHECK-PIC
6 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny -relocation-model=pic -global-isel < %s | FileCheck %s --check-prefix=CHECK-PIC-GLOBISEL
7
8 ; Note fast-isel tests here will fall back to isel
9
10 @src = external local_unnamed_addr global [65536 x i8], align 1
11 @dst = external global [65536 x i8], align 1
12 @ptr = external local_unnamed_addr global i8*, align 8
13
14 define void @foo1() {
15 ; CHECK-LABEL: foo1:
16 ; CHECK: // %bb.0: // %entry
17 ; CHECK-NEXT: adr x8, src
18 ; CHECK-NEXT: ldrb w8, [x8]
19 ; CHECK-NEXT: adr x9, dst
20 ; CHECK-NEXT: strb w8, [x9]
21 ; CHECK-NEXT: ret
22 ;
23 ; CHECK-GLOBISEL-LABEL: foo1:
24 ; CHECK-GLOBISEL: // %bb.0: // %entry
25 ; CHECK-GLOBISEL-NEXT: adr x8, src
26 ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8]
27 ; CHECK-GLOBISEL-NEXT: adr x9, dst
28 ; CHECK-GLOBISEL-NEXT: strb w8, [x9]
29 ; CHECK-GLOBISEL-NEXT: ret
30 ;
31 ; CHECK-PIC-LABEL: foo1:
32 ; CHECK-PIC: // %bb.0: // %entry
33 ; CHECK-PIC-NEXT: ldr x8, :got:src
34 ; CHECK-PIC-NEXT: ldrb w8, [x8]
35 ; CHECK-PIC-NEXT: ldr x9, :got:dst
36 ; CHECK-PIC-NEXT: strb w8, [x9]
37 ; CHECK-PIC-NEXT: ret
38 ;
39 ; CHECK-PIC-GLOBISEL-LABEL: foo1:
40 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
41 ; CHECK-PIC-GLOBISEL-NEXT: ldr x8, :got:src
42 ; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8]
43 ; CHECK-PIC-GLOBISEL-NEXT: ldr x9, :got:dst
44 ; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9]
45 ; CHECK-PIC-GLOBISEL-NEXT: ret
46 entry:
47 %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @src, i64 0, i64 0), align 1
48 store i8 %0, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @dst, i64 0, i64 0), align 1
49 ret void
50 }
51
52 define void @foo2() {
53 ; CHECK-LABEL: foo2:
54 ; CHECK: // %bb.0: // %entry
55 ; CHECK-NEXT: adr x8, ptr
56 ; CHECK-NEXT: adr x9, dst
57 ; CHECK-NEXT: str x9, [x8]
58 ; CHECK-NEXT: ret
59 ;
60 ; CHECK-GLOBISEL-LABEL: foo2:
61 ; CHECK-GLOBISEL: // %bb.0: // %entry
62 ; CHECK-GLOBISEL-NEXT: adr x8, dst
63 ; CHECK-GLOBISEL-NEXT: adr x9, ptr
64 ; CHECK-GLOBISEL-NEXT: str x8, [x9]
65 ; CHECK-GLOBISEL-NEXT: ret
66 ;
67 ; CHECK-PIC-LABEL: foo2:
68 ; CHECK-PIC: // %bb.0: // %entry
69 ; CHECK-PIC-NEXT: ldr x8, :got:ptr
70 ; CHECK-PIC-NEXT: ldr x9, :got:dst
71 ; CHECK-PIC-NEXT: str x9, [x8]
72 ; CHECK-PIC-NEXT: ret
73 ;
74 ; CHECK-PIC-GLOBISEL-LABEL: foo2:
75 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
76 ; CHECK-PIC-GLOBISEL-NEXT: ldr x8, :got:dst
77 ; CHECK-PIC-GLOBISEL-NEXT: ldr x9, :got:ptr
78 ; CHECK-PIC-GLOBISEL-NEXT: str x8, [x9]
79 ; CHECK-PIC-GLOBISEL-NEXT: ret
80 entry:
81 store i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @dst, i64 0, i64 0), i8** @ptr, align 8
82 ret void
83 }
84
85 define void @foo3() {
86 ; FIXME: Needn't adr ptr
87 ;
88 ; CHECK-LABEL: foo3:
89 ; CHECK: // %bb.0: // %entry
90 ; CHECK-NEXT: adr x8, src
91 ; CHECK-NEXT: adr x9, ptr
92 ; CHECK-NEXT: ldrb w8, [x8]
93 ; CHECK-NEXT: ldr x9, [x9]
94 ; CHECK-NEXT: strb w8, [x9]
95 ; CHECK-NEXT: ret
96 ;
97 ; CHECK-GLOBISEL-LABEL: foo3:
98 ; CHECK-GLOBISEL: // %bb.0: // %entry
99 ; CHECK-GLOBISEL-NEXT: adr x8, src
100 ; CHECK-GLOBISEL-NEXT: adr x9, ptr
101 ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8]
102 ; CHECK-GLOBISEL-NEXT: ldr x9, [x9]
103 ; CHECK-GLOBISEL-NEXT: strb w8, [x9]
104 ; CHECK-GLOBISEL-NEXT: ret
105 ;
106 ; CHECK-PIC-LABEL: foo3:
107 ; CHECK-PIC: // %bb.0: // %entry
108 ; CHECK-PIC-NEXT: ldr x8, :got:src
109 ; CHECK-PIC-NEXT: ldr x9, :got:ptr
110 ; CHECK-PIC-NEXT: ldrb w8, [x8]
111 ; CHECK-PIC-NEXT: ldr x9, [x9]
112 ; CHECK-PIC-NEXT: strb w8, [x9]
113 ; CHECK-PIC-NEXT: ret
114 ;
115 ; CHECK-PIC-GLOBISEL-LABEL: foo3:
116 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
117 ; CHECK-PIC-GLOBISEL-NEXT: ldr x8, :got:src
118 ; CHECK-PIC-GLOBISEL-NEXT: ldr x9, :got:ptr
119 ; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8]
120 ; CHECK-PIC-GLOBISEL-NEXT: ldr x9, [x9]
121 ; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9]
122 ; CHECK-PIC-GLOBISEL-NEXT: ret
123 entry:
124 %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @src, i64 0, i64 0), align 1
125 %1 = load i8*, i8** @ptr, align 8
126 store i8 %0, i8* %1, align 1
127 ret void
128 }
129
130 @lsrc = internal global i8 0, align 4
131 @ldst = internal global i8 0, align 4
132 @lptr = internal global i8* null, align 8
133
134 define void @bar1() {
135 ; CHECK-LABEL: bar1:
136 ; CHECK: // %bb.0: // %entry
137 ; CHECK-NEXT: adr x8, lsrc
138 ; CHECK-NEXT: ldrb w8, [x8]
139 ; CHECK-NEXT: adr x9, ldst
140 ; CHECK-NEXT: strb w8, [x9]
141 ; CHECK-NEXT: ret
142 ;
143 ; CHECK-GLOBISEL-LABEL: bar1:
144 ; CHECK-GLOBISEL: // %bb.0: // %entry
145 ; CHECK-GLOBISEL-NEXT: adr x8, lsrc
146 ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8]
147 ; CHECK-GLOBISEL-NEXT: adr x9, ldst
148 ; CHECK-GLOBISEL-NEXT: strb w8, [x9]
149 ; CHECK-GLOBISEL-NEXT: ret
150 ;
151 ; CHECK-PIC-LABEL: bar1:
152 ; CHECK-PIC: // %bb.0: // %entry
153 ; CHECK-PIC-NEXT: adr x8, lsrc
154 ; CHECK-PIC-NEXT: ldrb w8, [x8]
155 ; CHECK-PIC-NEXT: adr x9, ldst
156 ; CHECK-PIC-NEXT: strb w8, [x9]
157 ; CHECK-PIC-NEXT: ret
158 ;
159 ; CHECK-PIC-GLOBISEL-LABEL: bar1:
160 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
161 ; CHECK-PIC-GLOBISEL-NEXT: adr x8, lsrc
162 ; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8]
163 ; CHECK-PIC-GLOBISEL-NEXT: adr x9, ldst
164 ; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9]
165 ; CHECK-PIC-GLOBISEL-NEXT: ret
166 entry:
167 %0 = load i8, i8* @lsrc, align 4
168 store i8 %0, i8* @ldst, align 4
169 ret void
170 }
171
172 define void @bar2() {
173 ; CHECK-LABEL: bar2:
174 ; CHECK: // %bb.0: // %entry
175 ; CHECK-NEXT: adr x8, lptr
176 ; CHECK-NEXT: adr x9, ldst
177 ; CHECK-NEXT: str x9, [x8]
178 ; CHECK-NEXT: ret
179 ;
180 ; CHECK-GLOBISEL-LABEL: bar2:
181 ; CHECK-GLOBISEL: // %bb.0: // %entry
182 ; CHECK-GLOBISEL-NEXT: adr x8, ldst
183 ; CHECK-GLOBISEL-NEXT: adr x9, lptr
184 ; CHECK-GLOBISEL-NEXT: str x8, [x9]
185 ; CHECK-GLOBISEL-NEXT: ret
186 ;
187 ; CHECK-PIC-LABEL: bar2:
188 ; CHECK-PIC: // %bb.0: // %entry
189 ; CHECK-PIC-NEXT: adr x8, lptr
190 ; CHECK-PIC-NEXT: adr x9, ldst
191 ; CHECK-PIC-NEXT: str x9, [x8]
192 ; CHECK-PIC-NEXT: ret
193 ;
194 ; CHECK-PIC-GLOBISEL-LABEL: bar2:
195 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
196 ; CHECK-PIC-GLOBISEL-NEXT: adr x8, ldst
197 ; CHECK-PIC-GLOBISEL-NEXT: adr x9, lptr
198 ; CHECK-PIC-GLOBISEL-NEXT: str x8, [x9]
199 ; CHECK-PIC-GLOBISEL-NEXT: ret
200 entry:
201 store i8* @ldst, i8** @lptr, align 8
202 ret void
203 }
204
205 define void @bar3() {
206 ; FIXME: Needn't adr lptr
207 ;
208 ; CHECK-LABEL: bar3:
209 ; CHECK: // %bb.0: // %entry
210 ; CHECK-NEXT: adr x8, lsrc
211 ; CHECK-NEXT: adr x9, lptr
212 ; CHECK-NEXT: ldrb w8, [x8]
213 ; CHECK-NEXT: ldr x9, [x9]
214 ; CHECK-NEXT: strb w8, [x9]
215 ; CHECK-NEXT: ret
216 ;
217 ; CHECK-GLOBISEL-LABEL: bar3:
218 ; CHECK-GLOBISEL: // %bb.0: // %entry
219 ; CHECK-GLOBISEL-NEXT: adr x8, lsrc
220 ; CHECK-GLOBISEL-NEXT: adr x9, lptr
221 ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8]
222 ; CHECK-GLOBISEL-NEXT: ldr x9, [x9]
223 ; CHECK-GLOBISEL-NEXT: strb w8, [x9]
224 ; CHECK-GLOBISEL-NEXT: ret
225 ;
226 ; CHECK-PIC-LABEL: bar3:
227 ; CHECK-PIC: // %bb.0: // %entry
228 ; CHECK-PIC-NEXT: adr x8, lsrc
229 ; CHECK-PIC-NEXT: adr x9, lptr
230 ; CHECK-PIC-NEXT: ldrb w8, [x8]
231 ; CHECK-PIC-NEXT: ldr x9, [x9]
232 ; CHECK-PIC-NEXT: strb w8, [x9]
233 ; CHECK-PIC-NEXT: ret
234 ;
235 ; CHECK-PIC-GLOBISEL-LABEL: bar3:
236 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
237 ; CHECK-PIC-GLOBISEL-NEXT: adr x8, lsrc
238 ; CHECK-PIC-GLOBISEL-NEXT: adr x9, lptr
239 ; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8]
240 ; CHECK-PIC-GLOBISEL-NEXT: ldr x9, [x9]
241 ; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9]
242 ; CHECK-PIC-GLOBISEL-NEXT: ret
243 entry:
244 %0 = load i8, i8* @lsrc, align 4
245 %1 = load i8*, i8** @lptr, align 8
246 store i8 %0, i8* %1, align 1
247 ret void
248 }
249
250
251 @lbsrc = internal global [65536 x i8] zeroinitializer, align 4
252 @lbdst = internal global [65536 x i8] zeroinitializer, align 4
253
254 define void @baz1() {
255 ; CHECK-LABEL: baz1:
256 ; CHECK: // %bb.0: // %entry
257 ; CHECK-NEXT: adr x8, lbsrc
258 ; CHECK-NEXT: ldrb w8, [x8]
259 ; CHECK-NEXT: adr x9, lbdst
260 ; CHECK-NEXT: strb w8, [x9]
261 ; CHECK-NEXT: ret
262 ;
263 ; CHECK-GLOBISEL-LABEL: baz1:
264 ; CHECK-GLOBISEL: // %bb.0: // %entry
265 ; CHECK-GLOBISEL-NEXT: adr x8, lbsrc
266 ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8]
267 ; CHECK-GLOBISEL-NEXT: adr x9, lbdst
268 ; CHECK-GLOBISEL-NEXT: strb w8, [x9]
269 ; CHECK-GLOBISEL-NEXT: ret
270 ;
271 ; CHECK-PIC-LABEL: baz1:
272 ; CHECK-PIC: // %bb.0: // %entry
273 ; CHECK-PIC-NEXT: adr x8, lbsrc
274 ; CHECK-PIC-NEXT: ldrb w8, [x8]
275 ; CHECK-PIC-NEXT: adr x9, lbdst
276 ; CHECK-PIC-NEXT: strb w8, [x9]
277 ; CHECK-PIC-NEXT: ret
278 ;
279 ; CHECK-PIC-GLOBISEL-LABEL: baz1:
280 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
281 ; CHECK-PIC-GLOBISEL-NEXT: adr x8, lbsrc
282 ; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8]
283 ; CHECK-PIC-GLOBISEL-NEXT: adr x9, lbdst
284 ; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9]
285 ; CHECK-PIC-GLOBISEL-NEXT: ret
286 entry:
287 %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbsrc, i64 0, i64 0), align 4
288 store i8 %0, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbdst, i64 0, i64 0), align 4
289 ret void
290 }
291
292 define void @baz2() {
293 ; CHECK-LABEL: baz2:
294 ; CHECK: // %bb.0: // %entry
295 ; CHECK-NEXT: adr x8, lptr
296 ; CHECK-NEXT: adr x9, lbdst
297 ; CHECK-NEXT: str x9, [x8]
298 ; CHECK-NEXT: ret
299 ;
300 ; CHECK-GLOBISEL-LABEL: baz2:
301 ; CHECK-GLOBISEL: // %bb.0: // %entry
302 ; CHECK-GLOBISEL-NEXT: adr x8, lbdst
303 ; CHECK-GLOBISEL-NEXT: adr x9, lptr
304 ; CHECK-GLOBISEL-NEXT: str x8, [x9]
305 ; CHECK-GLOBISEL-NEXT: ret
306 ;
307 ; CHECK-PIC-LABEL: baz2:
308 ; CHECK-PIC: // %bb.0: // %entry
309 ; CHECK-PIC-NEXT: adr x8, lptr
310 ; CHECK-PIC-NEXT: adr x9, lbdst
311 ; CHECK-PIC-NEXT: str x9, [x8]
312 ; CHECK-PIC-NEXT: ret
313 ;
314 ; CHECK-PIC-GLOBISEL-LABEL: baz2:
315 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
316 ; CHECK-PIC-GLOBISEL-NEXT: adr x8, lbdst
317 ; CHECK-PIC-GLOBISEL-NEXT: adr x9, lptr
318 ; CHECK-PIC-GLOBISEL-NEXT: str x8, [x9]
319 ; CHECK-PIC-GLOBISEL-NEXT: ret
320 entry:
321 store i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbdst, i64 0, i64 0), i8** @lptr, align 8
322 ret void
323 }
324
325 define void @baz3() {
326 ; FIXME: Needn't adr lptr
327 ;
328 ; CHECK-LABEL: baz3:
329 ; CHECK: // %bb.0: // %entry
330 ; CHECK-NEXT: adr x8, lbsrc
331 ; CHECK-NEXT: adr x9, lptr
332 ; CHECK-NEXT: ldrb w8, [x8]
333 ; CHECK-NEXT: ldr x9, [x9]
334 ; CHECK-NEXT: strb w8, [x9]
335 ; CHECK-NEXT: ret
336 ;
337 ; CHECK-GLOBISEL-LABEL: baz3:
338 ; CHECK-GLOBISEL: // %bb.0: // %entry
339 ; CHECK-GLOBISEL-NEXT: adr x8, lbsrc
340 ; CHECK-GLOBISEL-NEXT: adr x9, lptr
341 ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8]
342 ; CHECK-GLOBISEL-NEXT: ldr x9, [x9]
343 ; CHECK-GLOBISEL-NEXT: strb w8, [x9]
344 ; CHECK-GLOBISEL-NEXT: ret
345 ;
346 ; CHECK-PIC-LABEL: baz3:
347 ; CHECK-PIC: // %bb.0: // %entry
348 ; CHECK-PIC-NEXT: adr x8, lbsrc
349 ; CHECK-PIC-NEXT: adr x9, lptr
350 ; CHECK-PIC-NEXT: ldrb w8, [x8]
351 ; CHECK-PIC-NEXT: ldr x9, [x9]
352 ; CHECK-PIC-NEXT: strb w8, [x9]
353 ; CHECK-PIC-NEXT: ret
354 ;
355 ; CHECK-PIC-GLOBISEL-LABEL: baz3:
356 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
357 ; CHECK-PIC-GLOBISEL-NEXT: adr x8, lbsrc
358 ; CHECK-PIC-GLOBISEL-NEXT: adr x9, lptr
359 ; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8]
360 ; CHECK-PIC-GLOBISEL-NEXT: ldr x9, [x9]
361 ; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9]
362 ; CHECK-PIC-GLOBISEL-NEXT: ret
363 entry:
364 %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbsrc, i64 0, i64 0), align 4
365 %1 = load i8*, i8** @lptr, align 8
366 store i8 %0, i8* %1, align 1
367 ret void
368 }
369
370
371 declare void @func(...)
372
373 define i8* @externfuncaddr() {
374 ; CHECK-LABEL: externfuncaddr:
375 ; CHECK: // %bb.0: // %entry
376 ; CHECK-NEXT: adr x0, func
377 ; CHECK-NEXT: ret
378 ;
379 ; CHECK-GLOBISEL-LABEL: externfuncaddr:
380 ; CHECK-GLOBISEL: // %bb.0: // %entry
381 ; CHECK-GLOBISEL-NEXT: adr x0, func
382 ; CHECK-GLOBISEL-NEXT: ret
383 ;
384 ; CHECK-PIC-LABEL: externfuncaddr:
385 ; CHECK-PIC: // %bb.0: // %entry
386 ; CHECK-PIC-NEXT: ldr x0, :got:func
387 ; CHECK-PIC-NEXT: ret
388 ;
389 ; CHECK-PIC-GLOBISEL-LABEL: externfuncaddr:
390 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
391 ; CHECK-PIC-GLOBISEL-NEXT: ldr x0, :got:func
392 ; CHECK-PIC-GLOBISEL-NEXT: ret
393 entry:
394 ret i8* bitcast (void (...)* @func to i8*)
395 }
396
397 define i8* @localfuncaddr() {
398 ; CHECK-LABEL: localfuncaddr:
399 ; CHECK: // %bb.0: // %entry
400 ; CHECK-NEXT: adr x0, externfuncaddr
401 ; CHECK-NEXT: ret
402 ;
403 ; CHECK-GLOBISEL-LABEL: localfuncaddr:
404 ; CHECK-GLOBISEL: // %bb.0: // %entry
405 ; CHECK-GLOBISEL-NEXT: adr x0, externfuncaddr
406 ; CHECK-GLOBISEL-NEXT: ret
407 ;
408 ; CHECK-PIC-LABEL: localfuncaddr:
409 ; CHECK-PIC: // %bb.0: // %entry
410 ; CHECK-PIC-NEXT: ldr x0, :got:externfuncaddr
411 ; CHECK-PIC-NEXT: ret
412 ;
413 ; CHECK-PIC-GLOBISEL-LABEL: localfuncaddr:
414 ; CHECK-PIC-GLOBISEL: // %bb.0: // %entry
415 ; CHECK-PIC-GLOBISEL-NEXT: ldr x0, :got:externfuncaddr
416 ; CHECK-PIC-GLOBISEL-NEXT: ret
417 entry:
418 ret i8* bitcast (i8* ()* @externfuncaddr to i8*)
419 }
420
0 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny < %s 2>&1 | FileCheck %s
1 ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-eabi -code-model=tiny < %s 2>&1 | FileCheck %s
2 ; RUN: not llc -verify-machineinstrs -o - -mtriple=arm64-apple-darwin -code-model=tiny < %s 2>&1 | FileCheck %s --check-prefix=NOTINY
3 ; RUN: not llc -verify-machineinstrs -o - -mtriple=arm64-apple-ios -code-model=tiny < %s 2>&1 | FileCheck %s --check-prefix=NOTINY
4 ; RUN: not llc -verify-machineinstrs -o - -mtriple=aarch64-unknown-windows-msvc -code-model=tiny < %s 2>&1 | FileCheck %s --check-prefix=NOTINY
5
6 ; CHECK-NOT: tiny code model is only supported on ELF
7 ; CHECK-LABEL: foo
8 ; NOTINY: tiny code model is only supported on ELF
9
10 define void @foo() {
11 ret void
12 }
33143314 //------------------------------------------------------------------------------
33153315
33163316 adr sp, loc // expects xzr
3317 adr x0, :got:loc // bad relocation type
33173318 adrp x3, #20 // Immediate unaligned
33183319 adrp w2, loc // 64-bit register needed
3320 adrp x5, :got_lo12:loc // bad relocation type
33193321 // CHECK-ERROR: error: invalid operand for instruction
33203322 // CHECK-ERROR-NEXT: adr sp, loc
3323 // CHECK-ERROR-NEXT: ^
3324 // CHECK-ERROR-NEXT: error: unexpected adr label
3325 // CHECK-ERROR-NEXT: adr x0, :got:loc
33213326 // CHECK-ERROR-NEXT: ^
33223327 // CHECK-ERROR-NEXT: error: expected label or encodable integer pc offset
33233328 // CHECK-ERROR-NEXT: adrp x3, #20
33253330 // CHECK-ERROR-NEXT: error: invalid operand for instruction
33263331 // CHECK-ERROR-NEXT: adrp w2, loc
33273332 // CHECK-ERROR-NEXT: ^
3333 // CHECK-ERROR-NEXT: error: page or gotpage label reference expected
3334 // CHECK-ERROR-NEXT: adrp x5, :got_lo12:loc
3335 // CHECK-ERROR-NEXT: ^
33283336
33293337 adr x9, #1048576
33303338 adr x2, #-1048577