[llvm-branch-commits] [llvm] e0721a0 - [AArch64][GlobalISel] Notify observer of mutated instruction for shift custom legalization.

2020-12-25 Thread Amara Emerson via llvm-branch-commits

Author: Amara Emerson
Date: 2020-12-25T00:31:47-08:00
New Revision: e0721a0992288122d62940f622b4c2127098a2da

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

LOG: [AArch64][GlobalISel] Notify observer of mutated instruction for shift 
custom legalization.

No test for this because it's a CSE verifier failure that's only exposed in a
WIP patch for enabling CSE throughout the AArch64 GISel pipeline.

Added: 


Modified: 
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Removed: 




diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 0774f7b02dd2..a611d68cb2e5 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -841,7 +841,9 @@ bool AArch64LegalizerInfo::legalizeShlAshrLshr(
   if (Amount > 31)
 return true; // This will have to remain a register variant.
   auto ExtCst = MIRBuilder.buildConstant(LLT::scalar(64), Amount);
+  Observer.changingInstr(MI);
   MI.getOperand(2).setReg(ExtCst.getReg(0));
+  Observer.changedInstr(MI);
   return true;
 }
 



___
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] 438bc15 - [libObject] - Add more ELF types to LLVM_ELF_IMPORT_TYPES_ELFT define (ELFTypes.h).

2020-12-25 Thread Georgii Rymar via llvm-branch-commits

Author: Georgii Rymar
Date: 2020-12-25T11:39:05+03:00
New Revision: 438bc157a47a03d36d81977a3ee9974cd021a885

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

LOG: [libObject] - Add more ELF types to LLVM_ELF_IMPORT_TYPES_ELFT define 
(ELFTypes.h).

This allows to get rid of lots for typedefs/usings from many places.

Differential revision: https://reviews.llvm.org/D93801

Added: 


Modified: 
llvm/include/llvm/Object/ELF.h
llvm/include/llvm/Object/ELFObjectFile.h
llvm/include/llvm/Object/ELFTypes.h
llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
llvm/lib/ObjectYAML/ELFEmitter.cpp
llvm/tools/llvm-readobj/ELFDumper.cpp
llvm/tools/obj2yaml/elf2yaml.cpp

Removed: 




diff  --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index a5233bd3ac10..bd224ada7783 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -90,32 +90,6 @@ template 
 class ELFFile {
 public:
   LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
-  using uintX_t = typename ELFT::uint;
-  using Elf_Ehdr = typename ELFT::Ehdr;
-  using Elf_Shdr = typename ELFT::Shdr;
-  using Elf_Sym = typename ELFT::Sym;
-  using Elf_Dyn = typename ELFT::Dyn;
-  using Elf_Phdr = typename ELFT::Phdr;
-  using Elf_Rel = typename ELFT::Rel;
-  using Elf_Rela = typename ELFT::Rela;
-  using Elf_Relr = typename ELFT::Relr;
-  using Elf_Verdef = typename ELFT::Verdef;
-  using Elf_Verdaux = typename ELFT::Verdaux;
-  using Elf_Verneed = typename ELFT::Verneed;
-  using Elf_Vernaux = typename ELFT::Vernaux;
-  using Elf_Versym = typename ELFT::Versym;
-  using Elf_Hash = typename ELFT::Hash;
-  using Elf_GnuHash = typename ELFT::GnuHash;
-  using Elf_Nhdr = typename ELFT::Nhdr;
-  using Elf_Note = typename ELFT::Note;
-  using Elf_Note_Iterator = typename ELFT::NoteIterator;
-  using Elf_Dyn_Range = typename ELFT::DynRange;
-  using Elf_Shdr_Range = typename ELFT::ShdrRange;
-  using Elf_Sym_Range = typename ELFT::SymRange;
-  using Elf_Rel_Range = typename ELFT::RelRange;
-  using Elf_Rela_Range = typename ELFT::RelaRange;
-  using Elf_Relr_Range = typename ELFT::RelrRange;
-  using Elf_Phdr_Range = typename ELFT::PhdrRange;
 
   // This is a callback that can be passed to a number of functions.
   // It can be used to ignore non-critical errors (warnings), which is

diff  --git a/llvm/include/llvm/Object/ELFObjectFile.h 
b/llvm/include/llvm/Object/ELFObjectFile.h
index ca4363572d90..33b4c28db951 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -233,15 +233,6 @@ template  class ELFObjectFile : public 
ELFObjectFileBase {
 public:
   LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
 
-  using uintX_t = typename ELFT::uint;
-
-  using Elf_Sym = typename ELFT::Sym;
-  using Elf_Shdr = typename ELFT::Shdr;
-  using Elf_Ehdr = typename ELFT::Ehdr;
-  using Elf_Rel = typename ELFT::Rel;
-  using Elf_Rela = typename ELFT::Rela;
-  using Elf_Dyn = typename ELFT::Dyn;
-
   SectionRef toSectionRef(const Elf_Shdr *Sec) const {
 return SectionRef(toDRI(Sec), this);
   }

diff  --git a/llvm/include/llvm/Object/ELFTypes.h 
b/llvm/include/llvm/Object/ELFTypes.h
index 5e85e6cc4653..f64e7c06e03b 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -107,7 +107,34 @@ using ELF64BE = ELFType;
   using Elf_Word = typename ELFT::Word;
\
   using Elf_Sword = typename ELFT::Sword;  
\
   using Elf_Xword = typename ELFT::Xword;  
\
-  using Elf_Sxword = typename ELFT::Sxword;
+  using Elf_Sxword = typename ELFT::Sxword;
\
+  using uintX_t = typename ELFT::uint; 
\
+  using Elf_Ehdr = typename ELFT::Ehdr;
\
+  using Elf_Shdr = typename ELFT::Shdr;
\
+  using Elf_Sym = typename ELFT::Sym;  
\
+  using Elf_Dyn = typename ELFT::Dyn;  
\
+  using Elf_Phdr = typename ELFT::Phdr;
\
+  using Elf_Rel = typename ELFT::Rel;  
\
+  using Elf_Rela = typename ELFT::Rela;
\
+  using Elf_Relr = typename ELFT::Relr;
\
+  using Elf_Verdef = typename ELFT::Verdef;
\
+  using Elf_Verdaux = typename ELFT::Verdaux;  
\
+  using Elf_Verneed = typename ELFT::Verneed;  
\
+  using Elf_Vernaux = typename ELFT::Vernaux;  

[llvm-branch-commits] [llvm] 177779e - [llvm-readelf/obj] - Improve the warning reported when unable to read the stack size.

2020-12-25 Thread Georgii Rymar via llvm-branch-commits

Author: Georgii Rymar
Date: 2020-12-25T11:40:35+03:00
New Revision: 19e8dd9f7d20b96d4711a81d65ab7d480bb5

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

LOG: [llvm-readelf/obj] - Improve the warning reported when unable to read the 
stack size.

It was discussed in D92545 that we might want to improve messages
reported when something is wrong with the stack size section.
This patch does it.

Differential revision: https://reviews.llvm.org/D93802

Added: 


Modified: 
llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 




diff  --git a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test 
b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
index 9d0c0b532e5e..8a8e481d8ff3 100644
--- a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
+++ b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
@@ -442,11 +442,13 @@ Symbols:
 ## ends in a byte with the high bit set.
 
 # RUN: yaml2obj --docnum=6 %s -o %t06
-# RUN: llvm-readelf --stack-sizes %t06 2>&1 | FileCheck %s 
--check-prefix=BADSIZE -DFILE=%t06
-# RUN: llvm-readobj --stack-sizes %t06 2>&1 | FileCheck %s 
--check-prefix=BADSIZE -DFILE=%t06
+# RUN: llvm-readelf --stack-sizes %t06 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=BADSIZE -DFILE=%t06 
--implicit-check-not=warning:
+# RUN: llvm-readobj --stack-sizes %t06 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=BADSIZE -DFILE=%t06 
--implicit-check-not=warning:
 
-# BADSIZE: warning: '[[FILE]]': could not extract a valid stack size from 
SHT_PROGBITS section with index 2
-# BADSIZE: warning: '[[FILE]]': could not extract a valid stack size from 
SHT_PROGBITS section with index 3
+# BADSIZE: warning: '[[FILE]]': could not extract a valid stack size from 
SHT_PROGBITS section with index 2: unable to decode LEB128 at offset 
0x0008: malformed uleb128, extends past end
+# BADSIZE: warning: '[[FILE]]': could not extract a valid stack size from 
SHT_PROGBITS section with index 3: unable to decode LEB128 at offset 
0x0008: malformed uleb128, extends past end
 
 --- !ELF
 FileHeader:

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp 
b/llvm/tools/llvm-readobj/ELFDumper.cpp
index fe2aad166250..8fbef39c5a25 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -759,7 +759,7 @@ template  class DumpStyle {
   virtual void printStackSizes() = 0;
   void printNonRelocatableStackSizes(std::function PrintHeader);
   void printRelocatableStackSizes(std::function PrintHeader);
-  void printFunctionStackSize(uint64_t SymValue,
+  bool printFunctionStackSize(uint64_t SymValue,
   Optional FunctionSec,
   const Elf_Shdr &StackSizeSec, DataExtractor Data,
   uint64_t *Offset);
@@ -5833,7 +5833,7 @@ template  void 
GNUStyle::printDependentLibs() {
 }
 
 template 
-void DumpStyle::printFunctionStackSize(
+bool DumpStyle::printFunctionStackSize(
 uint64_t SymValue, Optional FunctionSec,
 const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) {
   uint32_t FuncSymIndex = 0;
@@ -5893,16 +5893,16 @@ void DumpStyle::printFunctionStackSize(
 
   // Extract the size. The expectation is that Offset is pointing to the right
   // place, i.e. past the function address.
-  uint64_t PrevOffset = *Offset;
-  uint64_t StackSize = Data.getULEB128(Offset);
-  // getULEB128() does not advance Offset if it is not able to extract a valid
-  // integer.
-  if (*Offset == PrevOffset) {
+  Error Err = Error::success();
+  uint64_t StackSize = Data.getULEB128(Offset, &Err);
+  if (Err) {
 reportUniqueWarning("could not extract a valid stack size from " +
-describe(Obj, StackSizeSec));
-return;
+describe(Obj, StackSizeSec) + ": " +
+toString(std::move(Err)));
+return false;
   }
   printStackSizeEntry(StackSize, FuncName);
+  return true;
 }
 
 template 
@@ -5991,8 +5991,9 @@ void DumpStyle::printNonRelocatableStackSizes(
 break;
   }
   uint64_t SymValue = Data.getAddress(&Offset);
-  printFunctionStackSize(SymValue, /*FunctionSec=*/None, Sec, Data,
- &Offset);
+  if (!printFunctionStackSize(SymValue, /*FunctionSec=*/None, Sec, Data,
+  &Offset))
+break;
 }
   }
 }



___
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] 893c84d - [obj2yaml] - Dump the content of a broken hash table properly.

2020-12-25 Thread Georgii Rymar via llvm-branch-commits

Author: Georgii Rymar
Date: 2020-12-25T11:51:28+03:00
New Revision: 893c84d71c4ad223ae495d66a0c733a91c72e7bf

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

LOG: [obj2yaml] - Dump the content of a broken hash table properly.

This is similar to D93760.

When something is wrong with the hash table header we dump
its context as a raw data.

Currently we have the calculation overflow issue and it is possible to
bypass the validation we have (and crash).

The patch fixes it.

Differential revision: https://reviews.llvm.org/D93799

Added: 


Modified: 
llvm/test/tools/obj2yaml/ELF/hash-section.yaml
llvm/tools/obj2yaml/elf2yaml.cpp

Removed: 




diff  --git a/llvm/test/tools/obj2yaml/ELF/hash-section.yaml 
b/llvm/test/tools/obj2yaml/ELF/hash-section.yaml
index 389b4bbb6972..57d823b3a0be 100644
--- a/llvm/test/tools/obj2yaml/ELF/hash-section.yaml
+++ b/llvm/test/tools/obj2yaml/ELF/hash-section.yaml
@@ -49,6 +49,13 @@ Sections:
 # CONTENT-NEXT: - Name:.oversized
 # CONTENT-NEXT:   Type:SHT_HASH
 # CONTENT-NEXT:   Content: '01000200030004'
+# CONTENT-NEXT: - Name:.overflow1
+# CONTENT-NEXT:   Type:SHT_HASH
+# CONTENT-NEXT:   Content: 0100{{$}}
+# CONTENT-NEXT: - Name:.overflow2
+# CONTENT-NEXT:   Type:SHT_HASH
+# CONTENT-NEXT:   Content: 0100{{$}}
+# CONTENT-NEXT: ...
 
 --- !ELF
 FileHeader:
@@ -74,6 +81,20 @@ Sections:
   - Name:.oversized
 Type:SHT_HASH
 Content: '01000200030004'
+## Case 5, 6: NChain/NBucket are incorrect and causing 32-bit
+##unsigned overflows of intermediate expressions.
+  - Name:.overflow1
+Type:SHT_HASH
+Bucket:  [ ]
+Chain:   [ ]
+NBucket: 0x1
+NChain:  0x
+  - Name:.overflow2
+Type:SHT_HASH
+Bucket:  [ ]
+Chain:   [ ]
+NBucket: 0x
+NChain:  0x1
 
 ## Check how we dump the "EntSize" field. When the sh_entsize is 4,
 ## we don't print it, because it is the default value for the SHT_HASH section.

diff  --git a/llvm/tools/obj2yaml/elf2yaml.cpp 
b/llvm/tools/obj2yaml/elf2yaml.cpp
index 50c3e90eb667..da32eaba5a69 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -1224,8 +1224,8 @@ ELFDumper::dumpHashSection(const Elf_Shdr *Shdr) {
 
   DataExtractor::Cursor Cur(0);
   DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0);
-  uint32_t NBucket = Data.getU32(Cur);
-  uint32_t NChain = Data.getU32(Cur);
+  uint64_t NBucket = Data.getU32(Cur);
+  uint64_t NChain = Data.getU32(Cur);
   if (Content.size() != (2 + NBucket + NChain) * 4) {
 S->Content = yaml::BinaryRef(Content);
 if (Cur)



___
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] [flang] a2ca6bb - [Flang][OpenMP] Add semantic check for OpenMP Private, Firstprivate and Lastprivate clauses.

2020-12-25 Thread via llvm-branch-commits

Author: Praveen
Date: 2020-12-25T14:43:41+05:30
New Revision: a2ca6bbda6160c1b474fffd6204bcac9456c7eb1

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

LOG: [Flang][OpenMP] Add semantic check for OpenMP Private, Firstprivate and 
Lastprivate clauses.

OpenMP 4.5 - Variables that appear in expressions for statement function 
definitions
 may not appear in OpenMP Private, Firstprivate or Lastprivate 
clauses.

Test case : omp-private03.f90

Reviewed By: kiranchandramohan

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

Added: 
flang/test/Semantics/omp-private03.f90

Modified: 
flang/lib/Semantics/resolve-directives.cpp

Removed: 




diff  --git a/flang/lib/Semantics/resolve-directives.cpp 
b/flang/lib/Semantics/resolve-directives.cpp
index a4297ab42540..e10d797d0308 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -232,6 +232,18 @@ class OmpAttributeVisitor : 
DirectiveAttributeVisitor {
 return true;
   }
 
+  bool Pre(const parser::StmtFunctionStmt &x) {
+const auto &parsedExpr{std::get>(x.t)};
+if (const auto *expr{GetExpr(parsedExpr)}) {
+  for (const Symbol &symbol : evaluate::CollectSymbols(*expr)) {
+if (!IsStmtFunctionDummy(symbol)) {
+  stmtFunctionExprSymbols_.insert(symbol.GetUltimate());
+}
+  }
+}
+return true;
+  }
+
   bool Pre(const parser::OpenMPBlockConstruct &);
   void Post(const parser::OpenMPBlockConstruct &);
 
@@ -342,6 +354,7 @@ class OmpAttributeVisitor : 
DirectiveAttributeVisitor {
 
   std::vector allocateNames_; // on one directive
   SymbolSet privateDataSharingAttributeObjects_; // on one directive
+  SymbolSet stmtFunctionExprSymbols_;
 
   void AddAllocateName(const parser::Name *&object) {
 allocateNames_.push_back(object);
@@ -377,7 +390,7 @@ class OmpAttributeVisitor : 
DirectiveAttributeVisitor {
   const parser::Name &, const Symbol &, Symbol::Flag);
 
   void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause 
*clause);
-  void CheckObjectInNamelist(
+  void CheckPrivateDSAObject(
   const parser::Name &, const Symbol &, Symbol::Flag);
 };
 
@@ -1163,7 +1176,7 @@ void OmpAttributeVisitor::ResolveOmpObject(
 CheckMultipleAppearances(*name, *symbol, ompFlag);
   }
   if (privateDataSharingAttributeFlags.test(ompFlag)) {
-CheckObjectInNamelist(*name, *symbol, ompFlag);
+CheckPrivateDSAObject(*name, *symbol, ompFlag);
   }
 
   if (ompFlag == Symbol::Flag::OmpAllocate) {
@@ -1317,18 +1330,28 @@ void OmpAttributeVisitor::CheckDataCopyingClause(
   }
 }
 
-void OmpAttributeVisitor::CheckObjectInNamelist(
+void OmpAttributeVisitor::CheckPrivateDSAObject(
 const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
-  if (symbol.GetUltimate().test(Symbol::Flag::InNamelist)) {
-llvm::StringRef clauseName{"PRIVATE"};
-if (ompFlag == Symbol::Flag::OmpFirstPrivate)
-  clauseName = "FIRSTPRIVATE";
-else if (ompFlag == Symbol::Flag::OmpLastPrivate)
-  clauseName = "LASTPRIVATE";
+  const auto &ultimateSymbol{symbol.GetUltimate()};
+  llvm::StringRef clauseName{"PRIVATE"};
+  if (ompFlag == Symbol::Flag::OmpFirstPrivate)
+clauseName = "FIRSTPRIVATE";
+  else if (ompFlag == Symbol::Flag::OmpLastPrivate)
+clauseName = "LASTPRIVATE";
+
+  if (ultimateSymbol.test(Symbol::Flag::InNamelist)) {
 context_.Say(name.source,
 "Variable '%s' in NAMELIST cannot be in a %s clause"_err_en_US,
 name.ToString(), clauseName.str());
   }
+
+  if (stmtFunctionExprSymbols_.find(ultimateSymbol) !=
+  stmtFunctionExprSymbols_.end()) {
+context_.Say(name.source,
+"Variable '%s' in STATEMENT FUNCTION expression cannot be in a "
+"%s clause"_err_en_US,
+name.ToString(), clauseName.str());
+  }
 }
 
 } // namespace Fortran::semantics

diff  --git a/flang/test/Semantics/omp-private03.f90 
b/flang/test/Semantics/omp-private03.f90
new file mode 100644
index ..50748f5508ed
--- /dev/null
+++ b/flang/test/Semantics/omp-private03.f90
@@ -0,0 +1,39 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! Variables that appear in expressions for statement function definitions
+! may not appear in private, firstprivate or lastprivate clauses.
+
+subroutine stmt_function(temp)
+
+  integer :: i, p, q, r
+  real :: c, f, s, v, t(10)
+  real, intent(in) :: temp
+
+  c(temp) = p * (temp - q) / r
+  f(temp) = q + (temp * r/p)
+  v(temp) = c(temp) + f(temp)/2 - s
+
+  p = 5
+  q = 32
+  r = 9
+
+  !ERROR: Variable 'p' in STATEMENT FUNCTION expression cannot be in a PRIVATE 
clause
+  !$omp parallel

[llvm-branch-commits] [mlir] 621ad46 - [mlir] Async: lowering async.value to LLVM

2020-12-25 Thread Eugene Zhulenev via llvm-branch-commits

Author: Eugene Zhulenev
Date: 2020-12-25T02:23:48-08:00
New Revision: 621ad468d99d4013a4298465f02707a5e9e89cae

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

LOG: [mlir] Async: lowering async.value to LLVM

1. Add new methods to Async runtime API to support yielding async values
2. Add lowering from `async.yield` with value payload to the new runtime API 
calls

`async.value` lowering requires that payload type is convertible to LLVM and 
supported by `llvm.mlir.cast` (DialectCast) operation.

Reviewed By: csigg

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

Added: 
mlir/test/mlir-cpu-runner/async-value.mlir

Modified: 
mlir/include/mlir/ExecutionEngine/AsyncRuntime.h
mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
mlir/lib/Conversion/AsyncToLLVM/CMakeLists.txt
mlir/lib/ExecutionEngine/AsyncRuntime.cpp
mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir

Removed: 




diff  --git a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h 
b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h
index e3d90198f36c..0fe44cd1c127 100644
--- a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h
+++ b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h
@@ -45,6 +45,12 @@ typedef struct AsyncToken AsyncToken;
 // Runtime implementation of `async.group` data type.
 typedef struct AsyncGroup AsyncGroup;
 
+// Runtime implementation of `async.value` data type.
+typedef struct AsyncValue AsyncValue;
+
+// Async value payload stored in a memory owned by the async.value.
+using ValueStorage = void *;
+
 // Async runtime uses LLVM coroutines to represent asynchronous tasks. Task
 // function is a coroutine handle and a resume function that continue coroutine
 // execution from a suspension point.
@@ -66,6 +72,13 @@ extern "C" MLIR_ASYNCRUNTIME_EXPORT void
 // Create a new `async.token` in not-ready state.
 extern "C" MLIR_ASYNCRUNTIME_EXPORT AsyncToken *mlirAsyncRuntimeCreateToken();
 
+// Create a new `async.value` in not-ready state. Size parameter specifies the
+// number of bytes that will be allocated for the async value storage. Storage
+// is owned by the `async.value` and deallocated when the async value is
+// destructed (reference count drops to zero).
+extern "C" MLIR_ASYNCRUNTIME_EXPORT AsyncValue *
+mlirAsyncRuntimeCreateValue(int32_t);
+
 // Create a new `async.group` in empty state.
 extern "C" MLIR_ASYNCRUNTIME_EXPORT AsyncGroup *mlirAsyncRuntimeCreateGroup();
 
@@ -76,14 +89,26 @@ mlirAsyncRuntimeAddTokenToGroup(AsyncToken *, AsyncGroup *);
 extern "C" MLIR_ASYNCRUNTIME_EXPORT void
 mlirAsyncRuntimeEmplaceToken(AsyncToken *);
 
+// Switches `async.value` to ready state and runs all awaiters.
+extern "C" MLIR_ASYNCRUNTIME_EXPORT void
+mlirAsyncRuntimeEmplaceValue(AsyncValue *);
+
 // Blocks the caller thread until the token becomes ready.
 extern "C" MLIR_ASYNCRUNTIME_EXPORT void
 mlirAsyncRuntimeAwaitToken(AsyncToken *);
 
+// Blocks the caller thread until the value becomes ready.
+extern "C" MLIR_ASYNCRUNTIME_EXPORT void
+mlirAsyncRuntimeAwaitValue(AsyncValue *);
+
 // Blocks the caller thread until the elements in the group become ready.
 extern "C" MLIR_ASYNCRUNTIME_EXPORT void
 mlirAsyncRuntimeAwaitAllInGroup(AsyncGroup *);
 
+// Returns a pointer to the storage owned by the async value.
+extern "C" MLIR_ASYNCRUNTIME_EXPORT ValueStorage
+mlirAsyncRuntimeGetValueStorage(AsyncValue *);
+
 // Executes the task (coro handle + resume function) in one of the threads
 // managed by the runtime.
 extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeExecute(CoroHandle,
@@ -94,6 +119,11 @@ extern "C" MLIR_ASYNCRUNTIME_EXPORT void 
mlirAsyncRuntimeExecute(CoroHandle,
 extern "C" MLIR_ASYNCRUNTIME_EXPORT void
 mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *, CoroHandle, CoroResume);
 
+// Executes the task (coro handle + resume function) in one of the threads
+// managed by the runtime after the value becomes ready.
+extern "C" MLIR_ASYNCRUNTIME_EXPORT void
+mlirAsyncRuntimeAwaitValueAndExecute(AsyncValue *, CoroHandle, CoroResume);
+
 // Executes the task (coro handle + resume function) in one of the threads
 // managed by the runtime after the all members of the group become ready.
 extern "C" MLIR_ASYNCRUNTIME_EXPORT void

diff  --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp 
b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
index 3daa70b0a952..f1d6264606be 100644
--- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
+++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
@@ -9,9 +9,11 @@
 #include "mlir/Conversion/AsyncToLLVM/AsyncToLLVM.h"
 
 #include "../PassDetail.h"
+#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
 #include "mlir/Dialect/Async/IR/Async.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Dialect/Sta

[llvm-branch-commits] [mlir] 61422c8 - [mlir] Async: add support for lowering async value operands to LLVM

2020-12-25 Thread Eugene Zhulenev via llvm-branch-commits

Author: Eugene Zhulenev
Date: 2020-12-25T02:25:20-08:00
New Revision: 61422c8b661c506b25b5ac705cdbb2265af120d1

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

LOG: [mlir] Async: add support for lowering async value operands to LLVM

Depends On D93592

Add support for `async.execute` async value unwrapping operands:

```
%token = async.execute(%async_value as %unwrapped : !async.value) {
  ...
  async.yield
}
```

Reviewed By: csigg

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

Added: 


Modified: 
mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir
mlir/test/mlir-cpu-runner/async-value.mlir

Removed: 




diff  --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp 
b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
index f1d6264606be..517c8d2c6f56 100644
--- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
+++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
@@ -586,7 +586,7 @@ outlineExecuteOp(SymbolTable &symbolTable, ExecuteOp 
execute) {
   // Collect all outlined function inputs.
   llvm::SetVector functionInputs(execute.dependencies().begin(),
   execute.dependencies().end());
-  assert(execute.operands().empty() && "operands are not supported");
+  functionInputs.insert(execute.operands().begin(), execute.operands().end());
   getUsedValuesDefinedAbove(execute.body(), functionInputs);
 
   // Collect types for the outlined function inputs and outputs.
@@ -636,15 +636,26 @@ outlineExecuteOp(SymbolTable &symbolTable, ExecuteOp 
execute) {
   addSuspensionPoint(coro, coroSave.getResult(0), terminatorOp, suspended,
  resume, builder);
 
+  size_t numDependencies = execute.dependencies().size();
+  size_t numOperands = execute.operands().size();
+
   // Await on all dependencies before starting to execute the body region.
   builder.setInsertionPointToStart(resume);
-  for (size_t i = 0; i < execute.dependencies().size(); ++i)
+  for (size_t i = 0; i < numDependencies; ++i)
 builder.create(func.getArgument(i));
 
+  // Await on all async value operands and unwrap the payload.
+  SmallVector unwrappedOperands(numOperands);
+  for (size_t i = 0; i < numOperands; ++i) {
+Value operand = func.getArgument(numDependencies + i);
+unwrappedOperands[i] = builder.create(loc, operand).result();
+  }
+
   // Map from function inputs defined above the execute op to the function
   // arguments.
   BlockAndValueMapping valueMapping;
   valueMapping.map(functionInputs, func.getArguments());
+  valueMapping.map(execute.body().getArguments(), unwrappedOperands);
 
   // Clone all operations from the execute operation body into the outlined
   // function body.
@@ -1069,14 +1080,6 @@ void ConvertAsyncToLLVMPass::runOnOperation() {
   return WalkResult::interrupt();
 }
 
-// We currently do not support execute operations that have async value
-// operands or produce async results.
-if (!execute.operands().empty()) {
-  execute.emitOpError(
-  "can't outline async.execute op with async value operands");
-  return WalkResult::interrupt();
-}
-
 outlinedFunctions.insert(outlineExecuteOp(symbolTable, execute));
 
 return WalkResult::advance();

diff  --git a/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir 
b/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir
index dce0cf89628f..75b323490cbb 100644
--- a/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir
+++ b/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir
@@ -252,3 +252,54 @@ func @execute_and_return_f32() -> f32 {
 // Emplace result token.
 // CHECK: call @mlirAsyncRuntimeEmplaceToken(%[[TOKEN]])
 
+// -
+
+// RUN: mlir-opt %s -split-input-file -convert-async-to-llvm | FileCheck %s
+
+func @async_value_operands() {
+  // CHECK: %[[RET:.*]]:2 = call @async_execute_fn
+  %token, %result = async.execute -> !async.value {
+%c0 = constant 123.0 : f32
+async.yield %c0 : f32
+  }
+
+  // CHECK: %[[TOKEN:.*]] = call @async_execute_fn_0(%[[RET]]#1)
+  %token0 = async.execute(%result as %value: !async.value) {
+%0 = addf %value, %value : f32
+async.yield
+  }
+
+  // CHECK: call @mlirAsyncRuntimeAwaitToken(%[[TOKEN]])
+  async.await %token0 : !async.token
+
+  return
+}
+
+// Function outlined from the first async.execute operation.
+// CHECK-LABEL: func private @async_execute_fn()
+
+// Function outlined from the second async.execute operation.
+// CHECK-LABEL: func private @async_execute_fn_0(%arg0: !llvm.ptr)
+// CHECK: %[[TOKEN:.*]] = call @mlirAsyncRuntimeCreateToken()
+// CHECK: %[[HDL:.*]] = llvm.call @llvm.coro.begin
+
+// Suspend coroutine in the beginning.
+// CHECK: call @mlirAsyncRuntimeExecute(%[[HDL]],
+// CHEC

[llvm-branch-commits] [llvm] b96a6ea - [BasicAA] Make sure context instruction is symmetric

2020-12-25 Thread Nikita Popov via llvm-branch-commits

Author: Nikita Popov
Date: 2020-12-25T11:35:46+01:00
New Revision: b96a6ea0a94e45ede46f534c6b5319f4ffb9d986

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

LOG: [BasicAA] Make sure context instruction is symmetric

D71264 started using a context instruction in a computeKnownBits()
call. However, if aliasing between two GEPs is checked, then the
choice of context instruction will be different for alias(GEP1, GEP2)
and alias(GEP2, GEP1), which is not supposed to happen.

Resolve this by remembering which GEP a certain VarIndex belongs to,
and use that as the context instruction. This makes the choice of
context instruction predictable and symmetric.

It should be noted that this choice of context instruction is
non-optimal (just like the previous choice): The AA query result is
only valid at points that are reachable from *both* instructions.
Using either one of them is conservatively correct, but a larger
context may also be valid to use.

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

Added: 


Modified: 
llvm/include/llvm/Analysis/BasicAliasAnalysis.h
llvm/lib/Analysis/BasicAliasAnalysis.cpp
llvm/test/Analysis/BasicAA/assume-index-positive.ll

Removed: 




diff  --git a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h 
b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
index 6eb37c1c4b07..cffe9ed3c738 100644
--- a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -117,6 +117,9 @@ class BasicAAResult : public AAResultBase {
 
 APInt Scale;
 
+// Context instruction to use when querying information about this index.
+const Instruction *CxtI;
+
 bool operator==(const VariableGEPIndex &Other) const {
   return V == Other.V && ZExtBits == Other.ZExtBits &&
  SExtBits == Other.SExtBits && Scale == Other.Scale;

diff  --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp 
b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index caa0635459b3..4a30e075af0a 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -422,6 +422,7 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const 
DataLayout &DL,
   // Limit recursion depth to limit compile time in crazy cases.
   unsigned MaxLookup = MaxLookupSearchDepth;
   SearchTimes++;
+  const Instruction *CxtI = dyn_cast(V);
 
   unsigned MaxPointerSize = getMaxPointerSize(DL);
   DecomposedGEP Decomposed;
@@ -584,7 +585,7 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const 
DataLayout &DL,
   Scale = adjustToPointerSize(Scale, PointerSize);
 
   if (!!Scale) {
-VariableGEPIndex Entry = {Index, ZExtBits, SExtBits, Scale};
+VariableGEPIndex Entry = {Index, ZExtBits, SExtBits, Scale, CxtI};
 Decomposed.VarIndices.push_back(Entry);
   }
 }
@@ -1225,9 +1226,9 @@ AliasResult BasicAAResult::aliasGEP(
 // the Value this cycle may not hold in the next cycle. We'll just
 // give up if we can't determine conditions that hold for every cycle:
 const Value *V = DecompGEP1.VarIndices[i].V;
+const Instruction *CxtI = DecompGEP1.VarIndices[i].CxtI;
 
-KnownBits Known =
-computeKnownBits(V, DL, 0, &AC, dyn_cast(GEP1), DT);
+KnownBits Known = computeKnownBits(V, DL, 0, &AC, CxtI, DT);
 bool SignKnownZero = Known.isNonNegative();
 bool SignKnownOne = Known.isNegative();
 
@@ -1755,7 +1756,7 @@ void BasicAAResult::GetIndexDifference(
 
 // If we didn't consume this entry, add it to the end of the Dest list.
 if (!!Scale) {
-  VariableGEPIndex Entry = {V, ZExtBits, SExtBits, -Scale};
+  VariableGEPIndex Entry = {V, ZExtBits, SExtBits, -Scale, Src[i].CxtI};
   Dest.push_back(Entry);
 }
   }

diff  --git a/llvm/test/Analysis/BasicAA/assume-index-positive.ll 
b/llvm/test/Analysis/BasicAA/assume-index-positive.ll
index e8a039a1018e..54eb34a2cdb9 100644
--- a/llvm/test/Analysis/BasicAA/assume-index-positive.ll
+++ b/llvm/test/Analysis/BasicAA/assume-index-positive.ll
@@ -113,4 +113,20 @@ define void @test4(double* %ptr, i32 %skip) {
   ret void
 }
 
+define void @symmetry([0 x i8]* %ptr, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: Function: symmetry
+; CHECK: NoAlias: i8* %gep1, i8* %gep2
+;
+  %b.cmp = icmp slt i32 %b, 0
+  call void @llvm.assume(i1 %b.cmp)
+  %gep1 = getelementptr [0 x i8], [0 x i8]* %ptr, i32 %a, i32 %b
+  call void @barrier()
+  %c.cmp = icmp sgt i32 %c, -1
+  call void @llvm.assume(i1 %c.cmp)
+  %c.off = add nuw nsw i32 %c, 1
+  %gep2 = getelementptr [0 x i8], [0 x i8]* %ptr, i32 %a, i32 %c.off
+  ret void
+}
+
 declare void @llvm.assume(i1 %cond)
+declare void @barrier()



___
llvm-branch-commits mailing 

[llvm-branch-commits] [llvm] a3614a3 - [BasicAA] Pass context instruction to isKnownNonZero()

2020-12-25 Thread Nikita Popov via llvm-branch-commits

Author: Nikita Popov
Date: 2020-12-25T12:58:19+01:00
New Revision: a3614a31c46a41b76fd6a6c6b30b353bc4131b94

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

LOG: [BasicAA] Pass context instruction to isKnownNonZero()

This allows us to handle additional cases like assumes.

Added: 


Modified: 
llvm/lib/Analysis/BasicAliasAnalysis.cpp
llvm/test/Analysis/BasicAA/sequential-gep.ll

Removed: 




diff  --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp 
b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 4a30e075af0a..2dca64447fde 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1280,7 +1280,7 @@ AliasResult BasicAAResult::aliasGEP(
   if (DecompGEP1.VarIndices.size() == 1) {
 // VarIndex = Scale*V. If V != 0 then abs(VarIndex) >= abs(Scale).
 const VariableGEPIndex &Var = DecompGEP1.VarIndices[0];
-if (isKnownNonZero(Var.V, DL))
+if (isKnownNonZero(Var.V, DL, 0, &AC, Var.CxtI, DT))
   MinAbsVarIndex = Var.Scale.abs();
   } else if (DecompGEP1.VarIndices.size() == 2) {
 // VarIndex = Scale*V0 + (-Scale)*V1.

diff  --git a/llvm/test/Analysis/BasicAA/sequential-gep.ll 
b/llvm/test/Analysis/BasicAA/sequential-gep.ll
index b6e84fa97138..e5b744ba6bf8 100644
--- a/llvm/test/Analysis/BasicAA/sequential-gep.ll
+++ b/llvm/test/Analysis/BasicAA/sequential-gep.ll
@@ -135,4 +135,15 @@ define void @non_zero_index_with_offset(i32* %p, i32* %q) {
   ret void
 }
 
+; CHECK-LABEL: non_zero_index_assume
+; CHECK: NoAlias: i32* %gep, i32* %p
+define void @non_zero_index_assume(i32* %p, i32 %knownnonzero) {
+  %cmp = icmp ne i32 %knownnonzero, 0
+  call void @llvm.assume(i1 %cmp)
+  %gep = getelementptr i32, i32* %p, i32 %knownnonzero
+  ret void
+}
+
+declare void @llvm.assume(i1)
+
 !0 = !{ i32 1, i32 5 }



___
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] b0e6007 - [InstCombine] Add additional tests for known non zero (NFC)

2020-12-25 Thread Nikita Popov via llvm-branch-commits

Author: Nikita Popov
Date: 2020-12-25T16:28:30+01:00
New Revision: b0e6007c8254811a5828c1a253a615e45359c653

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

LOG: [InstCombine] Add additional tests for known non zero (NFC)

Check conditions that imply non-zero, even if they are not literally
"x != 0".

Using ctlz for testing, as explicit comparison might get folded by
other reasoning.

Added: 


Modified: 
llvm/test/Transforms/InstCombine/known-non-zero.ll

Removed: 




diff  --git a/llvm/test/Transforms/InstCombine/known-non-zero.ll 
b/llvm/test/Transforms/InstCombine/known-non-zero.ll
index 5467db556632..e2049b22690d 100644
--- a/llvm/test/Transforms/InstCombine/known-non-zero.ll
+++ b/llvm/test/Transforms/InstCombine/known-non-zero.ll
@@ -13,7 +13,7 @@ define i32 @test0(i64 %x) {
 ; CHECK-NEXT:[[C:%.*]] = icmp eq i64 [[X:%.*]], 0
 ; CHECK-NEXT:br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
 ; CHECK:   non_zero:
-; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.cttz.i64(i64 [[X]], i1 true), 
!range !0
+; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.cttz.i64(i64 [[X]], i1 true), 
[[RNG0:!range !.*]]
 ; CHECK-NEXT:[[CTZ32:%.*]] = trunc i64 [[CTZ]] to i32
 ; CHECK-NEXT:br label [[EXIT]]
 ; CHECK:   exit:
@@ -40,7 +40,7 @@ define i32 @test1(i64 %x) {
 ; CHECK-NEXT:[[C:%.*]] = icmp eq i64 [[X:%.*]], 0
 ; CHECK-NEXT:br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
 ; CHECK:   non_zero:
-; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 true), 
!range !0
+; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 true), 
[[RNG0]]
 ; CHECK-NEXT:[[CTZ32:%.*]] = trunc i64 [[CTZ]] to i32
 ; CHECK-NEXT:br label [[EXIT]]
 ; CHECK:   exit:
@@ -93,8 +93,8 @@ exit:
 }
 
 ; Test that exposed a bug in the PHI handling after D60846. No folding should 
happen here!
-define void @D60846_misompile(i1* %p) {
-; CHECK-LABEL: @D60846_misompile(
+define void @D60846_miscompile(i1* %p) {
+; CHECK-LABEL: @D60846_miscompile(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:br label [[LOOP:%.*]]
 ; CHECK:   loop:
@@ -133,3 +133,95 @@ common:   ; preds 
= %non_zero, %loop
 exit: ; preds = %common
   ret void
 }
+
+define i64 @test_sgt_zero(i64 %x) {
+; CHECK-LABEL: @test_sgt_zero(
+; CHECK-NEXT:  start:
+; CHECK-NEXT:[[C:%.*]] = icmp sgt i64 [[X:%.*]], 0
+; CHECK-NEXT:br i1 [[C]], label [[NON_ZERO:%.*]], label [[EXIT:%.*]]
+; CHECK:   non_zero:
+; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 false), 
[[RNG0]]
+; CHECK-NEXT:ret i64 [[CTZ]]
+; CHECK:   exit:
+; CHECK-NEXT:ret i64 -1
+;
+start:
+  %c = icmp sgt i64 %x, 0
+  br i1 %c, label %non_zero, label %exit
+
+non_zero:
+  %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+  ret i64 %ctz
+
+exit:
+  ret i64 -1
+}
+
+define i64 @test_slt_neg_ten(i64 %x) {
+; CHECK-LABEL: @test_slt_neg_ten(
+; CHECK-NEXT:  start:
+; CHECK-NEXT:[[C:%.*]] = icmp slt i64 [[X:%.*]], -10
+; CHECK-NEXT:br i1 [[C]], label [[NON_ZERO:%.*]], label [[EXIT:%.*]]
+; CHECK:   non_zero:
+; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 false), 
[[RNG0]]
+; CHECK-NEXT:ret i64 [[CTZ]]
+; CHECK:   exit:
+; CHECK-NEXT:ret i64 -1
+;
+start:
+  %c = icmp slt i64 %x, -10
+  br i1 %c, label %non_zero, label %exit
+
+non_zero:
+  %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+  ret i64 %ctz
+
+exit:
+  ret i64 -1
+}
+
+define i64 @test_slt_ten(i64 %x) {
+; CHECK-LABEL: @test_slt_ten(
+; CHECK-NEXT:  start:
+; CHECK-NEXT:[[C:%.*]] = icmp slt i64 [[X:%.*]], 10
+; CHECK-NEXT:br i1 [[C]], label [[MAYBE_ZERO:%.*]], label [[EXIT:%.*]]
+; CHECK:   maybe_zero:
+; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 false), 
[[RNG0]]
+; CHECK-NEXT:ret i64 [[CTZ]]
+; CHECK:   exit:
+; CHECK-NEXT:ret i64 -1
+;
+start:
+  %c = icmp slt i64 %x, 10
+  br i1 %c, label %maybe_zero, label %exit
+
+maybe_zero:
+  %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+  ret i64 %ctz
+
+exit:
+  ret i64 -1
+}
+
+define i64 @test_ugt_unknown(i64 %x, i64 %y) {
+; CHECK-LABEL: @test_ugt_unknown(
+; CHECK-NEXT:  start:
+; CHECK-NEXT:[[C:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:br i1 [[C]], label [[NON_ZERO:%.*]], label [[EXIT:%.*]]
+; CHECK:   non_zero:
+; CHECK-NEXT:[[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 false), 
[[RNG0]]
+; CHECK-NEXT:ret i64 [[CTZ]]
+; CHECK:   exit:
+; CHECK-NEXT:ret i64 -1
+;
+start:
+  %c = icmp ugt i64 %x, %y
+  br i1 %c, label %non_zero, label %exit
+
+non_zero:
+  %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+  ret i64 %ctz
+
+exit:
+  ret i64 -

[llvm-branch-commits] [llvm] 35676a4 - [InstCombine] Generalize icmp handling in isKnownNonZero()

2020-12-25 Thread Nikita Popov via llvm-branch-commits

Author: Nikita Popov
Date: 2020-12-25T16:49:23+01:00
New Revision: 35676a4f9a536a2aab768af63ddbb15bc722d7f9

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

LOG: [InstCombine] Generalize icmp handling in isKnownNonZero()

The dominating condition handling in isKnownNonZero() currently
only takes into account conditions of the form "x != 0" or "x == 0".
However, there are plenty of other conditions that imply non-zero,
a common one being "x s> 0".

Peculiarly, the handling for assumes was already dealing with more
general non-zero-ness conditions, so this just reuses the same
logic for the dominating condition case.

Added: 


Modified: 
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Transforms/Attributor/nonnull.ll
llvm/test/Transforms/InstCombine/known-non-zero.ll

Removed: 




diff  --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index eeb505868703..fdbb7f49cf18 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -590,41 +590,30 @@ bool llvm::isValidAssumeForContext(const Instruction *Inv,
   return false;
 }
 
+static bool cmpExcludesZero(CmpInst::Predicate Pred, const Value *RHS) {
+  // v u> y implies v != 0.
+  if (Pred == ICmpInst::ICMP_UGT)
+return true;
+
+  // Special-case v != 0 to also handle v != null.
+  if (Pred == ICmpInst::ICMP_NE)
+return match(RHS, m_Zero());
+
+  // All other predicates - rely on generic ConstantRange handling.
+  const APInt *C;
+  if (!match(RHS, m_APInt(C)))
+return false;
+
+  ConstantRange TrueValues = ConstantRange::makeExactICmpRegion(Pred, *C);
+  return !TrueValues.contains(APInt::getNullValue(C->getBitWidth()));
+}
+
 static bool isKnownNonZeroFromAssume(const Value *V, const Query &Q) {
   // Use of assumptions is context-sensitive. If we don't have a context, we
   // cannot use them!
   if (!Q.AC || !Q.CxtI)
 return false;
 
-  // Note that the patterns below need to be kept in sync with the code
-  // in AssumptionCache::updateAffectedValues.
-
-  auto CmpExcludesZero = [V](ICmpInst *Cmp) {
-auto m_V = m_CombineOr(m_Specific(V), m_PtrToInt(m_Specific(V)));
-
-Value *RHS;
-CmpInst::Predicate Pred;
-if (!match(Cmp, m_c_ICmp(Pred, m_V, m_Value(RHS
-  return false;
-// assume(v u> y) -> assume(v != 0)
-if (Pred == ICmpInst::ICMP_UGT)
-  return true;
-
-// assume(v != 0)
-// We special-case this one to ensure that we handle `assume(v != null)`.
-if (Pred == ICmpInst::ICMP_NE)
-  return match(RHS, m_Zero());
-
-// All other predicates - rely on generic ConstantRange handling.
-ConstantInt *CI;
-if (!match(RHS, m_ConstantInt(CI)))
-  return false;
-ConstantRange RHSRange(CI->getValue());
-ConstantRange TrueValues =
-ConstantRange::makeAllowedICmpRegion(Pred, RHSRange);
-return !TrueValues.contains(APInt::getNullValue(CI->getBitWidth()));
-  };
-
   if (Q.CxtI && V->getType()->isPointerTy()) {
 SmallVector AttrKinds{Attribute::NonNull};
 if (!NullPointerIsDefined(Q.CxtI->getFunction(),
@@ -651,12 +640,13 @@ static bool isKnownNonZeroFromAssume(const Value *V, 
const Query &Q) {
 assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume &&
"must be an assume intrinsic");
 
-Value *Arg = I->getArgOperand(0);
-ICmpInst *Cmp = dyn_cast(Arg);
-if (!Cmp)
-  continue;
+Value *RHS;
+CmpInst::Predicate Pred;
+auto m_V = m_CombineOr(m_Specific(V), m_PtrToInt(m_Specific(V)));
+if (!match(I->getArgOperand(0), m_c_ICmp(Pred, m_V, m_Value(RHS
+  return false;
 
-if (CmpExcludesZero(Cmp) && isValidAssumeForContext(I, Q.CxtI, Q.DT))
+if (cmpExcludesZero(Pred, RHS) && isValidAssumeForContext(I, Q.CxtI, Q.DT))
   return true;
   }
 
@@ -2113,10 +2103,17 @@ static bool isKnownNonNullFromDominatingCondition(const 
Value *V,
 }
 
 // Consider only compare instructions uniquely controlling a branch
+Value *RHS;
 CmpInst::Predicate Pred;
-if (!match(const_cast(U),
-   m_c_ICmp(Pred, m_Specific(V), m_Zero())) ||
-(Pred != ICmpInst::ICMP_EQ && Pred != ICmpInst::ICMP_NE))
+if (!match(U, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS
+  continue;
+
+bool NonNullIfTrue;
+if (cmpExcludesZero(Pred, RHS))
+  NonNullIfTrue = true;
+else if (Pred == ICmpInst::ICMP_EQ && match(RHS, m_Zero()))
+  NonNullIfTrue = false;
+else
   continue;
 
 SmallVector WorkList;
@@ -2133,7 +2130,7 @@ static bool isKnownNonNullFromDominatingCondition(const 
Value *V,
 // propagate "pred != null" condition through AND because it is only
 // correct to assume that all conditions of AND are met in true branch.
 // TOD

[llvm-branch-commits] [llvm] ea39991 - [llvm-nm, llvm-objdump] Use llvm::is_contained (NFC)

2020-12-25 Thread Kazu Hirata via llvm-branch-commits

Author: Kazu Hirata
Date: 2020-12-25T09:22:37-08:00
New Revision: ea399912514eb0a128821b3edc6da52594656ef1

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

LOG: [llvm-nm, llvm-objdump] Use llvm::is_contained (NFC)

Added: 


Modified: 
llvm/tools/llvm-nm/llvm-nm.cpp
llvm/tools/llvm-objdump/MachODump.cpp

Removed: 




diff  --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index 9680149d4f8c..d9dc1f1b419c 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -1811,9 +1811,7 @@ static bool checkMachOAndArchFlags(SymbolicFile *O, 
std::string &Filename) {
&McpuDefault, &ArchFlag);
   }
   const std::string ArchFlagName(ArchFlag);
-  if (none_of(ArchFlags, [&](const std::string &Name) {
-return Name == ArchFlagName;
-  })) {
+  if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
 error("No architecture specified", Filename);
 return false;
   }
@@ -2115,8 +2113,7 @@ static void dumpSymbolNamesFromFile(std::string 
&Filename) {
 for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
   StringRef ArchName = I.getArchFlagName();
   const bool ShowArch =
-  ArchFlags.empty() ||
-  any_of(ArchFlags, [&](StringRef Name) { return Name == ArchName; });
+  ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName);
   if (!ShowArch)
 continue;
   if (!AddInlinedInfo && !I.isTopLevelLib())

diff  --git a/llvm/tools/llvm-objdump/MachODump.cpp 
b/llvm/tools/llvm-objdump/MachODump.cpp
index b3ec20f97c97..1fa9879c821a 100644
--- a/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/llvm/tools/llvm-objdump/MachODump.cpp
@@ -1889,9 +1889,7 @@ static bool checkMachOAndArchFlags(ObjectFile *O, 
StringRef Filename) {
&McpuDefault, &ArchFlag);
   }
   const std::string ArchFlagName(ArchFlag);
-  if (none_of(ArchFlags, [&](const std::string &Name) {
-return Name == ArchFlagName;
-  })) {
+  if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
 WithColor::error(errs(), "llvm-objdump")
 << Filename << ": no architecture specified.\n";
 return false;



___
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] c795dd1 - [BasicAA] Pass AC/DT to isKnownNonEqual()

2020-12-25 Thread Nikita Popov via llvm-branch-commits

Author: Nikita Popov
Date: 2020-12-25T18:29:20+01:00
New Revision: c795dd19265d80e835ea1137f19f73624d7983e4

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

LOG: [BasicAA] Pass AC/DT to isKnownNonEqual()

This allows us to handle assumes etc in the recursive
isKnownNonZero() checks.

Added: 


Modified: 
llvm/lib/Analysis/BasicAliasAnalysis.cpp
llvm/test/Analysis/BasicAA/sequential-gep.ll

Removed: 




diff  --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp 
b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 2dca64447fde..f9275daf1224 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1291,7 +1291,7 @@ AliasResult BasicAAResult::aliasGEP(
 const VariableGEPIndex &Var1 = DecompGEP1.VarIndices[1];
 if (Var0.Scale == -Var1.Scale && Var0.ZExtBits == Var1.ZExtBits &&
 Var0.SExtBits == Var1.SExtBits && VisitedPhiBBs.empty() &&
-isKnownNonEqual(Var0.V, Var1.V, DL))
+isKnownNonEqual(Var0.V, Var1.V, DL, &AC, /* CxtI */ nullptr, DT))
   MinAbsVarIndex = Var0.Scale.abs();
   }
 

diff  --git a/llvm/test/Analysis/BasicAA/sequential-gep.ll 
b/llvm/test/Analysis/BasicAA/sequential-gep.ll
index e5b744ba6bf8..d7a1af024cec 100644
--- a/llvm/test/Analysis/BasicAA/sequential-gep.ll
+++ b/llvm/test/Analysis/BasicAA/sequential-gep.ll
@@ -110,6 +110,17 @@ define void @add_non_zero_with_offset(i32* %p, i32 
%addend, i32* %q) {
   ret void
 }
 
+; CHECK-LABEL: Function: add_non_zero_assume
+; CHECK: NoAlias: i32* %gep1, i32* %gep2
+define void @add_non_zero_assume(i32* %p, i32 %addend, i32 %knownnonzero) {
+  %cmp = icmp ne i32 %knownnonzero, 0
+  call void @llvm.assume(i1 %cmp)
+  %add = add i32 %addend, %knownnonzero
+  %gep1 = getelementptr i32, i32* %p, i32 %addend
+  %gep2 = getelementptr i32, i32* %p, i32 %add
+  ret void
+}
+
 ; CHECK-LABEL: non_zero_index_simple
 ; CHECK: NoAlias: i32* %gep, i32* %p
 ; CHECK: NoAlias: i16* %gep.16, i32* %p



___
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] 46bea9b - [Local] Remove unused function RemovePredecessorAndSimplify (NFC)

2020-12-25 Thread Kazu Hirata via llvm-branch-commits

Author: Kazu Hirata
Date: 2020-12-25T09:35:20-08:00
New Revision: 46bea9b29714ba77010612b04ba13aff56d62e7b

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

LOG: [Local] Remove unused function RemovePredecessorAndSimplify (NFC)

The last use of the function was removed on Sep 29, 2010 in commit
99c985c37dd45dd0fbd03863037d8e93153783e6.

Added: 


Modified: 
llvm/include/llvm/Transforms/Utils/Local.h
llvm/lib/Transforms/Utils/Local.cpp

Removed: 




diff  --git a/llvm/include/llvm/Transforms/Utils/Local.h 
b/llvm/include/llvm/Transforms/Utils/Local.h
index f62af365a27c..ebfb62a48bbf 100644
--- a/llvm/include/llvm/Transforms/Utils/Local.h
+++ b/llvm/include/llvm/Transforms/Utils/Local.h
@@ -150,20 +150,6 @@ bool replaceDbgUsesWithUndef(Instruction *I);
 //  Control Flow Graph Restructuring.
 //
 
-/// Like BasicBlock::removePredecessor, this method is called when we're about
-/// to delete Pred as a predecessor of BB. If BB contains any PHI nodes, this
-/// drops the entries in the PHI nodes for Pred.
-///
-/// Unlike the removePredecessor method, this attempts to simplify uses of PHI
-/// nodes that collapse into identity values.  For example, if we have:
-///   x = phi(1, 0, 0, 0)
-///   y = and x, z
-///
-/// .. and delete the predecessor corresponding to the '1', this will attempt 
to
-/// recursively fold the 'and' to 0.
-void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
-  DomTreeUpdater *DTU = nullptr);
-
 /// BB is a block with one predecessor and its predecessor is known to have one
 /// successor (BB!). Eliminate the edge between them, moving the instructions 
in
 /// the predecessor into BB. This deletes the predecessor block.

diff  --git a/llvm/lib/Transforms/Utils/Local.cpp 
b/llvm/lib/Transforms/Utils/Local.cpp
index 125431d6afc8..e32b0f142f07 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -704,34 +704,6 @@ bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB,
 //  Control Flow Graph Restructuring.
 //
 
-void llvm::RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
-DomTreeUpdater *DTU) {
-  // This only adjusts blocks with PHI nodes.
-  if (!isa(BB->begin()))
-return;
-
-  // Remove the entries for Pred from the PHI nodes in BB, but do not simplify
-  // them down.  This will leave us with single entry phi nodes and other phis
-  // that can be removed.
-  BB->removePredecessor(Pred, true);
-
-  WeakTrackingVH PhiIt = &BB->front();
-  while (PHINode *PN = dyn_cast(PhiIt)) {
-PhiIt = &*++BasicBlock::iterator(cast(PhiIt));
-Value *OldPhiIt = PhiIt;
-
-if (!recursivelySimplifyInstruction(PN))
-  continue;
-
-// If recursive simplification ended up deleting the next PHI node we would
-// iterate to, then our iterator is invalid, restart scanning from the top
-// of the block.
-if (PhiIt != OldPhiIt) PhiIt = &BB->front();
-  }
-  if (DTU)
-DTU->applyUpdatesPermissive({{DominatorTree::Delete, Pred, BB}});
-}
-
 void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB,
DomTreeUpdater *DTU) {
 



___
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] e334c52 - [llvm-objcopy] Use llvm::erase_if (NFC)

2020-12-25 Thread Kazu Hirata via llvm-branch-commits

Author: Kazu Hirata
Date: 2020-12-25T10:13:18-08:00
New Revision: e334c52addc591b95bb0c125e8e289abbf3b67af

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

LOG: [llvm-objcopy] Use llvm::erase_if (NFC)

Added: 


Modified: 
llvm/tools/llvm-objcopy/COFF/Object.cpp
llvm/tools/llvm-objcopy/MachO/Object.cpp
llvm/tools/llvm-objcopy/wasm/Object.cpp

Removed: 




diff  --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp 
b/llvm/tools/llvm-objcopy/COFF/Object.cpp
index 2a57f9707055..cf3afe5e545e 100644
--- a/llvm/tools/llvm-objcopy/COFF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp
@@ -40,17 +40,14 @@ const Symbol *Object::findSymbol(size_t UniqueId) const {
 Error Object::removeSymbols(
 function_ref(const Symbol &)> ToRemove) {
   Error Errs = Error::success();
-  Symbols.erase(std::remove_if(std::begin(Symbols), std::end(Symbols),
-   [ToRemove, &Errs](const Symbol &Sym) {
- Expected ShouldRemove = ToRemove(Sym);
- if (!ShouldRemove) {
-   Errs = joinErrors(std::move(Errs),
- ShouldRemove.takeError());
-   return false;
- }
- return *ShouldRemove;
-   }),
-std::end(Symbols));
+  llvm::erase_if(Symbols, [ToRemove, &Errs](const Symbol &Sym) {
+Expected ShouldRemove = ToRemove(Sym);
+if (!ShouldRemove) {
+  Errs = joinErrors(std::move(Errs), ShouldRemove.takeError());
+  return false;
+}
+return *ShouldRemove;
+  });
 
   updateSymbols();
   return Errs;

diff  --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp 
b/llvm/tools/llvm-objcopy/MachO/Object.cpp
index e0a59b180465..cdb97531fb66 100644
--- a/llvm/tools/llvm-objcopy/MachO/Object.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/Object.cpp
@@ -26,9 +26,7 @@ SymbolEntry *SymbolTable::getSymbolByIndex(uint32_t Index) {
 
 void SymbolTable::removeSymbols(
 function_ref &)> ToRemove) {
-  Symbols.erase(
-  std::remove_if(std::begin(Symbols), std::end(Symbols), ToRemove),
-  std::end(Symbols));
+  llvm::erase_if(Symbols, ToRemove);
 }
 
 void Object::updateLoadCommandIndexes() {

diff  --git a/llvm/tools/llvm-objcopy/wasm/Object.cpp 
b/llvm/tools/llvm-objcopy/wasm/Object.cpp
index 0c416483663f..e7a2956fedca 100644
--- a/llvm/tools/llvm-objcopy/wasm/Object.cpp
+++ b/llvm/tools/llvm-objcopy/wasm/Object.cpp
@@ -26,9 +26,7 @@ void Object::addSectionWithOwnedContents(
 
 void Object::removeSections(function_ref ToRemove) {
   // TODO: remove reloc sections for the removed section, handle symbols, etc.
-  Sections.erase(
-  std::remove_if(std::begin(Sections), std::end(Sections), ToRemove),
-  std::end(Sections));
+  llvm::erase_if(Sections, ToRemove);
 }
 
 } // end namespace wasm



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits