[llvm-branch-commits] [mlir] 9672d11 - [MLIR][Presburger] Disambiguate call to floor

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Rainer Orth
Date: 2022-02-22T11:10:22-08:00
New Revision: 9672d11441fd619d419554fee2ce006053d1d937

URL: 
https://github.com/llvm/llvm-project/commit/9672d11441fd619d419554fee2ce006053d1d937
DIFF: 
https://github.com/llvm/llvm-project/commit/9672d11441fd619d419554fee2ce006053d1d937.diff

LOG: [MLIR][Presburger] Disambiguate call to floor

While testing LLVM 14.0.0 rc1 on Solaris, compilation of `FAIL`ed with

  
/var/llvm/llvm-14.0.0-rc1/rc1/llvm-project/mlir/lib/Analysis/Presburger/Utils.cpp:
 In lambda function:
  
/var/llvm/llvm-14.0.0-rc1/rc1/llvm-project/mlir/lib/Analysis/Presburger/Utils.cpp:48:58:
 error: call of overloaded ‘floor(int64_t)’ is ambiguous
 48 |  [gcd](int64_t &n) { return floor(n / gcd); });
|  ^
  ...
  
/usr/gcc/10/lib/gcc/sparcv9-sun-solaris2.11/10.3.0/include-fixed/iso/math_iso.h:201:21:
note: candidate: ‘long double std::floor(long double)’
201 |  inline long double floor(long double __X) { return __floorl(__X); }
| ^
  
/usr/gcc/10/lib/gcc/sparcv9-sun-solaris2.11/10.3.0/include-fixed/iso/math_iso.h:165:15:
note: candidate: ‘float std::floor(float)’
165 |  inline float floor(float __X) { return __floorf(__X); }
|   ^
  
/usr/gcc/10/lib/gcc/sparcv9-sun-solaris2.11/10.3.0/include-fixed/iso/math_iso.h:78:15:
note: candidate: ‘double std::floor(double)’
 78 | extern double floor __P((double));
|   ^

The same issue had already occured in the past, cf. D108750
, and the solution is the same: cast the
`floor` arg to `double`.

Tested on `amd64-pc-solaris2.11` and `sparcv9-sun-solaris2.11`.

Differential Revision: https://reviews.llvm.org/D119324

(cherry picked from commit 91596755359e29c677bfa84d86edcaa1e70df955)

Added: 


Modified: 
mlir/lib/Analysis/Presburger/Utils.cpp

Removed: 




diff  --git a/mlir/lib/Analysis/Presburger/Utils.cpp 
b/mlir/lib/Analysis/Presburger/Utils.cpp
index bb7288185257..a8de71df252d 100644
--- a/mlir/lib/Analysis/Presburger/Utils.cpp
+++ b/mlir/lib/Analysis/Presburger/Utils.cpp
@@ -45,7 +45,7 @@ static void normalizeDivisionByGCD(SmallVectorImpl 
÷nd,
 
   // Normalize the dividend and the denominator.
   std::transform(dividend.begin(), dividend.end(), dividend.begin(),
- [gcd](int64_t &n) { return floor(n / gcd); });
+ [gcd](int64_t &n) { return floor((double)(n / gcd)); });
   divisor /= gcd;
 }
 



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] 3367c24 - [COFF] Move section name encoding into BinaryFormat

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Nicolas Miller
Date: 2022-02-22T11:11:28-08:00
New Revision: 3367c24735c3408517c6088061eee39030a69e70

URL: 
https://github.com/llvm/llvm-project/commit/3367c24735c3408517c6088061eee39030a69e70
DIFF: 
https://github.com/llvm/llvm-project/commit/3367c24735c3408517c6088061eee39030a69e70.diff

LOG: [COFF] Move section name encoding into BinaryFormat

Large COFF section names are moved into the string table and the
section header field is the offset into the string table encoded in
ASCII for offset smaller than 7 digits and in base64 for larger
offsets.

The operation of taking the string table offsets is done in a few
places in the codebase, so it is helpful to move this operation into
`BinaryFormat` so that it can be shared everywhere it's done.

So this patch takes the implementation of this operation from
`llvm/lib/MC/WinCOFFObjectWriter.cpp` and moves it into `BinaryFormat`.

Reviewed By: jhenderson, rnk

Differential Revision: https://reviews.llvm.org/D118793

(cherry picked from commit 85f4023e731c0c42e45bf32bfcbf5f73c2013384)

Added: 
llvm/lib/BinaryFormat/COFF.cpp

Modified: 
llvm/include/llvm/BinaryFormat/COFF.h
llvm/lib/BinaryFormat/CMakeLists.txt
llvm/lib/MC/WinCOFFObjectWriter.cpp

Removed: 




diff  --git a/llvm/include/llvm/BinaryFormat/COFF.h 
b/llvm/include/llvm/BinaryFormat/COFF.h
index e7dde986784f..016fe0289406 100644
--- a/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/llvm/include/llvm/BinaryFormat/COFF.h
@@ -731,6 +731,10 @@ inline bool isReservedSectionNumber(int32_t SectionNumber) 
{
   return SectionNumber <= 0;
 }
 
+/// Encode section name based on string table offset.
+/// The size of Out must be at least COFF::NameSize.
+bool encodeSectionName(char *Out, uint64_t Offset);
+
 } // End namespace COFF.
 } // End namespace llvm.
 

diff  --git a/llvm/lib/BinaryFormat/CMakeLists.txt 
b/llvm/lib/BinaryFormat/CMakeLists.txt
index 37f6865a487e..50c171380436 100644
--- a/llvm/lib/BinaryFormat/CMakeLists.txt
+++ b/llvm/lib/BinaryFormat/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMBinaryFormat
   AMDGPUMetadataVerifier.cpp
+  COFF.cpp
   Dwarf.cpp
   ELF.cpp
   MachO.cpp

diff  --git a/llvm/lib/BinaryFormat/COFF.cpp b/llvm/lib/BinaryFormat/COFF.cpp
new file mode 100644
index ..8fbee0218b79
--- /dev/null
+++ b/llvm/lib/BinaryFormat/COFF.cpp
@@ -0,0 +1,57 @@
+//===- llvm/BinaryFormat/COFF.cpp - The COFF format 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Twine.h"
+
+// Maximum offsets for 
diff erent string table entry encodings.
+enum : unsigned { Max7DecimalOffset = 999U };
+enum : uint64_t { MaxBase64Offset = 0xFULL }; // 64^6, including 0
+
+// Encode a string table entry offset in base 64, padded to 6 chars, and
+// prefixed with a double slash: '//AA', '//AB', ...
+// Buffer must be at least 8 bytes large. No terminating null appended.
+static void encodeBase64StringEntry(char *Buffer, uint64_t Value) {
+  assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset &&
+ "Illegal section name encoding for value");
+
+  static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+  Buffer[0] = '/';
+  Buffer[1] = '/';
+
+  char *Ptr = Buffer + 7;
+  for (unsigned i = 0; i < 6; ++i) {
+unsigned Rem = Value % 64;
+Value /= 64;
+*(Ptr--) = Alphabet[Rem];
+  }
+}
+
+bool llvm::COFF::encodeSectionName(char *Out, uint64_t Offset) {
+  if (Offset <= Max7DecimalOffset) {
+// Offsets of 7 digits or less are encoded in ASCII.
+SmallVector Buffer;
+Twine('/').concat(Twine(Offset)).toVector(Buffer);
+assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2);
+std::memcpy(Out, Buffer.data(), Buffer.size());
+return true;
+  }
+
+  if (Offset <= MaxBase64Offset) {
+// Starting with 10,000,000, offsets are encoded as base64.
+encodeBase64StringEntry(Out, Offset);
+return true;
+  }
+
+  // The offset is too large to be encoded.
+  return false;
+}

diff  --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp 
b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 73c687331d30..aba2ad315535 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -452,32 +452,6 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol 
&MCSym,
   Sym->MC = &MCSym;
 }
 
-// Maximum offsets for 
diff erent string table entry encodings.
-enum : unsigned { Max7DecimalOffset = 999U };
-enum : uint64_t { MaxBase64Off

[llvm-branch-commits] [llvm] 1362f8b - [AArch64][SVE] Fix selection failure caused by fp/int convert using non-Neon types

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Bradley Smith
Date: 2022-02-22T11:13:11-08:00
New Revision: 1362f8bdfce732d99ad28556dcff4a0bcb391528

URL: 
https://github.com/llvm/llvm-project/commit/1362f8bdfce732d99ad28556dcff4a0bcb391528
DIFF: 
https://github.com/llvm/llvm-project/commit/1362f8bdfce732d99ad28556dcff4a0bcb391528.diff

LOG: [AArch64][SVE] Fix selection failure caused by fp/int convert using 
non-Neon types

Fixes: #53679

Differential Revision: https://reviews.llvm.org/D119428

(cherry picked from commit c53ad72aa93646a3ab1b9b2307319a7389a51039)

Added: 
llvm/test/CodeGen/AArch64/sve-fixed-length-fp-convert.ll

Modified: 
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Removed: 




diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index c539c8617d99..792e45bdb0dd 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -13676,8 +13676,10 @@ static SDValue performFpToIntCombine(SDNode *N, 
SelectionDAG &DAG,
 return SDValue();
 
   SDValue Op = N->getOperand(0);
-  if (!Op.getValueType().isVector() || !Op.getValueType().isSimple() ||
-  Op.getOpcode() != ISD::FMUL)
+  if (!Op.getValueType().isSimple() || Op.getOpcode() != ISD::FMUL)
+return SDValue();
+
+  if (!Op.getValueType().is64BitVector() && 
!Op.getValueType().is128BitVector())
 return SDValue();
 
   SDValue ConstVec = Op->getOperand(1);

diff  --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-fp-convert.ll 
b/llvm/test/CodeGen/AArch64/sve-fixed-length-fp-convert.ll
new file mode 100644
index ..72d0a5657f3c
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-fp-convert.ll
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+; Ensure we don't crash when trying to combine fp<->int conversions
+define void @fp_convert_combine_crash(<8 x float> *%a, <8 x i32> *%b) #0 {
+; CHECK-LABEL: fp_convert_combine_crash:
+; CHECK:   // %bb.0:
+; CHECK-NEXT:ptrue p0.s
+; CHECK-NEXT:fmov z1.s, #8.
+; CHECK-NEXT:ld1w { z0.s }, p0/z, [x0]
+; CHECK-NEXT:fmul z0.s, z0.s, z1.s
+; CHECK-NEXT:fcvtzs z0.s, p0/m, z0.s
+; CHECK-NEXT:st1w { z0.s }, p0, [x1]
+; CHECK-NEXT:ret
+  %f = load <8 x float>, <8 x float>* %a
+  %mul.i = fmul <8 x float> %f, 
+  %vcvt.i = fptosi <8 x float> %mul.i to <8 x i32>
+  store <8 x i32> %vcvt.i, <8 x i32>* %b
+  ret void
+}
+
+attributes #0 = { vscale_range(2,2) "target-features"="+sve" }



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] cefe687 - [llvm-objcopy][COFF] Fix section name encoding

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Nicolas Miller
Date: 2022-02-22T11:11:28-08:00
New Revision: cefe6876d6e55ee8d544ab98216251ddd35ee7a9

URL: 
https://github.com/llvm/llvm-project/commit/cefe6876d6e55ee8d544ab98216251ddd35ee7a9
DIFF: 
https://github.com/llvm/llvm-project/commit/cefe6876d6e55ee8d544ab98216251ddd35ee7a9.diff

LOG: [llvm-objcopy][COFF] Fix section name encoding

The section name encoding for `llvm-objcopy` had two main issues, the
first is that the size used for the `snprintf` in the original code is
incorrect because `snprintf` adds a null byte, so this code was only
able to encode offsets of 6 digits - `/`, `\0` and 6 digits of the
offset - rather than the 7 digits it should support.

And the second part is that it didn't support the base64 encoding for
offsets larger than 7 digits.

This issue specifically showed up when using the `clang-offload-bundler`
with a binary containing a lot of symbols/sections, since it uses
`llvm-objcopy` to add the sections containing the offload code.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D118692

(cherry picked from commit ddf528b7a092fd24647d7c6186ece7392c92de92)

Added: 
llvm/test/tools/llvm-objcopy/COFF/section-name-encoding.s

Modified: 
llvm/tools/llvm-objcopy/CMakeLists.txt
llvm/tools/llvm-objcopy/COFF/Writer.cpp
llvm/tools/llvm-objcopy/COFF/Writer.h

Removed: 




diff  --git a/llvm/test/tools/llvm-objcopy/COFF/section-name-encoding.s 
b/llvm/test/tools/llvm-objcopy/COFF/section-name-encoding.s
new file mode 100644
index ..bd8b7c1bcf96
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/COFF/section-name-encoding.s
@@ -0,0 +1,95 @@
+## Check that COFF section names of sections added by llvm-objcopy are properly
+## encoded.
+##
+## Encodings for 
diff erent name lengths and string table index:
+##   [0, 8]:   raw name
+##   (8, 99]:  base 10 string table index (/999)
+##   (99, 0x]: base 64 string table index (##AA)
+##
+## Note: the names in the string table will be sorted in reverse
+## lexicographical order. Use a suffix letter (z, y, x, ...) to
+## get the preferred ordering of names in the test.
+##
+# REQUIRES: x86-registered-target
+##
+# RUN: echo DEADBEEF > %t.sec
+# RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s -o %t.obj
+# RUN: llvm-objcopy --add-section=s1234567=%t.sec \
+# RUN:  --add-section=s1234567z=%t.sec\
+# RUN:  --add-section=sevendigitx=%t.sec  \
+# RUN:  --add-section=doubleslashv=%t.sec \
+# RUN:  %t.obj %t
+# RUN: llvm-readobj --sections %t | FileCheck %s
+
+## Raw encoding
+
+# CHECK:   Section {
+# CHECK: Number: 14
+# CHECK: Name: s1234567 (73 31 32 33 34 35 36 37)
+# CHECK:   }
+
+## Base 10 encoding with a small offset, section name at the beginning of the
+## string table.
+
+## /4
+##
+# CHECK:   Section {
+# CHECK: Number: 15
+# CHECK: Name: s1234567z (2F 34 00 00 00 00 00 00)
+# CHECK:   }
+
+## Base 10 encoding with a 7 digit offset, section name after the y padding in
+## the string table.
+
+## /129 == 4 + 10 + (5 * (2 + (20 * 10 * 1000) + 1))
+## v   | |v~~v
+##table size   v v   "p0"  y pad NULL separator
+## "s1234567z\0" # of pad sections
+##
+# CHECK:   Section {
+# CHECK: Number: 16
+# CHECK: Name: sevendigitx (2F 31 30 30 30 30 32 39)
+# CHECK:   }
+
+## Base 64 encoding, section name after the w padding in the string table.
+
+## //AAmJa4 == 129 + 12 + (5 * (2 + (9 * 20 * 10 * 1000) + 1)) == 38*64^3 
+ 9*64^2 + 26*64 + 56
+## v | |v~~v
+## sevendigitx offsetv v   "p0"   w padNULL separator
+## "sevendigitx\0" # of pad sections
+##
+## "2F 2F 41 41 6D 4A 61 34" is "//AAmJa4", which decodes to "0 0 38 9 26 56".
+##
+# CHECK:   Section {
+# CHECK: Number: 17
+# CHECK: Name: doubleslashv (2F 2F 41 41 6D 4A 61 34)
+# CHECK:   }
+
+## Generate padding sections to increase the string table size to at least
+## 1,000,000 bytes.
+.macro pad_sections2 pad
+  ## 10x \pad
+  .section p0\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad; .long 1
+  .section p1\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad; .long 1
+  .section p2\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad; .long 1
+  .section p3\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad; .long 1
+  .section p4\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad; .long 1
+.endm
+
+.macro pad_sections pad
+  ## 20x \pad
+  pad_sections2 
\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad
+.endm
+
+## 1000x 'y'
+pad_sections 

[llvm-branch-commits] [llvm] 88f8980 - [AArch64][SVE] Add structured load/store opcodes to getMemOpInfo

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Kerry McLaughlin
Date: 2022-02-22T11:12:31-08:00
New Revision: 88f8980a4d95b16a0dcd57bb6da298d4d60d8fd1

URL: 
https://github.com/llvm/llvm-project/commit/88f8980a4d95b16a0dcd57bb6da298d4d60d8fd1
DIFF: 
https://github.com/llvm/llvm-project/commit/88f8980a4d95b16a0dcd57bb6da298d4d60d8fd1.diff

LOG: [AArch64][SVE] Add structured load/store opcodes to getMemOpInfo

Currently, loading from or storing to a stack location with a structured load
or store crashes in isAArch64FrameOffsetLegal as the opcodes are not handled by
getMemOpInfo. This patch adds the opcodes for structured load/store instructions
with an immediate index to getMemOpInfo & getLoadStoreImmIdx, setting 
appropriate
values for the scale, width & min/max offsets.

Reviewed By: sdesmalen, david-arm

Differential Revision: https://reviews.llvm.org/D119338

(cherry picked from commit fc1b21228e39d63f1a2ab98026d548de66cb3760)

Added: 
llvm/test/CodeGen/AArch64/sve-fixed-ld2-alloca.ll
llvm/test/CodeGen/AArch64/sve-ldN.mir
llvm/test/CodeGen/AArch64/sve-stN.mir

Modified: 
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Removed: 




diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp 
b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index a9191924129c..ea9c1b620065 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -2270,6 +2270,19 @@ unsigned AArch64InstrInfo::getLoadStoreImmIdx(unsigned 
Opc) {
   case AArch64::LD1SW_D_IMM:
   case AArch64::LD1D_IMM:
 
+  case AArch64::LD2B_IMM:
+  case AArch64::LD2H_IMM:
+  case AArch64::LD2W_IMM:
+  case AArch64::LD2D_IMM:
+  case AArch64::LD3B_IMM:
+  case AArch64::LD3H_IMM:
+  case AArch64::LD3W_IMM:
+  case AArch64::LD3D_IMM:
+  case AArch64::LD4B_IMM:
+  case AArch64::LD4H_IMM:
+  case AArch64::LD4W_IMM:
+  case AArch64::LD4D_IMM:
+
   case AArch64::ST1B_IMM:
   case AArch64::ST1B_H_IMM:
   case AArch64::ST1B_S_IMM:
@@ -2281,6 +2294,19 @@ unsigned AArch64InstrInfo::getLoadStoreImmIdx(unsigned 
Opc) {
   case AArch64::ST1W_D_IMM:
   case AArch64::ST1D_IMM:
 
+  case AArch64::ST2B_IMM:
+  case AArch64::ST2H_IMM:
+  case AArch64::ST2W_IMM:
+  case AArch64::ST2D_IMM:
+  case AArch64::ST3B_IMM:
+  case AArch64::ST3H_IMM:
+  case AArch64::ST3W_IMM:
+  case AArch64::ST3D_IMM:
+  case AArch64::ST4B_IMM:
+  case AArch64::ST4H_IMM:
+  case AArch64::ST4W_IMM:
+  case AArch64::ST4D_IMM:
+
   case AArch64::LD1RB_IMM:
   case AArch64::LD1RB_H_IMM:
   case AArch64::LD1RB_S_IMM:
@@ -2897,6 +2923,45 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, 
TypeSize &Scale,
 MinOffset = -8;
 MaxOffset = 7;
 break;
+  case AArch64::LD2B_IMM:
+  case AArch64::LD2H_IMM:
+  case AArch64::LD2W_IMM:
+  case AArch64::LD2D_IMM:
+  case AArch64::ST2B_IMM:
+  case AArch64::ST2H_IMM:
+  case AArch64::ST2W_IMM:
+  case AArch64::ST2D_IMM:
+Scale = TypeSize::Scalable(32);
+Width = SVEMaxBytesPerVector * 2;
+MinOffset = -8;
+MaxOffset = 7;
+break;
+  case AArch64::LD3B_IMM:
+  case AArch64::LD3H_IMM:
+  case AArch64::LD3W_IMM:
+  case AArch64::LD3D_IMM:
+  case AArch64::ST3B_IMM:
+  case AArch64::ST3H_IMM:
+  case AArch64::ST3W_IMM:
+  case AArch64::ST3D_IMM:
+Scale = TypeSize::Scalable(48);
+Width = SVEMaxBytesPerVector * 3;
+MinOffset = -8;
+MaxOffset = 7;
+break;
+  case AArch64::LD4B_IMM:
+  case AArch64::LD4H_IMM:
+  case AArch64::LD4W_IMM:
+  case AArch64::LD4D_IMM:
+  case AArch64::ST4B_IMM:
+  case AArch64::ST4H_IMM:
+  case AArch64::ST4W_IMM:
+  case AArch64::ST4D_IMM:
+Scale = TypeSize::Scalable(64);
+Width = SVEMaxBytesPerVector * 4;
+MinOffset = -8;
+MaxOffset = 7;
+break;
   case AArch64::LD1B_H_IMM:
   case AArch64::LD1SB_H_IMM:
   case AArch64::LD1H_S_IMM:

diff  --git a/llvm/test/CodeGen/AArch64/sve-fixed-ld2-alloca.ll 
b/llvm/test/CodeGen/AArch64/sve-fixed-ld2-alloca.ll
new file mode 100644
index ..f59891c31e93
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-fixed-ld2-alloca.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+define void @st1d_fixed(<8 x double>* %ptr) #0 {
+; CHECK-LABEL: st1d_fixed:
+; CHECK:   // %bb.0:
+; CHECK-NEXT:sub sp, sp, #16
+; CHECK-NEXT:add x8, sp, #8
+; CHECK-NEXT:ptrue p0.d
+; CHECK-NEXT:ld2d { z0.d, z1.d }, p0/z, [x8]
+; CHECK-NEXT:mov x8, #4
+; CHECK-NEXT:mov z0.d, #0 // =0x0
+; CHECK-NEXT:st1d { z0.d }, p0, [x0]
+; CHECK-NEXT:st1d { z0.d }, p0, [x0, x8, lsl #3]
+; CHECK-NEXT:add sp, sp, #16
+; CHECK-NEXT:ret
+  %alloc = alloca [16 x double], i32 0
+  %bc = bitcast [16 x double]* %alloc to <8 x double>*
+  %load = load <8 x double>, <8 x double>* %bc
+  %strided.vec = shufflevector <8 x double> %load, <8 x double> poison, <4 x 
i32> 
+  store <8 x double> zeroinitialize

[llvm-branch-commits] [llvm] 8c33ea3 - [SVE][CodeGen] Bail out for scalable vectors in AArch64TargetLowering::ReconstructShuffle

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: David Sherwood
Date: 2022-02-22T11:13:38-08:00
New Revision: 8c33ea3ab0ef304e6f43be31e9c72660a6261bf7

URL: 
https://github.com/llvm/llvm-project/commit/8c33ea3ab0ef304e6f43be31e9c72660a6261bf7
DIFF: 
https://github.com/llvm/llvm-project/commit/8c33ea3ab0ef304e6f43be31e9c72660a6261bf7.diff

LOG: [SVE][CodeGen] Bail out for scalable vectors in 
AArch64TargetLowering::ReconstructShuffle

Previously the code in AArch64TargetLowering::ReconstructShuffle assumed
the input vectors were always fixed-width, however this is not always
the case since you can extract elements from scalable vectors and insert
into fixed-width ones. We were hitting crashes here for two different
cases:

1. When lowering a fixed-length vector extract from a scalable vector
with i1 element types. This happens due to the fact the i1 elements
get promoted to larger integer types for fixed-width vectors and leads
to sequences of INSERT_VECTOR_ELT and EXTRACT_VECTOR_ELT nodes. In this
case AArch64TargetLowering::ReconstructShuffle will still fail to make
a transformation, but at least it no longer crashes.
2. When lowering a sequence of extractelement/insertelement operations
on mixed fixed-width/scalable vectors.

For now, I've just changed AArch64TargetLowering::ReconstructShuffle to
bail out if it finds a scalable vector.

Tests for both instances described above have been added here:

  (1) CodeGen/AArch64/sve-extract-fixed-vector.ll
  (2) CodeGen/AArch64/sve-fixed-length-reshuffle.ll

Differential Revision: https://reviews.llvm.org/D116602

(cherry picked from commit a57a7f3de551bd0ae4e27b1f0c85437cd3e2e834)

Added: 
llvm/test/CodeGen/AArch64/sve-fixed-length-reshuffle.ll

Modified: 
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll

Removed: 




diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 792e45bdb0dd..aa2dca3eda4b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -8990,12 +8990,13 @@ SDValue 
AArch64TargetLowering::ReconstructShuffle(SDValue Op,
 if (V.isUndef())
   continue;
 else if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
- !isa(V.getOperand(1))) {
+ !isa(V.getOperand(1)) ||
+ V.getOperand(0).getValueType().isScalableVector()) {
   LLVM_DEBUG(
   dbgs() << "Reshuffle failed: "
 "a shuffle can only come from building a vector from "
-"various elements of other vectors, provided their "
-"indices are constant\n");
+"various elements of other fixed-width vectors, provided "
+"their indices are constant\n");
   return SDValue();
 }
 
@@ -9039,8 +9040,8 @@ SDValue AArch64TargetLowering::ReconstructShuffle(SDValue 
Op,
   for (auto &Src : Sources) {
 EVT SrcVT = Src.ShuffleVec.getValueType();
 
-uint64_t SrcVTSize = SrcVT.getFixedSizeInBits();
-if (SrcVTSize == VTSize)
+TypeSize SrcVTSize = SrcVT.getSizeInBits();
+if (SrcVTSize == TypeSize::Fixed(VTSize))
   continue;
 
 // This stage of the search produces a source with the same element type as
@@ -9049,7 +9050,7 @@ SDValue AArch64TargetLowering::ReconstructShuffle(SDValue 
Op,
 unsigned NumSrcElts = VTSize / EltVT.getFixedSizeInBits();
 EVT DestVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NumSrcElts);
 
-if (SrcVTSize < VTSize) {
+if (SrcVTSize.getFixedValue() < VTSize) {
   assert(2 * SrcVTSize == VTSize);
   // We can pad out the smaller vector for free, so if it's part of a
   // shuffle...
@@ -9059,7 +9060,7 @@ SDValue AArch64TargetLowering::ReconstructShuffle(SDValue 
Op,
   continue;
 }
 
-if (SrcVTSize != 2 * VTSize) {
+if (SrcVTSize.getFixedValue() != 2 * VTSize) {
   LLVM_DEBUG(
   dbgs() << "Reshuffle failed: result vector too small to extract\n");
   return SDValue();

diff  --git a/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll 
b/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll
index 3be4b94dedd2..a3d161ec4102 100644
--- a/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll
+++ b/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll
@@ -361,6 +361,106 @@ define <16 x i8> @extract_v16i8_nxv2i8_idx16( %vec) nounwind #1
   ret <16 x i8> %retval
 }
 
+
+; Predicates
+
+define <2 x i1> @extract_v2i1_nxv2i1( %inmask) {
+; CHECK-LABEL: extract_v2i1_nxv2i1:
+; CHECK:   // %bb.0:
+; CHECK-NEXT:mov z0.d, p0/z, #1 // =0x1
+; CHECK-NEXT:fmov x0, d0
+; CHECK-NEXT:mov x8, v0.d[1]
+; CHECK-NEXT:fmov s0, w0
+; CHECK-NEXT:mov v0.s[1], w8
+; CHECK-NEXT:// kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:ret
+  %mask = call <2 x i1> @llvm.experimental.vector.extract.v2i1.nxv2i1( %inmask, i64 

[llvm-branch-commits] [llvm] 8b5b29c - Fix incorrect TypeSize->uint64_t cast in InductionDescriptor::isInductionPHI

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: David Sherwood
Date: 2022-02-22T11:14:00-08:00
New Revision: 8b5b29c4c2c541ae23bcb51c57ce4bb57de477d1

URL: 
https://github.com/llvm/llvm-project/commit/8b5b29c4c2c541ae23bcb51c57ce4bb57de477d1
DIFF: 
https://github.com/llvm/llvm-project/commit/8b5b29c4c2c541ae23bcb51c57ce4bb57de477d1.diff

LOG: Fix incorrect TypeSize->uint64_t cast in 
InductionDescriptor::isInductionPHI

The code was relying upon the implicit conversion of TypeSize to
uint64_t and assuming the type in question was always fixed. However,
I discovered an issue when running the canon-freeze pass with some
IR loops that contains scalable vector types. I've changed the code
to bail out if the size is unknown at compile time, since we cannot
compute whether the step is a multiple of the type size or not.

I added a test here:

  Transforms/CanonicalizeFreezeInLoops/phis.ll

Differential Revision: https://reviews.llvm.org/D118696

(cherry picked from commit 1badfbb4fc1a16f6dbe3b4edccdef44d9142857e)

Added: 


Modified: 
llvm/lib/Analysis/IVDescriptors.cpp
llvm/unittests/Analysis/IVDescriptorsTest.cpp

Removed: 




diff  --git a/llvm/lib/Analysis/IVDescriptors.cpp 
b/llvm/lib/Analysis/IVDescriptors.cpp
index 44b1d94ebdc8..74b0d6751023 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -1428,10 +1428,14 @@ bool InductionDescriptor::isInductionPHI(
 
   ConstantInt *CV = ConstStep->getValue();
   const DataLayout &DL = Phi->getModule()->getDataLayout();
-  int64_t Size = static_cast(DL.getTypeAllocSize(ElementType));
-  if (!Size)
+  TypeSize TySize = DL.getTypeAllocSize(ElementType);
+  // TODO: We could potentially support this for scalable vectors if we can
+  // prove at compile time that the constant step is always a multiple of
+  // the scalable type.
+  if (TySize.isZero() || TySize.isScalable())
 return false;
 
+  int64_t Size = static_cast(TySize.getFixedSize());
   int64_t CVSize = CV->getSExtValue();
   if (CVSize % Size)
 return false;

diff  --git a/llvm/unittests/Analysis/IVDescriptorsTest.cpp 
b/llvm/unittests/Analysis/IVDescriptorsTest.cpp
index 1f63db3ff31c..e7948db10ae6 100644
--- a/llvm/unittests/Analysis/IVDescriptorsTest.cpp
+++ b/llvm/unittests/Analysis/IVDescriptorsTest.cpp
@@ -97,6 +97,47 @@ for.end:
   });
 }
 
+TEST(IVDescriptorsTest, LoopWithScalableTypes) {
+  // Parse the module.
+  LLVMContext Context;
+
+  std::unique_ptr M =
+  parseIR(Context,
+  R"(define void @foo(* %ptr) {
+entry:
+  br label %for.body
+
+for.body:
+  %lsr.iv1 = phi * [ %0, %for.body ], [ %ptr, %entry ]
+  %j.0117 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
+  %lsr.iv12 = bitcast * %lsr.iv1 to i8*
+  %inc = add nuw nsw i64 %j.0117, 1
+  %uglygep = getelementptr i8, i8* %lsr.iv12, i64 4
+  %0 = bitcast i8* %uglygep to *
+  %cmp = icmp ne i64 %inc, 1024
+  br i1 %cmp, label %for.body, label %end
+
+end:
+  ret void
+})");
+
+  runWithLoopInfoAndSE(
+  *M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
+Function::iterator FI = F.begin();
+// First basic block is entry - skip it.
+BasicBlock *Header = &*(++FI);
+assert(Header->getName() == "for.body");
+Loop *L = LI.getLoopFor(Header);
+EXPECT_NE(L, nullptr);
+PHINode *Inst_iv = dyn_cast(&Header->front());
+assert(Inst_iv->getName() == "lsr.iv1");
+InductionDescriptor IndDesc;
+bool IsInductionPHI =
+InductionDescriptor::isInductionPHI(Inst_iv, L, &SE, IndDesc);
+EXPECT_FALSE(IsInductionPHI);
+  });
+}
+
 // Depending on how SCEV deals with ptrtoint cast, the step of a phi could be
 // a pointer, and InductionDescriptor used to fail with an assertion.
 // So just check that it doesn't assert.



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] 03d9a40 - [AArch64][SVE] Fix selection failure during lowering of shuffle_vector

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Bradley Smith
Date: 2022-02-22T11:14:30-08:00
New Revision: 03d9a4094763b33be4e1ae908f5ff9a1787cf8d3

URL: 
https://github.com/llvm/llvm-project/commit/03d9a4094763b33be4e1ae908f5ff9a1787cf8d3
DIFF: 
https://github.com/llvm/llvm-project/commit/03d9a4094763b33be4e1ae908f5ff9a1787cf8d3.diff

LOG: [AArch64][SVE] Fix selection failure during lowering of shuffle_vector

The lowering code for shuffle_vector has a code path that looks through
extract_subvector, this code path did not properly account for the
potential presense of larger than Neon vector types and could produce
unselectable DAG nodes.

Differential Revision: https://reviews.llvm.org/D119252

(cherry picked from commit 98936aee7d41f9ae60dd06558fbbb1e6a4a89e17)

Added: 


Modified: 
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll

Removed: 




diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index aa2dca3eda4b..ac5e51e47ddf 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -9733,6 +9733,10 @@ static SDValue constructDup(SDValue V, int Lane, SDLoc 
dl, EVT VT,
 if (ExtIdxInBits % CastedEltBitWidth != 0)
   return false;
 
+// Can't handle cases where vector size is not 128-bit
+if (!Extract.getOperand(0).getValueType().is128BitVector())
+  return false;
+
 // Update the lane value by offsetting with the scaled extract index.
 LaneC += ExtIdxInBits / CastedEltBitWidth;
 

diff  --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll 
b/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll
index 4e53128e1346..98f4077ef85d 100644
--- a/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll
+++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll
@@ -1,4 +1,4 @@
-; RUN: llc -aarch64-sve-vector-bits-min=256 < %s | FileCheck %s
+; RUN: llc < %s | FileCheck %s
 
 target triple = "aarch64-unknown-linux-gnu"
 
@@ -14,4 +14,22 @@ define void @hang_when_merging_stores_after_legalisation(<8 
x i32>* %a, <2 x i32
   ret void
 }
 
-attributes #0 = { nounwind "target-features"="+sve" }
+; Ensure we don't crash when trying to lower a shuffle via and extract
+define void @crash_when_lowering_extract_shuffle(<32 x i32>* %dst, i1 %cond) 
#0 {
+; CHECK-LABEL: crash_when_lowering_extract_shuffle:
+; CHECK:   ld1w { z3.s }, p0/z, [x0]
+; CHECK:   st1w { z3.s }, p0, [x0]
+  %broadcast.splat = shufflevector <32 x i1> zeroinitializer, <32 x i1> 
zeroinitializer, <32 x i32> zeroinitializer
+  br i1 %cond, label %exit, label %vector.body
+
+vector.body:
+  %1 = load <32 x i32>, <32 x i32>* %dst, align 16
+  %predphi = select <32 x i1> %broadcast.splat, <32 x i32> zeroinitializer, 
<32 x i32> %1
+  store <32 x i32> %predphi, <32 x i32>* %dst, align 16
+  br label %exit
+
+exit:
+  ret void
+}
+
+attributes #0 = { vscale_range(2,2) "target-features"="+sve" }



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 46266b3 - [mlir][sparse] Rename index_t to index_type again

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Rainer Orth
Date: 2022-02-22T11:15:16-08:00
New Revision: 46266b3518b6190d4eaa8e4920371c87fd784f46

URL: 
https://github.com/llvm/llvm-project/commit/46266b3518b6190d4eaa8e4920371c87fd784f46
DIFF: 
https://github.com/llvm/llvm-project/commit/46266b3518b6190d4eaa8e4920371c87fd784f46.diff

LOG: [mlir][sparse] Rename index_t to index_type again

While testing LLVM 14.0.0 rc1 on Solaris, I ran into a compile failure:

   from 
/var/llvm/llvm-14.0.0-rc1/rc1/llvm-project/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp:22:
  /usr/include/sys/types.h:103:16: error: conflicting declaration ‘typedef 
short int index_t’
103 | typedef short  index_t;
|^~~
  In file included from
/var/llvm/llvm-14.0.0-rc1/rc1/llvm-project/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp:17:
  
/var/llvm/llvm-14.0.0-rc1/rc1/llvm-project/mlir/include/mlir/ExecutionEngine/SparseTensorUtils.h:26:7:
note: previous declaration as ‘using index_t = uint64_t’
 26 | using index_t = uint64_t;
|   ^~~

The same issue had already occured in the past and fixed in D72619
.  More detailed explanation can also be
found there.

Tested on `amd64-pc-solaris2.11` and `sparcv9-solaris2.11`.

Differential Revision: https://reviews.llvm.org/D119323

(cherry picked from commit d2215e79ac27301c2a7cad36b5bfe20bd12837fb)

Added: 


Modified: 
mlir/include/mlir/ExecutionEngine/SparseTensorUtils.h
mlir/lib/ExecutionEngine/SparseTensorUtils.cpp

Removed: 




diff  --git a/mlir/include/mlir/ExecutionEngine/SparseTensorUtils.h 
b/mlir/include/mlir/ExecutionEngine/SparseTensorUtils.h
index a1f1dd6ae32d..52eda9bace6d 100644
--- a/mlir/include/mlir/ExecutionEngine/SparseTensorUtils.h
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensorUtils.h
@@ -23,7 +23,7 @@ extern "C" {
 /// type is 64-bit, but targets with 
diff erent "index" bit widths should link
 /// with an alternatively built runtime support library.
 // TODO: support such targets?
-using index_t = uint64_t;
+using index_type = uint64_t;
 
 /// Encoding of overhead types (both pointer overhead and indices
 /// overhead), for "overloading" @newSparseTensor.

diff  --git a/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp 
b/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp
index 605e17764773..665dd8663a6c 100644
--- a/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp
+++ b/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp
@@ -796,7 +796,7 @@ extern "C" {
 
 #define IMPL_GETOVERHEAD(NAME, TYPE, LIB)  
\
   void _mlir_ciface_##NAME(StridedMemRefType *ref, void *tensor,  
\
-   index_t d) {
\
+   index_type d) { 
\
 assert(ref &&tensor);  
\
 std::vector *v;  
\
 static_cast(tensor)->LIB(&v, d);
\
@@ -808,15 +808,15 @@ extern "C" {
 
 #define IMPL_ADDELT(NAME, TYPE)
\
   void *_mlir_ciface_##NAME(void *tensor, TYPE value,  
\
-StridedMemRefType *iref,   
\
-StridedMemRefType *pref) { 
\
+StridedMemRefType *iref,
\
+StridedMemRefType *pref) {  
\
 assert(tensor &&iref &&pref);  
\
 assert(iref->strides[0] == 1 && pref->strides[0] == 1);
\
 assert(iref->sizes[0] == pref->sizes[0]);  
\
-const index_t *indx = iref->data + iref->offset;   
\
-const index_t *perm = pref->data + pref->offset;   
\
+const index_type *indx = iref->data + iref->offset;
\
+const index_type *perm = pref->data + pref->offset;
\
 uint64_t isize = iref->sizes[0];   
\
-std::vector indices(isize);   
\
+std::vector indices(isize);
\
 for (uint64_t r = 0; r < isize; r++)   
\
   indices[perm[r]] = indx[r];  
\
 static_cast *>(tensor)->add(indices, value); 
\
@@ -824,11 +824,12 @@ extern "C" {
   }
 
 #define IMPL_GETNEXT(NAME, V)  
\
-  bool _mlir_ciface_##NAME(void *tensor, StridedMemRefType *iref,  
\
+  bool _mlir_ciface_##NAME(void *tensor,   
\
+   StridedMemRefType *iref, 
\

[llvm-branch-commits] [clang] 2fe5bf5 - [Driver] Use libatomic for 32-bit SPARC atomics support

2022-02-22 Thread Tom Stellard via llvm-branch-commits

Author: Rainer Orth
Date: 2022-02-22T22:13:54-08:00
New Revision: 2fe5bf57172cebf5a3f0b3f82552cf5c2122eca2

URL: 
https://github.com/llvm/llvm-project/commit/2fe5bf57172cebf5a3f0b3f82552cf5c2122eca2
DIFF: 
https://github.com/llvm/llvm-project/commit/2fe5bf57172cebf5a3f0b3f82552cf5c2122eca2.diff

LOG: [Driver] Use libatomic for 32-bit SPARC atomics support

Even after D86621 , `clang -m32` on
Solaris/sparcv9 doesn't inline atomics with 8-byte operands, unlike `gcc`.
This leads to many link failures in the testsuite (undefined references to
`__atomic_load_8` and `__sync_val_compare_and_swap_8`.  Until a proper
codegen fix can be implemented, this patch works around the first of those
by linking with `-latomic`.

Tested on `sparcv9-sun-solaris2.11`.

Differential Revision: https://reviews.llvm.org/D118021

(cherry picked from commit a6afa9e6b0d9a08ecc878e62343a2af80ff30435)

Added: 


Modified: 
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Driver/ToolChains/CommonArgs.h
clang/lib/Driver/ToolChains/Solaris.cpp
clang/test/Driver/solaris-ld.c

Removed: 




diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 6364cd133e0bf..dfcef2304040e 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -756,7 +756,7 @@ static bool addSanitizerDynamicList(const ToolChain &TC, 
const ArgList &Args,
   return false;
 }
 
-static const char *getAsNeededOption(const ToolChain &TC, bool as_needed) {
+const char *tools::getAsNeededOption(const ToolChain &TC, bool as_needed) {
   assert(!TC.getTriple().isOSAIX() &&
  "AIX linker does not support any form of --as-needed option yet.");
 

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.h 
b/clang/lib/Driver/ToolChains/CommonArgs.h
index 646fa76949b78..23012dc247e41 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -117,6 +117,8 @@ bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, 
const ToolChain &TC,
   bool ForceStaticHostRuntime = false,
   bool IsOffloadingHost = false, bool GompNeedsRT = false);
 
+const char *getAsNeededOption(const ToolChain &TC, bool as_needed);
+
 llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args);
 llvm::opt::Arg *getLastProfileSampleUseArg(const llvm::opt::ArgList &Args);
 

diff  --git a/clang/lib/Driver/ToolChains/Solaris.cpp 
b/clang/lib/Driver/ToolChains/Solaris.cpp
index 4d1af094f4814..24f18b92dd661 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -132,6 +132,13 @@ void solaris::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
   CmdArgs.push_back("-lssp_nonshared");
   CmdArgs.push_back("-lssp");
 }
+// LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
+// forcibly link with libatomic as a workaround.
+if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
+  CmdArgs.push_back(getAsNeededOption(getToolChain(), true));
+  CmdArgs.push_back("-latomic");
+  CmdArgs.push_back(getAsNeededOption(getToolChain(), false));
+}
 CmdArgs.push_back("-lgcc_s");
 CmdArgs.push_back("-lc");
 if (!Args.hasArg(options::OPT_shared)) {

diff  --git a/clang/test/Driver/solaris-ld.c b/clang/test/Driver/solaris-ld.c
index 59d03c4d82253..d40e5dac2da9e 100644
--- a/clang/test/Driver/solaris-ld.c
+++ b/clang/test/Driver/solaris-ld.c
@@ -17,6 +17,7 @@
 // CHECK-LD-SPARC32-SAME: 
"-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2"
 // CHECK-LD-SPARC32-SAME: 
"-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../.."
 // CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/lib"
+// CHECK-LD-SPARC32-SAME: "-zignore" "-latomic" "-zrecord"
 // CHECK-LD-SPARC32-SAME: "-lgcc_s"
 // CHECK-LD-SPARC32-SAME: "-lc"
 // CHECK-LD-SPARC32-SAME: "-lgcc"
@@ -40,6 +41,7 @@
 // CHECK-LD-SPARC64-SAME: 
"-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9"
 // CHECK-LD-SPARC64-SAME: 
"-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../sparcv9"
 // CHECK-LD-SPARC64-SAME: "-L[[SYSROOT]]/usr/lib/sparcv9"
+// CHECK-LD-SPARC64-NOT:  "-latomic"
 // CHECK-LD-SPARC64-SAME: "-lgcc_s"
 // CHECK-LD-SPARC64-SAME: "-lc"
 // CHECK-LD-SPARC64-SAME: "-lgcc"
@@ -63,6 +65,7 @@
 // CHECK-LD-X32-SAME: 
"-L[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4"
 // CHECK-LD-X32-SAME: 
"-L[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../.."
 // CHECK-LD-X32-SAME: "-L[[SYSROOT]]/usr/lib"
+// CHECK-LD-X32-NOT:  "-latomic"
 // CHECK-LD-X32-SAME: "-lgcc_s"
 // CHECK-LD-X32-SAME: "-lc"
 // CHECK-LD-X32-SAME: "-lgcc"
@@ -86,6 +89,7 @@
 // CHECK-LD-X64-SAME: 
"-L[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64"
 // CHECK-LD-