llvm.org GIT mirror llvm / 6a1a59e
[GlobalISel][X86] Support G_STORE/G_LOAD operation Summary: 1. Support pointer type as function argumnet and return value 2. G_STORE/G_LOAD - set legal action for i8/i16/i32/i64/f32/f64/vec128 3. RegisterBank - support typeless operations like G_STORE/G_LOAD, for scalar use GPR bank. 4. Support instruction selection for G_LOAD/G_STORE Reviewers: zvi, rovka, ab, qcolombet Reviewed By: rovka Subscribers: llvm-commits, dberris, kristof.beyls, eladcohen, guyblank Differential Revision: https://reviews.llvm.org/D30973 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298609 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Breger 3 years ago
12 changed file(s) with 1359 addition(s) and 77 deletion(s). Raw diff Collapse all Expand all
4646 unsigned NumParts = TLI.getNumRegisters(Context, VT);
4747
4848 if (NumParts == 1) {
49 SplitArgs.push_back(OrigArg);
49 // replace the original type ( pointer -> GPR ).
50 SplitArgs.emplace_back(OrigArg.Reg, VT.getTypeForEVT(Context),
51 OrigArg.Flags, OrigArg.IsFixed);
5052 return;
5153 }
5254
1414 #error "You shouldn't build this"
1515 #endif
1616
17 namespace llvm {
17 #ifdef GET_TARGET_REGBANK_INFO_IMPL
1818 RegisterBankInfo::PartialMapping X86GenRegisterBankInfo::PartMappings[]{
1919 /* StartIdx, Length, RegBank */
2020 // GPR value
3030 {0, 256, X86::VECRRegBank}, // :7
3131 {0, 512, X86::VECRRegBank}, // :8
3232 };
33 #endif // GET_TARGET_REGBANK_INFO_IMPL
3334
35 #ifdef GET_TARGET_REGBANK_INFO_CLASS
3436 enum PartialMappingIdx {
3537 PMI_None = -1,
3638 PMI_GPR8,
4345 PMI_VEC256,
4446 PMI_VEC512
4547 };
48 #endif // GET_TARGET_REGBANK_INFO_CLASS
4649
50 #ifdef GET_TARGET_REGBANK_INFO_IMPL
4751 #define INSTR_3OP(INFO) INFO, INFO, INFO,
4852 #define BREAKDOWN(INDEX, NUM) \
4953 { &X86GenRegisterBankInfo::PartMappings[INDEX], NUM }
6468 };
6569 #undef INSTR_3OP
6670 #undef BREAKDOWN
71 #endif // GET_TARGET_REGBANK_INFO_IMPL
6772
73 #ifdef GET_TARGET_REGBANK_INFO_CLASS
6874 enum ValueMappingIdx {
6975 VMI_None = -1,
7076 VMI_3OpsGpr8Idx = PMI_GPR8 * 3,
7783 VMI_3OpsVec256Idx = PMI_VEC256 * 3,
7884 VMI_3OpsVec512Idx = PMI_VEC512 * 3,
7985 };
86 #undef GET_TARGET_REGBANK_INFO_CLASS
87 #endif // GET_TARGET_REGBANK_INFO_CLASS
8088
81 } // End llvm namespace.
89 #ifdef GET_TARGET_REGBANK_INFO_IMPL
90 #undef GET_TARGET_REGBANK_INFO_IMPL
91 const RegisterBankInfo::ValueMapping *
92 X86GenRegisterBankInfo::getValueMapping(PartialMappingIdx Idx,
93 unsigned NumOperands) {
94
95 // We can use VMI_3Ops Mapping for all the cases.
96 if (NumOperands <= 3 && (Idx >= PMI_GPR8 && Idx <= PMI_VEC512))
97 return &ValMappings[(unsigned)Idx * 3];
98
99 llvm_unreachable("Unsupported PartialMappingIdx.");
100 }
101
102 #endif // GET_TARGET_REGBANK_INFO_IMPL
103
1212 //===----------------------------------------------------------------------===//
1313
1414 #include "X86InstructionSelector.h"
15 #include "X86InstrBuilder.h"
1516 #include "X86InstrInfo.h"
1617 #include "X86RegisterBankInfo.h"
1718 #include "X86RegisterInfo.h"
153154
154155 // TODO: This should be implemented by tblgen, pattern with predicate not
155156 // supported yet.
156 if (selectBinaryOp(I, MRI))
157 if (selectBinaryOp(I, MRI, MF))
158 return true;
159 if (selectLoadStoreOp(I, MRI, MF))
157160 return true;
158161
159162 return selectImpl(I);
268271 }
269272
270273 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
271 MachineRegisterInfo &MRI) const {
272
273 LLT Ty = MRI.getType(I.getOperand(0).getReg());
274 MachineRegisterInfo &MRI,
275 MachineFunction &MF) const {
276
274277 const unsigned DefReg = I.getOperand(0).getReg();
278 LLT Ty = MRI.getType(DefReg);
275279 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
276280
277281 unsigned NewOpc = I.getOpcode();
278282
279 switch (I.getOpcode()) {
283 switch (NewOpc) {
280284 case TargetOpcode::G_FADD:
281285 NewOpc = getFAddOp(Ty, RB);
282286 break;
300304
301305 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
302306 }
307
308 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
309 unsigned Opc,
310 uint64_t Alignment) const {
311 bool Isload = (Opc == TargetOpcode::G_LOAD);
312 bool HasAVX = STI.hasAVX();
313 bool HasAVX512 = STI.hasAVX512();
314 bool HasVLX = STI.hasVLX();
315
316 if (Ty == LLT::scalar(8)) {
317 if (X86::GPRRegBankID == RB.getID())
318 return Isload ? X86::MOV8rm : X86::MOV8mr;
319 } else if (Ty == LLT::scalar(16)) {
320 if (X86::GPRRegBankID == RB.getID())
321 return Isload ? X86::MOV16rm : X86::MOV16mr;
322 } else if (Ty == LLT::scalar(32)) {
323 if (X86::GPRRegBankID == RB.getID())
324 return Isload ? X86::MOV32rm : X86::MOV32mr;
325 if (X86::VECRRegBankID == RB.getID())
326 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
327 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
328 : (HasAVX512 ? X86::VMOVSSZmr
329 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
330 } else if (Ty == LLT::scalar(64)) {
331 if (X86::GPRRegBankID == RB.getID())
332 return Isload ? X86::MOV64rm : X86::MOV64mr;
333 if (X86::VECRRegBankID == RB.getID())
334 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
335 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
336 : (HasAVX512 ? X86::VMOVSDZmr
337 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
338 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
339 if (Alignment >= 16)
340 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
341 : HasAVX512
342 ? X86::VMOVAPSZ128rm_NOVLX
343 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
344 : (HasVLX ? X86::VMOVAPSZ128mr
345 : HasAVX512
346 ? X86::VMOVAPSZ128mr_NOVLX
347 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
348 else
349 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
350 : HasAVX512
351 ? X86::VMOVUPSZ128rm_NOVLX
352 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
353 : (HasVLX ? X86::VMOVUPSZ128mr
354 : HasAVX512
355 ? X86::VMOVUPSZ128mr_NOVLX
356 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
357 }
358 return Opc;
359 }
360
361 bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
362 MachineRegisterInfo &MRI,
363 MachineFunction &MF) const {
364
365 unsigned Opc = I.getOpcode();
366
367 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
368 return false;
369
370 const unsigned DefReg = I.getOperand(0).getReg();
371 LLT Ty = MRI.getType(DefReg);
372 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
373
374 auto &MemOp = **I.memoperands_begin();
375 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
376 if (NewOpc == Opc)
377 return false;
378
379 I.setDesc(TII.get(NewOpc));
380 MachineInstrBuilder MIB(MF, I);
381 if (Opc == TargetOpcode::G_LOAD)
382 addOffset(MIB, 0);
383 else {
384 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
385 I.RemoveOperand(0);
386 addOffset(MIB, 0).addUse(DefReg);
387 }
388 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
389 }
390
2626 class LLT;
2727 class RegisterBank;
2828 class MachineRegisterInfo;
29 class MachineFunction;
2930
3031 class X86InstructionSelector : public InstructionSelector {
3132 public:
4445 unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const;
4546 unsigned getAddOp(LLT &Ty, const RegisterBank &RB) const;
4647 unsigned getSubOp(LLT &Ty, const RegisterBank &RB) const;
47 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI) const;
48 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
49 uint64_t Alignment) const;
50
51 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI,
52 MachineFunction &MF) const;
53 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
54 MachineFunction &MF) const;
4855
4956 const X86Subtarget &STI;
5057 const X86InstrInfo &TII;
3636
3737 void X86LegalizerInfo::setLegalizerInfo32bit() {
3838
39 if (Subtarget.is64Bit())
40 return;
41
42 const LLT p0 = LLT::pointer(0, 32);
3943 const LLT s8 = LLT::scalar(8);
4044 const LLT s16 = LLT::scalar(16);
4145 const LLT s32 = LLT::scalar(32);
4246
43 for (auto Ty : {s8, s16, s32}) {
44 setAction({G_ADD, Ty}, Legal);
45 setAction({G_SUB, Ty}, Legal);
47 for (unsigned BinOp : {G_ADD, G_SUB})
48 for (auto Ty : {s8, s16, s32})
49 setAction({BinOp, Ty}, Legal);
50
51 for (unsigned MemOp : {G_LOAD, G_STORE}) {
52 for (auto Ty : {s8, s16, s32, p0})
53 setAction({MemOp, Ty}, Legal);
54
55 // And everything's fine in addrspace 0.
56 setAction({MemOp, 1, p0}, Legal);
4657 }
4758 }
4859
5162 if (!Subtarget.is64Bit())
5263 return;
5364
65 const LLT p0 = LLT::pointer(0, 64);
66 const LLT s8 = LLT::scalar(8);
67 const LLT s16 = LLT::scalar(16);
68 const LLT s32 = LLT::scalar(32);
5469 const LLT s64 = LLT::scalar(64);
5570
56 setAction({G_ADD, s64}, Legal);
57 setAction({G_SUB, s64}, Legal);
71 for (unsigned BinOp : {G_ADD, G_SUB})
72 for (auto Ty : {s8, s16, s32, s64})
73 setAction({BinOp, Ty}, Legal);
74
75 for (unsigned MemOp : {G_LOAD, G_STORE}) {
76 for (auto Ty : {s8, s16, s32, s64, p0})
77 setAction({MemOp, Ty}, Legal);
78
79 // And everything's fine in addrspace 0.
80 setAction({MemOp, 1, p0}, Legal);
81 }
5882 }
5983
6084 void X86LegalizerInfo::setLegalizerInfoSSE1() {
6387
6488 const LLT s32 = LLT::scalar(32);
6589 const LLT v4s32 = LLT::vector(4, 32);
90 const LLT v2s64 = LLT::vector(2, 64);
6691
6792 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
6893 for (auto Ty : {s32, v4s32})
6994 setAction({BinOp, Ty}, Legal);
95
96 for (unsigned MemOp : {G_LOAD, G_STORE})
97 for (auto Ty : {v4s32, v2s64})
98 setAction({MemOp, Ty}, Legal);
7099 }
71100
72101 void X86LegalizerInfo::setLegalizerInfoSSE2() {
2020 #define GET_TARGET_REGBANK_IMPL
2121 #include "X86GenRegisterBank.inc"
2222
23 using namespace llvm;
2324 // This file will be TableGen'ed at some point.
25 #define GET_TARGET_REGBANK_INFO_IMPL
2426 #include "X86GenRegisterBankInfo.def"
25
26 using namespace llvm;
2727
2828 #ifndef LLVM_BUILD_GLOBAL_ISEL
2929 #error "You shouldn't build this"
6363 llvm_unreachable("Unsupported register kind yet.");
6464 }
6565
66 X86GenRegisterBankInfo::PartialMappingIdx
67 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
68 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
69 switch (Ty.getSizeInBits()) {
70 case 8:
71 return PMI_GPR8;
72 case 16:
73 return PMI_GPR16;
74 case 32:
75 return PMI_GPR32;
76 case 64:
77 return PMI_GPR64;
78 break;
79 default:
80 llvm_unreachable("Unsupported register size.");
81 }
82 } else if (Ty.isScalar()) {
83 switch (Ty.getSizeInBits()) {
84 case 32:
85 return PMI_FP32;
86 case 64:
87 return PMI_FP64;
88 default:
89 llvm_unreachable("Unsupported register size.");
90 }
91 } else {
92 switch (Ty.getSizeInBits()) {
93 case 128:
94 return PMI_VEC128;
95 case 256:
96 return PMI_VEC256;
97 case 512:
98 return PMI_VEC512;
99 default:
100 llvm_unreachable("Unsupported register size.");
101 }
102 }
103
104 return PMI_None;
105 }
106
66107 RegisterBankInfo::InstructionMapping
67 X86RegisterBankInfo::getOperandsMapping(const MachineInstr &MI, bool isFP) {
108 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI, bool isFP) {
68109 const MachineFunction &MF = *MI.getParent()->getParent();
69110 const MachineRegisterInfo &MRI = MF.getRegInfo();
70111
73114
74115 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
75116 (Ty != MRI.getType(MI.getOperand(2).getReg())))
76 llvm_unreachable("Unsupported operand maping yet.");
117 llvm_unreachable("Unsupported operand mapping yet.");
77118
78 ValueMappingIdx ValMapIdx = VMI_None;
79
80 if (Ty.isScalar()) {
81 if (!isFP) {
82 switch (Ty.getSizeInBits()) {
83 case 8:
84 ValMapIdx = VMI_3OpsGpr8Idx;
85 break;
86 case 16:
87 ValMapIdx = VMI_3OpsGpr16Idx;
88 break;
89 case 32:
90 ValMapIdx = VMI_3OpsGpr32Idx;
91 break;
92 case 64:
93 ValMapIdx = VMI_3OpsGpr64Idx;
94 break;
95 default:
96 llvm_unreachable("Unsupported register size.");
97 }
98 } else {
99 switch (Ty.getSizeInBits()) {
100 case 32:
101 ValMapIdx = VMI_3OpsFp32Idx;
102 break;
103 case 64:
104 ValMapIdx = VMI_3OpsFp64Idx;
105 break;
106 default:
107 llvm_unreachable("Unsupported register size.");
108 }
109 }
110 } else {
111 switch (Ty.getSizeInBits()) {
112 case 128:
113 ValMapIdx = VMI_3OpsVec128Idx;
114 break;
115 case 256:
116 ValMapIdx = VMI_3OpsVec256Idx;
117 break;
118 case 512:
119 ValMapIdx = VMI_3OpsVec512Idx;
120 break;
121 default:
122 llvm_unreachable("Unsupported register size.");
123 }
124 }
125
126 return InstructionMapping{DefaultMappingID, 1, &ValMappings[ValMapIdx],
127 NumOperands};
119 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
120 return InstructionMapping{DefaultMappingID, 1, Mapping, NumOperands};
128121 }
129122
130123 RegisterBankInfo::InstructionMapping
131124 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
125 const MachineFunction &MF = *MI.getParent()->getParent();
126 const MachineRegisterInfo &MRI = MF.getRegInfo();
132127 auto Opc = MI.getOpcode();
133128
134129 // Try the default logic for non-generic instructions that are either copies
142137 switch (Opc) {
143138 case TargetOpcode::G_ADD:
144139 case TargetOpcode::G_SUB:
145 return getOperandsMapping(MI, false);
140 return getSameOperandsMapping(MI, false);
146141 break;
147142 case TargetOpcode::G_FADD:
148143 case TargetOpcode::G_FSUB:
149144 case TargetOpcode::G_FMUL:
150145 case TargetOpcode::G_FDIV:
151 return getOperandsMapping(MI, true);
146 return getSameOperandsMapping(MI, true);
152147 break;
153148 default:
154 return InstructionMapping{};
149 break;
155150 }
156151
157 return InstructionMapping{};
152 unsigned NumOperands = MI.getNumOperands();
153 unsigned Cost = 1; // set dafault cost
154
155 // Track the bank of each register.
156 SmallVector OpRegBankIdx(NumOperands);
157 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
158 auto &MO = MI.getOperand(Idx);
159 if (!MO.isReg())
160 continue;
161
162 // As a top-level guess, use NotFP mapping (all scalars in GPRs)
163 OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), false);
164 }
165
166 // Finally construct the computed mapping.
167 RegisterBankInfo::InstructionMapping Mapping =
168 InstructionMapping{DefaultMappingID, Cost, nullptr, NumOperands};
169 SmallVector OpdsMapping(NumOperands);
170 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
171 if (MI.getOperand(Idx).isReg()) {
172 auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
173 if (!Mapping->isValid())
174 return InstructionMapping();
175
176 OpdsMapping[Idx] = Mapping;
177 }
178 }
179
180 Mapping.setOperandsMapping(getOperandsMapping(OpdsMapping));
181 return Mapping;
158182 }
2020
2121 namespace llvm {
2222
23 class LLT;
24
2325 class X86GenRegisterBankInfo : public RegisterBankInfo {
2426 protected:
27 #define GET_TARGET_REGBANK_CLASS
28 #include "X86GenRegisterBank.inc"
29 #define GET_TARGET_REGBANK_INFO_CLASS
30 #include "X86GenRegisterBankInfo.def"
31
2532 static RegisterBankInfo::PartialMapping PartMappings[];
2633 static RegisterBankInfo::ValueMapping ValMappings[];
2734
28 #define GET_TARGET_REGBANK_CLASS
29 #include "X86GenRegisterBank.inc"
35 static PartialMappingIdx getPartialMappingIdx(const LLT &Ty, bool isFP);
36 static const RegisterBankInfo::ValueMapping *
37 getValueMapping(PartialMappingIdx Idx, unsigned NumOperands);
3038 };
3139
3240 class TargetRegisterInfo;
3745 /// Get an instruction mapping.
3846 /// \return An InstructionMappings with a statically allocated
3947 /// OperandsMapping.
40 static InstructionMapping getOperandsMapping(const MachineInstr &MI,
41 bool isFP);
48 static InstructionMapping getSameOperandsMapping(const MachineInstr &MI,
49 bool isFP);
4250
4351 public:
4452 X86RegisterBankInfo(const TargetRegisterInfo &TRI);
4545 ret <4 x float> %ret
4646 }
4747
48 define i8 @test_load_i8(i8* %p1) {
49 %r = load i8, i8* %p1
50 ret i8 %r
51 }
52
53 define i16 @test_load_i16(i16* %p1) {
54 %r = load i16, i16* %p1
55 ret i16 %r
56 }
57
58 define i32 @test_load_i32(i32* %p1) {
59 %r = load i32, i32* %p1
60 ret i32 %r
61 }
62
63 define i64 @test_load_i64(i64* %p1) {
64 %r = load i64, i64* %p1
65 ret i64 %r
66 }
67
68 define float @test_load_float(float* %p1) {
69 %r = load float, float* %p1
70 ret float %r
71 }
72
73 define double @test_load_double(double* %p1) {
74 %r = load double, double* %p1
75 ret double %r
76 }
77
78 define <4 x i32> @test_load_v4i32(<4 x i32>* %p1) {
79 %r = load <4 x i32>, <4 x i32>* %p1, align 16
80 ret <4 x i32> %r
81 }
82
83 define i32* @test_store_i32(i32 %val, i32* %p1) {
84 store i32 %val, i32* %p1
85 ret i32* %p1
86 }
87
88 define i64* @test_store_i64(i64 %val, i64* %p1) {
89 store i64 %val, i64* %p1
90 ret i64* %p1
91 }
92
93 define float* @test_store_float(float %val, float* %p1) {
94 store float %val, float* %p1
95 ret float* %p1
96 }
97
98 define double* @test_store_double(double %val, double* %p1) {
99 store double %val, double* %p1
100 ret double* %p1
101 }
102
48103 ...
49104 ---
50105 name: test_add_i8
262317 RET 0, implicit %xmm0
263318
264319 ...
265
320 ---
321 name: test_load_i8
322 alignment: 4
323 legalized: true
324 regBankSelected: false
325 selected: false
326 # CHECK-LABEL: name: test_load_i8
327 # CHECK: registers:
328 # CHECK: - { id: 0, class: gpr }
329 # CHECK: - { id: 1, class: gpr }
330 registers:
331 - { id: 0, class: _ }
332 - { id: 1, class: _ }
333 body: |
334 bb.1 (%ir-block.0):
335 liveins: %rdi
336
337 %0(p0) = COPY %rdi
338 %1(s8) = G_LOAD %0(p0) :: (load 1 from %ir.p1)
339 %al = COPY %1(s8)
340 RET 0, implicit %al
341
342 ...
343 ---
344 name: test_load_i16
345 alignment: 4
346 legalized: true
347 regBankSelected: false
348 selected: false
349 # CHECK-LABEL: name: test_load_i16
350 # CHECK: registers:
351 # CHECK: - { id: 0, class: gpr }
352 # CHECK: - { id: 1, class: gpr }
353 registers:
354 - { id: 0, class: _ }
355 - { id: 1, class: _ }
356 body: |
357 bb.1 (%ir-block.0):
358 liveins: %rdi
359
360 %0(p0) = COPY %rdi
361 %1(s16) = G_LOAD %0(p0) :: (load 2 from %ir.p1)
362 %ax = COPY %1(s16)
363 RET 0, implicit %ax
364
365 ...
366 ---
367 name: test_load_i32
368 alignment: 4
369 legalized: true
370 regBankSelected: false
371 selected: false
372 # CHECK-LABEL: name: test_load_i32
373 # CHECK: registers:
374 # CHECK: - { id: 0, class: gpr }
375 # CHECK: - { id: 1, class: gpr }
376 registers:
377 - { id: 0, class: _ }
378 - { id: 1, class: _ }
379 body: |
380 bb.1 (%ir-block.0):
381 liveins: %rdi
382
383 %0(p0) = COPY %rdi
384 %1(s32) = G_LOAD %0(p0) :: (load 4 from %ir.p1)
385 %eax = COPY %1(s32)
386 RET 0, implicit %eax
387
388 ...
389 ---
390 name: test_load_i64
391 alignment: 4
392 exposesReturnsTwice: false
393 legalized: true
394 regBankSelected: false
395 selected: false
396 # CHECK-LABEL: name: test_load_i64
397 # CHECK: registers:
398 # CHECK: - { id: 0, class: gpr }
399 # CHECK: - { id: 1, class: gpr }
400 registers:
401 - { id: 0, class: _ }
402 - { id: 1, class: _ }
403 body: |
404 bb.1 (%ir-block.0):
405 liveins: %rdi
406
407 %0(p0) = COPY %rdi
408 %1(s64) = G_LOAD %0(p0) :: (load 8 from %ir.p1)
409 %rax = COPY %1(s64)
410 RET 0, implicit %rax
411
412 ...
413 ---
414 name: test_load_float
415 alignment: 4
416 legalized: true
417 regBankSelected: false
418 selected: false
419 # CHECK-LABEL: name: test_load_float
420 # CHECK: registers:
421 # CHECK: - { id: 0, class: gpr }
422 # CHECK: - { id: 1, class: gpr }
423 registers:
424 - { id: 0, class: _ }
425 - { id: 1, class: _ }
426 body: |
427 bb.1 (%ir-block.0):
428 liveins: %rdi
429
430 %0(p0) = COPY %rdi
431 %1(s32) = G_LOAD %0(p0) :: (load 4 from %ir.p1)
432 %xmm0 = COPY %1(s32)
433 RET 0, implicit %xmm0
434
435 ...
436 ---
437 name: test_load_double
438 alignment: 4
439 legalized: true
440 regBankSelected: false
441 selected: false
442 # CHECK-LABEL: name: test_load_double
443 # CHECK: registers:
444 # CHECK: - { id: 0, class: gpr }
445 # CHECK: - { id: 1, class: gpr }
446 registers:
447 - { id: 0, class: _ }
448 - { id: 1, class: _ }
449 body: |
450 bb.1 (%ir-block.0):
451 liveins: %rdi
452
453 %0(p0) = COPY %rdi
454 %1(s64) = G_LOAD %0(p0) :: (load 8 from %ir.p1)
455 %xmm0 = COPY %1(s64)
456 RET 0, implicit %xmm0
457
458 ...
459 ---
460 name: test_load_v4i32
461 alignment: 4
462 legalized: true
463 regBankSelected: false
464 selected: false
465 # CHECK-LABEL: name: test_load_v4i32
466 # CHECK: registers:
467 # CHECK: - { id: 0, class: gpr }
468 # CHECK: - { id: 1, class: vecr }
469 registers:
470 - { id: 0, class: _ }
471 - { id: 1, class: _ }
472 body: |
473 bb.1 (%ir-block.0):
474 liveins: %rdi
475
476 %0(p0) = COPY %rdi
477 %1(<4 x s32>) = G_LOAD %0(p0) :: (load 16 from %ir.p1, align 1)
478 %xmm0 = COPY %1(<4 x s32>)
479 RET 0, implicit %xmm0
480
481 ...
482 ---
483 name: test_store_i32
484 alignment: 4
485 legalized: true
486 regBankSelected: false
487 selected: false
488 # CHECK-LABEL: name: test_store_i32
489 # CHECK: registers:
490 # CHECK: - { id: 0, class: gpr }
491 # CHECK: - { id: 1, class: gpr }
492 registers:
493 - { id: 0, class: _ }
494 - { id: 1, class: _ }
495 body: |
496 bb.1 (%ir-block.0):
497 liveins: %edi, %rsi
498
499 %0(s32) = COPY %edi
500 %1(p0) = COPY %rsi
501 G_STORE %0(s32), %1(p0) :: (store 4 into %ir.p1)
502 %rax = COPY %1(p0)
503 RET 0, implicit %rax
504
505 ...
506 ---
507 name: test_store_i64
508 alignment: 4
509 legalized: true
510 regBankSelected: false
511 selected: false
512 # CHECK-LABEL: name: test_store_i64
513 # CHECK: registers:
514 # CHECK: - { id: 0, class: gpr }
515 # CHECK: - { id: 1, class: gpr }
516 registers:
517 - { id: 0, class: _ }
518 - { id: 1, class: _ }
519 body: |
520 bb.1 (%ir-block.0):
521 liveins: %rdi, %rsi
522
523 %0(s64) = COPY %rdi
524 %1(p0) = COPY %rsi
525 G_STORE %0(s64), %1(p0) :: (store 8 into %ir.p1)
526 %rax = COPY %1(p0)
527 RET 0, implicit %rax
528
529 ...
530 ---
531 name: test_store_float
532 alignment: 4
533 legalized: true
534 regBankSelected: false
535 selected: false
536 # CHECK-LABEL: name: test_store_float
537 # CHECK: registers:
538 # CHECK: - { id: 0, class: vecr }
539 # CHECK: - { id: 1, class: gpr }
540 # CHECK: - { id: 2, class: gpr }
541
542 registers:
543 - { id: 0, class: _ }
544 - { id: 1, class: _ }
545 body: |
546 bb.1 (%ir-block.0):
547 liveins: %rdi, %xmm0
548
549 %0(s32) = COPY %xmm0
550 %1(p0) = COPY %rdi
551 ; CHECK: %2(s32) = COPY %0(s32)
552 ; CHECK: G_STORE %2(s32), %1(p0) :: (store 4 into %ir.p1)
553 G_STORE %0(s32), %1(p0) :: (store 4 into %ir.p1)
554 %rax = COPY %1(p0)
555 RET 0, implicit %rax
556
557 ...
558 ---
559 name: test_store_double
560 alignment: 4
561 legalized: true
562 regBankSelected: false
563 selected: false
564 # CHECK-LABEL: name: test_store_double
565 # CHECK: registers:
566 # CHECK: - { id: 0, class: vecr }
567 # CHECK: - { id: 1, class: gpr }
568 # CHECK: - { id: 2, class: gpr }
569
570 registers:
571 - { id: 0, class: _ }
572 - { id: 1, class: _ }
573 body: |
574 bb.1 (%ir-block.0):
575 liveins: %rdi, %xmm0
576
577 %0(s64) = COPY %xmm0
578 %1(p0) = COPY %rdi
579 ; CHECK: %2(s64) = COPY %0(s64)
580 ; CHECK: G_STORE %2(s64), %1(p0) :: (store 8 into %ir.p1)
581 G_STORE %0(s64), %1(p0) :: (store 8 into %ir.p1)
582 %rax = COPY %1(p0)
583 RET 0, implicit %rax
584
585 ...
586
154154 %ret = fsub <4 x float> %arg1, %arg2
155155 ret <4 x float> %ret
156156 }
157
158 define i32 @test_copy_float(float %val) {
159 ; SSE-LABEL: test_copy_float:
160 ; SSE: # BB#0:
161 ; SSE-NEXT: movd %xmm0, %eax
162 ; SSE-NEXT: retq
163 ;
164 ; ALL_AVX-LABEL: test_copy_float:
165 ; ALL_AVX: # BB#0:
166 ; ALL_AVX-NEXT: vmovd %xmm0, %eax
167 ; ALL_AVX-NEXT: retq
168 %r = bitcast float %val to i32
169 ret i32 %r
170 }
171
172 define float @test_copy_i32(i32 %val) {
173 ; SSE-LABEL: test_copy_i32:
174 ; SSE: # BB#0:
175 ; SSE-NEXT: movd %edi, %xmm0
176 ; SSE-NEXT: retq
177 ;
178 ; ALL_AVX-LABEL: test_copy_i32:
179 ; ALL_AVX: # BB#0:
180 ; ALL_AVX-NEXT: vmovd %edi, %xmm0
181 ; ALL_AVX-NEXT: retq
182 %r = bitcast i32 %val to float
183 ret float %r
184 }
185
290290
291291 ret double %arg2
292292 }
293
294 define i32 * @test_memop_i32(i32 * %p1) {
295 ; ALL-LABEL:name: test_memop_i32
296 ;X64 liveins: %rdi
297 ;X64: %0(p0) = COPY %rdi
298 ;X64-NEXT: %rax = COPY %0(p0)
299 ;X64-NEXT: RET 0, implicit %rax
300
301 ;X32: fixedStack:
302 ;X32: id: [[STACK0:[0-9]+]], offset: 0, size: 4, alignment: 16, isImmutable: true, isAliased: false }
303 ;X32: %1(p0) = G_FRAME_INDEX %fixed-stack.[[STACK0]]
304 ;X32-NEXT: %0(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.[[STACK0]], align 0)
305 ;X32-NEXT: %eax = COPY %0(p0)
306 ;X32-NEXT: RET 0, implicit %eax
307
308 ret i32 * %p1;
309 }
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=SSE
2 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+avx -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=ALL_AVX --check-prefix=AVX
3 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+avx512f -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=ALL_AVX --check-prefix=AVX512F
4 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+avx512f -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=ALL_AVX --check-prefix=AVX512VL
5
6
7 define i8 @test_load_i8(i8 * %p1) {
8 ; ALL-LABEL: test_load_i8:
9 ; ALL: # BB#0:
10 ; ALL-NEXT: movb (%rdi), %al
11 ; ALL-NEXT: retq
12 %r = load i8, i8* %p1
13 ret i8 %r
14 }
15
16 define i16 @test_load_i16(i16 * %p1) {
17 ; ALL-LABEL: test_load_i16:
18 ; ALL: # BB#0:
19 ; ALL-NEXT: movzwl (%rdi), %eax
20 ; ALL-NEXT: retq
21 %r = load i16, i16* %p1
22 ret i16 %r
23 }
24
25 define i32 @test_load_i32(i32 * %p1) {
26 ; ALL-LABEL: test_load_i32:
27 ; ALL: # BB#0:
28 ; ALL-NEXT: movl (%rdi), %eax
29 ; ALL-NEXT: retq
30 %r = load i32, i32* %p1
31 ret i32 %r
32 }
33
34 define i64 @test_load_i64(i64 * %p1) {
35 ; ALL-LABEL: test_load_i64:
36 ; ALL: # BB#0:
37 ; ALL-NEXT: movq (%rdi), %rax
38 ; ALL-NEXT: retq
39 %r = load i64, i64* %p1
40 ret i64 %r
41 }
42
43 define float @test_load_float(float * %p1) {
44 ; SSE-LABEL: test_load_float:
45 ; SSE: # BB#0:
46 ; SSE-NEXT: movl (%rdi), %eax
47 ; SSE-NEXT: movd %eax, %xmm0
48 ; SSE-NEXT: retq
49 ;
50 ; ALL_AVX-LABEL: test_load_float:
51 ; ALL_AVX: # BB#0:
52 ; ALL_AVX-NEXT: movl (%rdi), %eax
53 ; ALL_AVX-NEXT: vmovd %eax, %xmm0
54 ; ALL_AVX-NEXT: retq
55 %r = load float, float* %p1
56 ret float %r
57 }
58
59 define double @test_load_double(double * %p1) {
60 ; SSE-LABEL: test_load_double:
61 ; SSE: # BB#0:
62 ; SSE-NEXT: movq (%rdi), %rax
63 ; SSE-NEXT: movd %rax, %xmm0
64 ; SSE-NEXT: retq
65 ;
66 ; ALL_AVX-LABEL: test_load_double:
67 ; ALL_AVX: # BB#0:
68 ; ALL_AVX-NEXT: movq (%rdi), %rax
69 ; ALL_AVX-NEXT: vmovq %rax, %xmm0
70 ; ALL_AVX-NEXT: retq
71 %r = load double, double* %p1
72 ret double %r
73 }
74
75 define <4 x i32> @test_load_v4i32_noalign(<4 x i32> * %p1) {
76 ; SSE-LABEL: test_load_v4i32_noalign:
77 ; SSE: # BB#0:
78 ; SSE-NEXT: movups (%rdi), %xmm0
79 ; SSE-NEXT: retq
80 ;
81 ; ALL_AVX-LABEL: test_load_v4i32_noalign:
82 ; ALL_AVX: # BB#0:
83 ; ALL_AVX-NEXT: vmovups (%rdi), %xmm0
84 ; ALL_AVX-NEXT: retq
85 %r = load <4 x i32>, <4 x i32>* %p1, align 1
86 ret <4 x i32> %r
87 }
88
89 define <4 x i32> @test_load_v4i32_align(<4 x i32> * %p1) {
90 ; SSE-LABEL: test_load_v4i32_align:
91 ; SSE: # BB#0:
92 ; SSE-NEXT: movaps (%rdi), %xmm0
93 ; SSE-NEXT: retq
94 ;
95 ; ALL_AVX-LABEL: test_load_v4i32_align:
96 ; ALL_AVX: # BB#0:
97 ; ALL_AVX-NEXT: vmovaps (%rdi), %xmm0
98 ; ALL_AVX-NEXT: retq
99 %r = load <4 x i32>, <4 x i32>* %p1, align 16
100 ret <4 x i32> %r
101 }
102
103 define i32 * @test_store_i32(i32 %val, i32 * %p1) {
104 ; ALL-LABEL: test_store_i32:
105 ; ALL: # BB#0:
106 ; ALL-NEXT: movl %edi, (%rsi)
107 ; ALL-NEXT: movq %rsi, %rax
108 ; ALL-NEXT: retq
109 store i32 %val, i32* %p1
110 ret i32 * %p1;
111 }
112
113 define i64 * @test_store_i64(i64 %val, i64 * %p1) {
114 ; ALL-LABEL: test_store_i64:
115 ; ALL: # BB#0:
116 ; ALL-NEXT: movq %rdi, (%rsi)
117 ; ALL-NEXT: movq %rsi, %rax
118 ; ALL-NEXT: retq
119 store i64 %val, i64* %p1
120 ret i64 * %p1;
121 }
122
123 define float * @test_store_float(float %val, float * %p1) {
124 ; SSE-LABEL: test_store_float:
125 ; SSE: # BB#0:
126 ; SSE-NEXT: movd %xmm0, %eax
127 ; SSE-NEXT: movl %eax, (%rdi)
128 ; SSE-NEXT: movq %rdi, %rax
129 ; SSE-NEXT: retq
130 ;
131 ; ALL_AVX-LABEL: test_store_float:
132 ; ALL_AVX: # BB#0:
133 ; ALL_AVX-NEXT: vmovd %xmm0, %eax
134 ; ALL_AVX-NEXT: movl %eax, (%rdi)
135 ; ALL_AVX-NEXT: movq %rdi, %rax
136 ; ALL_AVX-NEXT: retq
137 store float %val, float* %p1
138 ret float * %p1;
139 }
140
141 define double * @test_store_double(double %val, double * %p1) {
142 ; SSE-LABEL: test_store_double:
143 ; SSE: # BB#0:
144 ; SSE-NEXT: movd %xmm0, %rax
145 ; SSE-NEXT: movq %rax, (%rdi)
146 ; SSE-NEXT: movq %rdi, %rax
147 ; SSE-NEXT: retq
148 ;
149 ; ALL_AVX-LABEL: test_store_double:
150 ; ALL_AVX: # BB#0:
151 ; ALL_AVX-NEXT: vmovq %xmm0, %rax
152 ; ALL_AVX-NEXT: movq %rax, (%rdi)
153 ; ALL_AVX-NEXT: movq %rdi, %rax
154 ; ALL_AVX-NEXT: retq
155 store double %val, double* %p1
156 ret double * %p1;
157 }
158
6262 %ret = fsub <4 x float> %arg1, %arg2
6363 ret <4 x float> %ret
6464 }
65
66 define i8 @test_load_i8(i8* %p1) {
67 %r = load i8, i8* %p1
68 ret i8 %r
69 }
70
71 define i16 @test_load_i16(i16* %p1) {
72 %r = load i16, i16* %p1
73 ret i16 %r
74 }
75
76 define i32 @test_load_i32(i32* %p1) {
77 %r = load i32, i32* %p1
78 ret i32 %r
79 }
80
81 define i64 @test_load_i64(i64* %p1) {
82 %r = load i64, i64* %p1
83 ret i64 %r
84 }
85
86 define float @test_load_float(float* %p1) {
87 %r = load float, float* %p1
88 ret float %r
89 }
90
91 define float @test_load_float_vecreg(float* %p1) {
92 %r = load float, float* %p1
93 ret float %r
94 }
95
96
97 define double @test_load_double(double* %p1) {
98 %r = load double, double* %p1
99 ret double %r
100 }
101
102 define double @test_load_double_vecreg(double* %p1) {
103 %r = load double, double* %p1
104 ret double %r
105 }
106
107 define <4 x i32> @test_load_v4i32_noalign(<4 x i32>* %p1) {
108 %r = load <4 x i32>, <4 x i32>* %p1, align 1
109 ret <4 x i32> %r
110 }
111
112 define <4 x i32> @test_load_v4i32_align(<4 x i32>* %p1) {
113 %r = load <4 x i32>, <4 x i32>* %p1, align 16
114 ret <4 x i32> %r
115 }
116
117 define i32* @test_store_i32(i32 %val, i32* %p1) {
118 store i32 %val, i32* %p1
119 ret i32* %p1
120 }
121
122 define i64* @test_store_i64(i64 %val, i64* %p1) {
123 store i64 %val, i64* %p1
124 ret i64* %p1
125 }
126
127 define float* @test_store_float(float %val, float* %p1) {
128 store float %val, float* %p1
129 ret float* %p1
130 }
131
132 define float* @test_store_float_vec(float %val, float* %p1) {
133 store float %val, float* %p1
134 ret float* %p1
135 }
136
137 define double* @test_store_double(double %val, double* %p1) {
138 store double %val, double* %p1
139 ret double* %p1
140 }
141
142 define double* @test_store_double_vec(double %val, double* %p1) {
143 store double %val, double* %p1
144 ret double* %p1
145 }
146
147 define <4 x i32>* @test_store_v4i32_align(<4 x i32> %val, <4 x i32>* %p1) {
148 store <4 x i32> %val, <4 x i32>* %p1, align 16
149 ret <4 x i32>* %p1
150 }
151
152 define <4 x i32>* @test_store_v4i32_noalign(<4 x i32> %val, <4 x i32>* %p1) {
153 store <4 x i32> %val, <4 x i32>* %p1, align 1
154 ret <4 x i32>* %p1
155 }
156
65157 ...
66158
67159 ---
443535 RET 0, implicit %xmm0
444536
445537 ...
538 ---
539 # ALL-LABEL: name: test_load_i8
540 name: test_load_i8
541 alignment: 4
542 legalized: true
543 regBankSelected: true
544 registers:
545 # ALL: - { id: 0, class: gr64 }
546 # ALL: - { id: 1, class: gr8 }
547 - { id: 0, class: gpr }
548 - { id: 1, class: gpr }
549 # ALL: %0 = COPY %rdi
550 # ALL: %1 = MOV8rm %0, 1, _, 0, _ :: (load 1 from %ir.p1)
551 # ALL: %al = COPY %1
552 body: |
553 bb.1 (%ir-block.0):
554 liveins: %rdi
555
556 %0(p0) = COPY %rdi
557 %1(s8) = G_LOAD %0(p0) :: (load 1 from %ir.p1)
558 %al = COPY %1(s8)
559 RET 0, implicit %al
560
561 ...
562 ---
563 # ALL-LABEL: name: test_load_i16
564 name: test_load_i16
565 alignment: 4
566 legalized: true
567 regBankSelected: true
568 registers:
569 # ALL: - { id: 0, class: gr64 }
570 # ALL: - { id: 1, class: gr16 }
571 - { id: 0, class: gpr }
572 - { id: 1, class: gpr }
573 # ALL: %0 = COPY %rdi
574 # ALL: %1 = MOV16rm %0, 1, _, 0, _ :: (load 2 from %ir.p1)
575 # ALL: %ax = COPY %1
576 body: |
577 bb.1 (%ir-block.0):
578 liveins: %rdi
579
580 %0(p0) = COPY %rdi
581 %1(s16) = G_LOAD %0(p0) :: (load 2 from %ir.p1)
582 %ax = COPY %1(s16)
583 RET 0, implicit %ax
584
585 ...
586 ---
587 # ALL-LABEL: name: test_load_i32
588 name: test_load_i32
589 alignment: 4
590 legalized: true
591 regBankSelected: true
592 registers:
593 # ALL: - { id: 0, class: gr64 }
594 # ALL: - { id: 1, class: gr32 }
595 - { id: 0, class: gpr }
596 - { id: 1, class: gpr }
597 # ALL: %0 = COPY %rdi
598 # ALL: %1 = MOV32rm %0, 1, _, 0, _ :: (load 4 from %ir.p1)
599 # ALL: %eax = COPY %1
600 body: |
601 bb.1 (%ir-block.0):
602 liveins: %rdi
603
604 %0(p0) = COPY %rdi
605 %1(s32) = G_LOAD %0(p0) :: (load 4 from %ir.p1)
606 %eax = COPY %1(s32)
607 RET 0, implicit %eax
608
609 ...
610 ---
611 # ALL-LABEL: name: test_load_i64
612 name: test_load_i64
613 alignment: 4
614 legalized: true
615 regBankSelected: true
616 registers:
617 # ALL: - { id: 0, class: gr64 }
618 # ALL: - { id: 1, class: gr64 }
619 - { id: 0, class: gpr }
620 - { id: 1, class: gpr }
621 # ALL: %0 = COPY %rdi
622 # ALL: %1 = MOV64rm %0, 1, _, 0, _ :: (load 8 from %ir.p1)
623 # ALL: %rax = COPY %1
624 body: |
625 bb.1 (%ir-block.0):
626 liveins: %rdi
627
628 %0(p0) = COPY %rdi
629 %1(s64) = G_LOAD %0(p0) :: (load 8 from %ir.p1)
630 %rax = COPY %1(s64)
631 RET 0, implicit %rax
632
633 ...
634 ---
635 # ALL-LABEL: name: test_load_float
636 name: test_load_float
637 alignment: 4
638 legalized: true
639 regBankSelected: true
640 registers:
641 # ALL: - { id: 0, class: gr64 }
642 # ALL: - { id: 1, class: gr32 }
643 - { id: 0, class: gpr }
644 - { id: 1, class: gpr }
645 # ALL: %0 = COPY %rdi
646 # ALL: %1 = MOV32rm %0, 1, _, 0, _ :: (load 4 from %ir.p1)
647 # ALL: %xmm0 = COPY %1
648 body: |
649 bb.1 (%ir-block.0):
650 liveins: %rdi
651
652 %0(p0) = COPY %rdi
653 %1(s32) = G_LOAD %0(p0) :: (load 4 from %ir.p1)
654 %xmm0 = COPY %1(s32)
655 RET 0, implicit %xmm0
656
657 ...
658 ---
659 # ALL-LABEL: name: test_load_float_vecreg
660 name: test_load_float_vecreg
661 alignment: 4
662 legalized: true
663 regBankSelected: true
664 registers:
665 # ALL: - { id: 0, class: gr64 }
666 # NO_AVX512F: - { id: 1, class: fr32 }
667 # AVX512ALL: - { id: 1, class: fr32x }
668 - { id: 0, class: gpr }
669 - { id: 1, class: vecr }
670 # ALL: %0 = COPY %rdi
671 # SSE: %1 = MOVSSrm %0, 1, _, 0, _ :: (load 4 from %ir.p1)
672 # AVX: %1 = VMOVSSrm %0, 1, _, 0, _ :: (load 4 from %ir.p1)
673 # AVX512ALL: %1 = VMOVSSZrm %0, 1, _, 0, _ :: (load 4 from %ir.p1)
674 # ALL: %xmm0 = COPY %1
675 body: |
676 bb.1 (%ir-block.0):
677 liveins: %rdi
678
679 %0(p0) = COPY %rdi
680 %1(s32) = G_LOAD %0(p0) :: (load 4 from %ir.p1)
681 %xmm0 = COPY %1(s32)
682 RET 0, implicit %xmm0
683
684 ...
685 ---
686 # ALL-LABEL: name: test_load_double
687 name: test_load_double
688 alignment: 4
689 legalized: true
690 regBankSelected: true
691 registers:
692 # ALL: - { id: 0, class: gr64 }
693 # ALL: - { id: 1, class: gr64 }
694 - { id: 0, class: gpr }
695 - { id: 1, class: gpr }
696 # ALL: %0 = COPY %rdi
697 # ALL: %1 = MOV64rm %0, 1, _, 0, _ :: (load 8 from %ir.p1)
698 # ALL: %xmm0 = COPY %1
699 body: |
700 bb.1 (%ir-block.0):
701 liveins: %rdi
702
703 %0(p0) = COPY %rdi
704 %1(s64) = G_LOAD %0(p0) :: (load 8 from %ir.p1)
705 %xmm0 = COPY %1(s64)
706 RET 0, implicit %xmm0
707
708 ...
709 ---
710 # ALL-LABEL: name: test_load_double_vecreg
711 name: test_load_double_vecreg
712 alignment: 4
713 legalized: true
714 regBankSelected: true
715 registers:
716 # ALL: - { id: 0, class: gr64 }
717 # NO_AVX512F: - { id: 1, class: fr64 }
718 # AVX512ALL: - { id: 1, class: fr64x }
719 - { id: 0, class: gpr }
720 - { id: 1, class: vecr }
721 # ALL: %0 = COPY %rdi
722 # SSE: %1 = MOVSDrm %0, 1, _, 0, _ :: (load 8 from %ir.p1)
723 # AVX: %1 = VMOVSDrm %0, 1, _, 0, _ :: (load 8 from %ir.p1)
724 # AVX512ALL: %1 = VMOVSDZrm %0, 1, _, 0, _ :: (load 8 from %ir.p1)
725 # ALL: %xmm0 = COPY %1
726 body: |
727 bb.1 (%ir-block.0):
728 liveins: %rdi
729
730 %0(p0) = COPY %rdi
731 %1(s64) = G_LOAD %0(p0) :: (load 8 from %ir.p1)
732 %xmm0 = COPY %1(s64)
733 RET 0, implicit %xmm0
734
735 ...
736 ---
737 # ALL-LABEL: name: test_load_v4i32_noalign
738 name: test_load_v4i32_noalign
739 alignment: 4
740 legalized: true
741 regBankSelected: true
742 registers:
743 # ALL: - { id: 0, class: gr64 }
744 # NO_AVX512F: - { id: 1, class: vr128 }
745 # AVX512ALL: - { id: 1, class: vr128x }
746 - { id: 0, class: gpr }
747 - { id: 1, class: vecr }
748 # ALL: %0 = COPY %rdi
749 # SSE: %1 = MOVUPSrm %0, 1, _, 0, _ :: (load 16 from %ir.p1, align 1)
750 # AVX: %1 = VMOVUPSrm %0, 1, _, 0, _ :: (load 16 from %ir.p1, align 1)
751 # AVX512F: %1 = VMOVUPSZ128rm_NOVLX %0, 1, _, 0, _ :: (load 16 from %ir.p1, align 1)
752 # AVX512VL: %1 = VMOVUPSZ128rm %0, 1, _, 0, _ :: (load 16 from %ir.p1, align 1)
753 # ALL: %xmm0 = COPY %1
754 body: |
755 bb.1 (%ir-block.0):
756 liveins: %rdi
757
758 %0(p0) = COPY %rdi
759 %1(<4 x s32>) = G_LOAD %0(p0) :: (load 16 from %ir.p1, align 1)
760 %xmm0 = COPY %1(<4 x s32>)
761 RET 0, implicit %xmm0
762
763 ...
764 ---
765 # ALL-LABEL: name: test_load_v4i32_align
766 name: test_load_v4i32_align
767 alignment: 4
768 legalized: true
769 regBankSelected: true
770 registers:
771 # ALL: - { id: 0, class: gr64 }
772 # NO_AVX512F: - { id: 1, class: vr128 }
773 # AVX512ALL: - { id: 1, class: vr128x }
774 - { id: 0, class: gpr }
775 - { id: 1, class: vecr }
776 # ALL: %0 = COPY %rdi
777 # SSE: %1 = MOVAPSrm %0, 1, _, 0, _ :: (load 16 from %ir.p1)
778 # AVX: %1 = VMOVAPSrm %0, 1, _, 0, _ :: (load 16 from %ir.p1)
779 # AVX512F: %1 = VMOVAPSZ128rm_NOVLX %0, 1, _, 0, _ :: (load 16 from %ir.p1)
780 # AVX512VL: %1 = VMOVAPSZ128rm %0, 1, _, 0, _ :: (load 16 from %ir.p1)
781 # ALL: %xmm0 = COPY %1
782 body: |
783 bb.1 (%ir-block.0):
784 liveins: %rdi
785
786 %0(p0) = COPY %rdi
787 %1(<4 x s32>) = G_LOAD %0(p0) :: (load 16 from %ir.p1)
788 %xmm0 = COPY %1(<4 x s32>)
789 RET 0, implicit %xmm0
790
791 ...
792 ---
793 # ALL-LABEL: name: test_store_i32
794 name: test_store_i32
795 alignment: 4
796 legalized: true
797 regBankSelected: true
798 registers:
799 # ALL: - { id: 0, class: gr32 }
800 # ALL: - { id: 1, class: gr64 }
801 - { id: 0, class: gpr }
802 - { id: 1, class: gpr }
803 # ALL: %0 = COPY %edi
804 # ALL: %1 = COPY %rsi
805 # ALL: MOV32mr %1, 1, _, 0, _, %0 :: (store 4 into %ir.p1)
806 # ALL: %rax = COPY %1
807 body: |
808 bb.1 (%ir-block.0):
809 liveins: %edi, %rsi
810
811 %0(s32) = COPY %edi
812 %1(p0) = COPY %rsi
813 G_STORE %0(s32), %1(p0) :: (store 4 into %ir.p1)
814 %rax = COPY %1(p0)
815 RET 0, implicit %rax
816
817 ...
818 ---
819 # ALL-LABEL: name: test_store_i64
820 name: test_store_i64
821 alignment: 4
822 legalized: true
823 regBankSelected: true
824 registers:
825 # ALL: - { id: 0, class: gr64 }
826 # ALL: - { id: 1, class: gr64 }
827 - { id: 0, class: gpr }
828 - { id: 1, class: gpr }
829 # ALL: %0 = COPY %rdi
830 # ALL: %1 = COPY %rsi
831 # ALL: MOV64mr %1, 1, _, 0, _, %0 :: (store 8 into %ir.p1)
832 # ALL: %rax = COPY %1
833 body: |
834 bb.1 (%ir-block.0):
835 liveins: %rdi, %rsi
836
837 %0(s64) = COPY %rdi
838 %1(p0) = COPY %rsi
839 G_STORE %0(s64), %1(p0) :: (store 8 into %ir.p1)
840 %rax = COPY %1(p0)
841 RET 0, implicit %rax
842
843 ...
844 ---
845 # ALL-LABEL: name: test_store_float
846 name: test_store_float
847 alignment: 4
848 legalized: true
849 regBankSelected: true
850 registers:
851 # ALL: - { id: 0, class: fr32x }
852 # ALL: - { id: 1, class: gr64 }
853 # ALL: - { id: 2, class: gr32 }
854 - { id: 0, class: vecr }
855 - { id: 1, class: gpr }
856 - { id: 2, class: gpr }
857 # ALL: %0 = COPY %xmm0
858 # ALL: %1 = COPY %rdi
859 # ALL: %2 = COPY %0
860 # ALL: MOV32mr %1, 1, _, 0, _, %2 :: (store 4 into %ir.p1)
861 # ALL: %rax = COPY %1
862 body: |
863 bb.1 (%ir-block.0):
864 liveins: %rdi, %xmm0
865
866 %0(s32) = COPY %xmm0
867 %1(p0) = COPY %rdi
868 %2(s32) = COPY %0(s32)
869 G_STORE %2(s32), %1(p0) :: (store 4 into %ir.p1)
870 %rax = COPY %1(p0)
871 RET 0, implicit %rax
872
873 ...
874 ---
875 # ALL-LABEL: name: test_store_float_vec
876 name: test_store_float_vec
877 alignment: 4
878 legalized: true
879 regBankSelected: true
880 registers:
881 # NO_AVX512F: - { id: 0, class: fr32 }
882 # AVX512ALL: - { id: 0, class: fr32x }
883 # ALL: - { id: 1, class: gr64 }
884 - { id: 0, class: vecr }
885 - { id: 1, class: gpr }
886 # ALL: %0 = COPY %xmm0
887 # ALL: %1 = COPY %rdi
888 # SSE: MOVSSmr %1, 1, _, 0, _, %0 :: (store 4 into %ir.p1)
889 # AVX: VMOVSSmr %1, 1, _, 0, _, %0 :: (store 4 into %ir.p1)
890 # AVX512ALL: VMOVSSZmr %1, 1, _, 0, _, %0 :: (store 4 into %ir.p1)
891 # ALL: %rax = COPY %1
892 body: |
893 bb.1 (%ir-block.0):
894 liveins: %rdi, %xmm0
895
896 %0(s32) = COPY %xmm0
897 %1(p0) = COPY %rdi
898 G_STORE %0(s32), %1(p0) :: (store 4 into %ir.p1)
899 %rax = COPY %1(p0)
900 RET 0, implicit %rax
901
902 ...
903 ---
904 # ALL-LABEL: name: test_store_double
905 name: test_store_double
906 alignment: 4
907 legalized: true
908 regBankSelected: true
909 registers:
910 # ALL: - { id: 0, class: fr64x }
911 # ALL: - { id: 1, class: gr64 }
912 # ALL: - { id: 2, class: gr64 }
913 - { id: 0, class: vecr }
914 - { id: 1, class: gpr }
915 - { id: 2, class: gpr }
916 # ALL: %0 = COPY %xmm0
917 # ALL: %1 = COPY %rdi
918 # ALL: %2 = COPY %0
919 # ALL: MOV64mr %1, 1, _, 0, _, %2 :: (store 8 into %ir.p1)
920 # ALL: %rax = COPY %1
921 body: |
922 bb.1 (%ir-block.0):
923 liveins: %rdi, %xmm0
924
925 %0(s64) = COPY %xmm0
926 %1(p0) = COPY %rdi
927 %2(s64) = COPY %0(s64)
928 G_STORE %2(s64), %1(p0) :: (store 8 into %ir.p1)
929 %rax = COPY %1(p0)
930 RET 0, implicit %rax
931
932 ...
933 ---
934 # ALL-LABEL: name: test_store_double_vec
935 name: test_store_double_vec
936 alignment: 4
937 legalized: true
938 regBankSelected: true
939 registers:
940 # NO_AVX512F: - { id: 0, class: fr64 }
941 # AVX512ALL: - { id: 0, class: fr64x }
942 # ALL: - { id: 1, class: gr64 }
943 - { id: 0, class: vecr }
944 - { id: 1, class: gpr }
945 # ALL: %0 = COPY %xmm0
946 # ALL: %1 = COPY %rdi
947 # SSE: MOVSDmr %1, 1, _, 0, _, %0 :: (store 8 into %ir.p1)
948 # AVX: VMOVSDmr %1, 1, _, 0, _, %0 :: (store 8 into %ir.p1)
949 # AVX512ALL: VMOVSDZmr %1, 1, _, 0, _, %0 :: (store 8 into %ir.p1)
950 # ALL: %rax = COPY %1
951 body: |
952 bb.1 (%ir-block.0):
953 liveins: %rdi, %xmm0
954
955 %0(s64) = COPY %xmm0
956 %1(p0) = COPY %rdi
957 G_STORE %0(s64), %1(p0) :: (store 8 into %ir.p1)
958 %rax = COPY %1(p0)
959 RET 0, implicit %rax
960
961 ...
962 ---
963 # ALL-LABEL: name: test_store_v4i32_align
964 name: test_store_v4i32_align
965 alignment: 4
966 legalized: true
967 regBankSelected: true
968 registers:
969 # NO_AVX512F: - { id: 0, class: vr128 }
970 # AVX512ALL: - { id: 0, class: vr128x }
971 # ALL: - { id: 1, class: gr64 }
972 - { id: 0, class: vecr }
973 - { id: 1, class: gpr }
974 # ALL: %0 = COPY %xmm0
975 # ALL: %1 = COPY %rdi
976 # SSE: MOVAPSmr %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1)
977 # AVX: VMOVAPSmr %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1)
978 # AVX512F: VMOVAPSZ128mr_NOVLX %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1)
979 # AVX512VL: VMOVAPSZ128mr %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1)
980 # ALL: %rax = COPY %1
981 body: |
982 bb.1 (%ir-block.0):
983 liveins: %rdi, %xmm0
984
985 %0(<4 x s32>) = COPY %xmm0
986 %1(p0) = COPY %rdi
987 G_STORE %0(<4 x s32>), %1(p0) :: (store 16 into %ir.p1, align 16)
988 %rax = COPY %1(p0)
989 RET 0, implicit %rax
990
991 ...
992 ---
993 # ALL-LABEL: name: test_store_v4i32_noalign
994 name: test_store_v4i32_noalign
995 alignment: 4
996 legalized: true
997 regBankSelected: true
998 registers:
999 # NO_AVX512F: - { id: 0, class: vr128 }
1000 # AVX512ALL: - { id: 0, class: vr128x }
1001 # ALL: - { id: 1, class: gr64 }
1002 - { id: 0, class: vecr }
1003 - { id: 1, class: gpr }
1004 # ALL: %0 = COPY %xmm0
1005 # ALL: %1 = COPY %rdi
1006 # SSE: MOVUPSmr %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1, align 1)
1007 # AVX: VMOVUPSmr %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1, align 1)
1008 # AVX512F: VMOVUPSZ128mr_NOVLX %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1, align 1)
1009 # AVX512VL: VMOVUPSZ128mr %1, 1, _, 0, _, %0 :: (store 16 into %ir.p1, align 1)
1010 # ALL: %rax = COPY %1
1011 body: |
1012 bb.1 (%ir-block.0):
1013 liveins: %rdi, %xmm0
1014
1015 %0(<4 x s32>) = COPY %xmm0
1016 %1(p0) = COPY %rdi
1017 G_STORE %0(<4 x s32>), %1(p0) :: (store 16 into %ir.p1, align 1)
1018 %rax = COPY %1(p0)
1019 RET 0, implicit %rax
1020
1021 ...