Index: include/llvm/Transforms/Utils/CodeExtractor.h =================================================================== --- include/llvm/Transforms/Utils/CodeExtractor.h +++ include/llvm/Transforms/Utils/CodeExtractor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" +#include "llvm/IR/Attributes.h" #include namespace llvm { @@ -162,9 +163,9 @@ BranchProbabilityInfo *BPI); void emitCallAndSwitchStatement(Function *newFunction, - BasicBlock *newHeader, - ValueSet &inputs, - ValueSet &outputs); + BasicBlock *newHeader, ValueSet &inputs, + ValueSet &outputs, + const AttributeList &OldFnAttrs); }; } // end namespace llvm Index: lib/Transforms/Utils/CodeExtractor.cpp =================================================================== --- lib/Transforms/Utils/CodeExtractor.cpp +++ lib/Transforms/Utils/CodeExtractor.cpp @@ -684,9 +684,9 @@ /// emitCallAndSwitchStatement - This method sets up the caller side by adding /// the call instruction, splitting any PHI nodes in the header block as /// necessary. -void CodeExtractor:: -emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer, - ValueSet &inputs, ValueSet &outputs) { +void CodeExtractor::emitCallAndSwitchStatement( + Function *newFunction, BasicBlock *codeReplacer, ValueSet &inputs, + ValueSet &outputs, const AttributeList &OldFnAttrs) { // Emit a call to the new function, passing in: *pointer to struct (if // aggregating parameters), or plan inputs and allocated memory for outputs std::vector params, StructValues, ReloadOutputs, Reloads; @@ -754,6 +754,11 @@ if (auto DL = newFunction->getEntryBlock().getTerminator()->getDebugLoc()) call->setDebugLoc(DL); } + // Set function attributes for call. We cannot set argument or return + // attributes here, as we do not have access to a particular call site. + call->setAttributes(AttributeList::get( + call->getContext(), + OldFnAttrs.getAttributes(AttributeList::FunctionIndex), {}, {})); codeReplacer->getInstList().push_back(call); Function::arg_iterator OutputArgBegin = newFunction->arg_begin(); @@ -1100,7 +1105,8 @@ BFI->setBlockFreq(codeReplacer, EntryFreq.getFrequency()); } - emitCallAndSwitchStatement(newFunction, codeReplacer, inputs, outputs); + emitCallAndSwitchStatement(newFunction, codeReplacer, inputs, outputs, + oldFunction->getAttributes()); moveCodeToFunction(newFunction); Index: test/Transforms/CodeExtractor/PartialInlineDebug.ll =================================================================== --- test/Transforms/CodeExtractor/PartialInlineDebug.ll +++ test/Transforms/CodeExtractor/PartialInlineDebug.ll @@ -31,9 +31,9 @@ } -; CHECK-LABEL: @callee2 +; CHECK: define i32 @callee2(i32 %v) [[FN_ATTRS:#[0-9]+]] ; CHECK: %sub = sub i32 %v, 10, !dbg ![[DBG3:[0-9]+]] -define i32 @callee2(i32 %v) !dbg !18 { +define i32 @callee2(i32 %v) #0 !dbg !18 { entry: %cmp = icmp sgt i32 %v, 2000 br i1 %cmp, label %if.then, label %if.end @@ -53,19 +53,20 @@ ; CHECK-LABEL: @caller2 ; CHECK: codeRepl.i: -; CHECK-NEXT: call void @callee2.1_if.then(i32 %v, i32* %sub.loc.i), !dbg ![[DBG4:[0-9]+]] +; CHECK-NEXT: call void @callee2.1_if.then(i32 %v, i32* %sub.loc.i) [[FN_ATTRS]], !dbg ![[DBG4:[0-9]+]] define i32 @caller2(i32 %v) !dbg !21 { entry: - %call = call i32 @callee2(i32 %v), !dbg !22 + %call = call i32 @callee2(i32 %v) #0, !dbg !22 ret i32 %call } -; CHECK-LABEL: define internal void @callee2.1_if.then +; CHECK: define internal void @callee2.1_if.then(i32 %v, i32* %sub.out) [[FN_ATTRS]] ; CHECK: br label %if.then, !dbg ![[DBG5:[0-9]+]] ; CHECK-LABEL: define internal void @callee.2_if.then ; CHECK: br label %if.then, !dbg ![[DBG6:[0-9]+]] +; CHECK: attributes [[FN_ATTRS]] = { "foo"="bar" } ; CHECK: ![[DBG1]] = !DILocation(line: 10, column: 7, ; CHECK: ![[DBG2]] = !DILocation(line: 10, column: 7, ; CHECK: ![[DBG3]] = !DILocation(line: 110, column: 17, @@ -74,6 +75,8 @@ ; CHECK: ![[DBG6]] = !DILocation(line: 10, column: 7, +attributes #0 = { "foo"="bar" } + !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4, !5, !6} !llvm.ident = !{!7}