[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:
Juergen Ributzka 2014-06-11 21:44:44 +00:00
parent 2e4cd27799
commit a2d36a20fa
5 changed files with 79 additions and 33 deletions

View File

@ -1653,6 +1653,58 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) {
// FIXME: Handle more intrinsics.
switch (I.getIntrinsicID()) {
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: {
const MemCpyInst &MCI = cast<MemCpyInst>(I);
// Don't handle volatile or variable length memcpys.

View 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

View File

@ -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

View File

@ -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

View File

@ -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