[clang] [llvm] [IR] Add getelementptr nusw and nuw flags (PR #90824)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
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)
@@ -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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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