Index: llvm/trunk/include/llvm/CodeGen/CommandFlags.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/CommandFlags.h +++ llvm/trunk/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 @@ 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 Index: llvm/trunk/include/llvm/IR/Function.h =================================================================== --- llvm/trunk/include/llvm/IR/Function.h +++ llvm/trunk/include/llvm/IR/Function.h @@ -584,6 +584,9 @@ return F ? &F->getValueSymbolTable() : nullptr; } +/// \brief Overwrite attribute Kind in function F. +void overrideFunctionAttribute(StringRef Kind, StringRef Value, Function &F); + } // End llvm namespace #endif Index: llvm/trunk/lib/IR/Function.cpp =================================================================== --- llvm/trunk/lib/IR/Function.cpp +++ llvm/trunk/lib/IR/Function.cpp @@ -975,3 +975,16 @@ } 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); +} Index: llvm/trunk/test/CodeGen/X86/llc-override-mcpu-mattr.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/llc-override-mcpu-mattr.ll +++ llvm/trunk/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" } Index: llvm/trunk/test/Other/opt-override-mcpu-mattr.ll =================================================================== --- llvm/trunk/test/Other/opt-override-mcpu-mattr.ll +++ llvm/trunk/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" } Index: llvm/trunk/test/Transforms/SLPVectorizer/X86/call.ll =================================================================== --- llvm/trunk/test/Transforms/SLPVectorizer/X86/call.ll +++ llvm/trunk/test/Transforms/SLPVectorizer/X86/call.ll @@ -119,10 +119,10 @@ } -; 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 } Index: llvm/trunk/tools/llc/llc.cpp =================================================================== --- llvm/trunk/tools/llc/llc.cpp +++ llvm/trunk/tools/llc/llc.cpp @@ -305,6 +305,9 @@ 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] Index: llvm/trunk/tools/opt/opt.cpp =================================================================== --- llvm/trunk/tools/opt/opt.cpp +++ llvm/trunk/tools/opt/opt.cpp @@ -394,6 +394,9 @@ 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.