119 lines
3.8 KiB
C++
119 lines
3.8 KiB
C++
//===-- 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
|
|
|
|
#include <assert.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)
|
|
: Flags(IsInBounds ? (InBoundsFlag | NUSWFlag) : 0) {}
|
|
|
|
static GEPNoWrapFlags none() { return GEPNoWrapFlags(); }
|
|
static GEPNoWrapFlags all() {
|
|
return GEPNoWrapFlags(InBoundsFlag | NUSWFlag | NUWFlag);
|
|
}
|
|
static GEPNoWrapFlags inBounds() {
|
|
return GEPNoWrapFlags(InBoundsFlag | NUSWFlag);
|
|
}
|
|
static GEPNoWrapFlags noUnsignedSignedWrap() {
|
|
return GEPNoWrapFlags(NUSWFlag);
|
|
}
|
|
static GEPNoWrapFlags noUnsignedWrap() { return GEPNoWrapFlags(NUWFlag); }
|
|
|
|
static GEPNoWrapFlags fromRaw(unsigned Flags) {
|
|
return GEPNoWrapFlags(Flags);
|
|
}
|
|
unsigned getRaw() const { return Flags; }
|
|
|
|
bool isInBounds() const { return Flags & InBoundsFlag; }
|
|
bool hasNoUnsignedSignedWrap() const { return Flags & NUSWFlag; }
|
|
bool hasNoUnsignedWrap() const { return Flags & NUWFlag; }
|
|
|
|
GEPNoWrapFlags withoutInBounds() const {
|
|
return GEPNoWrapFlags(Flags & ~InBoundsFlag);
|
|
}
|
|
GEPNoWrapFlags withoutNoUnsignedSignedWrap() const {
|
|
return GEPNoWrapFlags(Flags & ~(InBoundsFlag | NUSWFlag));
|
|
}
|
|
GEPNoWrapFlags withoutNoUnsignedWrap() const {
|
|
return GEPNoWrapFlags(Flags & ~NUWFlag);
|
|
}
|
|
|
|
/// Given (gep (gep p, x), y), determine the nowrap flags for (gep p, x+y).
|
|
GEPNoWrapFlags intersectForOffsetAdd(GEPNoWrapFlags Other) const {
|
|
GEPNoWrapFlags Res = *this & Other;
|
|
// Without inbounds, we could only preserve nusw if we know that x + y does
|
|
// not wrap.
|
|
if (!Res.isInBounds() && Res.hasNoUnsignedSignedWrap())
|
|
Res = Res.withoutNoUnsignedSignedWrap();
|
|
return Res;
|
|
}
|
|
|
|
/// Given (gep (gep p, x), y), determine the nowrap flags for
|
|
/// (gep (gep, p, y), x).
|
|
GEPNoWrapFlags intersectForReassociate(GEPNoWrapFlags Other) const {
|
|
GEPNoWrapFlags Res = *this & Other;
|
|
// We can only preserve inbounds and nusw if nuw is also set.
|
|
if (!Res.hasNoUnsignedWrap())
|
|
return none();
|
|
return Res;
|
|
}
|
|
|
|
bool operator==(GEPNoWrapFlags Other) const { return Flags == Other.Flags; }
|
|
bool operator!=(GEPNoWrapFlags Other) const { return !(*this == Other); }
|
|
|
|
GEPNoWrapFlags operator&(GEPNoWrapFlags Other) const {
|
|
return GEPNoWrapFlags(Flags & Other.Flags);
|
|
}
|
|
GEPNoWrapFlags operator|(GEPNoWrapFlags Other) const {
|
|
return GEPNoWrapFlags(Flags | Other.Flags);
|
|
}
|
|
GEPNoWrapFlags &operator&=(GEPNoWrapFlags Other) {
|
|
Flags &= Other.Flags;
|
|
return *this;
|
|
}
|
|
GEPNoWrapFlags &operator|=(GEPNoWrapFlags Other) {
|
|
Flags |= Other.Flags;
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_IR_GEPNOWRAPFLAGS_H
|