llvm.org GIT mirror llvm / c0199e4
[GlobalIsel][X86] support G_TRUNC selection. Summary: [GlobalIsel][X86] support G_TRUNC selection. Add regbank-select and legalizer tests. Currently legalization of trunc i64 on 32bit platform not supported. Reviewers: ab, zvi, rovka Reviewed By: zvi Subscribers: dberris, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D32115 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300678 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Breger 3 years ago
6 changed file(s) with 361 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
6666 MachineFunction &MF) const;
6767 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
6868 MachineFunction &MF) const;
69 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
70 MachineFunction &MF) const;
6971
7072 const X86Subtarget &STI;
7173 const X86InstrInfo &TII;
98100 static const TargetRegisterClass *
99101 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
100102 if (RB.getID() == X86::GPRRegBankID) {
103 if (Ty.getSizeInBits() <= 8)
104 return &X86::GR8RegClass;
105 if (Ty.getSizeInBits() == 16)
106 return &X86::GR16RegClass;
101107 if (Ty.getSizeInBits() == 32)
102108 return &X86::GR32RegClass;
103109 if (Ty.getSizeInBits() == 64)
205211 if (selectFrameIndex(I, MRI, MF))
206212 return true;
207213 if (selectConstant(I, MRI, MF))
214 return true;
215 if (selectTrunc(I, MRI, MF))
208216 return true;
209217
210218 return selectImpl(I);
508516 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
509517 }
510518
519 bool X86InstructionSelector::selectTrunc(MachineInstr &I,
520 MachineRegisterInfo &MRI,
521 MachineFunction &MF) const {
522 if (I.getOpcode() != TargetOpcode::G_TRUNC)
523 return false;
524
525 const unsigned DstReg = I.getOperand(0).getReg();
526 const unsigned SrcReg = I.getOperand(1).getReg();
527
528 const LLT DstTy = MRI.getType(DstReg);
529 const LLT SrcTy = MRI.getType(SrcReg);
530
531 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
532 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
533
534 if (DstRB.getID() != SrcRB.getID()) {
535 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
536 return false;
537 }
538
539 if (DstRB.getID() != X86::GPRRegBankID)
540 return false;
541
542 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
543 if (!DstRC)
544 return false;
545
546 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
547 if (!SrcRC)
548 return false;
549
550 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
551 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
552 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
553 return false;
554 }
555
556 if (DstRC == SrcRC) {
557 // Nothing to be done
558 } else if (DstRC == &X86::GR32RegClass) {
559 I.getOperand(1).setSubReg(X86::sub_32bit);
560 } else if (DstRC == &X86::GR16RegClass) {
561 I.getOperand(1).setSubReg(X86::sub_16bit);
562 } else if (DstRC == &X86::GR8RegClass) {
563 I.getOperand(1).setSubReg(X86::sub_8bit);
564 } else {
565 return false;
566 }
567
568 I.setDesc(TII.get(X86::COPY));
569 return true;
570 }
571
511572 InstructionSelector *
512573 llvm::createX86InstructionSelector(X86Subtarget &Subtarget,
513574 X86RegisterBankInfo &RBI) {
6767 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
6868 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
6969 switch (Ty.getSizeInBits()) {
70 case 1:
7071 case 8:
7172 return PMI_GPR8;
7273 case 16:
102102 }
103103
104104 define void @constInt_check() {
105 ret void
106 }
107
108 define void @trunc_check() {
105109 ret void
106110 }
107111
631635 RET 0
632636
633637 ...
638 ---
639 name: trunc_check
640 alignment: 4
641 legalized: true
642 # CHECK-LABEL: name: trunc_check
643 # CHECK: registers:
644 # CHECK-NEXT: - { id: 0, class: gpr }
645 # CHECK-NEXT: - { id: 1, class: gpr }
646 # CHECK-NEXT: - { id: 2, class: gpr }
647 # CHECK-NEXT: - { id: 3, class: gpr }
648 registers:
649 - { id: 0, class: _ }
650 - { id: 1, class: _ }
651 - { id: 2, class: _ }
652 - { id: 3, class: _ }
653 body: |
654 bb.0 (%ir-block.0):
655 %0(s32) = IMPLICIT_DEF
656 %1(s1) = G_TRUNC %0(s32)
657 %2(s8) = G_TRUNC %0(s32)
658 %3(s16) = G_TRUNC %0(s32)
659 RET 0
660
661 ...
0 # 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
2 --- |
3 define void @trunc_check() {
4 ret void
5 }
6
7 ...
8 ---
9 name: trunc_check
10 # ALL-LABEL: name: trunc_check
11 registers:
12 - { id: 0, class: _ }
13 - { id: 1, class: _ }
14 - { id: 2, class: _ }
15 - { id: 3, class: _ }
16 body: |
17 bb.1 (%ir-block.0):
18 %0(s32) = IMPLICIT_DEF
19 ; ALL: %1(s1) = G_TRUNC %0(s32)
20 %1(s1) = G_TRUNC %0(s32)
21
22 ; ALL: %2(s8) = G_TRUNC %0(s32)
23 %2(s8) = G_TRUNC %0(s32)
24
25 ; ALL: %3(s16) = G_TRUNC %0(s32)
26 %3(s16) = G_TRUNC %0(s32)
27 RET 0
28
29 ...
30
0 # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=CHECK
1 --- |
2 define i1 @trunc_i32toi1(i32 %a) {
3 %r = trunc i32 %a to i1
4 ret i1 %r
5 }
6
7 define i8 @trunc_i32toi8(i32 %a) {
8 %r = trunc i32 %a to i8
9 ret i8 %r
10 }
11
12 define i16 @trunc_i32toi16(i32 %a) {
13 %r = trunc i32 %a to i16
14 ret i16 %r
15 }
16
17 define i8 @trunc_i64toi8(i64 %a) {
18 %r = trunc i64 %a to i8
19 ret i8 %r
20 }
21
22 define i16 @trunc_i64toi16(i64 %a) {
23 %r = trunc i64 %a to i16
24 ret i16 %r
25 }
26
27 define i32 @trunc_i64toi32(i64 %a) {
28 %r = trunc i64 %a to i32
29 ret i32 %r
30 }
31
32 ...
33 ---
34 name: trunc_i32toi1
35 alignment: 4
36 legalized: true
37 regBankSelected: true
38 selected: false
39 # CHECK-LABEL: name: trunc_i32toi1
40 # CHECK: registers:
41 # CHECK-NEXT: - { id: 0, class: gr32 }
42 # CHECK-NEXT: - { id: 1, class: gr8 }
43 registers:
44 - { id: 0, class: gpr }
45 - { id: 1, class: gpr }
46 # CHECK: body:
47 # CHECK: %1 = COPY %0.sub_8
48 body: |
49 bb.1 (%ir-block.0):
50 liveins: %edi
51
52 %0(s32) = COPY %edi
53 %1(s1) = G_TRUNC %0(s32)
54 %al = COPY %1(s1)
55 RET 0, implicit %al
56
57 ...
58 ---
59 name: trunc_i32toi8
60 alignment: 4
61 legalized: true
62 regBankSelected: true
63 selected: false
64 # CHECK-LABEL: name: trunc_i32toi8
65 # CHECK: registers:
66 # CHECK-NEXT: - { id: 0, class: gr32 }
67 # CHECK-NEXT: - { id: 1, class: gr8 }
68 registers:
69 - { id: 0, class: gpr }
70 - { id: 1, class: gpr }
71 # CHECK: body:
72 # CHECK: %1 = COPY %0.sub_8
73 body: |
74 bb.1 (%ir-block.0):
75 liveins: %edi
76
77 %0(s32) = COPY %edi
78 %1(s8) = G_TRUNC %0(s32)
79 %al = COPY %1(s8)
80 RET 0, implicit %al
81
82 ...
83 ---
84 name: trunc_i32toi16
85 alignment: 4
86 legalized: true
87 regBankSelected: true
88 selected: false
89 # CHECK-LABEL: name: trunc_i32toi16
90 # CHECK: registers:
91 # CHECK-NEXT: - { id: 0, class: gr32 }
92 # CHECK-NEXT: - { id: 1, class: gr16 }
93 registers:
94 - { id: 0, class: gpr }
95 - { id: 1, class: gpr }
96 # CHECK: body:
97 # CHECK: %1 = COPY %0.sub_16
98 body: |
99 bb.1 (%ir-block.0):
100 liveins: %edi
101
102 %0(s32) = COPY %edi
103 %1(s16) = G_TRUNC %0(s32)
104 %ax = COPY %1(s16)
105 RET 0, implicit %ax
106
107 ...
108 ---
109 name: trunc_i64toi8
110 alignment: 4
111 legalized: true
112 regBankSelected: true
113 selected: false
114 # CHECK-LABEL: name: trunc_i64toi8
115 # CHECK: registers:
116 # CHECK-NEXT: - { id: 0, class: gr64 }
117 # CHECK-NEXT: - { id: 1, class: gr8 }
118 registers:
119 - { id: 0, class: gpr }
120 - { id: 1, class: gpr }
121 # CHECK: body:
122 # CHECK: %1 = COPY %0.sub_8
123 body: |
124 bb.1 (%ir-block.0):
125 liveins: %rdi
126
127 %0(s64) = COPY %rdi
128 %1(s8) = G_TRUNC %0(s64)
129 %al = COPY %1(s8)
130 RET 0, implicit %al
131
132 ...
133 ---
134 name: trunc_i64toi16
135 alignment: 4
136 legalized: true
137 regBankSelected: true
138 selected: false
139 # CHECK-LABEL: name: trunc_i64toi16
140 # CHECK: registers:
141 # CHECK-NEXT: - { id: 0, class: gr64 }
142 # CHECK-NEXT: - { id: 1, class: gr16 }
143 registers:
144 - { id: 0, class: gpr }
145 - { id: 1, class: gpr }
146 # CHECK: body:
147 # CHECK: %1 = COPY %0.sub_16
148 body: |
149 bb.1 (%ir-block.0):
150 liveins: %rdi
151
152 %0(s64) = COPY %rdi
153 %1(s16) = G_TRUNC %0(s64)
154 %ax = COPY %1(s16)
155 RET 0, implicit %ax
156
157 ...
158 ---
159 name: trunc_i64toi32
160 alignment: 4
161 legalized: true
162 regBankSelected: true
163 selected: false
164 # CHECK-LABEL: name: trunc_i64toi32
165 # CHECK: registers:
166 # CHECK-NEXT: - { id: 0, class: gr64 }
167 # CHECK-NEXT: - { id: 1, class: gr32 }
168 registers:
169 - { id: 0, class: gpr }
170 - { id: 1, class: gpr }
171 # CHECK: body:
172 # CHECK: %1 = COPY %0.sub_32
173 body: |
174 bb.1 (%ir-block.0):
175 liveins: %rdi
176
177 %0(s64) = COPY %rdi
178 %1(s32) = G_TRUNC %0(s64)
179 %eax = COPY %1(s32)
180 RET 0, implicit %eax
181
182 ...
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=CHECK
2
3 define i1 @trunc_i32toi1(i32 %a) {
4 ; CHECK-LABEL: trunc_i32toi1:
5 ; CHECK: # BB#0:
6 ; CHECK-NEXT: movl %edi, %eax
7 ; CHECK-NEXT: retq
8 %r = trunc i32 %a to i1
9 ret i1 %r
10 }
11
12 define i8 @trunc_i32toi8(i32 %a) {
13 ; CHECK-LABEL: trunc_i32toi8:
14 ; CHECK: # BB#0:
15 ; CHECK-NEXT: movl %edi, %eax
16 ; CHECK-NEXT: retq
17 %r = trunc i32 %a to i8
18 ret i8 %r
19 }
20
21 define i16 @trunc_i32toi16(i32 %a) {
22 ; CHECK-LABEL: trunc_i32toi16:
23 ; CHECK: # BB#0:
24 ; CHECK-NEXT: movl %edi, %eax
25 ; CHECK-NEXT: retq
26 %r = trunc i32 %a to i16
27 ret i16 %r
28 }
29
30 define i8 @trunc_i64toi8(i64 %a) {
31 ; CHECK-LABEL: trunc_i64toi8:
32 ; CHECK: # BB#0:
33 ; CHECK-NEXT: movl %edi, %eax
34 ; CHECK-NEXT: retq
35 %r = trunc i64 %a to i8
36 ret i8 %r
37 }
38
39 define i16 @trunc_i64toi16(i64 %a) {
40 ; CHECK-LABEL: trunc_i64toi16:
41 ; CHECK: # BB#0:
42 ; CHECK-NEXT: movl %edi, %eax
43 ; CHECK-NEXT: retq
44 %r = trunc i64 %a to i16
45 ret i16 %r
46 }
47
48 define i32 @trunc_i64toi32(i64 %a) {
49 ; CHECK-LABEL: trunc_i64toi32:
50 ; CHECK: # BB#0:
51 ; CHECK-NEXT: movl %edi, %eax
52 ; CHECK-NEXT: retq
53 %r = trunc i64 %a to i32
54 ret i32 %r
55 }
56