Index: lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- lib/Target/X86/X86InstructionSelector.cpp +++ lib/Target/X86/X86InstructionSelector.cpp @@ -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 @@ 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 @@ return true; if (selectFrameIndex(I, MRI, MF)) return true; + if (selectConstant(I, MRI, MF)) + return true; return selectImpl(I); } @@ -458,6 +462,53 @@ 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) { Index: test/CodeGen/X86/GlobalISel/X86-regbankselect.mir =================================================================== --- test/CodeGen/X86/GlobalISel/X86-regbankselect.mir +++ test/CodeGen/X86/GlobalISel/X86-regbankselect.mir @@ -102,6 +102,10 @@ ret double* %p1 } + define void @constInt_check() { + ret void + } + ... --- name: test_add_i8 @@ -604,4 +608,27 @@ 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 +... Index: test/CodeGen/X86/GlobalISel/constant.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/constant.ll @@ -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 +} + + Index: test/CodeGen/X86/GlobalISel/select-constant.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/select-constant.mir @@ -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 + +...