mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
[FastISel][X86] Add support for the frameaddress intrinsic.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210709 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2e4cd27799
commit
a2d36a20fa
@ -1653,6 +1653,58 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) {
|
|||||||
// FIXME: Handle more intrinsics.
|
// FIXME: Handle more intrinsics.
|
||||||
switch (I.getIntrinsicID()) {
|
switch (I.getIntrinsicID()) {
|
||||||
default: return false;
|
default: return false;
|
||||||
|
case Intrinsic::frameaddress: {
|
||||||
|
Type *RetTy = I.getCalledFunction()->getReturnType();
|
||||||
|
|
||||||
|
MVT VT;
|
||||||
|
if (!isTypeLegal(RetTy, VT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned Opc;
|
||||||
|
const TargetRegisterClass *RC = nullptr;
|
||||||
|
|
||||||
|
switch (VT.SimpleTy) {
|
||||||
|
default: llvm_unreachable("Invalid result type for frameaddress.");
|
||||||
|
case MVT::i32: Opc = X86::MOV32rm; RC = &X86::GR32RegClass; break;
|
||||||
|
case MVT::i64: Opc = X86::MOV64rm; RC = &X86::GR64RegClass; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This needs to be set before we call getFrameRegister, otherwise we get
|
||||||
|
// the wrong frame register.
|
||||||
|
MachineFrameInfo *MFI = FuncInfo.MF->getFrameInfo();
|
||||||
|
MFI->setFrameAddressIsTaken(true);
|
||||||
|
|
||||||
|
const X86RegisterInfo *RegInfo =
|
||||||
|
static_cast<const X86RegisterInfo*>(TM.getRegisterInfo());
|
||||||
|
unsigned FrameReg = RegInfo->getFrameRegister(*(FuncInfo.MF));
|
||||||
|
assert(((FrameReg == X86::RBP && VT == MVT::i64) ||
|
||||||
|
(FrameReg == X86::EBP && VT == MVT::i32)) &&
|
||||||
|
"Invalid Frame Register!");
|
||||||
|
|
||||||
|
// Always make a copy of the frame register to to a vreg first, so that we
|
||||||
|
// never directly reference the frame register (the TwoAddressInstruction-
|
||||||
|
// Pass doesn't like that).
|
||||||
|
unsigned SrcReg = createResultReg(RC);
|
||||||
|
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||||
|
TII.get(TargetOpcode::COPY), SrcReg).addReg(FrameReg);
|
||||||
|
|
||||||
|
// Now recursively load from the frame address.
|
||||||
|
// movq (%rbp), %rax
|
||||||
|
// movq (%rax), %rax
|
||||||
|
// movq (%rax), %rax
|
||||||
|
// ...
|
||||||
|
unsigned DestReg;
|
||||||
|
unsigned Depth = cast<ConstantInt>(I.getOperand(0))->getZExtValue();
|
||||||
|
while (Depth--) {
|
||||||
|
DestReg = createResultReg(RC);
|
||||||
|
addDirectMem(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||||
|
TII.get(Opc), DestReg), SrcReg);
|
||||||
|
SrcReg = DestReg;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateValueMap(&I, SrcReg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case Intrinsic::memcpy: {
|
case Intrinsic::memcpy: {
|
||||||
const MemCpyInst &MCI = cast<MemCpyInst>(I);
|
const MemCpyInst &MCI = cast<MemCpyInst>(I);
|
||||||
// Don't handle volatile or variable length memcpys.
|
// Don't handle volatile or variable length memcpys.
|
||||||
|
27
test/CodeGen/X86/frameaddr.ll
Normal file
27
test/CodeGen/X86/frameaddr.ll
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; RUN: llc < %s -march=x86 | FileCheck %s --check-prefix=CHECK-32
|
||||||
|
; RUN: llc < %s -march=x86 -fast-isel -fast-isel-abort | FileCheck %s --check-prefix=CHECK-32
|
||||||
|
; RUN: llc < %s -march=x86-64 | FileCheck %s --check-prefix=CHECK-64
|
||||||
|
; RUN: llc < %s -march=x86-64 -fast-isel -fast-isel-abort | FileCheck %s --check-prefix=CHECK-64
|
||||||
|
|
||||||
|
define i8* @test1() nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK-32: movl %esp, %ebp
|
||||||
|
; CHECK-32-NEXT: movl %ebp, %eax
|
||||||
|
; CHECK-64: movq %rsp, %rbp
|
||||||
|
; CHECK-64-NEXT: movq %rbp, %rax
|
||||||
|
%0 = tail call i8* @llvm.frameaddress(i32 0)
|
||||||
|
ret i8* %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i8* @test2() nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK-32: movl %esp, %ebp
|
||||||
|
; CHECK-32-NEXT: movl (%ebp), %eax
|
||||||
|
; CHECK-32-NEXT: movl (%eax), %eax
|
||||||
|
; CHECK-64: movq %rsp, %rbp
|
||||||
|
; CHECK-64-NEXT: movq (%rbp), %rax
|
||||||
|
; CHECK-64-NEXT: movq (%rax), %rax
|
||||||
|
%0 = tail call i8* @llvm.frameaddress(i32 2)
|
||||||
|
ret i8* %0
|
||||||
|
}
|
||||||
|
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
@ -1,15 +0,0 @@
|
|||||||
; RUN: llc < %s -march=x86-64 | FileCheck %s
|
|
||||||
|
|
||||||
; CHECK: stack_end_address
|
|
||||||
; CHECK: {{movq.+rbp.*$}}
|
|
||||||
; CHECK: {{movq.+rbp.*$}}
|
|
||||||
; CHECK: ret
|
|
||||||
|
|
||||||
define i64* @stack_end_address() nounwind {
|
|
||||||
entry:
|
|
||||||
tail call i8* @llvm.frameaddress( i32 0 )
|
|
||||||
bitcast i8* %0 to i64*
|
|
||||||
ret i64* %1
|
|
||||||
}
|
|
||||||
|
|
||||||
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
|
@ -1,9 +0,0 @@
|
|||||||
; RUN: llc < %s -march=x86 | grep mov | grep ebp
|
|
||||||
|
|
||||||
define i8* @t() nounwind {
|
|
||||||
entry:
|
|
||||||
%0 = tail call i8* @llvm.frameaddress(i32 0)
|
|
||||||
ret i8* %0
|
|
||||||
}
|
|
||||||
|
|
||||||
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
|
@ -1,9 +0,0 @@
|
|||||||
; RUN: llc < %s -march=x86 | grep mov | count 3
|
|
||||||
|
|
||||||
define i8* @t() nounwind {
|
|
||||||
entry:
|
|
||||||
%0 = tail call i8* @llvm.frameaddress(i32 2)
|
|
||||||
ret i8* %0
|
|
||||||
}
|
|
||||||
|
|
||||||
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
|
Loading…
Reference in New Issue
Block a user