[llvm] r294022 - GlobalISel: translate dynamic alloca instructions.
Tim Northover via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 3 10:22:46 PST 2017
Author: tnorthover
Date: Fri Feb 3 12:22:45 2017
New Revision: 294022
URL: http://llvm.org/viewvc/llvm-project?rev=294022&view=rev
Log:
GlobalISel: translate dynamic alloca instructions.
Added:
llvm/trunk/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll
Modified:
llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h
llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp
llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h?rev=294022&r1=294021&r2=294022&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h Fri Feb 3 12:22:45 2017
@@ -155,11 +155,6 @@ private:
bool translateCast(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder);
- /// Translate static alloca instruction (i.e. one of constant size and in the
- /// first basic block).
- bool translateStaticAlloca(const AllocaInst &Inst,
- MachineIRBuilder &MIRBuilder);
-
/// Translate a phi instruction.
bool translatePHI(const User &U, MachineIRBuilder &MIRBuilder);
@@ -202,6 +197,8 @@ private:
bool translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder);
+
/// Translate return (ret) instruction.
/// The target needs to implement CallLowering::lowerReturn for
/// this to succeed.
@@ -239,9 +236,6 @@ private:
bool translateSRem(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_SREM, U, MIRBuilder);
}
- bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder) {
- return translateStaticAlloca(cast<AllocaInst>(U), MIRBuilder);
- }
bool translateIntToPtr(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder);
}
Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=294022&r1=294021&r2=294022&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Fri Feb 3 12:22:45 2017
@@ -246,6 +246,19 @@ public:
MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0,
unsigned Op1, unsigned CarryIn);
+ /// Build and insert \p Res<def> = G_AND \p Op0, \p Op1
+ ///
+ /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
+ /// Op1.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+ /// with the same (scalar or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
+ unsigned Op1);
+
/// Build and insert \p Res<def> = G_ANYEXT \p Op0
///
/// G_ANYEXT produces a register of the specified width, with bits 0 to
@@ -299,6 +312,16 @@ public:
/// \return The newly created instruction.
MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op);
+ /// Build and insert \p Res<def> = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
+ /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
+ /// ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res must be a generic virtual register with scalar or vector type.
+ /// \pre \p Op must be a generic virtual register with scalar or vector type.
+ ///
+ /// \return The newly created instruction.
+ MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op);
+
/// Build and insert G_BR \p Dest
///
/// G_BR is an unconditional branch to \p Dest.
Modified: llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp?rev=294022&r1=294021&r2=294022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp Fri Feb 3 12:22:45 2017
@@ -28,6 +28,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
+#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetIntrinsicInfo.h"
#include "llvm/Target/TargetLowering.h"
@@ -820,15 +821,81 @@ bool IRTranslator::translateLandingPad(c
return true;
}
-bool IRTranslator::translateStaticAlloca(const AllocaInst &AI,
- MachineIRBuilder &MIRBuilder) {
- if (!TPC->isGlobalISelAbortEnabled() && !AI.isStaticAlloca())
- return false;
+bool IRTranslator::translateAlloca(const User &U,
+ MachineIRBuilder &MIRBuilder) {
+ auto &AI = cast<AllocaInst>(U);
+
+ if (AI.isStaticAlloca()) {
+ unsigned Res = getOrCreateVReg(AI);
+ int FI = getOrCreateFrameIndex(AI);
+ MIRBuilder.buildFrameIndex(Res, FI);
+ return true;
+ }
+
+ // Now we're in the harder dynamic case.
+ Type *Ty = AI.getAllocatedType();
+ unsigned Align =
+ std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI.getAlignment());
+
+ unsigned NumElts = getOrCreateVReg(*AI.getArraySize());
+
+ LLT IntPtrTy = LLT::scalar(DL->getPointerSizeInBits());
+ if (MRI->getType(NumElts) != IntPtrTy) {
+ unsigned ExtElts = MRI->createGenericVirtualRegister(IntPtrTy);
+ MIRBuilder.buildZExtOrTrunc(ExtElts, NumElts);
+ NumElts = ExtElts;
+ }
+
+ unsigned AllocSize = MRI->createGenericVirtualRegister(IntPtrTy);
+ unsigned TySize = MRI->createGenericVirtualRegister(IntPtrTy);
+ MIRBuilder.buildConstant(TySize, DL->getTypeAllocSize(Ty));
+ MIRBuilder.buildMul(AllocSize, NumElts, TySize);
+
+ LLT PtrTy = LLT{*AI.getType(), *DL};
+ auto &TLI = *MF->getSubtarget().getTargetLowering();
+ unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
+
+ unsigned SPTmp = MRI->createGenericVirtualRegister(PtrTy);
+ MIRBuilder.buildCopy(SPTmp, SPReg);
+
+ unsigned SPInt = MRI->createGenericVirtualRegister(IntPtrTy);
+ MIRBuilder.buildInstr(TargetOpcode::G_PTRTOINT).addDef(SPInt).addUse(SPTmp);
+
+ unsigned AllocInt = MRI->createGenericVirtualRegister(IntPtrTy);
+ MIRBuilder.buildSub(AllocInt, SPInt, AllocSize);
+
+ // Handle alignment. We have to realign if the allocation granule was smaller
+ // than stack alignment, or the specific alloca requires more than stack
+ // alignment.
+ unsigned StackAlign =
+ MF->getSubtarget().getFrameLowering()->getStackAlignment();
+ Align = std::max(Align, StackAlign);
+ if (Align > StackAlign || DL->getTypeAllocSize(Ty) % StackAlign != 0) {
+ // Round the size of the allocation up to the stack alignment size
+ // by add SA-1 to the size. This doesn't overflow because we're computing
+ // an address inside an alloca.
+ unsigned TmpSize = MRI->createGenericVirtualRegister(IntPtrTy);
+ unsigned AlignMinus1 = MRI->createGenericVirtualRegister(IntPtrTy);
+ MIRBuilder.buildConstant(AlignMinus1, Align - 1);
+ MIRBuilder.buildSub(TmpSize, AllocInt, AlignMinus1);
+
+ unsigned AlignedAlloc = MRI->createGenericVirtualRegister(IntPtrTy);
+ unsigned AlignMask = MRI->createGenericVirtualRegister(IntPtrTy);
+ MIRBuilder.buildConstant(AlignMask, -(uint64_t)Align);
+ MIRBuilder.buildAnd(AlignedAlloc, TmpSize, AlignMask);
+
+ AllocInt = AlignedAlloc;
+ }
+
+ unsigned DstReg = getOrCreateVReg(AI);
+ MIRBuilder.buildInstr(TargetOpcode::G_INTTOPTR)
+ .addDef(DstReg)
+ .addUse(AllocInt);
+
+ MIRBuilder.buildCopy(SPReg, DstReg);
- assert(AI.isStaticAlloca() && "only handle static allocas now");
- unsigned Res = getOrCreateVReg(AI);
- int FI = getOrCreateFrameIndex(AI);
- MIRBuilder.buildFrameIndex(Res, FI);
+ MF->getFrameInfo().CreateVariableSizedObject(Align ? Align : 1, &AI);
+ assert(MF->getFrameInfo().hasVarSizedObjects());
return true;
}
Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=294022&r1=294021&r2=294022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Fri Feb 3 12:22:45 2017
@@ -213,6 +213,19 @@ MachineInstrBuilder MachineIRBuilder::bu
.addUse(Op1);
}
+MachineInstrBuilder MachineIRBuilder::buildAnd(unsigned Res, unsigned Op0,
+ unsigned Op1) {
+ assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) &&
+ "invalid operand type");
+ assert(MRI->getType(Res) == MRI->getType(Op0) &&
+ MRI->getType(Res) == MRI->getType(Op1) && "type mismatch");
+
+ return buildInstr(TargetOpcode::G_AND)
+ .addDef(Res)
+ .addUse(Op0)
+ .addUse(Op1);
+}
+
MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
}
@@ -324,6 +337,17 @@ MachineInstrBuilder MachineIRBuilder::bu
else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits())
Opcode = TargetOpcode::G_TRUNC;
+ return buildInstr(Opcode).addDef(Res).addUse(Op);
+}
+
+MachineInstrBuilder MachineIRBuilder::buildZExtOrTrunc(unsigned Res,
+ unsigned Op) {
+ unsigned Opcode = TargetOpcode::COPY;
+ if (MRI->getType(Res).getSizeInBits() > MRI->getType(Op).getSizeInBits())
+ Opcode = TargetOpcode::G_ZEXT;
+ else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits())
+ Opcode = TargetOpcode::G_TRUNC;
+
return buildInstr(Opcode).addDef(Res).addUse(Op);
}
Added: llvm/trunk/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll?rev=294022&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll Fri Feb 3 12:22:45 2017
@@ -0,0 +1,57 @@
+; RUN: llc -mtriple=aarch64 -global-isel %s -o - -stop-after=irtranslator | FileCheck %s
+
+; CHECK-LABEL: name: test_simple_alloca
+; CHECK: [[NUMELTS:%[0-9]+]](s32) = COPY %w0
+; CHECK: [[NUMELTS_64:%[0-9]+]](s64) = G_ZEXT [[NUMELTS]](s32)
+; CHECK: [[TYPE_SIZE:%[0-9]+]](s64) = G_CONSTANT i64 1
+; CHECK: [[NUMBYTES:%[0-9]+]](s64) = G_MUL [[NUMELTS_64]], [[TYPE_SIZE]]
+; CHECK: [[SP_TMP:%[0-9]+]](p0) = COPY %sp
+; CHECK: [[SP_INT:%[0-9]+]](s64) = G_PTRTOINT [[SP_TMP]](p0)
+; CHECK: [[ALLOC:%[0-9]+]](s64) = G_SUB [[SP_INT]], [[NUMBYTES]]
+; CHECK: [[ALIGN_M_1:%[0-9]+]](s64) = G_CONSTANT i64 15
+; CHECK: [[ALIGN_TMP:%[0-9]+]](s64) = G_SUB [[ALLOC]], [[ALIGN_M_1]]
+; CHECK: [[ALIGN_MASK:%[0-9]+]](s64) = G_CONSTANT i64 -16
+; CHECK: [[ALIGNED_ALLOC:%[0-9]+]](s64) = G_AND [[ALIGN_TMP]], [[ALIGN_MASK]]
+; CHECK: [[ALLOC_PTR:%[0-9]+]](p0) = G_INTTOPTR [[ALIGNED_ALLOC]](s64)
+; CHECK: %sp = COPY [[ALLOC_PTR]]
+; CHECK: %x0 = COPY [[ALLOC_PTR]]
+define i8* @test_simple_alloca(i32 %numelts) {
+ %addr = alloca i8, i32 %numelts
+ ret i8* %addr
+}
+
+; CHECK-LABEL: name: test_aligned_alloca
+; CHECK: [[NUMELTS:%[0-9]+]](s32) = COPY %w0
+; CHECK: [[NUMELTS_64:%[0-9]+]](s64) = G_ZEXT [[NUMELTS]](s32)
+; CHECK: [[TYPE_SIZE:%[0-9]+]](s64) = G_CONSTANT i64 1
+; CHECK: [[NUMBYTES:%[0-9]+]](s64) = G_MUL [[NUMELTS_64]], [[TYPE_SIZE]]
+; CHECK: [[SP_TMP:%[0-9]+]](p0) = COPY %sp
+; CHECK: [[SP_INT:%[0-9]+]](s64) = G_PTRTOINT [[SP_TMP]](p0)
+; CHECK: [[ALLOC:%[0-9]+]](s64) = G_SUB [[SP_INT]], [[NUMBYTES]]
+; CHECK: [[ALIGN_M_1:%[0-9]+]](s64) = G_CONSTANT i64 31
+; CHECK: [[ALIGN_TMP:%[0-9]+]](s64) = G_SUB [[ALLOC]], [[ALIGN_M_1]]
+; CHECK: [[ALIGN_MASK:%[0-9]+]](s64) = G_CONSTANT i64 -32
+; CHECK: [[ALIGNED_ALLOC:%[0-9]+]](s64) = G_AND [[ALIGN_TMP]], [[ALIGN_MASK]]
+; CHECK: [[ALLOC_PTR:%[0-9]+]](p0) = G_INTTOPTR [[ALIGNED_ALLOC]](s64)
+; CHECK: %sp = COPY [[ALLOC_PTR]]
+; CHECK: %x0 = COPY [[ALLOC_PTR]]
+define i8* @test_aligned_alloca(i32 %numelts) {
+ %addr = alloca i8, i32 %numelts, align 32
+ ret i8* %addr
+}
+
+; CHECK-LABEL: name: test_natural_alloca
+; CHECK: [[NUMELTS:%[0-9]+]](s32) = COPY %w0
+; CHECK: [[NUMELTS_64:%[0-9]+]](s64) = G_ZEXT [[NUMELTS]](s32)
+; CHECK: [[TYPE_SIZE:%[0-9]+]](s64) = G_CONSTANT i64 16
+; CHECK: [[NUMBYTES:%[0-9]+]](s64) = G_MUL [[NUMELTS_64]], [[TYPE_SIZE]]
+; CHECK: [[SP_TMP:%[0-9]+]](p0) = COPY %sp
+; CHECK: [[SP_INT:%[0-9]+]](s64) = G_PTRTOINT [[SP_TMP]](p0)
+; CHECK: [[ALLOC:%[0-9]+]](s64) = G_SUB [[SP_INT]], [[NUMBYTES]]
+; CHECK: [[ALLOC_PTR:%[0-9]+]](p0) = G_INTTOPTR [[ALLOC]](s64)
+; CHECK: %sp = COPY [[ALLOC_PTR]]
+; CHECK: %x0 = COPY [[ALLOC_PTR]]
+define i128* @test_natural_alloca(i32 %numelts) {
+ %addr = alloca i128, i32 %numelts
+ ret i128* %addr
+}
More information about the llvm-commits
mailing list