llvm.org GIT mirror llvm / d3db945
Re-land r335297 "[X86] Implement more of x86-64 large and medium PIC code models" Don't try to generate large PIC code for non-ELF targets. Neither COFF nor MachO have relocations for large position independent code, and users have been using "large PIC" code models to JIT 64-bit code for a while now. With this change, if they are generating ELF code, their JITed code will truly be PIC, but if they target MachO or COFF, it will contain 64-bit immediates that directly reference external symbols. For a JIT, that's perfectly fine. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337740 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 1 year, 11 months ago
15 changed file(s) with 546 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
990990
991991 bool IsRIPRel = N.getOpcode() == X86ISD::WrapperRIP;
992992
993 // Only do this address mode folding for 64-bit if we're in the small code
994 // model.
995 // FIXME: But we can do GOTPCREL addressing in the medium code model.
993 // We can't use an addressing mode in the 64-bit large code model. In the
994 // medium code model, we use can use an mode when RIP wrappers are present.
995 // That signifies access to globals that are known to be "near", such as the
996 // GOT itself.
996997 CodeModel::Model M = TM.getCodeModel();
997 if (Subtarget->is64Bit() && M != CodeModel::Small && M != CodeModel::Kernel)
998 if (Subtarget->is64Bit() &&
999 (M == CodeModel::Large || (M == CodeModel::Medium && !IsRIPRel)))
9981000 return true;
9991001
10001002 // Base and index reg must be 0 in order to use %rip as base.
3636 def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label),
3737 "", []>;
3838
39 // 64-bit large code model PIC base construction.
40 let hasSideEffects = 0, mayLoad = 1, isNotDuplicable = 1, SchedRW = [WriteJump] in
41 def MOVGOT64r : PseudoI<(outs GR64:$reg),
42 (ins GR64:$scratch, i64i32imm_pcrel:$got), []>;
3943
4044 // ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
4145 // a stack adjustment and the codegen must know that they may modify the stack
58505850 /// TODO: Eliminate this and move the code to X86MachineFunctionInfo.
58515851 ///
58525852 unsigned X86InstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
5853 assert(!Subtarget.is64Bit() &&
5853 assert((!Subtarget.is64Bit() ||
5854 MF->getTarget().getCodeModel() == CodeModel::Medium ||
5855 MF->getTarget().getCodeModel() == CodeModel::Large) &&
58545856 "X86-64 PIC uses RIP relative addressing");
58555857
58565858 X86MachineFunctionInfo *X86FI = MF->getInfo();
58615863 // Create the register. The code to initialize it is inserted
58625864 // later, by the CGBR pass (below).
58635865 MachineRegisterInfo &RegInfo = MF->getRegInfo();
5864 GlobalBaseReg = RegInfo.createVirtualRegister(&X86::GR32_NOSPRegClass);
5866 GlobalBaseReg = RegInfo.createVirtualRegister(
5867 Subtarget.is64Bit() ? &X86::GR64_NOSPRegClass : &X86::GR32_NOSPRegClass);
58655868 X86FI->setGlobalBaseReg(GlobalBaseReg);
58665869 return GlobalBaseReg;
58675870 }
73207323 static_cast(&MF.getTarget());
73217324 const X86Subtarget &STI = MF.getSubtarget();
73227325
7323 // Don't do anything if this is 64-bit as 64-bit PIC
7324 // uses RIP relative addressing.
7325 if (STI.is64Bit())
7326 // Don't do anything in the 64-bit small and kernel code models. They use
7327 // RIP-relative addressing for everything.
7328 if (STI.is64Bit() && (TM->getCodeModel() == CodeModel::Small ||
7329 TM->getCodeModel() == CodeModel::Kernel))
73267330 return false;
73277331
73287332 // Only emit a global base reg in PIC mode.
73497353 else
73507354 PC = GlobalBaseReg;
73517355
7352 // Operand of MovePCtoStack is completely ignored by asm printer. It's
7353 // only used in JIT code emission as displacement to pc.
7354 BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0);
7355
7356 // If we're using vanilla 'GOT' PIC style, we should use relative addressing
7357 // not to pc, but to _GLOBAL_OFFSET_TABLE_ external.
7358 if (STI.isPICStyleGOT()) {
7359 // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel], %some_register
7360 BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg)
7361 .addReg(PC).addExternalSymbol("_GLOBAL_OFFSET_TABLE_",
7362 X86II::MO_GOT_ABSOLUTE_ADDRESS);
7356 if (STI.is64Bit()) {
7357 if (TM->getCodeModel() == CodeModel::Medium) {
7358 // In the medium code model, use a RIP-relative LEA to materialize the
7359 // GOT.
7360 BuildMI(FirstMBB, MBBI, DL, TII->get(X86::LEA64r), PC)
7361 .addReg(X86::RIP)
7362 .addImm(0)
7363 .addReg(0)
7364 .addExternalSymbol("_GLOBAL_OFFSET_TABLE_")
7365 .addReg(0);
7366 } else if (TM->getCodeModel() == CodeModel::Large) {
7367 // Loading the GOT in the large code model requires math with labels,
7368 // so we use a pseudo instruction and expand it during MC emission.
7369 unsigned Scratch = RegInfo.createVirtualRegister(&X86::GR64RegClass);
7370 BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVGOT64r), PC)
7371 .addReg(Scratch, RegState::Undef | RegState::Define)
7372 .addExternalSymbol("_GLOBAL_OFFSET_TABLE_");
7373 } else {
7374 llvm_unreachable("unexpected code model");
7375 }
7376 } else {
7377 // Operand of MovePCtoStack is completely ignored by asm printer. It's
7378 // only used in JIT code emission as displacement to pc.
7379 BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0);
7380
7381 // If we're using vanilla 'GOT' PIC style, we should use relative
7382 // addressing not to pc, but to _GLOBAL_OFFSET_TABLE_ external.
7383 if (STI.isPICStyleGOT()) {
7384 // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel],
7385 // %some_register
7386 BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg)
7387 .addReg(PC)
7388 .addExternalSymbol("_GLOBAL_OFFSET_TABLE_",
7389 X86II::MO_GOT_ABSOLUTE_ADDRESS);
7390 }
73637391 }
73647392
73657393 return true;
17191719 return;
17201720 }
17211721
1722 case X86::MOVGOT64r: {
1723 // Materializes the GOT for the 64-bit large code model.
1724 MCSymbol *DotSym = OutContext.createTempSymbol();
1725 OutStreamer->EmitLabel(DotSym);
1726
1727 unsigned DstReg = MI->getOperand(0).getReg();
1728 unsigned ScratchReg = MI->getOperand(1).getReg();
1729 MCSymbol *GOTSym = MCInstLowering.GetSymbolFromOperand(MI->getOperand(2));
1730
1731 // .LtmpN: leaq .LtmpN(%rip), %dst
1732 const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);
1733 EmitAndCountInstruction(MCInstBuilder(X86::LEA64r)
1734 .addReg(DstReg) // dest
1735 .addReg(X86::RIP) // base
1736 .addImm(1) // scale
1737 .addReg(0) // index
1738 .addExpr(DotExpr) // disp
1739 .addReg(0)); // seg
1740
1741 // movq $_GLOBAL_OFFSET_TABLE_ - .LtmpN, %scratch
1742 const MCExpr *GOTSymExpr = MCSymbolRefExpr::create(GOTSym, OutContext);
1743 const MCExpr *GOTDiffExpr =
1744 MCBinaryExpr::createSub(GOTSymExpr, DotExpr, OutContext);
1745 EmitAndCountInstruction(MCInstBuilder(X86::MOV64ri)
1746 .addReg(ScratchReg) // dest
1747 .addExpr(GOTDiffExpr)); // disp
1748
1749 // addq %scratch, %dst
1750 EmitAndCountInstruction(MCInstBuilder(X86::ADD64rr)
1751 .addReg(DstReg) // dest
1752 .addReg(DstReg) // dest
1753 .addReg(ScratchReg)); // src
1754 return;
1755 }
1756
17221757 case X86::ADD32ri: {
17231758 // Lower the MO_GOT_ABSOLUTE_ADDRESS form of ADD32ri.
17241759 if (MI->getOperand(2).getTargetFlags() != X86II::MO_GOT_ABSOLUTE_ADDRESS)
6767
6868 unsigned char
6969 X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
70 // 64 bits can use %rip addressing for anything local.
71 if (is64Bit())
72 return X86II::MO_NO_FLAG;
73
74 // If this is for a position dependent executable, the static linker can
75 // figure it out.
70 // If we're not PIC, it's not very interesting.
7671 if (!isPositionIndependent())
7772 return X86II::MO_NO_FLAG;
73
74 if (is64Bit()) {
75 // 64-bit ELF PIC local references may use GOTOFF relocations.
76 if (isTargetELF()) {
77 switch (TM.getCodeModel()) {
78 // 64-bit small code model is simple: All rip-relative.
79 case CodeModel::Small:
80 case CodeModel::Kernel:
81 return X86II::MO_NO_FLAG;
82
83 // The large PIC code model uses GOTOFF.
84 case CodeModel::Large:
85 return X86II::MO_GOTOFF;
86
87 // Medium is a hybrid: RIP-rel for code, GOTOFF for DSO local data.
88 case CodeModel::Medium:
89 if (isa(GV))
90 return X86II::MO_NO_FLAG; // All code is RIP-relative
91 return X86II::MO_GOTOFF; // Local symbols use GOTOFF.
92 }
93 llvm_unreachable("invalid code model");
94 }
95
96 // Otherwise, this is either a RIP-relative reference or a 64-bit movabsq,
97 // both of which use MO_NO_FLAG.
98 return X86II::MO_NO_FLAG;
99 }
78100
79101 // The COFF dynamic linker just patches the executable sections.
80102 if (isTargetCOFF())
96118
97119 unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV,
98120 const Module &M) const {
99 // Large model never uses stubs.
100 if (TM.getCodeModel() == CodeModel::Large)
121 // The static large model never uses stubs.
122 if (TM.getCodeModel() == CodeModel::Large && !isPositionIndependent())
101123 return X86II::MO_NO_FLAG;
102124
103125 // Absolute symbols can be referenced directly.
119141 if (isTargetCOFF())
120142 return X86II::MO_DLLIMPORT;
121143
122 if (is64Bit())
144 if (is64Bit()) {
145 // ELF supports a large, truly PIC code model with non-PC relative GOT
146 // references. Other object file formats do not. Use the no-flag, 64-bit
147 // reference for them.
148 if (TM.getCodeModel() == CodeModel::Large)
149 return isTargetELF() ? X86II::MO_GOT : X86II::MO_NO_FLAG;
123150 return X86II::MO_GOTPCREL;
151 }
124152
125153 if (isTargetDarwin()) {
126154 if (!isPositionIndependent())
159159 }
160160
161161 static Reloc::Model getEffectiveRelocModel(const Triple &TT,
162 bool JIT,
162163 Optional RM) {
163164 bool is64Bit = TT.getArch() == Triple::x86_64;
164165 if (!RM.hasValue()) {
166 // JIT codegen should use static relocations by default, since it's
167 // typically executed in process and not relocatable.
168 if (JIT)
169 return Reloc::Static;
170
165171 // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode.
166172 // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we
167173 // use static relocation model by default.
213219 CodeGenOpt::Level OL, bool JIT)
214220 : LLVMTargetMachine(
215221 T, computeDataLayout(TT), TT, CPU, FS, Options,
216 getEffectiveRelocModel(TT, RM),
222 getEffectiveRelocModel(TT, JIT, RM),
217223 getEffectiveCodeModel(CM, JIT, TT.getArch() == Triple::x86_64), OL),
218224 TLOF(createTLOF(getTargetTriple())) {
219225 // Windows stack unwinder gets confused when execution flow "falls through"
None ; RUN: llc -mtriple=x86_64-pc-windows-msvc -code-model=large -o - < %s | FileCheck %s
0 ; RUN: llc -mtriple=x86_64-pc-windows-msvc -code-model=large -relocation-model=static -o - < %s | FileCheck %s
11
22 declare i32 @__CxxFrameHandler3(...)
33
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; Run with --no_x86_scrub_rip because we care a lot about how globals are
2 ; accessed in the code model.
3
4 ; RUN: llc < %s -relocation-model=static -code-model=small | FileCheck %s --check-prefix=CHECK --check-prefix=SMALL-STATIC
5 ; RUN: llc < %s -relocation-model=static -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-STATIC
6 ; RUN: llc < %s -relocation-model=static -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-STATIC
7 ; RUN: llc < %s -relocation-model=pic -code-model=small | FileCheck %s --check-prefix=CHECK --check-prefix=SMALL-PIC
8 ; RUN: llc < %s -relocation-model=pic -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-PIC
9 ; RUN: llc < %s -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC
10
11 ; Generated from this C source:
12 ;
13 ; static int static_data[10];
14 ; int global_data[10] = {1, 2};
15 ; extern int extern_data[10];
16 ;
17 ; int *lea_static_data() { return &static_data[0]; }
18 ; int *lea_global_data() { return &global_data[0]; }
19 ; int *lea_extern_data() { return &extern_data[0]; }
20 ;
21 ; static void static_fn(void) {}
22 ; void global_fn(void) {}
23 ; void extern_fn(void);
24 ;
25 ; typedef void (*void_fn)(void);
26 ; void_fn lea_static_fn() { return &static_fn; }
27 ; void_fn lea_global_fn() { return &global_fn; }
28 ; void_fn lea_extern_fn() { return &extern_fn; }
29
30
31 ; ModuleID = 'model.c'
32 source_filename = "model.c"
33 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
34 target triple = "x86_64--linux"
35
36 @global_data = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16
37 @static_data = internal global [10 x i32] zeroinitializer, align 16
38 @extern_data = external global [10 x i32], align 16
39
40 define dso_local i32* @lea_static_data() #0 {
41 ; SMALL-STATIC-LABEL: lea_static_data:
42 ; SMALL-STATIC: # %bb.0:
43 ; SMALL-STATIC-NEXT: movl $static_data, %eax
44 ; SMALL-STATIC-NEXT: retq
45 ;
46 ; MEDIUM-STATIC-LABEL: lea_static_data:
47 ; MEDIUM-STATIC: # %bb.0:
48 ; MEDIUM-STATIC-NEXT: movabsq $static_data, %rax
49 ; MEDIUM-STATIC-NEXT: retq
50 ;
51 ; LARGE-STATIC-LABEL: lea_static_data:
52 ; LARGE-STATIC: # %bb.0:
53 ; LARGE-STATIC-NEXT: movabsq $static_data, %rax
54 ; LARGE-STATIC-NEXT: retq
55 ;
56 ; SMALL-PIC-LABEL: lea_static_data:
57 ; SMALL-PIC: # %bb.0:
58 ; SMALL-PIC-NEXT: leaq static_data(%rip), %rax
59 ; SMALL-PIC-NEXT: retq
60 ;
61 ; MEDIUM-PIC-LABEL: lea_static_data:
62 ; MEDIUM-PIC: # %bb.0:
63 ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx
64 ; MEDIUM-PIC-NEXT: movabsq $static_data@GOTOFF, %rax
65 ; MEDIUM-PIC-NEXT: addq %rcx, %rax
66 ; MEDIUM-PIC-NEXT: retq
67 ;
68 ; LARGE-PIC-LABEL: lea_static_data:
69 ; LARGE-PIC: # %bb.0:
70 ; LARGE-PIC-NEXT: .Ltmp0:
71 ; LARGE-PIC-NEXT: leaq .Ltmp0(%rip), %rcx
72 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp0, %rax
73 ; LARGE-PIC-NEXT: addq %rax, %rcx
74 ; LARGE-PIC-NEXT: movabsq $static_data@GOTOFF, %rax
75 ; LARGE-PIC-NEXT: addq %rcx, %rax
76 ; LARGE-PIC-NEXT: retq
77 ret i32* getelementptr inbounds ([10 x i32], [10 x i32]* @static_data, i64 0, i64 0)
78 }
79
80 define dso_local i32* @lea_global_data() #0 {
81 ; SMALL-STATIC-LABEL: lea_global_data:
82 ; SMALL-STATIC: # %bb.0:
83 ; SMALL-STATIC-NEXT: movl $global_data, %eax
84 ; SMALL-STATIC-NEXT: retq
85 ;
86 ; MEDIUM-STATIC-LABEL: lea_global_data:
87 ; MEDIUM-STATIC: # %bb.0:
88 ; MEDIUM-STATIC-NEXT: movabsq $global_data, %rax
89 ; MEDIUM-STATIC-NEXT: retq
90 ;
91 ; LARGE-STATIC-LABEL: lea_global_data:
92 ; LARGE-STATIC: # %bb.0:
93 ; LARGE-STATIC-NEXT: movabsq $global_data, %rax
94 ; LARGE-STATIC-NEXT: retq
95 ;
96 ; SMALL-PIC-LABEL: lea_global_data:
97 ; SMALL-PIC: # %bb.0:
98 ; SMALL-PIC-NEXT: leaq global_data(%rip), %rax
99 ; SMALL-PIC-NEXT: retq
100 ;
101 ; MEDIUM-PIC-LABEL: lea_global_data:
102 ; MEDIUM-PIC: # %bb.0:
103 ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx
104 ; MEDIUM-PIC-NEXT: movabsq $global_data@GOTOFF, %rax
105 ; MEDIUM-PIC-NEXT: addq %rcx, %rax
106 ; MEDIUM-PIC-NEXT: retq
107 ;
108 ; LARGE-PIC-LABEL: lea_global_data:
109 ; LARGE-PIC: # %bb.0:
110 ; LARGE-PIC-NEXT: .Ltmp1:
111 ; LARGE-PIC-NEXT: leaq .Ltmp1(%rip), %rcx
112 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp1, %rax
113 ; LARGE-PIC-NEXT: addq %rax, %rcx
114 ; LARGE-PIC-NEXT: movabsq $global_data@GOTOFF, %rax
115 ; LARGE-PIC-NEXT: addq %rcx, %rax
116 ; LARGE-PIC-NEXT: retq
117 ret i32* getelementptr inbounds ([10 x i32], [10 x i32]* @global_data, i64 0, i64 0)
118 }
119
120 define dso_local i32* @lea_extern_data() #0 {
121 ; SMALL-STATIC-LABEL: lea_extern_data:
122 ; SMALL-STATIC: # %bb.0:
123 ; SMALL-STATIC-NEXT: movl $extern_data, %eax
124 ; SMALL-STATIC-NEXT: retq
125 ;
126 ; MEDIUM-STATIC-LABEL: lea_extern_data:
127 ; MEDIUM-STATIC: # %bb.0:
128 ; MEDIUM-STATIC-NEXT: movabsq $extern_data, %rax
129 ; MEDIUM-STATIC-NEXT: retq
130 ;
131 ; LARGE-STATIC-LABEL: lea_extern_data:
132 ; LARGE-STATIC: # %bb.0:
133 ; LARGE-STATIC-NEXT: movabsq $extern_data, %rax
134 ; LARGE-STATIC-NEXT: retq
135 ;
136 ; SMALL-PIC-LABEL: lea_extern_data:
137 ; SMALL-PIC: # %bb.0:
138 ; SMALL-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax
139 ; SMALL-PIC-NEXT: retq
140 ;
141 ; MEDIUM-PIC-LABEL: lea_extern_data:
142 ; MEDIUM-PIC: # %bb.0:
143 ; MEDIUM-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax
144 ; MEDIUM-PIC-NEXT: retq
145 ;
146 ; LARGE-PIC-LABEL: lea_extern_data:
147 ; LARGE-PIC: # %bb.0:
148 ; LARGE-PIC-NEXT: .Ltmp2:
149 ; LARGE-PIC-NEXT: leaq .Ltmp2(%rip), %rax
150 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp2, %rcx
151 ; LARGE-PIC-NEXT: addq %rcx, %rax
152 ; LARGE-PIC-NEXT: movabsq $extern_data@GOT, %rcx
153 ; LARGE-PIC-NEXT: movq (%rax,%rcx), %rax
154 ; LARGE-PIC-NEXT: retq
155 ret i32* getelementptr inbounds ([10 x i32], [10 x i32]* @extern_data, i64 0, i64 0)
156 }
157
158 define dso_local i32 @load_global_data() #0 {
159 ; SMALL-STATIC-LABEL: load_global_data:
160 ; SMALL-STATIC: # %bb.0:
161 ; SMALL-STATIC-NEXT: movl global_data+8(%rip), %eax
162 ; SMALL-STATIC-NEXT: retq
163 ;
164 ; MEDIUM-STATIC-LABEL: load_global_data:
165 ; MEDIUM-STATIC: # %bb.0:
166 ; MEDIUM-STATIC-NEXT: movabsq $global_data, %rax
167 ; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax
168 ; MEDIUM-STATIC-NEXT: retq
169 ;
170 ; LARGE-STATIC-LABEL: load_global_data:
171 ; LARGE-STATIC: # %bb.0:
172 ; LARGE-STATIC-NEXT: movabsq $global_data, %rax
173 ; LARGE-STATIC-NEXT: movl 8(%rax), %eax
174 ; LARGE-STATIC-NEXT: retq
175 ;
176 ; SMALL-PIC-LABEL: load_global_data:
177 ; SMALL-PIC: # %bb.0:
178 ; SMALL-PIC-NEXT: movl global_data+8(%rip), %eax
179 ; SMALL-PIC-NEXT: retq
180 ;
181 ; MEDIUM-PIC-LABEL: load_global_data:
182 ; MEDIUM-PIC: # %bb.0:
183 ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax
184 ; MEDIUM-PIC-NEXT: movabsq $global_data@GOTOFF, %rcx
185 ; MEDIUM-PIC-NEXT: movl 8(%rax,%rcx), %eax
186 ; MEDIUM-PIC-NEXT: retq
187 ;
188 ; LARGE-PIC-LABEL: load_global_data:
189 ; LARGE-PIC: # %bb.0:
190 ; LARGE-PIC-NEXT: .Ltmp3:
191 ; LARGE-PIC-NEXT: leaq .Ltmp3(%rip), %rax
192 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp3, %rcx
193 ; LARGE-PIC-NEXT: addq %rcx, %rax
194 ; LARGE-PIC-NEXT: movabsq $global_data@GOTOFF, %rcx
195 ; LARGE-PIC-NEXT: movl 8(%rax,%rcx), %eax
196 ; LARGE-PIC-NEXT: retq
197 %rv = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @global_data, i64 0, i64 2)
198 ret i32 %rv
199 }
200
201 define dso_local i32 @load_extern_data() #0 {
202 ; SMALL-STATIC-LABEL: load_extern_data:
203 ; SMALL-STATIC: # %bb.0:
204 ; SMALL-STATIC-NEXT: movl extern_data+8(%rip), %eax
205 ; SMALL-STATIC-NEXT: retq
206 ;
207 ; MEDIUM-STATIC-LABEL: load_extern_data:
208 ; MEDIUM-STATIC: # %bb.0:
209 ; MEDIUM-STATIC-NEXT: movabsq $extern_data, %rax
210 ; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax
211 ; MEDIUM-STATIC-NEXT: retq
212 ;
213 ; LARGE-STATIC-LABEL: load_extern_data:
214 ; LARGE-STATIC: # %bb.0:
215 ; LARGE-STATIC-NEXT: movabsq $extern_data, %rax
216 ; LARGE-STATIC-NEXT: movl 8(%rax), %eax
217 ; LARGE-STATIC-NEXT: retq
218 ;
219 ; SMALL-PIC-LABEL: load_extern_data:
220 ; SMALL-PIC: # %bb.0:
221 ; SMALL-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax
222 ; SMALL-PIC-NEXT: movl 8(%rax), %eax
223 ; SMALL-PIC-NEXT: retq
224 ;
225 ; MEDIUM-PIC-LABEL: load_extern_data:
226 ; MEDIUM-PIC: # %bb.0:
227 ; MEDIUM-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax
228 ; MEDIUM-PIC-NEXT: movl 8(%rax), %eax
229 ; MEDIUM-PIC-NEXT: retq
230 ;
231 ; LARGE-PIC-LABEL: load_extern_data:
232 ; LARGE-PIC: # %bb.0:
233 ; LARGE-PIC-NEXT: .Ltmp4:
234 ; LARGE-PIC-NEXT: leaq .Ltmp4(%rip), %rax
235 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp4, %rcx
236 ; LARGE-PIC-NEXT: addq %rcx, %rax
237 ; LARGE-PIC-NEXT: movabsq $extern_data@GOT, %rcx
238 ; LARGE-PIC-NEXT: movq (%rax,%rcx), %rax
239 ; LARGE-PIC-NEXT: movl 8(%rax), %eax
240 ; LARGE-PIC-NEXT: retq
241 %rv = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @extern_data, i64 0, i64 2)
242 ret i32 %rv
243 }
244
245 define dso_local void @global_fn() #0 {
246 ; CHECK-LABEL: global_fn:
247 ; CHECK: # %bb.0:
248 ; CHECK-NEXT: retq
249 ret void
250 }
251
252 define internal void @static_fn() #0 {
253 ; CHECK-LABEL: static_fn:
254 ; CHECK: # %bb.0:
255 ; CHECK-NEXT: retq
256 ret void
257 }
258
259 declare void @extern_fn()
260
261 define dso_local void ()* @lea_static_fn() #0 {
262 ; SMALL-STATIC-LABEL: lea_static_fn:
263 ; SMALL-STATIC: # %bb.0:
264 ; SMALL-STATIC-NEXT: movl $static_fn, %eax
265 ; SMALL-STATIC-NEXT: retq
266 ;
267 ; MEDIUM-STATIC-LABEL: lea_static_fn:
268 ; MEDIUM-STATIC: # %bb.0:
269 ; MEDIUM-STATIC-NEXT: movabsq $static_fn, %rax
270 ; MEDIUM-STATIC-NEXT: retq
271 ;
272 ; LARGE-STATIC-LABEL: lea_static_fn:
273 ; LARGE-STATIC: # %bb.0:
274 ; LARGE-STATIC-NEXT: movabsq $static_fn, %rax
275 ; LARGE-STATIC-NEXT: retq
276 ;
277 ; SMALL-PIC-LABEL: lea_static_fn:
278 ; SMALL-PIC: # %bb.0:
279 ; SMALL-PIC-NEXT: leaq static_fn(%rip), %rax
280 ; SMALL-PIC-NEXT: retq
281 ;
282 ; MEDIUM-PIC-LABEL: lea_static_fn:
283 ; MEDIUM-PIC: # %bb.0:
284 ; MEDIUM-PIC-NEXT: movabsq $static_fn, %rax
285 ; MEDIUM-PIC-NEXT: retq
286 ;
287 ; LARGE-PIC-LABEL: lea_static_fn:
288 ; LARGE-PIC: # %bb.0:
289 ; LARGE-PIC-NEXT: .Ltmp5:
290 ; LARGE-PIC-NEXT: leaq .Ltmp5(%rip), %rcx
291 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp5, %rax
292 ; LARGE-PIC-NEXT: addq %rax, %rcx
293 ; LARGE-PIC-NEXT: movabsq $static_fn@GOTOFF, %rax
294 ; LARGE-PIC-NEXT: addq %rcx, %rax
295 ; LARGE-PIC-NEXT: retq
296 ret void ()* @static_fn
297 }
298
299 define dso_local void ()* @lea_global_fn() #0 {
300 ; SMALL-STATIC-LABEL: lea_global_fn:
301 ; SMALL-STATIC: # %bb.0:
302 ; SMALL-STATIC-NEXT: movl $global_fn, %eax
303 ; SMALL-STATIC-NEXT: retq
304 ;
305 ; MEDIUM-STATIC-LABEL: lea_global_fn:
306 ; MEDIUM-STATIC: # %bb.0:
307 ; MEDIUM-STATIC-NEXT: movabsq $global_fn, %rax
308 ; MEDIUM-STATIC-NEXT: retq
309 ;
310 ; LARGE-STATIC-LABEL: lea_global_fn:
311 ; LARGE-STATIC: # %bb.0:
312 ; LARGE-STATIC-NEXT: movabsq $global_fn, %rax
313 ; LARGE-STATIC-NEXT: retq
314 ;
315 ; SMALL-PIC-LABEL: lea_global_fn:
316 ; SMALL-PIC: # %bb.0:
317 ; SMALL-PIC-NEXT: leaq global_fn(%rip), %rax
318 ; SMALL-PIC-NEXT: retq
319 ;
320 ; MEDIUM-PIC-LABEL: lea_global_fn:
321 ; MEDIUM-PIC: # %bb.0:
322 ; MEDIUM-PIC-NEXT: movabsq $global_fn, %rax
323 ; MEDIUM-PIC-NEXT: retq
324 ;
325 ; LARGE-PIC-LABEL: lea_global_fn:
326 ; LARGE-PIC: # %bb.0:
327 ; LARGE-PIC-NEXT: .Ltmp6:
328 ; LARGE-PIC-NEXT: leaq .Ltmp6(%rip), %rcx
329 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp6, %rax
330 ; LARGE-PIC-NEXT: addq %rax, %rcx
331 ; LARGE-PIC-NEXT: movabsq $global_fn@GOTOFF, %rax
332 ; LARGE-PIC-NEXT: addq %rcx, %rax
333 ; LARGE-PIC-NEXT: retq
334 ret void ()* @global_fn
335 }
336
337 define dso_local void ()* @lea_extern_fn() #0 {
338 ; SMALL-STATIC-LABEL: lea_extern_fn:
339 ; SMALL-STATIC: # %bb.0:
340 ; SMALL-STATIC-NEXT: movl $extern_fn, %eax
341 ; SMALL-STATIC-NEXT: retq
342 ;
343 ; MEDIUM-STATIC-LABEL: lea_extern_fn:
344 ; MEDIUM-STATIC: # %bb.0:
345 ; MEDIUM-STATIC-NEXT: movabsq $extern_fn, %rax
346 ; MEDIUM-STATIC-NEXT: retq
347 ;
348 ; LARGE-STATIC-LABEL: lea_extern_fn:
349 ; LARGE-STATIC: # %bb.0:
350 ; LARGE-STATIC-NEXT: movabsq $extern_fn, %rax
351 ; LARGE-STATIC-NEXT: retq
352 ;
353 ; SMALL-PIC-LABEL: lea_extern_fn:
354 ; SMALL-PIC: # %bb.0:
355 ; SMALL-PIC-NEXT: movq extern_fn@GOTPCREL(%rip), %rax
356 ; SMALL-PIC-NEXT: retq
357 ;
358 ; MEDIUM-PIC-LABEL: lea_extern_fn:
359 ; MEDIUM-PIC: # %bb.0:
360 ; MEDIUM-PIC-NEXT: movq extern_fn@GOTPCREL(%rip), %rax
361 ; MEDIUM-PIC-NEXT: retq
362 ;
363 ; LARGE-PIC-LABEL: lea_extern_fn:
364 ; LARGE-PIC: # %bb.0:
365 ; LARGE-PIC-NEXT: .Ltmp7:
366 ; LARGE-PIC-NEXT: leaq .Ltmp7(%rip), %rax
367 ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp7, %rcx
368 ; LARGE-PIC-NEXT: addq %rcx, %rax
369 ; LARGE-PIC-NEXT: movabsq $extern_fn@GOT, %rcx
370 ; LARGE-PIC-NEXT: movq (%rax,%rcx), %rax
371 ; LARGE-PIC-NEXT: retq
372 ret void ()* @extern_fn
373 }
374
375 attributes #0 = { noinline nounwind uwtable }
376
377 !llvm.module.flags = !{!0, !1, !2}
378 !llvm.ident = !{!3}
379
380 !0 = !{i32 1, !"wchar_size", i32 4}
381 !1 = !{i32 7, !"PIC Level", i32 2}
382 !2 = !{i32 7, !"PIE Level", i32 2}
383 !3 = !{!"clang version 7.0.0 "}
None ; RUN: llc -fast-isel-sink-local-values -fast-isel -O0 -code-model=large -mcpu=generic -mtriple=x86_64-apple-darwin10 -relocation-model=pic < %s | FileCheck %s
0 ; RUN: llc -fast-isel-sink-local-values -fast-isel -O0 -code-model=large -mcpu=generic -mtriple=x86_64-linux -relocation-model=static < %s | FileCheck %s
11
22 ; Check that fast-isel cleans up when it fails to lower a call instruction.
33 define void @fastiselcall() {
88 ; FastISel's local value code was dead, so it's gone.
99 ; CHECK-NOT: movl $42,
1010 ; SDag-ISel's arg mov:
11 ; CHECK: movabsq $_targetfn, %[[REG:[^ ]*]]
11 ; CHECK: movabsq $targetfn, %[[REG:[^ ]*]]
1212 ; CHECK: movl $42, %edi
1313 ; CHECK: callq *%[[REG]]
1414
None ; RUN: llc < %s -stack-symbol-ordering=0 -tailcallopt -code-model=medium -stack-alignment=8 -mtriple=x86_64-linux-gnu -mcpu=opteron | FileCheck %s
0 ; RUN: llc < %s -stack-symbol-ordering=0 -tailcallopt -relocation-model=static -code-model=medium -stack-alignment=8 -mtriple=x86_64-linux-gnu -mcpu=opteron | FileCheck %s
11
22 ; Check the HiPE calling convention works (x86-64)
33
None ; RUN: llc < %s -relocation-model=pic -code-model=large
0 ; RUN: llc < %s -relocation-model=pic -code-model=large | FileCheck %s
1
2 ; CHECK-LABEL: foo:
3 ; CHECK: movabsq $_xscanf, %[[REG:[^ ]*]]
4 ; CHECK: callq *%[[REG]]
15
26 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
37 target triple = "x86_64-apple-darwin8"
1414 unreachable
1515 }
1616
17 ; Make an internal function so we exercise R_X86_64_GOTOFF64 relocations.
18 define internal dso_local void @use_gotoff() {
19 ret void
20 }
21
1722 define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
1823 entry:
24 call void @use_gotoff()
1925 invoke void @throwException()
2026 to label %try.cont unwind label %lpad
2127
1414 unreachable
1515 }
1616
17 ; Make an internal function so we exercise R_X86_64_GOTOFF64 relocations.
18 define internal dso_local void @use_gotoff() {
19 ret void
20 }
21
1722 define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
1823 entry:
24 call void @use_gotoff()
1925 invoke void @throwException()
2026 to label %try.cont unwind label %lpad
2127
109109 asm = SCRUB_X86_SPILL_RELOAD_RE.sub(r'{{[-0-9]+}}(%\1{{[sb]}}p)\2', asm)
110110 # Generically match the stack offset of a memory operand.
111111 asm = SCRUB_X86_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm)
112 # Generically match a RIP-relative memory operand.
113 asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm)
112 if getattr(args, 'x86_scrub_rip', False):
113 # Generically match a RIP-relative memory operand.
114 asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm)
114115 # Generically match a LCP symbol.
115116 asm = SCRUB_X86_LCP_RE.sub(r'{{\.LCPI.*}}', asm)
116117 if getattr(args, 'extra_scrub', False):
2929 parser.add_argument(
3030 '--extra_scrub', action='store_true',
3131 help='Always use additional regex to further reduce diffs between various subtargets')
32 parser.add_argument(
33 '--x86_scrub_rip', action='store_true', default=True,
34 help='Use more regex for x86 matching to reduce diffs between various subtargets')
35 parser.add_argument(
36 '--no_x86_scrub_rip', action='store_false', dest='x86_scrub_rip')
3237 parser.add_argument('tests', nargs='+')
3338 args = parser.parse_args()
3439