From: Dylan McKay Date: Tue, 18 Dec 2018 09:52:52 +0000 (+0000) Subject: [IPO][AVR] Create new Functions in the default address space specified in the data... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f14481850f5735cf7b55b5ee2ed878e79d5cbfc7;p=llvm [IPO][AVR] Create new Functions in the default address space specified in the data layout This modifies the IPO pass so that it respects any explicit function address space specified in the data layout. In targets with nonzero program address spaces, all functions should, by default, be placed into the default program address space. This is required for Harvard architectures like AVR. Without this, the functions will be marked as residing in data space, and thus not be callable. This has no effect to any in-tree official backends, as none use an explicit program address space in their data layouts. Patch by Tim Neumann. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349469 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index f2c2b55b1c5..517a9c082a4 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -213,7 +213,8 @@ doPromotion(Function *F, SmallPtrSetImpl &ArgsToPromote, FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); // Create the new function body and insert it into the module. - Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName()); + Function *NF = Function::Create(NFTy, F->getLinkage(), F->getAddressSpace(), + F->getName()); NF->copyAttributesFrom(F); // Patch the pointer to LLVM function in debug info descriptor. diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index cffb3325f1c..cb30e8f46a5 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -164,7 +164,7 @@ bool DeadArgumentEliminationPass::DeleteDeadVarargs(Function &Fn) { unsigned NumArgs = Params.size(); // Create the new function body and insert it into the module... - Function *NF = Function::Create(NFTy, Fn.getLinkage()); + Function *NF = Function::Create(NFTy, Fn.getLinkage(), Fn.getAddressSpace()); NF->copyAttributesFrom(&Fn); NF->setComdat(Fn.getComdat()); Fn.getParent()->getFunctionList().insert(Fn.getIterator(), NF); @@ -863,7 +863,7 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { return false; // Create the new function body and insert it into the module... - Function *NF = Function::Create(NFTy, F->getLinkage()); + Function *NF = Function::Create(NFTy, F->getLinkage(), F->getAddressSpace()); NF->copyAttributesFrom(F); NF->setComdat(F->getComdat()); NF->setAttributes(NewPAL); diff --git a/lib/Transforms/IPO/ExtractGV.cpp b/lib/Transforms/IPO/ExtractGV.cpp index d45a8832391..a744d7f2d2d 100644 --- a/lib/Transforms/IPO/ExtractGV.cpp +++ b/lib/Transforms/IPO/ExtractGV.cpp @@ -135,6 +135,7 @@ namespace { llvm::Value *Declaration; if (FunctionType *FTy = dyn_cast(Ty)) { Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, + CurI->getAddressSpace(), CurI->getName(), &M); } else { diff --git a/lib/Transforms/IPO/FunctionImport.cpp b/lib/Transforms/IPO/FunctionImport.cpp index c5490f13d9a..531a7c19e36 100644 --- a/lib/Transforms/IPO/FunctionImport.cpp +++ b/lib/Transforms/IPO/FunctionImport.cpp @@ -911,7 +911,8 @@ bool llvm::convertToDeclaration(GlobalValue &GV) { if (GV.getValueType()->isFunctionTy()) NewGV = Function::Create(cast(GV.getValueType()), - GlobalValue::ExternalLinkage, "", GV.getParent()); + GlobalValue::ExternalLinkage, GV.getAddressSpace(), + "", GV.getParent()); else NewGV = new GlobalVariable(*GV.getParent(), GV.getValueType(), diff --git a/lib/Transforms/IPO/LowerTypeTests.cpp b/lib/Transforms/IPO/LowerTypeTests.cpp index 2d29e93b1ca..e4dcd4d4dd7 100644 --- a/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/lib/Transforms/IPO/LowerTypeTests.cpp @@ -989,6 +989,7 @@ void LowerTypeTestsModule::importFunction(Function *F, bool isDefinition) { if (F->isDSOLocal()) { Function *RealF = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage, + F->getAddressSpace(), Name + ".cfi", &M); RealF->setVisibility(GlobalVariable::HiddenVisibility); replaceDirectCalls(F, RealF); @@ -1000,13 +1001,13 @@ void LowerTypeTestsModule::importFunction(Function *F, bool isDefinition) { if (F->isDeclarationForLinker() && !isDefinition) { // Declaration of an external function. FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage, - Name + ".cfi_jt", &M); + F->getAddressSpace(), Name + ".cfi_jt", &M); FDecl->setVisibility(GlobalValue::HiddenVisibility); } else if (isDefinition) { F->setName(Name + ".cfi"); F->setLinkage(GlobalValue::ExternalLinkage); FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage, - Name, &M); + F->getAddressSpace(), Name, &M); FDecl->setVisibility(Visibility); Visibility = GlobalValue::HiddenVisibility; @@ -1016,7 +1017,8 @@ void LowerTypeTestsModule::importFunction(Function *F, bool isDefinition) { for (auto &U : F->uses()) { if (auto *A = dyn_cast(U.getUser())) { Function *AliasDecl = Function::Create( - F->getFunctionType(), GlobalValue::ExternalLinkage, "", &M); + F->getFunctionType(), GlobalValue::ExternalLinkage, + F->getAddressSpace(), "", &M); AliasDecl->takeName(A); A->replaceAllUsesWith(AliasDecl); ToErase.push_back(A); @@ -1191,7 +1193,9 @@ void LowerTypeTestsModule::moveInitializerToModuleConstructor( WeakInitializerFn = Function::Create( FunctionType::get(Type::getVoidTy(M.getContext()), /* IsVarArg */ false), - GlobalValue::InternalLinkage, "__cfi_global_var_init", &M); + GlobalValue::InternalLinkage, + M.getDataLayout().getProgramAddressSpace(), + "__cfi_global_var_init", &M); BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", WeakInitializerFn); ReturnInst::Create(M.getContext(), BB); @@ -1234,7 +1238,8 @@ void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr( // placeholder first. Function *PlaceholderFn = Function::Create(cast(F->getValueType()), - GlobalValue::ExternalWeakLinkage, "", &M); + GlobalValue::ExternalWeakLinkage, + F->getAddressSpace(), "", &M); replaceCfiUses(F, PlaceholderFn, IsDefinition); Constant *Target = ConstantExpr::getSelect( @@ -1424,7 +1429,9 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative( Function *JumpTableFn = Function::Create(FunctionType::get(Type::getVoidTy(M.getContext()), /* IsVarArg */ false), - GlobalValue::PrivateLinkage, ".cfi.jumptable", &M); + GlobalValue::PrivateLinkage, + M.getDataLayout().getProgramAddressSpace(), + ".cfi.jumptable", &M); ArrayType *JumpTableType = ArrayType::get(getJumpTableEntryType(), Functions.size()); auto JumpTable = @@ -1813,7 +1820,8 @@ bool LowerTypeTestsModule::lower() { if (!F) F = Function::Create( FunctionType::get(Type::getVoidTy(M.getContext()), false), - GlobalVariable::ExternalLinkage, FunctionName, &M); + GlobalVariable::ExternalLinkage, + M.getDataLayout().getProgramAddressSpace(), FunctionName, &M); // If the function is available_externally, remove its definition so // that it is handled the same way as a declaration. Later we will try diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index e84de09c7e0..550750d1743 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -693,8 +693,8 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { GEntryBlock->getTerminator()->eraseFromParent(); BB = GEntryBlock; } else { - NewG = Function::Create(G->getFunctionType(), G->getLinkage(), "", - G->getParent()); + NewG = Function::Create(G->getFunctionType(), G->getLinkage(), + G->getAddressSpace(), "", G->getParent()); BB = BasicBlock::Create(F->getContext(), "", NewG); } @@ -807,8 +807,8 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) { } // Make them both thunks to the same internal function. - Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(), "", - F->getParent()); + Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(), + F->getAddressSpace(), "", F->getParent()); NewF->copyAttributesFrom(F); NewF->takeName(F); removeUsers(F); diff --git a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index bfab96a1ddb..a5382c4638d 100644 --- a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -154,7 +154,8 @@ void simplifyExternals(Module &M) { continue; Function *NewF = - Function::Create(EmptyFT, GlobalValue::ExternalLinkage, "", &M); + Function::Create(EmptyFT, GlobalValue::ExternalLinkage, + F.getAddressSpace(), "", &M); NewF->setVisibility(F.getVisibility()); NewF->takeName(&F); F.replaceAllUsesWith(ConstantExpr::getBitCast(NewF, F.getType())); diff --git a/lib/Transforms/IPO/WholeProgramDevirt.cpp b/lib/Transforms/IPO/WholeProgramDevirt.cpp index b8f68d4d15d..37905daee4c 100644 --- a/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -864,10 +864,13 @@ void DevirtModule::tryICallBranchFunnel( Function *JT; if (isa(Slot.TypeID)) { JT = Function::Create(FT, Function::ExternalLinkage, + M.getDataLayout().getProgramAddressSpace(), getGlobalName(Slot, {}, "branch_funnel"), &M); JT->setVisibility(GlobalValue::HiddenVisibility); } else { - JT = Function::Create(FT, Function::InternalLinkage, "branch_funnel", &M); + JT = Function::Create(FT, Function::InternalLinkage, + M.getDataLayout().getProgramAddressSpace(), + "branch_funnel", &M); } JT->addAttribute(1, Attribute::Nest); diff --git a/test/Transforms/ArgumentPromotion/nonzero-address-spaces.ll b/test/Transforms/ArgumentPromotion/nonzero-address-spaces.ll new file mode 100644 index 00000000000..2ed362b873f --- /dev/null +++ b/test/Transforms/ArgumentPromotion/nonzero-address-spaces.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -argpromotion -S | FileCheck %s + +; ArgumentPromotion should preserve the default function address space +; from the data layout. + +target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8" + +@g = common global i32 0, align 4 + +define i32 @bar() { +entry: + %call = call i32 @foo(i32* @g) +; CHECK: %call = call addrspace(1) i32 @foo() + ret i32 %call +} + +; CHECK: define internal i32 @foo() addrspace(1) +define internal i32 @foo(i32*) { +entry: + %retval = alloca i32, align 4 + call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""() + unreachable +} + diff --git a/test/Transforms/DeadArgElim/nonzero-address-spaces.ll b/test/Transforms/DeadArgElim/nonzero-address-spaces.ll new file mode 100644 index 00000000000..1b2aa06adf2 --- /dev/null +++ b/test/Transforms/DeadArgElim/nonzero-address-spaces.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -deadargelim %s | FileCheck %s + +; DeadArgumentElimination should respect the function address space +; in the data layout. + +target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8" + +; CHECK: define internal i32 @foo() addrspace(1) +define internal i32 @foo(i32 %x) #0 { + tail call void asm sideeffect inteldialect "mov eax, [esp + $$4]\0A\09ret", "~{eax},~{dirflag},~{fpsr},~{flags}"() + unreachable +} + +define i32 @f(i32 %x, i32 %y) { + ; CHECK: %r = call addrspace(1) i32 @foo() + %r = call i32 @foo(i32 %x) + + ret i32 %r +} + diff --git a/test/Transforms/MergeFunc/nonzero-address-spaces.ll b/test/Transforms/MergeFunc/nonzero-address-spaces.ll new file mode 100644 index 00000000000..3ee887c9de0 --- /dev/null +++ b/test/Transforms/MergeFunc/nonzero-address-spaces.ll @@ -0,0 +1,30 @@ +; RUN: opt -S -mergefunc < %s | FileCheck %s + +; MergeFunctions should respect the default function address +; space specified in the data layout. + +target datalayout = "e-P1-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +declare void @stuff() + +; CHECK-LABEL: @f0( +define void @f0(i64 %p0) { +entry: + call void @stuff() + call void @stuff() + call void @stuff() + ret void +} + +; CHECK-LABEL: @f1( +; CHECK: ptrtoint i64* +; CHECK: tail call addrspace(1) void @f0(i64 + +define void @f1(i64* %p0) { +entry: + call void @stuff() + call void @stuff() + call void @stuff() + ret void +} +