Hi echristo, dexonsmith,

This patch is part of the work to make LTO and function multi-versioning work 
correctly.

Currently, -mlong-calls, which is converted to cc1 option -arm-long-calls, is 
ignored when building with LTO because the option isn't passed to the linker or 
libLTO. This patch saves the option in the IR as a function attribute to fix 
this problem.

The corresponding llvm patch is here:
http://reviews.llvm.org/D9364

There are a few things to discuss:

1. Should "arm-long-calls" be a binary attribute or a tri-state like 
"unsafe-fp-math" that takes a value "true" or "false"? I made it a binary 
attribute because it simplifies the backend and frontend without breaking 
backward compatibility, but might be use cases that I'm unaware of in which 
this approach wouldn't work.

2. Since we are saving the option in the IR, should we stop passing it as a cc1 
backend option and stop passing it to llvm::cl::ParseCommandLineOptions? It's 
not needed if this attribute is a tri-state, but is needed if it's a binary to 
preserve backward compatibility. By "backward compatibility", I mean the 
following commands should produce the same result before and after this patch 
is committed:

1. clang -target armv7-apple-ios -static -mlong-calls old.bc -o old
2. clang -target armv7-apple-ios -static old.bc -o old

Here, old.bc is generated by an older version of clang that doesn't save 
"arm-long-calls" in the IR.

http://reviews.llvm.org/D9414

Files:
  include/clang/Frontend/CodeGenOptions.h
  lib/CodeGen/CGCall.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/fn-attr.c

Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -151,6 +151,9 @@
   /// A list of command-line options to forward to the LLVM backend.
   std::vector<std::string> BackendOptions;
 
+  /// A list of function attributes to save to the IR.
+  std::vector<std::pair<std::string, std::string>> FunctionAttributes;
+
   /// A list of dependent libraries.
   std::vector<std::string> DependentLibraries;
 
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1455,6 +1455,9 @@
       FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
   } else {
     // Attributes that should go on the function, but not the call site.
+    for (auto &KV : CodeGenOpts.FunctionAttributes)
+      FuncAttrs.addAttribute(KV.first, KV.second);
+
     if (!CodeGenOpts.DisableFPElim) {
       FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
     } else if (CodeGenOpts.OmitLeafFramePointer) {
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -340,6 +340,14 @@
   }
 }
 
+static void getFunctionAttributes(CodeGenOptions &Opts) {
+  StringRef Opt = "-arm-long-calls", Key = Opt.drop_front(1);
+
+  if (std::find(Opts.BackendOptions.begin(), Opts.BackendOptions.end(),
+                Opt) != Opts.BackendOptions.end())
+    Opts.FunctionAttributes.push_back(std::make_pair(Key, ""));
+}
+
 static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
                              DiagnosticsEngine &Diags,
                              const TargetOptions &TargetOpts) {
@@ -643,6 +651,8 @@
                       Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
                       Opts.SanitizeRecover);
 
+  getFunctionAttributes(Opts);
+
   return Success;
 }
 
Index: test/CodeGen/fn-attr.c
===================================================================
--- /dev/null
+++ test/CodeGen/fn-attr.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -backend-option -arm-long-calls 
-emit-llvm -o - %s | FileCheck -check-prefix=LONGCALL %s
+// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck 
-check-prefix=NOLONGCALL %s
+
+// LONGCALL: attributes #0 = { {{.*}} "arm-long-calls
+// NOLONGCALL-NOT: attributes #0 = { {{.*}} "arm-long-calls
+
+int foo1(int a) { return a; }

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -151,6 +151,9 @@
   /// A list of command-line options to forward to the LLVM backend.
   std::vector<std::string> BackendOptions;
 
+  /// A list of function attributes to save to the IR.
+  std::vector<std::pair<std::string, std::string>> FunctionAttributes;
+
   /// A list of dependent libraries.
   std::vector<std::string> DependentLibraries;
 
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1455,6 +1455,9 @@
       FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
   } else {
     // Attributes that should go on the function, but not the call site.
+    for (auto &KV : CodeGenOpts.FunctionAttributes)
+      FuncAttrs.addAttribute(KV.first, KV.second);
+
     if (!CodeGenOpts.DisableFPElim) {
       FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
     } else if (CodeGenOpts.OmitLeafFramePointer) {
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -340,6 +340,14 @@
   }
 }
 
+static void getFunctionAttributes(CodeGenOptions &Opts) {
+  StringRef Opt = "-arm-long-calls", Key = Opt.drop_front(1);
+
+  if (std::find(Opts.BackendOptions.begin(), Opts.BackendOptions.end(),
+                Opt) != Opts.BackendOptions.end())
+    Opts.FunctionAttributes.push_back(std::make_pair(Key, ""));
+}
+
 static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
                              DiagnosticsEngine &Diags,
                              const TargetOptions &TargetOpts) {
@@ -643,6 +651,8 @@
                       Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
                       Opts.SanitizeRecover);
 
+  getFunctionAttributes(Opts);
+
   return Success;
 }
 
Index: test/CodeGen/fn-attr.c
===================================================================
--- /dev/null
+++ test/CodeGen/fn-attr.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -backend-option -arm-long-calls -emit-llvm -o - %s | FileCheck -check-prefix=LONGCALL %s
+// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck -check-prefix=NOLONGCALL %s
+
+// LONGCALL: attributes #0 = { {{.*}} "arm-long-calls
+// NOLONGCALL-NOT: attributes #0 = { {{.*}} "arm-long-calls
+
+int foo1(int a) { return a; }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to