Skip to content

Commit

Permalink
[GlobalIsel][X86] Support G_PTRTOINT instruction.
Browse files Browse the repository at this point in the history
Add legalization/selection for x86/x86_64 and
corresponding tests.

Reviewed By: igorb

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

llvm-svn: 326311
  • Loading branch information
Alexander Ivchenko committed Feb 28, 2018
1 parent 212e676 commit 46e07e3
Show file tree
Hide file tree
Showing 7 changed files with 682 additions and 10 deletions.
25 changes: 15 additions & 10 deletions llvm/lib/Target/X86/X86InstructionSelector.cpp
Expand Up @@ -81,8 +81,8 @@ class X86InstructionSelector : public InstructionSelector {
MachineFunction &MF) const;
bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectTruncOrPtrToInt(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectAnyext(MachineInstr &I, MachineRegisterInfo &MRI,
Expand Down Expand Up @@ -347,8 +347,9 @@ bool X86InstructionSelector::select(MachineInstr &I,
return selectConstant(I, MRI, MF);
case TargetOpcode::G_FCONSTANT:
return materializeFP(I, MRI, MF);
case TargetOpcode::G_PTRTOINT:
case TargetOpcode::G_TRUNC:
return selectTrunc(I, MRI, MF);
return selectTruncOrPtrToInt(I, MRI, MF);
case TargetOpcode::G_ZEXT:
return selectZext(I, MRI, MF);
case TargetOpcode::G_ANYEXT:
Expand Down Expand Up @@ -645,7 +646,7 @@ bool X86InstructionSelector::selectConstant(MachineInstr &I,
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}

// Helper function for selectTrunc and selectAnyext.
// Helper function for selectTruncOrPtrToInt and selectAnyext.
// Returns true if DstRC lives on a floating register class and
// SrcRC lives on a 128-bit vector class.
static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC,
Expand All @@ -670,10 +671,12 @@ bool X86InstructionSelector::selectTurnIntoCOPY(
return true;
}

bool X86InstructionSelector::selectTrunc(MachineInstr &I,
MachineRegisterInfo &MRI,
MachineFunction &MF) const {
assert((I.getOpcode() == TargetOpcode::G_TRUNC) && "unexpected instruction");
bool X86InstructionSelector::selectTruncOrPtrToInt(MachineInstr &I,
MachineRegisterInfo &MRI,
MachineFunction &MF) const {
assert((I.getOpcode() == TargetOpcode::G_TRUNC ||
I.getOpcode() == TargetOpcode::G_PTRTOINT) &&
"unexpected instruction");

const unsigned DstReg = I.getOperand(0).getReg();
const unsigned SrcReg = I.getOperand(1).getReg();
Expand All @@ -685,7 +688,8 @@ bool X86InstructionSelector::selectTrunc(MachineInstr &I,
const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);

if (DstRB.getID() != SrcRB.getID()) {
DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
DEBUG(dbgs() << TII.getName(I.getOpcode())
<< " input/output on different banks\n");
return false;
}

Expand Down Expand Up @@ -722,7 +726,8 @@ bool X86InstructionSelector::selectTrunc(MachineInstr &I,

if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
<< "\n");
return false;
}

Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/X86/X86LegalizerInfo.cpp
Expand Up @@ -124,6 +124,12 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
setAction({G_GEP, p0}, Legal);
setAction({G_GEP, 1, s32}, Legal);

if (!Subtarget.is64Bit())
getActionDefinitionsBuilder(G_PTRTOINT)
.legalForCartesianProduct({s1, s8, s16, s32}, {p0})
.maxScalar(0, s32)
.widenScalarToNextPow2(0, /*Min*/ 8);

// Control-flow
setAction({G_BRCOND, s1}, Legal);

Expand Down Expand Up @@ -161,6 +167,11 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
if (!Subtarget.is64Bit())
return;

const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8);
const LLT s1 = LLT::scalar(1);
const LLT s8 = LLT::scalar(8);
const LLT s16 = LLT::scalar(16);
const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);
const LLT s128 = LLT::scalar(128);

Expand All @@ -179,6 +190,10 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {

// Pointer-handling
setAction({G_GEP, 1, s64}, Legal);
getActionDefinitionsBuilder(G_PTRTOINT)
.legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0})
.maxScalar(0, s64)
.widenScalarToNextPow2(0, /*Min*/ 8);

// Constants
setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
Expand Down
52 changes: 52 additions & 0 deletions llvm/test/CodeGen/X86/GlobalISel/ptrtoint.ll
@@ -0,0 +1,52 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=CHECK

define i1 @ptrtoint_s1_p0(i64* %p) {
; CHECK-LABEL: ptrtoint_s1_p0:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
entry:
%0 = ptrtoint i64* %p to i1
ret i1 %0
}

define i8 @ptrtoint_s8_p0(i64* %p) {
; CHECK-LABEL: ptrtoint_s8_p0:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
entry:
%0 = ptrtoint i64* %p to i8
ret i8 %0
}

define i16 @ptrtoint_s16_p0(i64* %p) {
; CHECK-LABEL: ptrtoint_s16_p0:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
entry:
%0 = ptrtoint i64* %p to i16
ret i16 %0
}

define i32 @ptrtoint_s32_p0(i64* %p) {
; CHECK-LABEL: ptrtoint_s32_p0:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
entry:
%0 = ptrtoint i64* %p to i32
ret i32 %0
}

define i64 @ptrtoint_s64_p0(i64* %p) {
; CHECK-LABEL: ptrtoint_s64_p0:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: retq
entry:
%0 = ptrtoint i64* %p to i64
ret i64 %0
}
141 changes: 141 additions & 0 deletions llvm/test/CodeGen/X86/GlobalISel/x86-legalize-ptrtoint.mir
@@ -0,0 +1,141 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=i686-linux-gnu -global-isel -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s

--- |

define i1 @ptrtoint_s1_p0(i64* %p) {
entry:
%0 = ptrtoint i64* %p to i1
ret i1 %0
}

define i8 @ptrtoint_s8_p0(i64* %p) {
entry:
%0 = ptrtoint i64* %p to i8
ret i8 %0
}

define i16 @ptrtoint_s16_p0(i64* %p) {
entry:
%0 = ptrtoint i64* %p to i16
ret i16 %0
}

define i32 @ptrtoint_s32_p0(i64* %p) {
entry:
%0 = ptrtoint i64* %p to i32
ret i32 %0
}

...
---
name: ptrtoint_s1_p0
alignment: 4
tracksRegLiveness: true
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
- { id: 3, class: _ }
frameInfo:
maxAlignment: 4
fixedStack:
- { id: 0, size: 4, alignment: 16, stack-id: 0, isImmutable: true }
body: |
bb.1.entry:
; CHECK-LABEL: name: ptrtoint_s1_p0
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
; CHECK: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (invariant load 4 from %fixed-stack.0, align 0)
; CHECK: [[PTRTOINT:%[0-9]+]]:_(s1) = G_PTRTOINT [[LOAD]](p0)
; CHECK: [[ANYEXT:%[0-9]+]]:_(s8) = G_ANYEXT [[PTRTOINT]](s1)
; CHECK: $al = COPY [[ANYEXT]](s8)
; CHECK: RET 0, implicit $al
%1:_(p0) = G_FRAME_INDEX %fixed-stack.0
%0:_(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0)
%2:_(s1) = G_PTRTOINT %0(p0)
%3:_(s8) = G_ANYEXT %2(s1)
$al = COPY %3(s8)
RET 0, implicit $al
...
---
name: ptrtoint_s8_p0
alignment: 4
tracksRegLiveness: true
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
frameInfo:
maxAlignment: 4
fixedStack:
- { id: 0, size: 4, alignment: 16, stack-id: 0, isImmutable: true }
body: |
bb.1.entry:
; CHECK-LABEL: name: ptrtoint_s8_p0
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
; CHECK: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (invariant load 4 from %fixed-stack.0, align 0)
; CHECK: [[PTRTOINT:%[0-9]+]]:_(s8) = G_PTRTOINT [[LOAD]](p0)
; CHECK: $al = COPY [[PTRTOINT]](s8)
; CHECK: RET 0, implicit $al
%1:_(p0) = G_FRAME_INDEX %fixed-stack.0
%0:_(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0)
%2:_(s8) = G_PTRTOINT %0(p0)
$al = COPY %2(s8)
RET 0, implicit $al
...
---
name: ptrtoint_s16_p0
alignment: 4
tracksRegLiveness: true
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
frameInfo:
maxAlignment: 4
fixedStack:
- { id: 0, size: 4, alignment: 16, stack-id: 0, isImmutable: true }
body: |
bb.1.entry:
; CHECK-LABEL: name: ptrtoint_s16_p0
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
; CHECK: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (invariant load 4 from %fixed-stack.0, align 0)
; CHECK: [[PTRTOINT:%[0-9]+]]:_(s16) = G_PTRTOINT [[LOAD]](p0)
; CHECK: $ax = COPY [[PTRTOINT]](s16)
; CHECK: RET 0, implicit $ax
%1:_(p0) = G_FRAME_INDEX %fixed-stack.0
%0:_(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0)
%2:_(s16) = G_PTRTOINT %0(p0)
$ax = COPY %2(s16)
RET 0, implicit $ax
...
---
name: ptrtoint_s32_p0
alignment: 4
tracksRegLiveness: true
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
frameInfo:
maxAlignment: 4
fixedStack:
- { id: 0, size: 4, alignment: 16, stack-id: 0, isImmutable: true }
body: |
bb.1.entry:
; CHECK-LABEL: name: ptrtoint_s32_p0
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
; CHECK: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (invariant load 4 from %fixed-stack.0, align 0)
; CHECK: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[LOAD]](p0)
; CHECK: $eax = COPY [[PTRTOINT]](s32)
; CHECK: RET 0, implicit $eax
%1:_(p0) = G_FRAME_INDEX %fixed-stack.0
%0:_(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0)
%2:_(s32) = G_PTRTOINT %0(p0)
$eax = COPY %2(s32)
RET 0, implicit $eax
...

0 comments on commit 46e07e3

Please sign in to comment.