mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
ee36276e53
Summary: This is done by first adding two additional instructions to convert the alloca returned address to local and convert it back to generic. Then replace all uses of alloca instruction with the converted generic address. Then we can rely NVPTXFavorNonGenericAddrSpace pass to combine the generic addresscast and the corresponding Load, Store, Bitcast, GEP Instruction together. Patched by Xuetian Weng (xweng@google.com). Test Plan: test/CodeGen/NVPTX/lower-alloca.ll Reviewers: jholewinski, jingyue Reviewed By: jingyue Subscribers: meheff, broune, eliben, jholewinski, llvm-commits Differential Revision: http://reviews.llvm.org/D10483 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239964 91177308-0d34-0410-b5e6-96231b3b80d8
116 lines
4.1 KiB
C++
116 lines
4.1 KiB
C++
//===-- NVPTXLowerAlloca.cpp - Make alloca to use local memory =====--===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// For all alloca instructions, and add a pair of cast to local address for
|
|
// each of them. For example,
|
|
//
|
|
// %A = alloca i32
|
|
// store i32 0, i32* %A ; emits st.u32
|
|
//
|
|
// will be transformed to
|
|
//
|
|
// %A = alloca i32
|
|
// %Local = addrspacecast i32* %A to i32 addrspace(5)*
|
|
// %Generic = addrspacecast i32 addrspace(5)* %A to i32*
|
|
// store i32 0, i32 addrspace(5)* %Generic ; emits st.local.u32
|
|
//
|
|
// And we will rely on NVPTXFavorNonGenericAddrSpace to combine the last
|
|
// two instructions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "NVPTX.h"
|
|
#include "NVPTXUtilities.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/Pass.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace llvm {
|
|
void initializeNVPTXLowerAllocaPass(PassRegistry &);
|
|
}
|
|
|
|
namespace {
|
|
class NVPTXLowerAlloca : public BasicBlockPass {
|
|
bool runOnBasicBlock(BasicBlock &BB) override;
|
|
|
|
public:
|
|
static char ID; // Pass identification, replacement for typeid
|
|
NVPTXLowerAlloca() : BasicBlockPass(ID) {}
|
|
const char *getPassName() const override {
|
|
return "convert address space of alloca'ed memory to local";
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
char NVPTXLowerAlloca::ID = 1;
|
|
|
|
INITIALIZE_PASS(NVPTXLowerAlloca, "nvptx-lower-alloca",
|
|
"Lower Alloca", false, false)
|
|
|
|
// =============================================================================
|
|
// Main function for this pass.
|
|
// =============================================================================
|
|
bool NVPTXLowerAlloca::runOnBasicBlock(BasicBlock &BB) {
|
|
bool Changed = false;
|
|
for (auto &I : BB) {
|
|
if (auto allocaInst = dyn_cast<AllocaInst>(&I)) {
|
|
Changed = true;
|
|
auto PTy = dyn_cast<PointerType>(allocaInst->getType());
|
|
auto ETy = PTy->getElementType();
|
|
auto LocalAddrTy = PointerType::get(ETy, ADDRESS_SPACE_LOCAL);
|
|
auto NewASCToLocal = new AddrSpaceCastInst(allocaInst, LocalAddrTy, "");
|
|
auto GenericAddrTy = PointerType::get(ETy, ADDRESS_SPACE_GENERIC);
|
|
auto NewASCToGeneric = new AddrSpaceCastInst(NewASCToLocal,
|
|
GenericAddrTy, "");
|
|
NewASCToLocal->insertAfter(allocaInst);
|
|
NewASCToGeneric->insertAfter(NewASCToLocal);
|
|
for (Value::use_iterator UI = allocaInst->use_begin(),
|
|
UE = allocaInst->use_end();
|
|
UI != UE; ) {
|
|
// Check Load, Store, GEP, and BitCast Uses on alloca and make them
|
|
// use the converted generic address, in order to expose non-generic
|
|
// addrspacecast to NVPTXFavorNonGenericAddrSpace. For other types
|
|
// of instructions this is unecessary and may introduce redudant
|
|
// address cast.
|
|
const auto &AllocaUse = *UI++;
|
|
auto LI = dyn_cast<LoadInst>(AllocaUse.getUser());
|
|
if (LI && LI->getPointerOperand() == allocaInst && !LI->isVolatile()) {
|
|
LI->setOperand(LI->getPointerOperandIndex(), NewASCToGeneric);
|
|
continue;
|
|
}
|
|
auto SI = dyn_cast<StoreInst>(AllocaUse.getUser());
|
|
if (SI && SI->getPointerOperand() == allocaInst && !SI->isVolatile()) {
|
|
SI->setOperand(SI->getPointerOperandIndex(), NewASCToGeneric);
|
|
continue;
|
|
}
|
|
auto GI = dyn_cast<GetElementPtrInst>(AllocaUse.getUser());
|
|
if (GI && GI->getPointerOperand() == allocaInst) {
|
|
GI->setOperand(GI->getPointerOperandIndex(), NewASCToGeneric);
|
|
continue;
|
|
}
|
|
auto BI = dyn_cast<BitCastInst>(AllocaUse.getUser());
|
|
if (BI && BI->getOperand(0) == allocaInst) {
|
|
BI->setOperand(0, NewASCToGeneric);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Changed;
|
|
}
|
|
|
|
BasicBlockPass *llvm::createNVPTXLowerAllocaPass() {
|
|
return new NVPTXLowerAlloca();
|
|
}
|