llvm.org GIT mirror llvm / 9e0b9aa
[GlobalISel][X86] G_FCONSTANT support. Summary: G_FCONSTANT support, port the implementation from X86FastIsel. Reviewers: zvi, delena, guyblank Reviewed By: delena Subscribers: rovka, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D37734 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313478 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Breger 2 years ago
7 changed file(s) with 261 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
2020 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
2121 #include "llvm/CodeGen/GlobalISel/Utils.h"
2222 #include "llvm/CodeGen/MachineBasicBlock.h"
23 #include "llvm/CodeGen/MachineConstantPool.h"
2324 #include "llvm/CodeGen/MachineFunction.h"
2425 #include "llvm/CodeGen/MachineInstr.h"
2526 #include "llvm/CodeGen/MachineInstrBuilder.h"
5455 bool selectImpl(MachineInstr &I) const;
5556
5657 // TODO: remove after supported by Tablegen-erated instruction selection.
57 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
58 unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned Opc,
5859 uint64_t Alignment) const;
5960
6061 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
8687 MachineFunction &MF) const;
8788 bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
8889 MachineFunction &MF) const;
90 bool materializeFP(MachineInstr &I, MachineRegisterInfo &MRI,
91 MachineFunction &MF) const;
8992 bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;
9093
9194 // emit insert subreg instruction and insert it before MachineInstr &I
335338 return true;
336339 if (selectCondBranch(I, MRI, MF))
337340 return true;
341 if (materializeFP(I, MRI, MF))
342 return true;
338343 if (selectImplicitDefOrPHI(I, MRI))
339344 return true;
340345
341346 return false;
342347 }
343348
344 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
349 unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty,
350 const RegisterBank &RB,
345351 unsigned Opc,
346352 uint64_t Alignment) const {
347353 bool Isload = (Opc == TargetOpcode::G_LOAD);
739745 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
740746 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
741747
742 assert (DstRB.getID() == SrcRB.getID() &&
743 "G_ANYEXT input/output on different banks\n");
744
745 assert (DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
746 "G_ANYEXT incorrect operand size");
748 assert(DstRB.getID() == SrcRB.getID() &&
749 "G_ANYEXT input/output on different banks\n");
750
751 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
752 "G_ANYEXT incorrect operand size");
747753
748754 if (DstRB.getID() != X86::GPRRegBankID)
749755 return false;
11821188 return true;
11831189 }
11841190
1191 bool X86InstructionSelector::materializeFP(MachineInstr &I,
1192 MachineRegisterInfo &MRI,
1193 MachineFunction &MF) const {
1194 if (I.getOpcode() != TargetOpcode::G_FCONSTANT)
1195 return false;
1196
1197 // Can't handle alternate code models yet.
1198 CodeModel::Model CM = TM.getCodeModel();
1199 if (CM != CodeModel::Small && CM != CodeModel::Large)
1200 return false;
1201
1202 const unsigned DstReg = I.getOperand(0).getReg();
1203 const LLT DstTy = MRI.getType(DstReg);
1204 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1205 unsigned Align = DstTy.getSizeInBits();
1206 const DebugLoc &DbgLoc = I.getDebugLoc();
1207
1208 unsigned Opc = getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Align);
1209
1210 // Create the load from the constant pool.
1211 const ConstantFP *CFP = I.getOperand(1).getFPImm();
1212 unsigned CPI = MF.getConstantPool()->getConstantPoolIndex(CFP, Align);
1213 MachineInstr *LoadInst = nullptr;
1214 unsigned char OpFlag = STI.classifyLocalReference(nullptr);
1215
1216 if (CM == CodeModel::Large && STI.is64Bit()) {
1217 // Under X86-64 non-small code model, GV (and friends) are 64-bits, so
1218 // they cannot be folded into immediate fields.
1219
1220 unsigned AddrReg = MRI.createVirtualRegister(&X86::GR64RegClass);
1221 BuildMI(*I.getParent(), I, DbgLoc, TII.get(X86::MOV64ri), AddrReg)
1222 .addConstantPoolIndex(CPI, 0, OpFlag);
1223
1224 MachineMemOperand *MMO = MF.getMachineMemOperand(
1225 MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
1226 MF.getDataLayout().getPointerSize(), Align);
1227
1228 LoadInst =
1229 addDirectMem(BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg),
1230 AddrReg)
1231 .addMemOperand(MMO);
1232
1233 } else if(CM == CodeModel::Small || !STI.is64Bit()){
1234 // Handle the case when globals fit in our immediate field.
1235 // This is true for X86-32 always and X86-64 when in -mcmodel=small mode.
1236
1237 // x86-32 PIC requires a PIC base register for constant pools.
1238 unsigned PICBase = 0;
1239 if (OpFlag == X86II::MO_PIC_BASE_OFFSET || OpFlag == X86II::MO_GOTOFF) {
1240 // PICBase can be allocated by TII.getGlobalBaseReg(&MF).
1241 // In DAGISEL the code that initialize it generated by the CGBR pass.
1242 return false; // TODO support the mode.
1243 }
1244 else if (STI.is64Bit() && TM.getCodeModel() == CodeModel::Small)
1245 PICBase = X86::RIP;
1246
1247 LoadInst = addConstantPoolReference(
1248 BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg), CPI, PICBase,
1249 OpFlag);
1250 } else
1251 return false;
1252
1253 constrainSelectedInstRegOperands(*LoadInst, TII, TRI, RBI);
1254 I.eraseFromParent();
1255 return true;
1256 }
1257
11851258 bool X86InstructionSelector::selectImplicitDefOrPHI(
11861259 MachineInstr &I, MachineRegisterInfo &MRI) const {
11871260
163163 for (unsigned MemOp : {G_LOAD, G_STORE})
164164 for (auto Ty : {v4s32, v2s64})
165165 setAction({MemOp, Ty}, Legal);
166
167 // Constants
168 setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
166169 }
167170
168171 void X86LegalizerInfo::setLegalizerInfoSSE2() {
188191
189192 setAction({G_FPEXT, s64}, Legal);
190193 setAction({G_FPEXT, 1, s32}, Legal);
194
195 // Constants
196 setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
191197 }
192198
193199 void X86LegalizerInfo::setLegalizerInfoSSE41() {
185185
186186 switch (Opc) {
187187 case TargetOpcode::G_FPEXT:
188 case TargetOpcode::G_FCONSTANT:
188189 // Instruction having only floating-point operands (all scalars in VECRReg)
189190 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
190191 break;
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sse2 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK64 --check-prefix=CHECK_SMALL --check-prefix=CHECK_SMALL64 --check-prefix=CHECK_NOPIC64
2 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sse2 -global-isel -code-model=large -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK64 --check-prefix=CHECK_LARGE --check-prefix=CHECK_LARGE64
3 ; RUN: llc -mtriple=i386-linux-gnu -mattr=+sse2 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK32 --check-prefix=CHECK_SMALL --check-prefix=CHECK_SMALL32
4 ; RUN: llc -mtriple=i386-linux-gnu -mattr=+sse2 -global-isel -code-model=large -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK32 --check-prefix=CHECK_LARGE --check-prefix=CHECK_LARGE32
5 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sse2 -global-isel -relocation-model=pic -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK64 --check-prefix=CHECK_SMALL --check-prefix=CHECK_SMALL64 --check-prefix=CHECK_PIC64
6
7 define void @test_float(float* %a , float %b) {
8 ; CHECK_SMALL64-LABEL: test_float:
9 ; CHECK_SMALL64: # BB#0: # %entry
10 ; CHECK_SMALL64-NEXT: movss .LCPI0_0(%rip), %xmm1 # xmm1 = mem[0],zero,zero,zero
11 ; CHECK_SMALL64-NEXT: addss %xmm0, %xmm1
12 ; CHECK_SMALL64-NEXT: movd %xmm1, %eax
13 ; CHECK_SMALL64-NEXT: movl %eax, (%rdi)
14 ; CHECK_SMALL64-NEXT: retq
15 ;
16 ; CHECK_LARGE64-LABEL: test_float:
17 ; CHECK_LARGE64: # BB#0: # %entry
18 ; CHECK_LARGE64-NEXT: movabsq $.LCPI0_0, %rax
19 ; CHECK_LARGE64-NEXT: addss (%rax), %xmm0
20 ; CHECK_LARGE64-NEXT: movd %xmm0, %eax
21 ; CHECK_LARGE64-NEXT: movl %eax, (%rdi)
22 ; CHECK_LARGE64-NEXT: retq
23 ;
24 ; CHECK32-LABEL: test_float:
25 ; CHECK32: # BB#0: # %entry
26 ; CHECK32-NEXT: movl 4(%esp), %eax
27 ; CHECK32-NEXT: movl 8(%esp), %ecx
28 ; CHECK32-NEXT: movss .LCPI0_0, %xmm0 # xmm0 = mem[0],zero,zero,zero
29 ; CHECK32-NEXT: movd %ecx, %xmm1
30 ; CHECK32-NEXT: addss %xmm0, %xmm1
31 ; CHECK32-NEXT: movd %xmm1, %ecx
32 ; CHECK32-NEXT: movl %ecx, (%eax)
33 ; CHECK32-NEXT: retl
34 entry:
35 %aa = fadd float 5.500000e+00, %b
36 store float %aa, float* %a
37 ret void
38 }
39
None # RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32
1 # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
0 # RUN: llc -mtriple=i386-linux-gnu -mattr=+sse2 -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32
1 # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
22
33 --- |
4 define void @constInt_check() {
5 ret void
6 }
4 define void @test_constant() { ret void }
5 define void @test_fconstant() { ret void }
76
87 ...
98 ---
10 name: constInt_check
11 # ALL-LABEL: name: constInt_check
9 name: test_constant
10 # ALL-LABEL: name: test_constant
1211 registers:
1312 - { id: 0, class: _ }
1413 - { id: 1, class: _ }
3938
4039 RET 0
4140 ...
41 ---
42 name: test_fconstant
43 # ALL-LABEL: name: test_fconstant
44 registers:
45 - { id: 0, class: _ }
46 - { id: 1, class: _ }
47 body: |
48 bb.0:
49 ; ALL: %0(s32) = G_FCONSTANT float 1.000000e+00
50 ; ALL: %1(s64) = G_FCONSTANT double 2.000000e+00
4251
52 %0(s32) = G_FCONSTANT float 1.0
53 %1(s64) = G_FCONSTANT double 2.0
54 ...
55
234234 entry:
235235 %conv = fpext float %a to double
236236 ret double %conv
237 }
238
239 define void @test_fconstant() {
240 ret void
237241 }
238242
239243 ...
14101414 RET 0, implicit %xmm0
14111415
14121416 ...
1413
1417 ---
1418 name: test_fconstant
1419 # ALL-LABEL: name: test_fconstant
1420 legalized: true
1421 # CHECK: registers:
1422 # CHECK-NEXT: - { id: 0, class: vecr, preferred-register: '' }
1423 # CHECK-NEXT: - { id: 1, class: vecr, preferred-register: '' }
1424 registers:
1425 - { id: 0, class: _ }
1426 - { id: 1, class: _ }
1427 body: |
1428 bb.0:
1429 %0(s32) = G_FCONSTANT float 1.0
1430 %1(s64) = G_FCONSTANT double 2.0
1431 ...
1432
0 #RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sse2 -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK64 --check-prefix=CHECK_SMALL --check-prefix=CHECK_SMALL64 --check-prefix=CHECK_NOPIC64
1 #RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sse2 -global-isel -code-model=large -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK64 --check-prefix=CHECK_LARGE --check-prefix=CHECK_LARGE64
2 #RUN: llc -mtriple=i386-linux-gnu -mattr=+sse2 -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK32 --check-prefix=CHECK_SMALL --check-prefix=CHECK_SMALL32
3 #RUN: llc -mtriple=i386-linux-gnu -mattr=+sse2 -global-isel -code-model=large -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK32 --check-prefix=CHECK_LARGE --check-prefix=CHECK_LARGE32
4 #RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sse2 -global-isel -relocation-model=pic -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK64 --check-prefix=CHECK_SMALL --check-prefix=CHECK_SMALL64 --check-prefix=CHECK_PIC64
5
6 --- |
7 define float @test_float() {
8 entry:
9 ret float 5.500000e+00
10 }
11
12 define double @test_double() {
13 entry:
14 ret double 5.500000e+00
15 }
16 ---
17 name: test_float
18 # CHECK64-LABEL: name: test_float
19 #
20 # CHECK32-LABEL: name: test_float
21 alignment: 4
22 legalized: true
23 regBankSelected: true
24 tracksRegLiveness: true
25 # CHECK_SMALL64: registers:
26 # CHECK_SMALL64-NEXT: - { id: 0, class: fr32, preferred-register: '' }
27 #
28 # CHECK_LARGE64: registers:
29 # CHECK_LARGE64-NEXT: - { id: 0, class: fr32, preferred-register: '' }
30 # CHECK_LARGE64-NEXT: - { id: 1, class: gr64, preferred-register: '' }
31 #
32 # CHECK32: registers:
33 # CHECK32-NEXT: - { id: 0, class: fr32, preferred-register: '' }
34 registers:
35 - { id: 0, class: vecr, preferred-register: '' }
36 # CHECK_SMALL64: %0 = MOVSSrm %rip, 1, _, %const.0, _
37 # CHECK_SMALL64-NEXT: %xmm0 = COPY %0
38 # CHECK_SMALL64-NEXT: RET 0, implicit %xmm0
39 #
40 # CHECK_LARGE64: %1 = MOV64ri %const.0
41 # CHECK_LARGE64-NEXT: %0 = MOVSSrm %1, 1, _, 0, _ :: (load 8 from constant-pool, align 32)
42 # CHECK_LARGE64-NEXT: %xmm0 = COPY %0
43 # CHECK_LARGE64-NEXT: RET 0, implicit %xmm0
44 #
45 # CHECK32: %0 = MOVSSrm _, 1, _, %const.0, _
46 # CHECK32-NEXT: %xmm0 = COPY %0
47 # CHECK32-NEXT: RET 0, implicit %xmm0
48 body: |
49 bb.1.entry:
50 %0(s32) = G_FCONSTANT float 5.500000e+00
51 %xmm0 = COPY %0(s32)
52 RET 0, implicit %xmm0
53
54 ...
55 ---
56 name: test_double
57 # CHECK64-LABEL: name: test_double
58 #
59 # CHECK32-LABEL: name: test_double
60 alignment: 4
61 legalized: true
62 regBankSelected: true
63 tracksRegLiveness: true
64 # CHECK_SMALL64: registers:
65 # CHECK_SMALL64-NEXT: - { id: 0, class: fr64, preferred-register: '' }
66 #
67 # CHECK_LARGE64: registers:
68 # CHECK_LARGE64-NEXT: - { id: 0, class: fr64, preferred-register: '' }
69 # CHECK_LARGE64-NEXT: - { id: 1, class: gr64, preferred-register: '' }
70 #
71 # CHECK32: registers:
72 # CHECK32-NEXT: - { id: 0, class: fr64, preferred-register: '' }
73 registers:
74 - { id: 0, class: vecr, preferred-register: '' }
75 # CHECK_SMALL64: %0 = MOVSDrm %rip, 1, _, %const.0, _
76 # CHECK_SMALL64-NEXT: %xmm0 = COPY %0
77 # CHECK_SMALL64-NEXT: RET 0, implicit %xmm0
78 #
79 # CHECK_LARGE64: %1 = MOV64ri %const.0
80 # CHECK_LARGE64-NEXT: %0 = MOVSDrm %1, 1, _, 0, _ :: (load 8 from constant-pool, align 64)
81 # CHECK_LARGE64-NEXT: %xmm0 = COPY %0
82 # CHECK_LARGE64-NEXT: RET 0, implicit %xmm0
83 #
84 # CHECK32: %0 = MOVSDrm _, 1, _, %const.0, _
85 # CHECK32-NEXT: %xmm0 = COPY %0
86 # CHECK32-NEXT: RET 0, implicit %xmm0
87 body: |
88 bb.1.entry:
89 %0(s64) = G_FCONSTANT double 5.500000e+00
90 %xmm0 = COPY %0(s64)
91 RET 0, implicit %xmm0
92
93 ...