From de0a86879fd96b8ff687d764c7606da77a82b69c Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Wed, 8 Feb 2017 17:57:20 +0000 Subject: [PATCH] GlobalISel: translate @llvm.va_start intrinsic. Because we need to preserve the memory access being performed we need a separate instruction to represent this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294492 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/GenericOpcodes.td | 7 +++++++ include/llvm/Target/TargetLowering.h | 5 +++++ include/llvm/Target/TargetOpcodes.def | 3 +++ lib/CodeGen/GlobalISel/IRTranslator.cpp | 11 +++++++++++ lib/Target/AArch64/AArch64ISelLowering.cpp | 8 ++++++++ lib/Target/AArch64/AArch64ISelLowering.h | 3 +++ test/CodeGen/AArch64/GlobalISel/vastart.ll | 13 +++++++++++++ 7 files changed, 50 insertions(+) create mode 100644 test/CodeGen/AArch64/GlobalISel/vastart.ll diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index d3b2835d1bd..6352a6990f2 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -91,6 +91,13 @@ def G_FCONSTANT : Instruction { let hasSideEffects = 0; } +def G_VASTART : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$list); + let hasSideEffects = 0; + let mayStore = 1; +} + //------------------------------------------------------------------------------ // Binary ops. //------------------------------------------------------------------------------ diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index bc98673e029..68696763fca 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -987,6 +987,11 @@ public: return GatherAllAliasesMaxDepth; } + /// Returns the size of the platform's va_list object. + virtual unsigned getVaListSizeInBits(const DataLayout &DL) const { + return getPointerTy(DL).getSizeInBits(); + } + /// \brief Get maximum # of store operations permitted for llvm.memset /// /// This function returns the maximum number of store operations permitted diff --git a/include/llvm/Target/TargetOpcodes.def b/include/llvm/Target/TargetOpcodes.def index 290e3ff78f0..a0d6a6309dc 100644 --- a/include/llvm/Target/TargetOpcodes.def +++ b/include/llvm/Target/TargetOpcodes.def @@ -280,6 +280,9 @@ HANDLE_TARGET_OPCODE(G_CONSTANT) /// Generic floating constant. HANDLE_TARGET_OPCODE(G_FCONSTANT) +/// Generic va_start instruction. Stores to its one pointer operand. +HANDLE_TARGET_OPCODE(G_VASTART) + // Generic sign extend HANDLE_TARGET_OPCODE(G_SEXT) diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index eee78ea8cbc..8b06f4dc234 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -583,6 +583,17 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, // No target I know of cares about va_end. Certainly no in-tree target // does. Simplest intrinsic ever! return true; + case Intrinsic::vastart: { + auto &TLI = *MF->getSubtarget().getTargetLowering(); + Value *Ptr = CI.getArgOperand(0); + unsigned ListSize = TLI.getVaListSizeInBits(*DL) / 8; + + MIRBuilder.buildInstr(TargetOpcode::G_VASTART) + .addUse(getOrCreateVReg(*Ptr)) + .addMemOperand(MF->getMachineMemOperand( + MachinePointerInfo(Ptr), MachineMemOperand::MOStore, ListSize, 0)); + return true; + } case Intrinsic::dbg_value: { // This form of DBG_VALUE is target-independent. const DbgValueInst &DI = cast(CI); diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 5d2d4b114a2..3f43cb32c54 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -10702,3 +10702,11 @@ bool AArch64TargetLowering::isIntDivCheap(EVT VT, AttributeSet Attr) const { Attr.hasAttribute(AttributeSet::FunctionIndex, Attribute::MinSize); return OptSize && !VT.isVector(); } + +unsigned +AArch64TargetLowering::getVaListSizeInBits(const DataLayout &DL) const { + if (Subtarget->isTargetDarwin()) + return getPointerTy(DL).getSizeInBits(); + + return 3 * getPointerTy(DL).getSizeInBits() + 2 * 32; +} diff --git a/lib/Target/AArch64/AArch64ISelLowering.h b/lib/Target/AArch64/AArch64ISelLowering.h index 054ccc31674..167b78dde4b 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.h +++ b/lib/Target/AArch64/AArch64ISelLowering.h @@ -435,6 +435,9 @@ public: return true; } + /// Returns the size of the platform's va_list object. + unsigned getVaListSizeInBits(const DataLayout &DL) const override; + private: bool isExtFreeImpl(const Instruction *Ext) const override; diff --git a/test/CodeGen/AArch64/GlobalISel/vastart.ll b/test/CodeGen/AArch64/GlobalISel/vastart.ll new file mode 100644 index 00000000000..ae44e8fc5de --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/vastart.ll @@ -0,0 +1,13 @@ +; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - -mtriple=aarch64-apple-ios7.0 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-IOS %s +; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LINUX %s + + +declare void @llvm.va_start(i8*) +define void @test_va_start(i8* %list) { +; CHECK-LABEL: name: test_va_start +; CHECK: [[LIST:%[0-9]+]](p0) = COPY %x0 +; CHECK-IOS: G_VASTART [[LIST]](p0) :: (store 8 into %ir.list, align 0) +; CHECK-LINUX: G_VASTART [[LIST]](p0) :: (store 32 into %ir.list, align 0) + call void @llvm.va_start(i8* %list) + ret void +} -- 2.50.1