[GlobalIsel][X86] support G_CONSTANT selection.

Summary: [GlobalISel][X86] support G_CONSTANT selection. Add regbank select tests.

Reviewers: zvi, guyblank

Reviewed By: guyblank

Subscribers: llvm-commits, dberris, rovka, kristof.beyls

Differential Revision: https://reviews.llvm.org/D31974

llvm-svn: 300057
This commit is contained in:
Igor Breger 2017-04-12 12:54:54 +00:00
parent da74ed42da
commit 3b97ea39e7
4 changed files with 276 additions and 1 deletions

View File

@ -18,13 +18,13 @@
#include "X86RegisterInfo.h"
#include "X86Subtarget.h"
#include "X86TargetMachine.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@ -65,6 +65,8 @@ private:
MachineFunction &MF) const;
bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
const X86Subtarget &STI;
const X86InstrInfo &TII;
@ -203,6 +205,8 @@ bool X86InstructionSelector::select(MachineInstr &I) const {
return true;
if (selectFrameIndex(I, MRI, MF))
return true;
if (selectConstant(I, MRI, MF))
return true;
return selectImpl(I);
}
@ -458,6 +462,53 @@ bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}
bool X86InstructionSelector::selectConstant(MachineInstr &I,
MachineRegisterInfo &MRI,
MachineFunction &MF) const {
if (I.getOpcode() != TargetOpcode::G_CONSTANT)
return false;
const unsigned DefReg = I.getOperand(0).getReg();
LLT Ty = MRI.getType(DefReg);
assert(Ty.isScalar() && "invalid element type.");
uint64_t Val = 0;
if (I.getOperand(1).isCImm()) {
Val = I.getOperand(1).getCImm()->getZExtValue();
I.getOperand(1).ChangeToImmediate(Val);
} else if (I.getOperand(1).isImm()) {
Val = I.getOperand(1).getImm();
} else
llvm_unreachable("Unsupported operand type.");
unsigned NewOpc;
switch (Ty.getSizeInBits()) {
case 8:
NewOpc = X86::MOV8ri;
break;
case 16:
NewOpc = X86::MOV16ri;
break;
case 32:
NewOpc = X86::MOV32ri;
break;
case 64: {
// TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
if (isInt<32>(Val))
NewOpc = X86::MOV64ri32;
else
NewOpc = X86::MOV64ri;
break;
}
default:
llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
}
I.setDesc(TII.get(NewOpc));
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}
InstructionSelector *
llvm::createX86InstructionSelector(X86Subtarget &Subtarget,
X86RegisterBankInfo &RBI) {

View File

@ -102,6 +102,10 @@
ret double* %p1
}
define void @constInt_check() {
ret void
}
...
---
name: test_add_i8
@ -604,4 +608,27 @@ body: |
RET 0, implicit %rax
...
---
name: constInt_check
alignment: 4
legalized: true
# CHECK-LABEL: name: constInt_check
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr }
# CHECK-NEXT: - { id: 1, class: gpr }
# CHECK-NEXT: - { id: 2, class: gpr }
# CHECK-NEXT: - { id: 3, class: gpr }
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
- { id: 3, class: _ }
body: |
bb.0 (%ir-block.0):
%0(s8) = G_CONSTANT i8 8
%1(s16) = G_CONSTANT i16 16
%2(s32) = G_CONSTANT i32 32
%3(s64) = G_CONSTANT i64 64
RET 0
...

View File

@ -0,0 +1,54 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
define i8 @const_i8() {
; ALL-LABEL: const_i8:
; ALL: # BB#0:
; ALL-NEXT: movb $2, %al
; ALL-NEXT: retq
ret i8 2
}
define i16 @const_i16() {
; ALL-LABEL: const_i16:
; ALL: # BB#0:
; ALL-NEXT: movw $3, %ax
; ALL-NEXT: retq
ret i16 3
}
define i32 @const_i32() {
; ALL-LABEL: const_i32:
; ALL: # BB#0:
; ALL-NEXT: movl $4, %eax
; ALL-NEXT: retq
ret i32 4
}
define i64 @const_i64() {
; ALL-LABEL: const_i64:
; ALL: # BB#0:
; ALL-NEXT: movabsq $68719476720, %rax # imm = 0xFFFFFFFF0
; ALL-NEXT: retq
ret i64 68719476720
}
;i64 value fit into u32
define i64 @const_i64_u32() {
; ALL-LABEL: const_i64_u32:
; ALL: # BB#0:
; ALL-NEXT: movq $1879048192, %rax # imm = 0x70000000
; ALL-NEXT: retq
ret i64 1879048192
}
;i64 value fit into i32
define i64 @const_i64_i32() {
; ALL-LABEL: const_i64_i32:
; ALL: # BB#0:
; ALL-NEXT: movq $-1, %rax
; ALL-NEXT: retq
ret i64 -1
}

View File

@ -0,0 +1,143 @@
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=CHECK
--- |
define i8 @const_i8() {
ret i8 2
}
define i16 @const_i16() {
ret i16 3
}
define i32 @const_i32() {
ret i32 4
}
define i64 @const_i64() {
ret i64 68719476720
}
define i64 @const_i64_u32() {
ret i64 1879048192
}
define i64 @const_i64_i32() {
ret i64 -1
}
...
---
name: const_i8
legalized: true
regBankSelected: true
selected: false
# CHECK-LABEL: name: const_i8
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gr8 }
registers:
- { id: 0, class: gpr }
# CHECK: body:
# CHECK: %0 = MOV8ri 2
body: |
bb.1 (%ir-block.0):
%0(s8) = G_CONSTANT i8 2
%al = COPY %0(s8)
RET 0, implicit %al
...
---
name: const_i16
legalized: true
regBankSelected: true
selected: false
# CHECK-LABEL: name: const_i16
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gr16 }
registers:
- { id: 0, class: gpr }
# CHECK: body:
# CHECK: %0 = MOV16ri 3
body: |
bb.1 (%ir-block.0):
%0(s16) = G_CONSTANT i16 3
%ax = COPY %0(s16)
RET 0, implicit %ax
...
---
name: const_i32
legalized: true
regBankSelected: true
selected: false
# CHECK-LABEL: name: const_i32
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gr32 }
registers:
- { id: 0, class: gpr }
# CHECK: body:
# CHECK: %0 = MOV32ri 4
body: |
bb.1 (%ir-block.0):
%0(s32) = G_CONSTANT i32 4
%eax = COPY %0(s32)
RET 0, implicit %eax
...
---
name: const_i64
legalized: true
regBankSelected: true
selected: false
# CHECK-LABEL: name: const_i64
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gr64 }
registers:
- { id: 0, class: gpr }
# CHECK: body:
# CHECK: %0 = MOV64ri 68719476720
body: |
bb.1 (%ir-block.0):
%0(s64) = G_CONSTANT i64 68719476720
%rax = COPY %0(s64)
RET 0, implicit %rax
...
---
name: const_i64_u32
alignment: 4
legalized: true
regBankSelected: true
selected: false
# CHECK-LABEL: name: const_i64_u32
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gr64 }
registers:
- { id: 0, class: gpr }
# CHECK: body:
# CHECK: %0 = MOV64ri32 1879048192
body: |
bb.1 (%ir-block.0):
%0(s64) = G_CONSTANT i64 1879048192
%rax = COPY %0(s64)
RET 0, implicit %rax
...
---
name: const_i64_i32
legalized: true
regBankSelected: true
selected: false
# CHECK-LABEL: name: const_i64_i32
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gr64 }
registers:
- { id: 0, class: gpr }
# CHECK: body:
# CHECK: %0 = MOV64ri32 -1
body: |
bb.1 (%ir-block.0):
%0(s64) = G_CONSTANT i64 -1
%rax = COPY %0(s64)
RET 0, implicit %rax
...