diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 8d206ec0226..2b270b993bf 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -16,6 +16,7 @@ #ifndef LLVM_CODEGEN_COMMANDFLAGS_H #define LLVM_CODEGEN_COMMANDFLAGS_H +#include "llvm/IR/Module.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm//MC/SubtargetFeature.h" #include "llvm/Support/CodeGen.h" @@ -291,4 +292,15 @@ static inline std::string getFeaturesStr() { return Features.getString(); } +static inline void overrideFunctionAttributes(StringRef CPU, StringRef Features, + Module &M) { + for (auto &F : M) { + if (!CPU.empty()) + llvm::overrideFunctionAttribute("target-cpu", CPU, F); + + if (!Features.empty()) + llvm::overrideFunctionAttribute("target-features", Features, F); + } +} + #endif diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index b16d9f5e216..19ccbb19bb1 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -584,6 +584,9 @@ ilist_traits::getSymTab(Function *F) { return F ? &F->getValueSymbolTable() : nullptr; } +/// \brief Overwrite attribute Kind in function F. +void overrideFunctionAttribute(StringRef Kind, StringRef Value, Function &F); + } // End llvm namespace #endif diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index aea4bf52701..d896eea5803 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -975,3 +975,16 @@ void Function::setPrologueData(Constant *PrologueData) { } setValueSubclassData(PDData); } + +void llvm::overrideFunctionAttribute(StringRef Kind, StringRef Value, + Function &F) { + auto &Ctx = F.getContext(); + AttributeSet Attrs = F.getAttributes(), AttrsToRemove; + + AttrsToRemove = + AttrsToRemove.addAttribute(Ctx, AttributeSet::FunctionIndex, Kind); + Attrs = Attrs.removeAttributes(Ctx, AttributeSet::FunctionIndex, + AttrsToRemove); + Attrs = Attrs.addAttribute(Ctx, AttributeSet::FunctionIndex, Kind, Value); + F.setAttributes(Attrs); +} diff --git a/test/CodeGen/X86/llc-override-mcpu-mattr.ll b/test/CodeGen/X86/llc-override-mcpu-mattr.ll new file mode 100644 index 00000000000..52563bdba5b --- /dev/null +++ b/test/CodeGen/X86/llc-override-mcpu-mattr.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -march x86-64 -mcpu=broadwell | FileCheck %s +; RUN: llc < %s -march x86-64 -mattr=+avx2 | FileCheck %s + +; Check that llc can overide function attributes target-cpu and target-features +; using command line options -mcpu and -mattr. + +; CHECK: vpsadbw %ymm{{[0-9]+}}, %ymm{{[0-9]+}}, %ymm{{[0-9]+}} + +define <4 x i64> @foo1(<4 x i64> %s1, <4 x i64> %s2) #0 { +entry: + %0 = bitcast <4 x i64> %s1 to <32 x i8> + %1 = bitcast <4 x i64> %s2 to <32 x i8> + %2 = tail call <4 x i64> @llvm.x86.avx2.psad.bw(<32 x i8> %0, <32 x i8> %1) + ret <4 x i64> %2 +} + +declare <4 x i64> @llvm.x86.avx2.psad.bw(<32 x i8>, <32 x i8>) + +attributes #0 = { "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse4.2,+sse4.1,+sse,+sse2,+sse3,+avx,+popcnt" } diff --git a/test/Other/opt-override-mcpu-mattr.ll b/test/Other/opt-override-mcpu-mattr.ll new file mode 100644 index 00000000000..84d4209a996 --- /dev/null +++ b/test/Other/opt-override-mcpu-mattr.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -mtriple=x86_64-apple-darwin -mcpu=broadwell -mattr=+avx2 -S | FileCheck %s + +; Check that opt can rewrite function attributes target-cpu and target-features +; using command line options -mcpu and -mattr. + +; CHECK: attributes #0 = { nounwind readnone ssp uwtable "target-cpu"="broadwell" "target-features"="+avx2" "use-soft-float"="false" } + +define i32 @foo1() #0 { +entry: + ret i32 0 +} + +attributes #0 = { nounwind readnone ssp uwtable "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "use-soft-float"="false" } diff --git a/test/Transforms/SLPVectorizer/X86/call.ll b/test/Transforms/SLPVectorizer/X86/call.ll index b76ac2c15c6..a55cc1bf793 100644 --- a/test/Transforms/SLPVectorizer/X86/call.ll +++ b/test/Transforms/SLPVectorizer/X86/call.ll @@ -119,10 +119,10 @@ entry: } -; CHECK: declare <2 x double> @llvm.sin.v2f64(<2 x double>) #0 -; CHECK: declare <2 x double> @llvm.cos.v2f64(<2 x double>) #0 -; CHECK: declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) #0 -; CHECK: declare <2 x double> @llvm.exp2.v2f64(<2 x double>) #0 +; CHECK: declare <2 x double> @llvm.sin.v2f64(<2 x double>) [[ATTR0:#[0-9]+]] +; CHECK: declare <2 x double> @llvm.cos.v2f64(<2 x double>) [[ATTR0]] +; CHECK: declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) [[ATTR0]] +; CHECK: declare <2 x double> @llvm.exp2.v2f64(<2 x double>) [[ATTR0]] -; CHECK: attributes #0 = { nounwind readnone } +; CHECK: attributes [[ATTR0]] = { nounwind readnone } diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 7ef45b3feca..5dbb600540b 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -305,6 +305,9 @@ static int compileModule(char **argv, LLVMContext &Context) { if (const DataLayout *DL = Target->getDataLayout()) M->setDataLayout(*DL); + // Override function attributes. + overrideFunctionAttributes(CPUStr, FeaturesStr, *M); + if (RelaxAll.getNumOccurrences() > 0 && FileType != TargetMachine::CGFT_ObjectFile) errs() << argv[0] diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 8f2b3f7a72b..2aa84a8c8a8 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -394,6 +394,9 @@ int main(int argc, char **argv) { std::unique_ptr TM(Machine); + // Override function attributes. + overrideFunctionAttributes(CPUStr, FeaturesStr, *M); + // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal.