llvm.org GIT mirror llvm / 8ae3570
[X86][GlobalISel] Initial implementation , select G_ADD gpr, gpr Summary: Initial implementation for X86InstructionSelector. Handle selection COPY and G_ADD/G_SUB gpr, gpr . Reviewers: qcolombet, rovka, zvi, ab Reviewed By: rovka Subscribers: mgorny, dberris, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D29816 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295824 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Breger 3 years ago
10 changed file(s) with 407 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
5454 // constrainOperandRegClass does that for us.
5555 MO.setReg(constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(),
5656 Reg, OpI));
57
58 // Tie uses to defs as indicated in MCInstrDesc.
59 if (MO.isUse()) {
60 int DefIdx = I.getDesc().getOperandConstraint(OpI, MCOI::TIED_TO);
61 if (DefIdx != -1)
62 I.tieOperands(DefIdx, OpI);
63 }
5764 }
5865 return true;
5966 }
1111 tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
1212 if(LLVM_BUILD_GLOBAL_ISEL)
1313 tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank)
14 tablegen(LLVM X86GenGlobalISel.inc -gen-global-isel)
1415 endif()
1516
1617 add_public_tablegen_target(X86CommonTableGen)
2021 X86CallLowering.cpp
2122 X86LegalizerInfo.cpp
2223 X86RegisterBankInfo.cpp
24 X86InstructionSelector.cpp
2325 )
2426
2527 if(LLVM_BUILD_GLOBAL_ISEL)
0 //===- X86InstructionSelector.cpp ----------------------------*- C++ -*-==//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements the targeting of the InstructionSelector class for
10 /// X86.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13
14 #include "X86InstructionSelector.h"
15 #include "X86InstrInfo.h"
16 #include "X86RegisterBankInfo.h"
17 #include "X86RegisterInfo.h"
18 #include "X86Subtarget.h"
19 #include "X86TargetMachine.h"
20 #include "llvm/CodeGen/MachineBasicBlock.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstr.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/IR/Type.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/raw_ostream.h"
28
29 #define DEBUG_TYPE "X86-isel"
30
31 using namespace llvm;
32
33 #ifndef LLVM_BUILD_GLOBAL_ISEL
34 #error "You shouldn't build this"
35 #endif
36
37 #include "X86GenGlobalISel.inc"
38
39 X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
40 const X86Subtarget &STI,
41 const X86RegisterBankInfo &RBI)
42 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
43 TRI(*STI.getRegisterInfo()), RBI(RBI) {}
44
45 // FIXME: This should be target-independent, inferred from the types declared
46 // for each class in the bank.
47 static const TargetRegisterClass *
48 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
49 if (RB.getID() == X86::GPRRegBankID) {
50 if (Ty.getSizeInBits() <= 32)
51 return &X86::GR32RegClass;
52 if (Ty.getSizeInBits() == 64)
53 return &X86::GR64RegClass;
54 }
55
56 llvm_unreachable("Unknown RegBank!");
57 }
58
59 // Set X86 Opcode and constrain DestReg.
60 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
61 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
62 const RegisterBankInfo &RBI) {
63
64 unsigned DstReg = I.getOperand(0).getReg();
65 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
66 assert(I.isCopy() && "Generic operators do not allow physical registers");
67 return true;
68 }
69
70 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
71 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
72 unsigned SrcReg = I.getOperand(1).getReg();
73 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
74 (void)SrcSize;
75 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
76 "No phys reg on generic operators");
77 assert((DstSize == SrcSize ||
78 // Copies are a mean to setup initial types, the number of
79 // bits may not exactly match.
80 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
81 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
82 "Copy with different width?!");
83
84 const TargetRegisterClass *RC = nullptr;
85
86 switch (RegBank.getID()) {
87 case X86::GPRRegBankID:
88 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
89 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
90 break;
91 default:
92 llvm_unreachable("Unknown RegBank!");
93 }
94
95 // No need to constrain SrcReg. It will get constrained when
96 // we hit another of its use or its defs.
97 // Copies do not have constraints.
98 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
99 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
100 << " operand\n");
101 return false;
102 }
103 I.setDesc(TII.get(X86::COPY));
104 return true;
105 }
106
107 bool X86InstructionSelector::select(MachineInstr &I) const {
108 assert(I.getParent() && "Instruction should be in a basic block!");
109 assert(I.getParent()->getParent() && "Instruction should be in a function!");
110
111 MachineBasicBlock &MBB = *I.getParent();
112 MachineFunction &MF = *MBB.getParent();
113 MachineRegisterInfo &MRI = MF.getRegInfo();
114
115 unsigned Opcode = I.getOpcode();
116 if (!isPreISelGenericOpcode(Opcode)) {
117 // Certain non-generic instructions also need some special handling.
118
119 if (I.isCopy())
120 return selectCopy(I, TII, MRI, TRI, RBI);
121
122 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
123 return true;
124 }
125
126 if (I.getNumOperands() != I.getNumExplicitOperands()) {
127 assert("Generic instruction has unexpected implicit operands\n");
128 return false;
129 }
130
131 return selectImpl(I);
132 }
0 //===- X86InstructionSelector --------------------------------*- C++ -*-==//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file declares the targeting of the InstructionSelector class for X86.
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_LIB_TARGET_X86_X86INSTRUCTIONSELECTOR_H
13 #define LLVM_LIB_TARGET_X86_X86INSTRUCTIONSELECTOR_H
14
15 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
16
17 namespace llvm {
18
19 class X86InstrInfo;
20 class X86RegisterBankInfo;
21 class X86RegisterInfo;
22 class X86Subtarget;
23 class X86TargetMachine;
24
25 class X86InstructionSelector : public InstructionSelector {
26 public:
27 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
28 const X86RegisterBankInfo &RBI);
29
30 bool select(MachineInstr &I) const override;
31
32 private:
33 /// tblgen-erated 'select' implementation, used as the initial selector for
34 /// the patterns that don't require complex C++.
35 bool selectImpl(MachineInstr &I) const;
36
37 const X86TargetMachine &TM;
38 const X86Subtarget &STI;
39 const X86InstrInfo &TII;
40 const X86RegisterInfo &TRI;
41 const X86RegisterBankInfo &RBI;
42 };
43
44 } // end namespace llvm
45
46 #endif // LLVM_LIB_TARGET_X86_X86INSTRUCTIONSELECTOR_H
3737 const LLT s16 = LLT::scalar(16);
3838 const LLT s32 = LLT::scalar(32);
3939
40 for (auto Ty : {s8, s16, s32})
40 for (auto Ty : {s8, s16, s32}) {
4141 setAction({TargetOpcode::G_ADD, Ty}, Legal);
42 setAction({TargetOpcode::G_SUB, Ty}, Legal);
43 }
4244 }
43 void
4445
45 X86LegalizerInfo::setLegalizerInfo64bit() {
46 void X86LegalizerInfo::setLegalizerInfo64bit() {
4647
4748 if (!Subtarget.is64Bit())
4849 return;
5051 const LLT s64 = LLT::scalar(64);
5152
5253 setAction({TargetOpcode::G_ADD, s64}, Legal);
54 setAction({TargetOpcode::G_SUB, s64}, Legal);
5355 }
110110
111111 switch (Opc) {
112112 case TargetOpcode::G_ADD:
113 case TargetOpcode::G_SUB:
113114 return getOperandsMapping(MI, false);
114115 break;
115116 default:
1414 #include "X86.h"
1515 #include "X86CallLowering.h"
1616 #include "X86LegalizerInfo.h"
17 #include "X86InstructionSelector.h"
1718 #ifdef LLVM_BUILD_GLOBAL_ISEL
1819 #include "X86RegisterBankInfo.h"
1920 #endif
3334 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
3435 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
3536 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
37 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
3638 #include "llvm/CodeGen/MachineScheduler.h"
3739 #include "llvm/CodeGen/Passes.h"
3840 #include "llvm/CodeGen/TargetPassConfig.h"
210212 std::unique_ptr CallLoweringInfo;
211213 std::unique_ptr Legalizer;
212214 std::unique_ptr RegBankInfo;
215 std::unique_ptr InstSelector;
213216
214217 const CallLowering *getCallLowering() const override {
215218 return CallLoweringInfo.get();
216219 }
217220
218221 const InstructionSelector *getInstructionSelector() const override {
219 //TODO: Implement
220 return nullptr;
222 return InstSelector.get();
221223 }
222224
223225 const LegalizerInfo *getLegalizerInfo() const override {
281283
282284 auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo());
283285 GISel->RegBankInfo.reset(RBI);
286 GISel->InstSelector.reset(new X86InstructionSelector(*this, *I, *RBI));
284287
285288 #endif
286289 I->setGISelAccessor(*GISel);
390393 }
391394
392395 bool X86PassConfig::addGlobalInstructionSelect() {
393 //TODO: Implement
396 addPass(new InstructionSelect());
394397 return false;
395398 }
396399 #endif
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
2
3 define i64 @test_add_i64(i64 %arg1, i64 %arg2) {
4 ; CHECK-LABEL: test_add_i64:
5 ; CHECK: # BB#0:
6 ; CHECK-NEXT: leaq (%rsi,%rdi), %rax
7 ; CHECK-NEXT: retq
8 %ret = add i64 %arg1, %arg2
9 ret i64 %ret
10 }
11
12 define i32 @test_add_i32(i32 %arg1, i32 %arg2) {
13 ; CHECK-LABEL: test_add_i32:
14 ; CHECK: # BB#0:
15 ; CHECK-NEXT: # kill: %EDI %EDI %RDI
16 ; CHECK-NEXT: # kill: %ESI %ESI %RSI
17 ; CHECK-NEXT: leal (%rsi,%rdi), %eax
18 ; CHECK-NEXT: retq
19 %ret = add i32 %arg1, %arg2
20 ret i32 %ret
21 }
22
23 define i64 @test_sub_i64(i64 %arg1, i64 %arg2) {
24 ; CHECK-LABEL: test_sub_i64:
25 ; CHECK: # BB#0:
26 ; CHECK-NEXT: subq %rsi, %rdi
27 ; CHECK-NEXT: movq %rdi, %rax
28 ; CHECK-NEXT: retq
29 %ret = sub i64 %arg1, %arg2
30 ret i64 %ret
31 }
32
33 define i32 @test_sub_i32(i32 %arg1, i32 %arg2) {
34 ; CHECK-LABEL: test_sub_i32:
35 ; CHECK: # BB#0:
36 ; CHECK-NEXT: subl %esi, %edi
37 ; CHECK-NEXT: movl %edi, %eax
38 ; CHECK-NEXT: retq
39 %ret = sub i32 %arg1, %arg2
40 ret i32 %ret
41 }
0 # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s
1
2 --- |
3 ; ModuleID = ''
4 source_filename = ""
5 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6 target triple = "x86_64--linux-gnu"
7
8 define i32 @test_sub_i32(i32 %arg1, i32 %arg2) {
9 %ret = sub i32 %arg1, %arg2
10 ret i32 %ret
11 }
12
13 ...
14 ---
15 name: test_sub_i32
16 alignment: 4
17 legalized: false
18 regBankSelected: false
19 selected: false
20 tracksRegLiveness: true
21 registers:
22 - { id: 0, class: _ }
23 - { id: 1, class: _ }
24 - { id: 2, class: _ }
25 body: |
26 bb.1 (%ir-block.0):
27 liveins: %edi, %esi
28 ; CHECK-LABEL: name: test_sub_i32
29 ; CHECK: [[VAL1:%.*]](s32) = COPY %edi
30 ; CHECK: [[VAL2:%.*]](s32) = COPY %esi
31 ; CHECK: [[RES:%.*]](s32) = G_SUB [[VAL1:%.*]], [[VAL2:%.*]]
32
33 %0(s32) = COPY %edi
34 %1(s32) = COPY %esi
35 %2(s32) = G_SUB %0, %1
36 %eax = COPY %2(s32)
37 RET 0, implicit %eax
38
39 ...
0 # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
1
2 --- |
3 define i64 @test_add_i64(i64 %arg1, i64 %arg2) {
4 %ret = add i64 %arg1, %arg2
5 ret i64 %ret
6 }
7
8 define i32 @test_add_i32(i32 %arg1, i32 %arg2) {
9 %ret = add i32 %arg1, %arg2
10 ret i32 %ret
11 }
12
13 define i64 @test_sub_i64(i64 %arg1, i64 %arg2) {
14 %ret = sub i64 %arg1, %arg2
15 ret i64 %ret
16 }
17
18 define i32 @test_sub_i32(i32 %arg1, i32 %arg2) {
19 %ret = sub i32 %arg1, %arg2
20 ret i32 %ret
21 }
22
23 ...
24
25 ---
26 name: test_add_i64
27 legalized: true
28 regBankSelected: true
29 # CHECK: registers:
30 # CHECK-NEXT: - { id: 0, class: gr64 }
31 # CHECK-NEXT: - { id: 1, class: gr64 }
32 # CHECK-NEXT: - { id: 2, class: gr64 }
33 registers:
34 - { id: 0, class: gpr }
35 - { id: 1, class: gpr }
36 - { id: 2, class: gpr }
37 # CHECK: %0 = COPY %rdi
38 # CHECK-NEXT: %1 = COPY %rsi
39 # CHECK-NEXT: %2 = ADD64rr %0, %1
40 body: |
41 bb.1 (%ir-block.0):
42 liveins: %edi, %esi
43
44 %0(s64) = COPY %rdi
45 %1(s64) = COPY %rsi
46 %2(s64) = G_ADD %0, %1
47
48 ...
49
50 ---
51 name: test_add_i32
52 legalized: true
53 regBankSelected: true
54 # CHECK: registers:
55 # CHECK-NEXT: - { id: 0, class: gr32 }
56 # CHECK-NEXT: - { id: 1, class: gr32 }
57 # CHECK-NEXT: - { id: 2, class: gr32 }
58 registers:
59 - { id: 0, class: gpr }
60 - { id: 1, class: gpr }
61 - { id: 2, class: gpr }
62 # CHECK: %0 = COPY %edi
63 # CHECK-NEXT: %1 = COPY %esi
64 # CHECK-NEXT: %2 = ADD32rr %0, %1
65 body: |
66 bb.1 (%ir-block.0):
67 liveins: %edi, %esi
68
69 %0(s32) = COPY %edi
70 %1(s32) = COPY %esi
71 %2(s32) = G_ADD %0, %1
72
73 ...
74
75 ---
76 name: test_sub_i64
77 legalized: true
78 regBankSelected: true
79 # CHECK: registers:
80 # CHECK-NEXT: - { id: 0, class: gr64 }
81 # CHECK-NEXT: - { id: 1, class: gr64 }
82 # CHECK-NEXT: - { id: 2, class: gr64 }
83 registers:
84 - { id: 0, class: gpr }
85 - { id: 1, class: gpr }
86 - { id: 2, class: gpr }
87 # CHECK: %0 = COPY %rdi
88 # CHECK-NEXT: %1 = COPY %rsi
89 # CHECK-NEXT: %2 = SUB64rr %0, %1
90 body: |
91 bb.1 (%ir-block.0):
92 liveins: %edi, %esi
93
94 %0(s64) = COPY %rdi
95 %1(s64) = COPY %rsi
96 %2(s64) = G_SUB %0, %1
97
98 ...
99
100 ---
101 name: test_sub_i32
102 legalized: true
103 regBankSelected: true
104 # CHECK: registers:
105 # CHECK-NEXT: - { id: 0, class: gr32 }
106 # CHECK-NEXT: - { id: 1, class: gr32 }
107 # CHECK-NEXT: - { id: 2, class: gr32 }
108 registers:
109 - { id: 0, class: gpr }
110 - { id: 1, class: gpr }
111 - { id: 2, class: gpr }
112 # CHECK: %0 = COPY %edi
113 # CHECK-NEXT: %1 = COPY %esi
114 # CHECK-NEXT: %2 = SUB32rr %0, %1
115 body: |
116 bb.1 (%ir-block.0):
117 liveins: %edi, %esi
118
119 %0(s32) = COPY %edi
120 %1(s32) = COPY %esi
121 %2(s32) = G_SUB %0, %1
122
123 ...