[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-27 Thread Nikita Popov via cfe-commits

https://github.com/nikic closed https://github.com/llvm/llvm-project/pull/90824
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-27 Thread Nikita Popov via cfe-commits

https://github.com/nikic edited https://github.com/llvm/llvm-project/pull/90824
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-27 Thread Nikita Popov via cfe-commits

https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/90824

>From ff4658cf7661003d940452251147ee58315c774c Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Thu, 2 May 2024 12:11:18 +0900
Subject: [PATCH 1/7] Add support for getelementptr nusw and nuw

---
 llvm/docs/LangRef.rst | 57 --
 llvm/docs/ReleaseNotes.rst|  1 +
 llvm/include/llvm/AsmParser/LLToken.h |  1 +
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  8 +++
 llvm/include/llvm/IR/Instructions.h   | 14 +
 llvm/include/llvm/IR/Operator.h   | 26 +++-
 llvm/lib/AsmParser/LLLexer.cpp|  1 +
 llvm/lib/AsmParser/LLParser.cpp   | 21 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 20 +--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 +++-
 llvm/lib/IR/AsmWriter.cpp |  4 ++
 llvm/lib/IR/Instruction.cpp   | 22 +--
 llvm/lib/IR/Instructions.cpp  | 16 +
 llvm/lib/IR/Operator.cpp  |  3 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp |  8 +++
 .../Transforms/Utils/FunctionComparator.cpp   |  6 ++
 llvm/lib/Transforms/Vectorize/VPlan.h |  5 ++
 llvm/test/Assembler/flags.ll  | 43 +
 llvm/test/Transforms/InstCombine/freeze.ll| 22 +++
 llvm/test/Transforms/SimplifyCFG/HoistCode.ll | 60 +++
 llvm/test/tools/llvm-reduce/reduce-flags.ll   | 18 --
 .../deltas/ReduceInstructionFlags.cpp |  4 ++
 22 files changed, 333 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d2d21c7c4b5e3..1fb63fb761b58 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11184,6 +11184,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11299,27 +11301,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.
+
+For ``nuw`` (no unsigned wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the unsigned value
+   (``trunc nuw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in an unsigned sense (``mul nuw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in an unsigned sense (``add nuw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, also interpreted as
+   an unsigned number, does not wrap the index type (``add nuw``).
+
+For ``inbounds`` all rules of the ``nusw`` attribute apply. Additionally,
+if the ``getelementptr`` has any non-zero indices, the following rules apply:
+
+ * The base pointer has an *in bounds* address of an allocated object, which
means that it points into an allocated object, or to its end. Note that the
object does not have to be live anymore; being in-bounds of a deallocated
object is sufficient.
-*  If the type of an index is larger than the pointer index type, the
-   truncation to the pointer index type preserves the signed value.
-*  The multiplication of an index by the type size does not wrap the pointer
-   index type in a signed sense (``nsw``).
-*  The successive addition of each offset (without adding the base address) 
does
-   not wrap the pointer index type in a signed sense 

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-22 Thread Nikita Popov via cfe-commits

nikic wrote:

There's already another approval from @aeubanks, so I plan to merge this next 
Monday if there's no more feedback.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-21 Thread via cfe-commits

goldsteinn wrote:

LGTM. Wait on some additional approvals to push please.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-21 Thread Nikita Popov via cfe-commits

https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/90824

>From b74cc982c95f7750a581e93bc0f246786c69ef3d Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Thu, 2 May 2024 12:11:18 +0900
Subject: [PATCH 1/7] Add support for getelementptr nusw and nuw

---
 llvm/docs/LangRef.rst | 57 --
 llvm/docs/ReleaseNotes.rst|  1 +
 llvm/include/llvm/AsmParser/LLToken.h |  1 +
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  8 +++
 llvm/include/llvm/IR/Instructions.h   | 14 +
 llvm/include/llvm/IR/Operator.h   | 26 +++-
 llvm/lib/AsmParser/LLLexer.cpp|  1 +
 llvm/lib/AsmParser/LLParser.cpp   | 21 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 20 +--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 +++-
 llvm/lib/IR/AsmWriter.cpp |  4 ++
 llvm/lib/IR/Instruction.cpp   | 22 +--
 llvm/lib/IR/Instructions.cpp  | 16 +
 llvm/lib/IR/Operator.cpp  |  3 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp |  8 +++
 .../Transforms/Utils/FunctionComparator.cpp   |  6 ++
 llvm/lib/Transforms/Vectorize/VPlan.h |  5 ++
 llvm/test/Assembler/flags.ll  | 43 +
 llvm/test/Transforms/InstCombine/freeze.ll| 22 +++
 llvm/test/Transforms/SimplifyCFG/HoistCode.ll | 60 +++
 llvm/test/tools/llvm-reduce/reduce-flags.ll   | 18 --
 .../deltas/ReduceInstructionFlags.cpp |  4 ++
 22 files changed, 333 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 358eb4b867925..74097343a444d 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11184,6 +11184,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11299,27 +11301,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.
+
+For ``nuw`` (no unsigned wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the unsigned value
+   (``trunc nuw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in an unsigned sense (``mul nuw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in an unsigned sense (``add nuw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, also interpreted as
+   an unsigned number, does not wrap the index type (``add nuw``).
+
+For ``inbounds`` all rules of the ``nusw`` attribute apply. Additionally,
+if the ``getelementptr`` has any non-zero indices, the following rules apply:
+
+ * The base pointer has an *in bounds* address of an allocated object, which
means that it points into an allocated object, or to its end. Note that the
object does not have to be live anymore; being in-bounds of a deallocated
object is sufficient.
-*  If the type of an index is larger than the pointer index type, the
-   truncation to the pointer index type preserves the signed value.
-*  The multiplication of an index by the type size does not wrap the pointer
-   index type in a signed sense (``nsw``).
-*  The successive addition of each offset (without adding the base address) 
does
-   not wrap the pointer index type in a signed sense 

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-16 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,93 @@
+//===-- llvm/GEPNoWrapFlags.h - NoWrap flags for GEPs ---*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+//
+// This file defines the nowrap flags for getelementptr operators.
+//
+//===--===//
+
+#ifndef LLVM_IR_GEPNOWRAPFLAGS_H
+#define LLVM_IR_GEPNOWRAPFLAGS_H
+
+namespace llvm {
+
+/// Represents flags for the getelementptr instruction/expression.
+/// The following flags are supported:
+///  * inbounds (implies nusw)
+///  * nusw (no unsigned signed wrap)
+///  * nuw (no unsigned wrap)
+/// See LangRef for a description of their semantics.
+class GEPNoWrapFlags {
+  enum : unsigned {
+InBoundsFlag = (1 << 0),
+NUSWFlag = (1 << 1),
+NUWFlag = (1 << 2),
+  };
+
+  unsigned Flags;
+  GEPNoWrapFlags(unsigned Flags) : Flags(Flags) {
+assert((!isInBounds() || hasNoUnsignedSignedWrap()) &&
+   "inbounds implies nusw");
+  }
+
+public:
+  GEPNoWrapFlags() : Flags(0) {}
+  // For historical reasons, interpret plain boolean as InBounds.
+  // TODO: Migrate users to pass explicit GEPNoWrapFlags and remove this ctor.
+  GEPNoWrapFlags(bool IsInBounds)

nikic wrote:

This is a backwards-compatiblity ctor because we're replacing existing `bool 
IsInBounds` parameters with `GEPNoWrapFlags NW` instead. As the TODO indicates, 
this ctor will be removed in the future. It avoids having to touch large 
amounts of code in this PR in sub-optimal ways.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-16 Thread via cfe-commits


@@ -0,0 +1,93 @@
+//===-- llvm/GEPNoWrapFlags.h - NoWrap flags for GEPs ---*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+//
+// This file defines the nowrap flags for getelementptr operators.
+//
+//===--===//
+
+#ifndef LLVM_IR_GEPNOWRAPFLAGS_H
+#define LLVM_IR_GEPNOWRAPFLAGS_H
+
+namespace llvm {
+
+/// Represents flags for the getelementptr instruction/expression.
+/// The following flags are supported:
+///  * inbounds (implies nusw)
+///  * nusw (no unsigned signed wrap)
+///  * nuw (no unsigned wrap)
+/// See LangRef for a description of their semantics.
+class GEPNoWrapFlags {
+  enum : unsigned {
+InBoundsFlag = (1 << 0),
+NUSWFlag = (1 << 1),
+NUWFlag = (1 << 2),
+  };
+
+  unsigned Flags;
+  GEPNoWrapFlags(unsigned Flags) : Flags(Flags) {
+assert((!isInBounds() || hasNoUnsignedSignedWrap()) &&
+   "inbounds implies nusw");
+  }
+
+public:
+  GEPNoWrapFlags() : Flags(0) {}
+  // For historical reasons, interpret plain boolean as InBounds.
+  // TODO: Migrate users to pass explicit GEPNoWrapFlags and remove this ctor.
+  GEPNoWrapFlags(bool IsInBounds)

goldsteinn wrote:

Why do we need this CTOR? Seems to be entirely encapsulated with `inBounds` 
which is more expressive. Seems a bit non-intuitive to only have 1 bool 
constructor for a flags class that represents 3...

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-15 Thread Nikita Popov via cfe-commits

https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/90824

>From 009ffa45c131982caac5b9025678cde0418ac003 Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Thu, 2 May 2024 12:11:18 +0900
Subject: [PATCH 1/7] Add support for getelementptr nusw and nuw

---
 llvm/docs/LangRef.rst | 57 --
 llvm/docs/ReleaseNotes.rst|  1 +
 llvm/include/llvm/AsmParser/LLToken.h |  1 +
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  8 +++
 llvm/include/llvm/IR/Instructions.h   | 14 +
 llvm/include/llvm/IR/Operator.h   | 26 +++-
 llvm/lib/AsmParser/LLLexer.cpp|  1 +
 llvm/lib/AsmParser/LLParser.cpp   | 21 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 20 +--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 +++-
 llvm/lib/IR/AsmWriter.cpp |  4 ++
 llvm/lib/IR/Instruction.cpp   | 22 +--
 llvm/lib/IR/Instructions.cpp  | 16 +
 llvm/lib/IR/Operator.cpp  |  3 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp |  8 +++
 .../Transforms/Utils/FunctionComparator.cpp   |  6 ++
 llvm/lib/Transforms/Vectorize/VPlan.h |  5 ++
 llvm/test/Assembler/flags.ll  | 43 +
 llvm/test/Transforms/InstCombine/freeze.ll| 22 +++
 llvm/test/Transforms/SimplifyCFG/HoistCode.ll | 60 +++
 llvm/test/tools/llvm-reduce/reduce-flags.ll   | 18 --
 .../deltas/ReduceInstructionFlags.cpp |  4 ++
 22 files changed, 333 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index e2f4d8bfcaeed..aedd1c2281eff 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11180,6 +11180,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.
+
+For ``nuw`` (no unsigned wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the unsigned value
+   (``trunc nuw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in an unsigned sense (``mul nuw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in an unsigned sense (``add nuw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, also interpreted as
+   an unsigned number, does not wrap the index type (``add nuw``).
+
+For ``inbounds`` all rules of the ``nusw`` attribute apply. Additionally,
+if the ``getelementptr`` has any non-zero indices, the following rules apply:
+
+ * The base pointer has an *in bounds* address of an allocated object, which
means that it points into an allocated object, or to its end. Note that the
object does not have to be live anymore; being in-bounds of a deallocated
object is sufficient.
-*  If the type of an index is larger than the pointer index type, the
-   truncation to the pointer index type preserves the signed value.
-*  The multiplication of an index by the type size does not wrap the pointer
-   index type in a signed sense (``nsw``).
-*  The successive addition of each offset (without adding the base address) 
does
-   not wrap the pointer index type in a signed sense 

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-15 Thread Arthur Eubanks via cfe-commits


@@ -0,0 +1,86 @@
+//===-- llvm/GEPNoWrapFlags.h - NoWrap flags for GEPs ---*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+//
+// This file defines the nowrap flags for getelementptr operators.
+//
+//===--===//
+
+#ifndef LLVM_IR_GEPNOWRAPFLAGS_H
+#define LLVM_IR_GEPNOWRAPFLAGS_H
+
+namespace llvm {
+
+class GEPNoWrapFlags {
+  enum : unsigned{
+InBoundsFlag = (1 << 0),
+NUSWFlag = (1 << 1),
+NUWFlag = (1 << 2),
+  };
+
+  unsigned Flags;
+  GEPNoWrapFlags(unsigned Flags) : Flags(Flags) {
+assert((!isInBounds() || hasNoUnsignedSignedWrap()) &&
+   "inbounds implies nusw");
+  }
+
+public:
+  GEPNoWrapFlags() : Flags(0) {}
+  // For historical reasons, interpret plain boolean as InBounds.

aeubanks wrote:

TODO: remove?

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-15 Thread Arthur Eubanks via cfe-commits

https://github.com/aeubanks approved this pull request.

thanks, I think abstracting out GEPNoWrapFlags is good

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-15 Thread Arthur Eubanks via cfe-commits


@@ -0,0 +1,86 @@
+//===-- llvm/GEPNoWrapFlags.h - NoWrap flags for GEPs ---*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+//
+// This file defines the nowrap flags for getelementptr operators.
+//
+//===--===//
+
+#ifndef LLVM_IR_GEPNOWRAPFLAGS_H
+#define LLVM_IR_GEPNOWRAPFLAGS_H
+
+namespace llvm {
+
+class GEPNoWrapFlags {
+  enum : unsigned{

aeubanks wrote:

clang-format

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-15 Thread Arthur Eubanks via cfe-commits

https://github.com/aeubanks edited 
https://github.com/llvm/llvm-project/pull/90824
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-15 Thread Nikita Popov via cfe-commits

https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/90824

>From 009ffa45c131982caac5b9025678cde0418ac003 Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Thu, 2 May 2024 12:11:18 +0900
Subject: [PATCH 1/5] Add support for getelementptr nusw and nuw

---
 llvm/docs/LangRef.rst | 57 --
 llvm/docs/ReleaseNotes.rst|  1 +
 llvm/include/llvm/AsmParser/LLToken.h |  1 +
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  8 +++
 llvm/include/llvm/IR/Instructions.h   | 14 +
 llvm/include/llvm/IR/Operator.h   | 26 +++-
 llvm/lib/AsmParser/LLLexer.cpp|  1 +
 llvm/lib/AsmParser/LLParser.cpp   | 21 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 20 +--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 +++-
 llvm/lib/IR/AsmWriter.cpp |  4 ++
 llvm/lib/IR/Instruction.cpp   | 22 +--
 llvm/lib/IR/Instructions.cpp  | 16 +
 llvm/lib/IR/Operator.cpp  |  3 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp |  8 +++
 .../Transforms/Utils/FunctionComparator.cpp   |  6 ++
 llvm/lib/Transforms/Vectorize/VPlan.h |  5 ++
 llvm/test/Assembler/flags.ll  | 43 +
 llvm/test/Transforms/InstCombine/freeze.ll| 22 +++
 llvm/test/Transforms/SimplifyCFG/HoistCode.ll | 60 +++
 llvm/test/tools/llvm-reduce/reduce-flags.ll   | 18 --
 .../deltas/ReduceInstructionFlags.cpp |  4 ++
 22 files changed, 333 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index e2f4d8bfcaeed..aedd1c2281eff 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11180,6 +11180,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.
+
+For ``nuw`` (no unsigned wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the unsigned value
+   (``trunc nuw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in an unsigned sense (``mul nuw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in an unsigned sense (``add nuw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, also interpreted as
+   an unsigned number, does not wrap the index type (``add nuw``).
+
+For ``inbounds`` all rules of the ``nusw`` attribute apply. Additionally,
+if the ``getelementptr`` has any non-zero indices, the following rules apply:
+
+ * The base pointer has an *in bounds* address of an allocated object, which
means that it points into an allocated object, or to its end. Note that the
object does not have to be live anymore; being in-bounds of a deallocated
object is sufficient.
-*  If the type of an index is larger than the pointer index type, the
-   truncation to the pointer index type preserves the signed value.
-*  The multiplication of an index by the type size does not wrap the pointer
-   index type in a signed sense (``nsw``).
-*  The successive addition of each offset (without adding the base address) 
does
-   not wrap the pointer index type in a signed sense 

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Nikita Popov via cfe-commits


@@ -1699,8 +1701,12 @@ Expected 
BitcodeReader::materializeValue(unsigned StartValID,
 I = GetElementPtrInst::Create(BC->SrcElemTy, Ops[0],
   ArrayRef(Ops).drop_front(), "constexpr",
   InsertBB);
-if (BC->Flags)
+if (BC->Flags & (1 << bitc::GEP_INBOUNDS))
   cast(I)->setIsInBounds();
+if (BC->Flags & (1 << bitc::GEP_NUSW))

nikic wrote:

I think using `else if` would be correct here as `setIsInBounds` will also set 
nusw by itself, but keeping all cases separate seems cleaner?

Otherwise we'll have the following code here...
```
if (BC->Flags & (1 << bitc::GEP_INBOUNDS))
  cast(I)->setIsInBounds();
else if (BC->Flags & (1 << bitc::GEP_NUSW))
  cast(I)->setHasNoUnsignedSignedWrap();
if (BC->Flags & (1 << bitc::GEP_NUW))
  cast(I)->setHasNoUnsignedWrap();
```
...at which point it will probably need a comment to explain why there is only 
one `else if` there.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Nikita Popov via cfe-commits


@@ -316,3 +316,82 @@ define <2 x i32> @test_trunc_both_reversed_vector(<2 x 
i64> %a) {
   %res = trunc nsw nuw <2 x i64> %a to <2 x i32>
   ret <2 x i32> %res
 }
+
+define ptr @gep_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_inbounds_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_nusw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr nusw i8, ptr %p, i64 %idx
+  %gep = getelementptr nusw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+; inbounds implies nusw, so the flag is not printed back.
+define ptr @gep_inbounds_nusw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds i8, ptr %p, i64 %idx
+  %gep = getelementptr inbounds nusw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr nusw nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr nusw nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_inbounds_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr inbounds nusw nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_nuw_nusw_inbounds(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr nuw nusw inbounds i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @const_gep_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_inbounds_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_nusw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr nusw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nusw (i8, ptr @addr, i64 100)
+}
+
+; inbounds implies nusw, so the flag is not printed back.
+define ptr @const_gep_inbounds_nusw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds (i8, ptr @addr, i64 100)
+  ret ptr getelementptr inbounds nusw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr nusw nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nusw nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_inbounds_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr inbounds nusw nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_nuw_nusw_inbounds(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nuw nusw inbounds (i8, ptr @addr, i64 100)
+}

nikic wrote:

Done

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Nikita Popov via cfe-commits


@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.

nikic wrote:

> missing '(`add nsw`)' at the end of this?

No, because the base is unsigned here. This would be `add nusw` if it existed.

> Also maybe im a bit confused, but should this not be 'pointer index type'?

Yeah, I've updated this and other places to use "pointer index type".

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Nikita Popov via cfe-commits

https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/90824

>From eb27a1b94ec807323d204b51d5c01cc22056e1c7 Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Thu, 2 May 2024 12:11:18 +0900
Subject: [PATCH 1/4] Add support for getelementptr nusw and nuw

---
 llvm/docs/LangRef.rst | 57 --
 llvm/docs/ReleaseNotes.rst|  1 +
 llvm/include/llvm/AsmParser/LLToken.h |  1 +
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  8 +++
 llvm/include/llvm/IR/Instructions.h   | 14 +
 llvm/include/llvm/IR/Operator.h   | 26 +++-
 llvm/lib/AsmParser/LLLexer.cpp|  1 +
 llvm/lib/AsmParser/LLParser.cpp   | 21 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 20 +--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 +++-
 llvm/lib/IR/AsmWriter.cpp |  4 ++
 llvm/lib/IR/Instruction.cpp   | 22 +--
 llvm/lib/IR/Instructions.cpp  | 16 +
 llvm/lib/IR/Operator.cpp  |  3 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp | 13 
 .../Transforms/Utils/FunctionComparator.cpp   |  6 ++
 llvm/lib/Transforms/Vectorize/VPlan.h |  5 ++
 llvm/test/Assembler/flags.ll  | 43 +
 llvm/test/Transforms/InstCombine/freeze.ll| 22 +++
 llvm/test/Transforms/SimplifyCFG/HoistCode.ll | 60 +++
 llvm/test/tools/llvm-reduce/reduce-flags.ll   | 18 --
 .../deltas/ReduceInstructionFlags.cpp |  4 ++
 22 files changed, 338 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6291a4e57919a5..7aeed82ab84df7 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11180,6 +11180,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.
+
+For ``nuw`` (no unsigned wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the unsigned value
+   (``trunc nuw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in an unsigned sense (``mul nuw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in an unsigned sense (``add nuw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, also interpreted as
+   an unsigned number, does not wrap the index type (``add nuw``).
+
+For ``inbounds`` all rules of the ``nusw`` attribute apply. Additionally,
+if the ``getelementptr`` has any non-zero indices, the following rules apply:
+
+ * The base pointer has an *in bounds* address of an allocated object, which
means that it points into an allocated object, or to its end. Note that the
object does not have to be live anymore; being in-bounds of a deallocated
object is sufficient.
-*  If the type of an index is larger than the pointer index type, the
-   truncation to the pointer index type preserves the signed value.
-*  The multiplication of an index by the type size does not wrap the pointer
-   index type in a signed sense (``nsw``).
-*  The successive addition of each offset (without adding the base address) 
does
-   not wrap the pointer index type in a signed sense 

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Nikita Popov via cfe-commits

nikic wrote:

> Are the TODOs encompassing all the cases? Why we don't want to set the flags 
> in `PHITransAddr` as well?

No, the TODOs are only for places where I had to modify code, but the used 
implementation is obviously non-optimal to minimize initial impact. There are 
many more places that need to be modified to full propagate the flags 
everywhere.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Matt Arsenault via cfe-commits


@@ -316,3 +316,82 @@ define <2 x i32> @test_trunc_both_reversed_vector(<2 x 
i64> %a) {
   %res = trunc nsw nuw <2 x i64> %a to <2 x i32>
   ret <2 x i32> %res
 }
+
+define ptr @gep_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_inbounds_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_nusw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr nusw i8, ptr %p, i64 %idx
+  %gep = getelementptr nusw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+; inbounds implies nusw, so the flag is not printed back.
+define ptr @gep_inbounds_nusw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds i8, ptr %p, i64 %idx
+  %gep = getelementptr inbounds nusw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr nusw nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr nusw nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_inbounds_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr inbounds nusw nuw i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @gep_nuw_nusw_inbounds(ptr %p, i64 %idx) {
+; CHECK: %gep = getelementptr inbounds nuw i8, ptr %p, i64 %idx
+  %gep = getelementptr nuw nusw inbounds i8, ptr %p, i64 %idx
+  ret ptr %gep
+}
+
+define ptr @const_gep_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_inbounds_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_nusw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr nusw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nusw (i8, ptr @addr, i64 100)
+}
+
+; inbounds implies nusw, so the flag is not printed back.
+define ptr @const_gep_inbounds_nusw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds (i8, ptr @addr, i64 100)
+  ret ptr getelementptr inbounds nusw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr nusw nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nusw nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_inbounds_nusw_nuw(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr inbounds nusw nuw (i8, ptr @addr, i64 100)
+}
+
+define ptr @const_gep_nuw_nusw_inbounds(ptr %p, i64 %idx) {
+; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
+  ret ptr getelementptr nuw nusw inbounds (i8, ptr @addr, i64 100)
+}

arsenm wrote:

Maybe test non-0 AS and vectors?

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread via cfe-commits


@@ -1699,8 +1701,12 @@ Expected 
BitcodeReader::materializeValue(unsigned StartValID,
 I = GetElementPtrInst::Create(BC->SrcElemTy, Ops[0],
   ArrayRef(Ops).drop_front(), "constexpr",
   InsertBB);
-if (BC->Flags)
+if (BC->Flags & (1 << bitc::GEP_INBOUNDS))
   cast(I)->setIsInBounds();
+if (BC->Flags & (1 << bitc::GEP_NUSW))

goldsteinn wrote:

likewise elsewhere.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread via cfe-commits


@@ -1699,8 +1701,12 @@ Expected 
BitcodeReader::materializeValue(unsigned StartValID,
 I = GetElementPtrInst::Create(BC->SrcElemTy, Ops[0],
   ArrayRef(Ops).drop_front(), "constexpr",
   InsertBB);
-if (BC->Flags)
+if (BC->Flags & (1 << bitc::GEP_INBOUNDS))
   cast(I)->setIsInBounds();
+if (BC->Flags & (1 << bitc::GEP_NUSW))

goldsteinn wrote:

nit: this could be `else if`.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread via cfe-commits


@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.

goldsteinn wrote:

Also maybe im a bit confused, but should this not be 'pointer index type'?

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread via cfe-commits


@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.

goldsteinn wrote:

missing '(``add nsw``)' at the end of this?

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Antonio Frighetto via cfe-commits

antoniofrighetto wrote:

Are the TODOs encompassing all the cases? Why we don't want to set the flags in 
`PHITransAddr` as well?

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Thorsten Schütt via cfe-commits

tschuett wrote:

Could you please add a TODO here:
https://github.com/llvm/llvm-project/blob/e3f42b02a4129947ca2dd820bfb63ffed83027b7/llvm/lib/CodeGen/MachineInstr.cpp#L565
Thanks.

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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Nikita Popov via cfe-commits

https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/90824

>From eb27a1b94ec807323d204b51d5c01cc22056e1c7 Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Thu, 2 May 2024 12:11:18 +0900
Subject: [PATCH 1/2] Add support for getelementptr nusw and nuw

---
 llvm/docs/LangRef.rst | 57 --
 llvm/docs/ReleaseNotes.rst|  1 +
 llvm/include/llvm/AsmParser/LLToken.h |  1 +
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  8 +++
 llvm/include/llvm/IR/Instructions.h   | 14 +
 llvm/include/llvm/IR/Operator.h   | 26 +++-
 llvm/lib/AsmParser/LLLexer.cpp|  1 +
 llvm/lib/AsmParser/LLParser.cpp   | 21 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 20 +--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 +++-
 llvm/lib/IR/AsmWriter.cpp |  4 ++
 llvm/lib/IR/Instruction.cpp   | 22 +--
 llvm/lib/IR/Instructions.cpp  | 16 +
 llvm/lib/IR/Operator.cpp  |  3 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp | 13 
 .../Transforms/Utils/FunctionComparator.cpp   |  6 ++
 llvm/lib/Transforms/Vectorize/VPlan.h |  5 ++
 llvm/test/Assembler/flags.ll  | 43 +
 llvm/test/Transforms/InstCombine/freeze.ll| 22 +++
 llvm/test/Transforms/SimplifyCFG/HoistCode.ll | 60 +++
 llvm/test/tools/llvm-reduce/reduce-flags.ll   | 18 --
 .../deltas/ReduceInstructionFlags.cpp |  4 ++
 22 files changed, 338 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6291a4e57919a5..7aeed82ab84df7 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11180,6 +11180,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.
+
+For ``nuw`` (no unsigned wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the unsigned value
+   (``trunc nuw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in an unsigned sense (``mul nuw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in an unsigned sense (``add nuw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, also interpreted as
+   an unsigned number, does not wrap the index type (``add nuw``).
+
+For ``inbounds`` all rules of the ``nusw`` attribute apply. Additionally,
+if the ``getelementptr`` has any non-zero indices, the following rules apply:
+
+ * The base pointer has an *in bounds* address of an allocated object, which
means that it points into an allocated object, or to its end. Note that the
object does not have to be live anymore; being in-bounds of a deallocated
object is sufficient.
-*  If the type of an index is larger than the pointer index type, the
-   truncation to the pointer index type preserves the signed value.
-*  The multiplication of an index by the type size does not wrap the pointer
-   index type in a signed sense (``nsw``).
-*  The successive addition of each offset (without adding the base address) 
does
-   not wrap the pointer index type in a signed sense 

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 3d65bd935a91439c483c56a966edc283a2b1130d 
e6d87106fd677c98422efa97dffef600b053853c -- clang/lib/CodeGen/CGVTT.cpp 
clang/lib/CodeGen/ItaniumCXXABI.cpp llvm/include/llvm/AsmParser/LLToken.h 
llvm/include/llvm/Bitcode/LLVMBitCodes.h llvm/include/llvm/IR/Constants.h 
llvm/include/llvm/IR/Instructions.h llvm/include/llvm/IR/Operator.h 
llvm/lib/Analysis/ConstantFolding.cpp llvm/lib/AsmParser/LLLexer.cpp 
llvm/lib/AsmParser/LLParser.cpp llvm/lib/Bitcode/Reader/BitcodeReader.cpp 
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp llvm/lib/IR/AsmWriter.cpp 
llvm/lib/IR/ConstantFold.cpp llvm/lib/IR/Constants.cpp 
llvm/lib/IR/Instruction.cpp llvm/lib/IR/Instructions.cpp 
llvm/lib/IR/Operator.cpp 
llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp 
llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp 
llvm/lib/Transforms/Utils/FunctionComparator.cpp 
llvm/lib/Transforms/Vectorize/VPlan.h 
llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp
``





View the diff from clang-format here.


``diff
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp 
b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 278d2c6ada..6f844b7ea1 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -3341,7 +3341,6 @@ Error BitcodeReader::parseConstants() {
   BitCode == bitc::CST_CODE_CE_GEP || Record.size() % 2)
 PointeeType = getTypeByID(Record[OpNum++]);
 
-
   uint64_t Flags = 0;
   std::optional InRange;
   if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD) {

``




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


[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)


Changes

This implements the `nusw` and `nuw` flags for `getelementptr` as proposed at 
https://discourse.llvm.org/t/rfc-add-nusw-and-nuw-flags-for-getelementptr/78672.

There are a bunch of places annotated with `TODO(gep_nowrap)`, where I've had 
to touch code but opted to not infer or precisely preserve the new flags, so as 
to keep this as NFC as possible and make sure any changes of that kind get test 
coverage when they are made.

---

Patch is 47.89 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/90824.diff


29 Files Affected:

- (modified) clang/lib/CodeGen/CGVTT.cpp (+3-1) 
- (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+3-1) 
- (modified) llvm/docs/LangRef.rst (+43-18) 
- (modified) llvm/docs/ReleaseNotes.rst (+1) 
- (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) 
- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+10-1) 
- (modified) llvm/include/llvm/IR/Constants.h (+6-5) 
- (modified) llvm/include/llvm/IR/Instructions.h (+14) 
- (modified) llvm/include/llvm/IR/Operator.h (+25-1) 
- (modified) llvm/lib/Analysis/ConstantFolding.cpp (+9-3) 
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) 
- (modified) llvm/lib/AsmParser/LLParser.cpp (+32-7) 
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+39-16) 
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+11-5) 
- (modified) llvm/lib/IR/AsmWriter.cpp (+4) 
- (modified) llvm/lib/IR/ConstantFold.cpp (+4-1) 
- (modified) llvm/lib/IR/Constants.cpp (+11-2) 
- (modified) llvm/lib/IR/Instruction.cpp (+18-4) 
- (modified) llvm/lib/IR/Instructions.cpp (+16) 
- (modified) llvm/lib/IR/Operator.cpp (+2-1) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp (+2-1) 
- (modified) llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp (+13) 
- (modified) llvm/lib/Transforms/Utils/FunctionComparator.cpp (+6) 
- (modified) llvm/lib/Transforms/Vectorize/VPlan.h (+5) 
- (modified) llvm/test/Assembler/flags.ll (+79) 
- (modified) llvm/test/Transforms/InstCombine/freeze.ll (+22) 
- (modified) llvm/test/Transforms/SimplifyCFG/HoistCode.ll (+60) 
- (modified) llvm/test/tools/llvm-reduce/reduce-flags.ll (+13-5) 
- (modified) llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp (+4) 


``diff
diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp
index d2376b14dd5826..8c72f3dccfd6e3 100644
--- a/clang/lib/CodeGen/CGVTT.cpp
+++ b/clang/lib/CodeGen/CGVTT.cpp
@@ -87,8 +87,10 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
  unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
  llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
  llvm::APInt(32, VTableSize - Offset, true));
+ // TODO(gep_nowrap): Set nuw as well.
  llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
- VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange);
+ VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, 
/*NUSW=*/true,
+ /*NUW=*/false, InRange);
 
  VTTComponents.push_back(Init);
   }
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 18acf7784f714b..0138915ad35996 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -1901,8 +1901,10 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
   unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
   llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
   llvm::APInt(32, VTableSize - Offset, true));
+  // TODO(gep_nowrap): Set nuw as well.
   return llvm::ConstantExpr::getGetElementPtr(
-  VTable->getValueType(), VTable, Indices, /*InBounds=*/true, InRange);
+  VTable->getValueType(), VTable, Indices, /*InBounds=*/true, 
/*NUSW=*/true,
+  /*NUW=*/false, InRange);
 }
 
 // Check whether all the non-inline virtual methods for the class have the
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6291a4e57919a5..a4340f060d6f07 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11180,6 +11180,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-amdgpu

Author: Nikita Popov (nikic)


Changes

This implements the `nusw` and `nuw` flags for `getelementptr` as proposed at 
https://discourse.llvm.org/t/rfc-add-nusw-and-nuw-flags-for-getelementptr/78672.

There are a bunch of places annotated with `TODO(gep_nowrap)`, where I've had 
to touch code but opted to not infer or precisely preserve the new flags, so as 
to keep this as NFC as possible and make sure any changes of that kind get test 
coverage when they are made.

---

Patch is 47.89 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/90824.diff


29 Files Affected:

- (modified) clang/lib/CodeGen/CGVTT.cpp (+3-1) 
- (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+3-1) 
- (modified) llvm/docs/LangRef.rst (+43-18) 
- (modified) llvm/docs/ReleaseNotes.rst (+1) 
- (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) 
- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+10-1) 
- (modified) llvm/include/llvm/IR/Constants.h (+6-5) 
- (modified) llvm/include/llvm/IR/Instructions.h (+14) 
- (modified) llvm/include/llvm/IR/Operator.h (+25-1) 
- (modified) llvm/lib/Analysis/ConstantFolding.cpp (+9-3) 
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) 
- (modified) llvm/lib/AsmParser/LLParser.cpp (+32-7) 
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+39-16) 
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+11-5) 
- (modified) llvm/lib/IR/AsmWriter.cpp (+4) 
- (modified) llvm/lib/IR/ConstantFold.cpp (+4-1) 
- (modified) llvm/lib/IR/Constants.cpp (+11-2) 
- (modified) llvm/lib/IR/Instruction.cpp (+18-4) 
- (modified) llvm/lib/IR/Instructions.cpp (+16) 
- (modified) llvm/lib/IR/Operator.cpp (+2-1) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp (+2-1) 
- (modified) llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp (+13) 
- (modified) llvm/lib/Transforms/Utils/FunctionComparator.cpp (+6) 
- (modified) llvm/lib/Transforms/Vectorize/VPlan.h (+5) 
- (modified) llvm/test/Assembler/flags.ll (+79) 
- (modified) llvm/test/Transforms/InstCombine/freeze.ll (+22) 
- (modified) llvm/test/Transforms/SimplifyCFG/HoistCode.ll (+60) 
- (modified) llvm/test/tools/llvm-reduce/reduce-flags.ll (+13-5) 
- (modified) llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp (+4) 


``diff
diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp
index d2376b14dd5826..8c72f3dccfd6e3 100644
--- a/clang/lib/CodeGen/CGVTT.cpp
+++ b/clang/lib/CodeGen/CGVTT.cpp
@@ -87,8 +87,10 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
  unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
  llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
  llvm::APInt(32, VTableSize - Offset, true));
+ // TODO(gep_nowrap): Set nuw as well.
  llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
- VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange);
+ VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, 
/*NUSW=*/true,
+ /*NUW=*/false, InRange);
 
  VTTComponents.push_back(Init);
   }
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 18acf7784f714b..0138915ad35996 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -1901,8 +1901,10 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
   unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
   llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
   llvm::APInt(32, VTableSize - Offset, true));
+  // TODO(gep_nowrap): Set nuw as well.
   return llvm::ConstantExpr::getGetElementPtr(
-  VTable->getValueType(), VTable, Indices, /*InBounds=*/true, InRange);
+  VTable->getValueType(), VTable, Indices, /*InBounds=*/true, 
/*NUSW=*/true,
+  /*NUW=*/false, InRange);
 }
 
 // Check whether all the non-inline virtual methods for the class have the
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6291a4e57919a5..a4340f060d6f07 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11180,6 +11180,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose

[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)

2024-05-02 Thread Nikita Popov via cfe-commits

https://github.com/nikic created https://github.com/llvm/llvm-project/pull/90824

This implements the `nusw` and `nuw` flags for `getelementptr` as proposed at 
https://discourse.llvm.org/t/rfc-add-nusw-and-nuw-flags-for-getelementptr/78672.

There are a bunch of places annotated with `TODO(gep_nowrap)`, where I've had 
to touch code but opted to not infer or precisely preserve the new flags, so as 
to keep this as NFC as possible and make sure any changes of that kind get test 
coverage when they are made.

>From eb27a1b94ec807323d204b51d5c01cc22056e1c7 Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Thu, 2 May 2024 12:11:18 +0900
Subject: [PATCH 1/2] Add support for getelementptr nusw and nuw

---
 llvm/docs/LangRef.rst | 57 --
 llvm/docs/ReleaseNotes.rst|  1 +
 llvm/include/llvm/AsmParser/LLToken.h |  1 +
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  8 +++
 llvm/include/llvm/IR/Instructions.h   | 14 +
 llvm/include/llvm/IR/Operator.h   | 26 +++-
 llvm/lib/AsmParser/LLLexer.cpp|  1 +
 llvm/lib/AsmParser/LLParser.cpp   | 21 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 20 +--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 +++-
 llvm/lib/IR/AsmWriter.cpp |  4 ++
 llvm/lib/IR/Instruction.cpp   | 22 +--
 llvm/lib/IR/Instructions.cpp  | 16 +
 llvm/lib/IR/Operator.cpp  |  3 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp | 13 
 .../Transforms/Utils/FunctionComparator.cpp   |  6 ++
 llvm/lib/Transforms/Vectorize/VPlan.h |  5 ++
 llvm/test/Assembler/flags.ll  | 43 +
 llvm/test/Transforms/InstCombine/freeze.ll| 22 +++
 llvm/test/Transforms/SimplifyCFG/HoistCode.ll | 60 +++
 llvm/test/tools/llvm-reduce/reduce-flags.ll   | 18 --
 .../deltas/ReduceInstructionFlags.cpp |  4 ++
 22 files changed, 338 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6291a4e57919a5..7aeed82ab84df7 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11180,6 +11180,8 @@ Syntax:
 
= getelementptr , ptr {,  }*
= getelementptr inbounds , ptr {,  }*
+   = getelementptr nusw , ptr {,  }*
+   = getelementptr nuw , ptr {,  }*
= getelementptr inrange(S,E) , ptr {,  }*
= getelementptr ,  ,  

 
@@ -11295,27 +11297,46 @@ memory though, even if it happens to point into 
allocated storage. See the
 :ref:`Pointer Aliasing Rules ` section for more
 information.
 
-If the ``inbounds`` keyword is present, the result value of a
-``getelementptr`` with any non-zero indices is a
-:ref:`poison value ` if one of the following rules is violated:
-
-*  The base pointer has an *in bounds* address of an allocated object, which
+The ``getelementptr`` instruction may have a number of attributes that impose
+additional rules. If any of the rules are violated, the result value is a
+:ref:`poison value `. In cases where the base is a vector of
+pointers, the attributes apply to each computation element-wise.
+
+For ``nusw`` (no unsigned signed wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the signed value
+   (``trunc nsw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in a signed sense (``mul nsw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in a signed sense (``add nsw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, interpreted as
+   a signed number, does not wrap the index type.
+
+For ``nuw`` (no unsigned wrap):
+
+ * If the type of an index is larger than the pointer index type, the
+   truncation to the pointer index type preserves the unsigned value
+   (``trunc nuw``).
+ * The multiplication of an index by the type size does not wrap the pointer
+   index type in an unsigned sense (``mul nuw``).
+ * The successive addition of each offset (without adding the base address)
+   does not wrap the pointer index type in an unsigned sense (``add nuw``).
+ * The successive addition of the current address, truncated to the index type
+   and interpreted as an unsigned number, and each offset, also interpreted as
+   an unsigned number, does not wrap the index type (``add nuw``).
+
+For ``inbounds`` all rules of the ``nusw`` attribute apply. Additionally,
+if the ``getelementptr`` has any non-zero indices, the following rules apply:
+
+ * The base pointer has an *in bounds* address of an allocated object, which
means that it points into an allocated object, or to its end. Note that the
object does not have to be live anymore; being in-bounds of a