[llvm-branch-commits] [llvm] release/19.x: [AArch64] Don't replace dst of SWP instructions with (X|W)ZR (#102139) (PR #102316)

2024-08-07 Thread Simon Tatham via llvm-branch-commits

https://github.com/statham-arm approved this pull request.

Seems sensible to me. It's fixing a genuine codegen fault (a subtle one, but of 
course that makes it worse – harder to spot when it occurs!). And it's a small 
safe change that disables one very small case of a conceptually simple 
optimisation, unlikely to introduce other bugs.

https://github.com/llvm/llvm-project/pull/102316
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] release/19.x: [AArch64] Don't replace dst of SWP instructions with (X|W)ZR (#102139) (PR #102316)

2024-08-10 Thread Simon Tatham via llvm-branch-commits

https://github.com/statham-arm edited 
https://github.com/llvm/llvm-project/pull/102316
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-10-29 Thread Simon Tatham via llvm-branch-commits


@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) 
{
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::warn_drv_unsupported_opt)
+  << (custom_flag::Prefix + Unclaimed).str();
+else
+  D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+  << (custom_flag::Prefix + Unclaimed).str()
+  << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+  }
+}
+
+namespace clang::driver::custom_flag {
+class ValueNameToDetailMap {
+  SmallVector> Mapping;
+
+public:
+  template 
+  ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+  const CustomFlagDeclarationPtr &Decl = *DeclIt;
+  for (const auto &Value : Decl->ValueList)
+Mapping.emplace_back(Value.Name, &Value);
+}
+  }
+
+  const CustomFlagValueDetail *get(StringRef Key) const {
+auto Iter = llvm::find_if(
+Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+return Iter != Mapping.end() ? Iter->second : nullptr;
+  }
+};
+} // namespace clang::driver::custom_flag
+
+Multilib::flags_list
+MultilibSet::processCustomFlags(const Driver &D,
+const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  SmallVector
+  ClaimedCustomFlagValues;
+  SmallVector UnclaimedCustomFlagValueStrs;
+
+  const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+  CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+  for (StringRef Flag : Flags) {
+if (!Flag.starts_with(custom_flag::Prefix)) {
+  Result.push_back(Flag.str());
+  continue;
+}
+
+StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+const custom_flag::CustomFlagValueDetail *Detail =
+ValueNameToValueDetail.get(CustomFlagValueStr);
+if (Detail)
+  ClaimedCustomFlagValues.push_back(Detail);
+else
+  UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+  }
+
+  llvm::SmallSet
+  TriggeredCustomFlagDecls;
+
+  for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+  continue;
+Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+  }

statham-arm wrote:

Can you add some comments explaining what all this code is for, please?

It looks as if the first loop over `Flags` is picking out custom multilib 
flags, taking off the `-fmultilib-flag=` prefix, and storing them in 
`ClaimedCustomFlagValues`, and then this second loop is putting them back on to 
the result string, after putting the `-fmultilib-flag=` prefix back on.

I'm sure there's a reason why this is _not_ an elaborate no-op, but can you 
write down what the reason is? Why aren't we just putting the flags straight 
into `Result` without taking them apart and putting them back together in 
between? Without any comments it looks like a lot of processing for not much 
change.

https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-10-29 Thread Simon Tatham via llvm-branch-commits


@@ -14,6 +14,12 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt : Warning<
+  "unsupported option '%0'">,
+  InGroup;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup;

statham-arm wrote:

You mention in the commit message that an unrecognised custom flag is a warning 
rather than an error. But I'm curious about why. If a toolchain vendor ships a 
toolchain with a collection of flags that select particular libraries, and a 
user misspells a flag in their makefile, why _wouldn't_ they want a build error 
so that they notice and fix it? A warning can easily be scrolled off the screen 
in the enormous build log.

Warnings are for cases that _might_ be mistakes by the user, but might also be 
correct, so you can't afford to refuse to build. I don't see why an 
unrecognised flag falls into that category.

It would make sense if there was some kind of standard flag that _most_ 
multilib collections agreed on, and you wanted to be able to use that flag 
everywhere and have it quietly ignored when not supported. But is that your 
intention?

https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-10-29 Thread Simon Tatham via llvm-branch-commits


@@ -196,6 +196,16 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void
+processARMAArch64MultilibCustomFlags(Multilib::flags_list &List,

statham-arm wrote:

Is this system intended to be permanently specific to Arm and AArch64? I don't 
really see why it should be: the need to build libraries distinguished by a 
configuration option that isn't a standard compile flag is certainly not 
specific to Arm. Perhaps this should just be called 
`processMultilibCustomFlags`?

https://github.com/llvm/llvm-project/pull/110658
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [compiler-rt] release/19.x: [compiler-rt] Stop using x86 builtin on AArch64 with GCC (#93890) (PR #115006)

2024-11-05 Thread Simon Tatham via llvm-branch-commits

https://github.com/statham-arm approved this pull request.

Sounds like a good idea to me!


https://github.com/llvm/llvm-project/pull/115006
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-11-04 Thread Simon Tatham via llvm-branch-commits

https://github.com/statham-arm approved this pull request.


https://github.com/llvm/llvm-project/pull/110658
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-04 Thread Simon Tatham via llvm-branch-commits


@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) 
{
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::warn_drv_unsupported_opt)
+  << (custom_flag::Prefix + Unclaimed).str();
+else
+  D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+  << (custom_flag::Prefix + Unclaimed).str()
+  << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+  }
+}
+
+namespace clang::driver::custom_flag {
+class ValueNameToDetailMap {
+  SmallVector> Mapping;
+
+public:
+  template 
+  ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+  const CustomFlagDeclarationPtr &Decl = *DeclIt;
+  for (const auto &Value : Decl->ValueList)
+Mapping.emplace_back(Value.Name, &Value);
+}
+  }
+
+  const CustomFlagValueDetail *get(StringRef Key) const {
+auto Iter = llvm::find_if(
+Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+return Iter != Mapping.end() ? Iter->second : nullptr;
+  }
+};
+} // namespace clang::driver::custom_flag
+
+Multilib::flags_list
+MultilibSet::processCustomFlags(const Driver &D,
+const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  SmallVector
+  ClaimedCustomFlagValues;
+  SmallVector UnclaimedCustomFlagValueStrs;
+
+  const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+  CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+  for (StringRef Flag : Flags) {
+if (!Flag.starts_with(custom_flag::Prefix)) {
+  Result.push_back(Flag.str());
+  continue;
+}
+
+StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+const custom_flag::CustomFlagValueDetail *Detail =
+ValueNameToValueDetail.get(CustomFlagValueStr);
+if (Detail)
+  ClaimedCustomFlagValues.push_back(Detail);
+else
+  UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+  }
+
+  llvm::SmallSet
+  TriggeredCustomFlagDecls;
+
+  for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+  continue;
+Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+  }

statham-arm wrote:

Thanks. Yes, that's better: the de-duplication wasn't at all obvious, and now 
it is. (And I much prefer the explanation in comments in the code than here 
where nobody will ever look for it :-)

https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-04 Thread Simon Tatham via llvm-branch-commits

https://github.com/statham-arm approved this pull request.


https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [compiler-rt] release/19.x: [compiler-rt] Stop using x86 builtin on AArch64 with GCC (#93890) (PR #115006)

2024-11-12 Thread Simon Tatham via llvm-branch-commits

statham-arm wrote:

Despite the force-push, I think the current patch looks the same as the one I 
clicked approve on (maybe it was just rebased?). I can't see a problem – it's 
the same patch that hasn't been causing trouble on `main`.

https://github.com/llvm/llvm-project/pull/115006
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] "modular-format" attribute for functions using format strings (PR #147429)

2025-07-09 Thread Simon Tatham via llvm-branch-commits


@@ -2620,6 +2620,23 @@ For example:
 This attribute indicates that outlining passes should not modify the
 function.
 
+``"modular_format"=""``

statham-arm wrote:

Thanks.

An afterthought: even printf and _scanf_ are different enough that they'd need 
separate handling, so I don't even need to postulate a hypothetical format 
string syntax from some other language's standard library. For example, your 
check for arguments of actual floating-point type is fine for telling that a 
printf call doesn't need float formatting, but for a scanf call, you'd need to 
look for _pointers_ to floating types instead.

https://github.com/llvm/llvm-project/pull/147429
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libc] [libc] Modular printf option (float only) (PR #147426)

2025-07-09 Thread Simon Tatham via llvm-branch-commits


@@ -0,0 +1,41 @@
+#ifdef LIBC_COPT_PRINTF_MODULAR
+#include "src/__support/arg_list.h"
+
+#define LIBC_PRINTF_DEFINE_MODULAR
+#include "src/stdio/printf_core/float_dec_converter.h"
+#include "src/stdio/printf_core/float_hex_converter.h"
+#include "src/stdio/printf_core/parser.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace printf_core {
+template class Parser;
+template class Parser>;
+template class Parser>;
+template class Parser>;
+template class Parser>;
+
+#define INSTANTIATE_CONVERT_FN(NAME)   
\
+  template int NAME(   
\
+  Writer * writer, 
\
+  const FormatSection &to_conv);   
\
+  template int NAME(   
\
+  Writer * writer, 
\
+  const FormatSection &to_conv);   
\
+  template int NAME(  
\
+  Writer * writer,
\
+  const FormatSection &to_conv);   
\
+  template int NAME(  
\
+  Writer * writer,
\
+  const FormatSection &to_conv)
+
+INSTANTIATE_CONVERT_FN(convert_float_decimal);
+INSTANTIATE_CONVERT_FN(convert_float_dec_exp);
+INSTANTIATE_CONVERT_FN(convert_float_dec_auto);
+INSTANTIATE_CONVERT_FN(convert_float_hex_exp);
+
+} // namespace printf_core
+} // namespace LIBC_NAMESPACE_DECL
+
+// Bring this file into the link if __printf_float is referenced.
+extern "C" void __printf_float() {}

statham-arm wrote:

One risk with this strategy: what happens if this file is compiled with 
`-ffunction-sections`? Then `__printf_float` might be in a different code 
section from the template instantiations, and a linker might garbage-collect 
the functions you actually wanted, treating the weak references to them as not 
enough reason to keep them.

If I wanted to be sure of this technique, I'd either enforce via compile 
options that everything in this file is in the same code section, or else add 
further `BFD_RELOC_NONE` links from `__printf_float` to the payload functions, 
to make sure there's an unbroken chain of non-weak references from the import 
of `__printf_float` to the functions that actually do the work.

https://github.com/llvm/llvm-project/pull/147426
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] "modular-format" attribute for functions using format strings (PR #147429)

2025-07-08 Thread Simon Tatham via llvm-branch-commits


@@ -2620,6 +2620,23 @@ For example:
 This attribute indicates that outlining passes should not modify the
 function.
 
+``"modular_format"=""``

statham-arm wrote:

Is this intended to be specific to _printf_ style format strings? Or will it 
potentially be reusable for other formatting languages? The text here just says 
"format string" without saying what kind. For futureproofing, perhaps there 
should be some kind of a type parameter here saying which formatting mechanism 
is referred to? That way if two incompatible formatting syntaxes need to be 
supported later, there's space for expansion.

https://github.com/llvm/llvm-project/pull/147429
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libc] [libc] Modular printf option (float only) (PR #147426)

2025-07-11 Thread Simon Tatham via llvm-branch-commits


@@ -0,0 +1,41 @@
+#ifdef LIBC_COPT_PRINTF_MODULAR
+#include "src/__support/arg_list.h"
+
+#define LIBC_PRINTF_DEFINE_MODULAR
+#include "src/stdio/printf_core/float_dec_converter.h"
+#include "src/stdio/printf_core/float_hex_converter.h"
+#include "src/stdio/printf_core/parser.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace printf_core {
+template class Parser;
+template class Parser>;
+template class Parser>;
+template class Parser>;
+template class Parser>;
+
+#define INSTANTIATE_CONVERT_FN(NAME)   
\
+  template int NAME(   
\
+  Writer * writer, 
\
+  const FormatSection &to_conv);   
\
+  template int NAME(   
\
+  Writer * writer, 
\
+  const FormatSection &to_conv);   
\
+  template int NAME(  
\
+  Writer * writer,
\
+  const FormatSection &to_conv);   
\
+  template int NAME(  
\
+  Writer * writer,
\
+  const FormatSection &to_conv)
+
+INSTANTIATE_CONVERT_FN(convert_float_decimal);
+INSTANTIATE_CONVERT_FN(convert_float_dec_exp);
+INSTANTIATE_CONVERT_FN(convert_float_dec_auto);
+INSTANTIATE_CONVERT_FN(convert_float_hex_exp);
+
+} // namespace printf_core
+} // namespace LIBC_NAMESPACE_DECL
+
+// Bring this file into the link if __printf_float is referenced.
+extern "C" void __printf_float() {}

statham-arm wrote:

OK – of course you're right that those workarounds can easily be added later. 
As long as you've thought about this and checked it, I'm happy.

(Now I've slept on it, I think I vaguely recall that one rationale for 
armlink's choice of behavior is that it makes partial linking change the 
semantics less: if you combine a bunch of `.o` files into one big `.o`, then 
passing the combined file to a full link step has a very similar effect to 
passing the individual files one by one.)

https://github.com/llvm/llvm-project/pull/147426
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libc] [libc] Modular printf option (float only) (PR #147426)

2025-07-10 Thread Simon Tatham via llvm-branch-commits


@@ -0,0 +1,41 @@
+#ifdef LIBC_COPT_PRINTF_MODULAR
+#include "src/__support/arg_list.h"
+
+#define LIBC_PRINTF_DEFINE_MODULAR
+#include "src/stdio/printf_core/float_dec_converter.h"
+#include "src/stdio/printf_core/float_hex_converter.h"
+#include "src/stdio/printf_core/parser.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace printf_core {
+template class Parser;
+template class Parser>;
+template class Parser>;
+template class Parser>;
+template class Parser>;
+
+#define INSTANTIATE_CONVERT_FN(NAME)   
\
+  template int NAME(   
\
+  Writer * writer, 
\
+  const FormatSection &to_conv);   
\
+  template int NAME(   
\
+  Writer * writer, 
\
+  const FormatSection &to_conv);   
\
+  template int NAME(  
\
+  Writer * writer,
\
+  const FormatSection &to_conv);   
\
+  template int NAME(  
\
+  Writer * writer,
\
+  const FormatSection &to_conv)
+
+INSTANTIATE_CONVERT_FN(convert_float_decimal);
+INSTANTIATE_CONVERT_FN(convert_float_dec_exp);
+INSTANTIATE_CONVERT_FN(convert_float_dec_auto);
+INSTANTIATE_CONVERT_FN(convert_float_hex_exp);
+
+} // namespace printf_core
+} // namespace LIBC_NAMESPACE_DECL
+
+// Bring this file into the link if __printf_float is referenced.
+extern "C" void __printf_float() {}

statham-arm wrote:

> I'd be surprised if other linkers differ; wasn't this usage the whole point 
> of allowing undefined weak references?

Certainly this usage _in general_ is the whole point: a weak reference says "I 
won't insist that this function be included in the image, but if it has to be 
in the image anyway for some other reason, I'd like to call it."

The more specific question here is what counts as "has to be in the image 
anyway": do you need a non-weak reference to the _section itself_, or just to 
some section in the same object?

The linker in Arm's proprietary toolchain, `armlink`, takes the former 
attitude: garbage collection only follows non-weak references, so that if an 
object file containing many sections is pulled in to the link, the sections 
will then be independently GCed according to whether each one has a chain of 
non-weak references from the root. That's why I was concerned.

You _may_ be right that `armlink` is an outlier and no linker this code cares 
about will behave the same way. But personally I'd check them all before being 
sure!

https://github.com/llvm/llvm-project/pull/147426
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits