xref: /llvm-project/llvm/include/llvm/IR/GEPNoWrapFlags.h (revision e565a4fa0b09456265e28b017054b20ff4315c58)
1 //===-- llvm/GEPNoWrapFlags.h - NoWrap flags for GEPs -----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the nowrap flags for getelementptr operators.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_IR_GEPNOWRAPFLAGS_H
14 #define LLVM_IR_GEPNOWRAPFLAGS_H
15 
16 #include <assert.h>
17 
18 namespace llvm {
19 
20 /// Represents flags for the getelementptr instruction/expression.
21 /// The following flags are supported:
22 ///  * inbounds (implies nusw)
23 ///  * nusw (no unsigned signed wrap)
24 ///  * nuw (no unsigned wrap)
25 /// See LangRef for a description of their semantics.
26 class GEPNoWrapFlags {
27   enum : unsigned {
28     InBoundsFlag = (1 << 0),
29     NUSWFlag = (1 << 1),
30     NUWFlag = (1 << 2),
31   };
32 
33   unsigned Flags;
34   GEPNoWrapFlags(unsigned Flags) : Flags(Flags) {
35     assert((!isInBounds() || hasNoUnsignedSignedWrap()) &&
36            "inbounds implies nusw");
37   }
38 
39 public:
40   GEPNoWrapFlags() : Flags(0) {}
41   // For historical reasons, interpret plain boolean as InBounds.
42   // TODO: Migrate users to pass explicit GEPNoWrapFlags and remove this ctor.
43   GEPNoWrapFlags(bool IsInBounds)
44       : Flags(IsInBounds ? (InBoundsFlag | NUSWFlag) : 0) {}
45 
46   static GEPNoWrapFlags none() { return GEPNoWrapFlags(); }
47   static GEPNoWrapFlags all() {
48     return GEPNoWrapFlags(InBoundsFlag | NUSWFlag | NUWFlag);
49   }
50   static GEPNoWrapFlags inBounds() {
51     return GEPNoWrapFlags(InBoundsFlag | NUSWFlag);
52   }
53   static GEPNoWrapFlags noUnsignedSignedWrap() {
54     return GEPNoWrapFlags(NUSWFlag);
55   }
56   static GEPNoWrapFlags noUnsignedWrap() { return GEPNoWrapFlags(NUWFlag); }
57 
58   static GEPNoWrapFlags fromRaw(unsigned Flags) {
59     return GEPNoWrapFlags(Flags);
60   }
61   unsigned getRaw() const { return Flags; }
62 
63   bool isInBounds() const { return Flags & InBoundsFlag; }
64   bool hasNoUnsignedSignedWrap() const { return Flags & NUSWFlag; }
65   bool hasNoUnsignedWrap() const { return Flags & NUWFlag; }
66 
67   GEPNoWrapFlags withoutInBounds() const {
68     return GEPNoWrapFlags(Flags & ~InBoundsFlag);
69   }
70   GEPNoWrapFlags withoutNoUnsignedSignedWrap() const {
71     return GEPNoWrapFlags(Flags & ~(InBoundsFlag | NUSWFlag));
72   }
73   GEPNoWrapFlags withoutNoUnsignedWrap() const {
74     return GEPNoWrapFlags(Flags & ~NUWFlag);
75   }
76 
77   /// Given (gep (gep p, x), y), determine the nowrap flags for (gep p, x+y).
78   GEPNoWrapFlags intersectForOffsetAdd(GEPNoWrapFlags Other) const {
79     GEPNoWrapFlags Res = *this & Other;
80     // Without inbounds, we could only preserve nusw if we know that x + y does
81     // not wrap.
82     if (!Res.isInBounds() && Res.hasNoUnsignedSignedWrap())
83       Res = Res.withoutNoUnsignedSignedWrap();
84     return Res;
85   }
86 
87   bool operator==(GEPNoWrapFlags Other) const { return Flags == Other.Flags; }
88   bool operator!=(GEPNoWrapFlags Other) const { return !(*this == Other); }
89 
90   GEPNoWrapFlags operator&(GEPNoWrapFlags Other) const {
91     return GEPNoWrapFlags(Flags & Other.Flags);
92   }
93   GEPNoWrapFlags operator|(GEPNoWrapFlags Other) const {
94     return GEPNoWrapFlags(Flags | Other.Flags);
95   }
96   GEPNoWrapFlags &operator&=(GEPNoWrapFlags Other) {
97     Flags &= Other.Flags;
98     return *this;
99   }
100   GEPNoWrapFlags &operator|=(GEPNoWrapFlags Other) {
101     Flags |= Other.Flags;
102     return *this;
103   }
104 };
105 
106 } // end namespace llvm
107 
108 #endif // LLVM_IR_GEPNOWRAPFLAGS_H
109