mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Create instruction classes for identifying any atomicity of memory intrinsic. (NFC)
Summary: For reference, see: http://lists.llvm.org/pipermail/llvm-dev/2017-August/116589.html This patch fleshes out the instruction class hierarchy with respect to atomic and non-atomic memory intrinsics. With this change, the relevant part of the class hierarchy becomes: IntrinsicInst -> MemIntrinsicBase (methods-only class) -> MemIntrinsic (non-atomic intrinsics) -> MemSetInst -> MemTransferInst -> MemCpyInst -> MemMoveInst -> AtomicMemIntrinsic (atomic intrinsics) -> AtomicMemSetInst -> AtomicMemTransferInst -> AtomicMemCpyInst -> AtomicMemMoveInst -> AnyMemIntrinsic (both atomicities) -> AnyMemSetInst -> AnyMemTransferInst -> AnyMemCpyInst -> AnyMemMoveInst This involves some class renaming: ElementUnorderedAtomicMemCpyInst -> AtomicMemCpyInst ElementUnorderedAtomicMemMoveInst -> AtomicMemMoveInst ElementUnorderedAtomicMemSetInst -> AtomicMemSetInst A script for doing this renaming in downstream trees is included below. An example of where the Any* classes should be used in LLVM is when reasoning about the effects of an instruction (ex: aliasing). --- Script for renaming AtomicMem* classes: PREFIXES="[<,([:space:]]" CLASSES="MemIntrinsic|MemTransferInst|MemSetInst|MemMoveInst|MemCpyInst" SUFFIXES="[;)>,[:space:]]" REGEX="(${PREFIXES})ElementUnorderedAtomic(${CLASSES})(${SUFFIXES})" REGEX2="visitElementUnorderedAtomic(${CLASSES})" FILES=$( grep -E "(${REGEX}|${REGEX2})" -r . | tr ':' ' ' | awk '{print $1}' | sort | uniq ) SED_SCRIPT="s~${REGEX}~\1Atomic\2\3~g" SED_SCRIPT2="s~${REGEX2}~visitAtomic\1~g" for f in $FILES; do echo "Processing: $f" sed -i ".bak" -E "${SED_SCRIPT};${SED_SCRIPT2};${EA_SED_SCRIPT};${EA_SED_SCRIPT2}" $f done Reviewers: sanjoy, deadalnix, apilipenko, anna, skatkov, mkazantsev Reviewed By: sanjoy Subscribers: hfinkel, jholewinski, arsenm, sdardis, nhaehnle, JDevlieghere, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D38419 llvm-svn: 316950
This commit is contained in:
parent
67b94b1157
commit
0ad57a67a0
@ -213,12 +213,13 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
|
||||
/// This class represents atomic memcpy intrinsic
|
||||
/// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is
|
||||
/// C&P of all methods from that hierarchy
|
||||
class ElementUnorderedAtomicMemCpyInst : public IntrinsicInst {
|
||||
/// Common base class for all memory intrinsics. Simply provides
|
||||
/// common methods.
|
||||
/// Written as CRTP to avoid a common base class amongst the
|
||||
/// three atomicity hierarchies.
|
||||
template <typename Derived> class MemIntrinsicBase : public IntrinsicInst {
|
||||
private:
|
||||
enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };
|
||||
enum { ARG_DEST = 0, ARG_LENGTH = 2 };
|
||||
|
||||
public:
|
||||
Value *getRawDest() const {
|
||||
@ -227,21 +228,42 @@ namespace llvm {
|
||||
const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
|
||||
Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
|
||||
|
||||
/// Return the arguments to the instruction.
|
||||
Value *getRawSource() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_SOURCE));
|
||||
}
|
||||
const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
|
||||
Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
|
||||
|
||||
Value *getLength() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_LENGTH));
|
||||
}
|
||||
const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
|
||||
Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
|
||||
|
||||
bool isVolatile() const { return false; }
|
||||
/// This is just like getRawDest, but it strips off any cast
|
||||
/// instructions (including addrspacecast) that feed it, giving the
|
||||
/// original input. The returned value is guaranteed to be a pointer.
|
||||
Value *getDest() const { return getRawDest()->stripPointerCasts(); }
|
||||
|
||||
unsigned getDestAddressSpace() const {
|
||||
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
|
||||
}
|
||||
|
||||
/// Set the specified arguments of the instruction.
|
||||
void setDest(Value *Ptr) {
|
||||
assert(getRawDest()->getType() == Ptr->getType() &&
|
||||
"setDest called with pointer of wrong type!");
|
||||
setArgOperand(ARG_DEST, Ptr);
|
||||
}
|
||||
|
||||
void setLength(Value *L) {
|
||||
assert(getLength()->getType() == L->getType() &&
|
||||
"setLength called with value of wrong type!");
|
||||
setArgOperand(ARG_LENGTH, L);
|
||||
}
|
||||
};
|
||||
|
||||
// The common base class for the atomic memset/memmove/memcpy intrinsics
|
||||
// i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
|
||||
class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> {
|
||||
private:
|
||||
enum { ARG_ELEMENTSIZE = 3 };
|
||||
|
||||
public:
|
||||
Value *getRawElementSizeInBytes() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
|
||||
}
|
||||
@ -254,43 +276,6 @@ namespace llvm {
|
||||
return getElementSizeInBytesCst()->getZExtValue();
|
||||
}
|
||||
|
||||
/// This is just like getRawDest, but it strips off any cast
|
||||
/// instructions that feed it, giving the original input. The returned
|
||||
/// value is guaranteed to be a pointer.
|
||||
Value *getDest() const { return getRawDest()->stripPointerCasts(); }
|
||||
|
||||
/// This is just like getRawSource, but it strips off any cast
|
||||
/// instructions that feed it, giving the original input. The returned
|
||||
/// value is guaranteed to be a pointer.
|
||||
Value *getSource() const { return getRawSource()->stripPointerCasts(); }
|
||||
|
||||
unsigned getDestAddressSpace() const {
|
||||
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
|
||||
}
|
||||
|
||||
unsigned getSourceAddressSpace() const {
|
||||
return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
|
||||
}
|
||||
|
||||
/// Set the specified arguments of the instruction.
|
||||
void setDest(Value *Ptr) {
|
||||
assert(getRawDest()->getType() == Ptr->getType() &&
|
||||
"setDest called with pointer of wrong type!");
|
||||
setArgOperand(ARG_DEST, Ptr);
|
||||
}
|
||||
|
||||
void setSource(Value *Ptr) {
|
||||
assert(getRawSource()->getType() == Ptr->getType() &&
|
||||
"setSource called with pointer of wrong type!");
|
||||
setArgOperand(ARG_SOURCE, Ptr);
|
||||
}
|
||||
|
||||
void setLength(Value *L) {
|
||||
assert(getLength()->getType() == L->getType() &&
|
||||
"setLength called with value of wrong type!");
|
||||
setArgOperand(ARG_LENGTH, L);
|
||||
}
|
||||
|
||||
void setElementSizeInBytes(Constant *V) {
|
||||
assert(V->getType() == Type::getInt8Ty(getContext()) &&
|
||||
"setElementSizeInBytes called with value of wrong type!");
|
||||
@ -298,24 +283,54 @@ namespace llvm {
|
||||
}
|
||||
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic;
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::memcpy_element_unordered_atomic:
|
||||
case Intrinsic::memmove_element_unordered_atomic:
|
||||
case Intrinsic::memset_element_unordered_atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
class ElementUnorderedAtomicMemMoveInst : public IntrinsicInst {
|
||||
/// This class represents atomic memset intrinsic
|
||||
// i.e. llvm.element.unordered.atomic.memset
|
||||
class AtomicMemSetInst : public AtomicMemIntrinsic {
|
||||
private:
|
||||
enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };
|
||||
enum { ARG_VALUE = 1 };
|
||||
|
||||
public:
|
||||
Value *getRawDest() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_DEST));
|
||||
Value *getValue() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_VALUE));
|
||||
}
|
||||
const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
|
||||
Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
|
||||
const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); }
|
||||
Use &getValueUse() { return getArgOperandUse(ARG_VALUE); }
|
||||
|
||||
void setValue(Value *Val) {
|
||||
assert(getValue()->getType() == Val->getType() &&
|
||||
"setValue called with value of wrong type!");
|
||||
setArgOperand(ARG_VALUE, Val);
|
||||
}
|
||||
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic;
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
// This class wraps the atomic memcpy/memmove intrinsics
|
||||
// i.e. llvm.element.unordered.atomic.memcpy/memmove
|
||||
class AtomicMemTransferInst : public AtomicMemIntrinsic {
|
||||
private:
|
||||
enum { ARG_SOURCE = 1 };
|
||||
|
||||
public:
|
||||
/// Return the arguments to the instruction.
|
||||
Value *getRawSource() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_SOURCE));
|
||||
@ -323,170 +338,67 @@ namespace llvm {
|
||||
const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
|
||||
Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
|
||||
|
||||
Value *getLength() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_LENGTH));
|
||||
}
|
||||
const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
|
||||
Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
|
||||
|
||||
bool isVolatile() const { return false; }
|
||||
|
||||
Value *getRawElementSizeInBytes() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
|
||||
}
|
||||
|
||||
ConstantInt *getElementSizeInBytesCst() const {
|
||||
return cast<ConstantInt>(getRawElementSizeInBytes());
|
||||
}
|
||||
|
||||
uint32_t getElementSizeInBytes() const {
|
||||
return getElementSizeInBytesCst()->getZExtValue();
|
||||
}
|
||||
|
||||
/// This is just like getRawDest, but it strips off any cast
|
||||
/// instructions that feed it, giving the original input. The returned
|
||||
/// value is guaranteed to be a pointer.
|
||||
Value *getDest() const { return getRawDest()->stripPointerCasts(); }
|
||||
|
||||
/// This is just like getRawSource, but it strips off any cast
|
||||
/// instructions that feed it, giving the original input. The returned
|
||||
/// value is guaranteed to be a pointer.
|
||||
Value *getSource() const { return getRawSource()->stripPointerCasts(); }
|
||||
|
||||
unsigned getDestAddressSpace() const {
|
||||
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
|
||||
}
|
||||
|
||||
unsigned getSourceAddressSpace() const {
|
||||
return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
|
||||
}
|
||||
|
||||
/// Set the specified arguments of the instruction.
|
||||
void setDest(Value *Ptr) {
|
||||
assert(getRawDest()->getType() == Ptr->getType() &&
|
||||
"setDest called with pointer of wrong type!");
|
||||
setArgOperand(ARG_DEST, Ptr);
|
||||
}
|
||||
|
||||
void setSource(Value *Ptr) {
|
||||
assert(getRawSource()->getType() == Ptr->getType() &&
|
||||
"setSource called with pointer of wrong type!");
|
||||
setArgOperand(ARG_SOURCE, Ptr);
|
||||
}
|
||||
|
||||
void setLength(Value *L) {
|
||||
assert(getLength()->getType() == L->getType() &&
|
||||
"setLength called with value of wrong type!");
|
||||
setArgOperand(ARG_LENGTH, L);
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::memcpy_element_unordered_atomic:
|
||||
case Intrinsic::memmove_element_unordered_atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void setElementSizeInBytes(Constant *V) {
|
||||
assert(V->getType() == Type::getInt8Ty(getContext()) &&
|
||||
"setElementSizeInBytes called with value of wrong type!");
|
||||
setArgOperand(ARG_ELEMENTSIZE, V);
|
||||
}
|
||||
|
||||
static inline bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// This class represents atomic memset intrinsic
|
||||
/// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is
|
||||
/// C&P of all methods from that hierarchy
|
||||
class ElementUnorderedAtomicMemSetInst : public IntrinsicInst {
|
||||
private:
|
||||
enum { ARG_DEST = 0, ARG_VALUE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };
|
||||
|
||||
/// This class represents the atomic memcpy intrinsic
|
||||
/// i.e. llvm.element.unordered.atomic.memcpy
|
||||
class AtomicMemCpyInst : public AtomicMemTransferInst {
|
||||
public:
|
||||
Value *getRawDest() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_DEST));
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic;
|
||||
}
|
||||
const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
|
||||
Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
|
||||
|
||||
Value *getValue() const { return const_cast<Value*>(getArgOperand(ARG_VALUE)); }
|
||||
const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); }
|
||||
Use &getValueUse() { return getArgOperandUse(ARG_VALUE); }
|
||||
|
||||
Value *getLength() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_LENGTH));
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
|
||||
Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
|
||||
};
|
||||
|
||||
bool isVolatile() const { return false; }
|
||||
|
||||
Value *getRawElementSizeInBytes() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
|
||||
/// This class represents the atomic memmove intrinsic
|
||||
/// i.e. llvm.element.unordered.atomic.memmove
|
||||
class AtomicMemMoveInst : public AtomicMemTransferInst {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic;
|
||||
}
|
||||
|
||||
ConstantInt *getElementSizeInBytesCst() const {
|
||||
return cast<ConstantInt>(getRawElementSizeInBytes());
|
||||
}
|
||||
|
||||
uint32_t getElementSizeInBytes() const {
|
||||
return getElementSizeInBytesCst()->getZExtValue();
|
||||
}
|
||||
|
||||
/// This is just like getRawDest, but it strips off any cast
|
||||
/// instructions that feed it, giving the original input. The returned
|
||||
/// value is guaranteed to be a pointer.
|
||||
Value *getDest() const { return getRawDest()->stripPointerCasts(); }
|
||||
|
||||
unsigned getDestAddressSpace() const {
|
||||
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
|
||||
}
|
||||
|
||||
/// Set the specified arguments of the instruction.
|
||||
void setDest(Value *Ptr) {
|
||||
assert(getRawDest()->getType() == Ptr->getType() &&
|
||||
"setDest called with pointer of wrong type!");
|
||||
setArgOperand(ARG_DEST, Ptr);
|
||||
}
|
||||
|
||||
void setValue(Value *Val) {
|
||||
assert(getValue()->getType() == Val->getType() &&
|
||||
"setValue called with value of wrong type!");
|
||||
setArgOperand(ARG_VALUE, Val);
|
||||
}
|
||||
|
||||
void setLength(Value *L) {
|
||||
assert(getLength()->getType() == L->getType() &&
|
||||
"setLength called with value of wrong type!");
|
||||
setArgOperand(ARG_LENGTH, L);
|
||||
}
|
||||
|
||||
void setElementSizeInBytes(Constant *V) {
|
||||
assert(V->getType() == Type::getInt8Ty(getContext()) &&
|
||||
"setElementSizeInBytes called with value of wrong type!");
|
||||
setArgOperand(ARG_ELEMENTSIZE, V);
|
||||
}
|
||||
|
||||
static inline bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// This is the common base class for memset/memcpy/memmove.
|
||||
class MemIntrinsic : public IntrinsicInst {
|
||||
class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> {
|
||||
private:
|
||||
enum { ARG_ALIGN = 3, ARG_VOLATILE = 4 };
|
||||
|
||||
public:
|
||||
Value *getRawDest() const { return const_cast<Value*>(getArgOperand(0)); }
|
||||
const Use &getRawDestUse() const { return getArgOperandUse(0); }
|
||||
Use &getRawDestUse() { return getArgOperandUse(0); }
|
||||
|
||||
Value *getLength() const { return const_cast<Value*>(getArgOperand(2)); }
|
||||
const Use &getLengthUse() const { return getArgOperandUse(2); }
|
||||
Use &getLengthUse() { return getArgOperandUse(2); }
|
||||
|
||||
ConstantInt *getAlignmentCst() const {
|
||||
return cast<ConstantInt>(const_cast<Value*>(getArgOperand(3)));
|
||||
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_ALIGN)));
|
||||
}
|
||||
|
||||
unsigned getAlignment() const {
|
||||
@ -494,45 +406,20 @@ namespace llvm {
|
||||
}
|
||||
|
||||
ConstantInt *getVolatileCst() const {
|
||||
return cast<ConstantInt>(const_cast<Value*>(getArgOperand(4)));
|
||||
return cast<ConstantInt>(
|
||||
const_cast<Value *>(getArgOperand(ARG_VOLATILE)));
|
||||
}
|
||||
|
||||
bool isVolatile() const {
|
||||
return !getVolatileCst()->isZero();
|
||||
}
|
||||
|
||||
unsigned getDestAddressSpace() const {
|
||||
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
|
||||
}
|
||||
void setAlignment(Constant *A) { setArgOperand(ARG_ALIGN, A); }
|
||||
|
||||
/// This is just like getRawDest, but it strips off any cast
|
||||
/// instructions that feed it, giving the original input. The returned
|
||||
/// value is guaranteed to be a pointer.
|
||||
Value *getDest() const { return getRawDest()->stripPointerCasts(); }
|
||||
|
||||
/// Set the specified arguments of the instruction.
|
||||
void setDest(Value *Ptr) {
|
||||
assert(getRawDest()->getType() == Ptr->getType() &&
|
||||
"setDest called with pointer of wrong type!");
|
||||
setArgOperand(0, Ptr);
|
||||
}
|
||||
|
||||
void setLength(Value *L) {
|
||||
assert(getLength()->getType() == L->getType() &&
|
||||
"setLength called with value of wrong type!");
|
||||
setArgOperand(2, L);
|
||||
}
|
||||
|
||||
void setAlignment(Constant* A) {
|
||||
setArgOperand(3, A);
|
||||
}
|
||||
|
||||
void setVolatile(Constant* V) {
|
||||
setArgOperand(4, V);
|
||||
}
|
||||
void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); }
|
||||
|
||||
Type *getAlignmentType() const {
|
||||
return getArgOperand(3)->getType();
|
||||
return getArgOperand(ARG_ALIGN)->getType();
|
||||
}
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
@ -630,6 +517,155 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
|
||||
// The common base class for any memset/memmove/memcpy intrinsics;
|
||||
// whether they be atomic or non-atomic.
|
||||
// i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
|
||||
// and llvm.memset/memcpy/memmove
|
||||
class AnyMemIntrinsic : public MemIntrinsicBase<AnyMemIntrinsic> {
|
||||
public:
|
||||
bool isVolatile() const {
|
||||
// Only the non-atomic intrinsics can be volatile
|
||||
if (auto *MI = dyn_cast<MemIntrinsic>(this))
|
||||
return MI->isVolatile();
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::memcpy:
|
||||
case Intrinsic::memmove:
|
||||
case Intrinsic::memset:
|
||||
case Intrinsic::memcpy_element_unordered_atomic:
|
||||
case Intrinsic::memmove_element_unordered_atomic:
|
||||
case Intrinsic::memset_element_unordered_atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// This class represents any memset intrinsic
|
||||
// i.e. llvm.element.unordered.atomic.memset
|
||||
// and llvm.memset
|
||||
class AnyMemSetInst : public AnyMemIntrinsic {
|
||||
private:
|
||||
enum { ARG_VALUE = 1 };
|
||||
|
||||
public:
|
||||
Value *getValue() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_VALUE));
|
||||
}
|
||||
const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); }
|
||||
Use &getValueUse() { return getArgOperandUse(ARG_VALUE); }
|
||||
|
||||
void setValue(Value *Val) {
|
||||
assert(getValue()->getType() == Val->getType() &&
|
||||
"setValue called with value of wrong type!");
|
||||
setArgOperand(ARG_VALUE, Val);
|
||||
}
|
||||
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::memset:
|
||||
case Intrinsic::memset_element_unordered_atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
// This class wraps any memcpy/memmove intrinsics
|
||||
// i.e. llvm.element.unordered.atomic.memcpy/memmove
|
||||
// and llvm.memcpy/memmove
|
||||
class AnyMemTransferInst : public AnyMemIntrinsic {
|
||||
private:
|
||||
enum { ARG_SOURCE = 1 };
|
||||
|
||||
public:
|
||||
/// Return the arguments to the instruction.
|
||||
Value *getRawSource() const {
|
||||
return const_cast<Value *>(getArgOperand(ARG_SOURCE));
|
||||
}
|
||||
const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
|
||||
Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
|
||||
|
||||
/// This is just like getRawSource, but it strips off any cast
|
||||
/// instructions that feed it, giving the original input. The returned
|
||||
/// value is guaranteed to be a pointer.
|
||||
Value *getSource() const { return getRawSource()->stripPointerCasts(); }
|
||||
|
||||
unsigned getSourceAddressSpace() const {
|
||||
return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
|
||||
}
|
||||
|
||||
void setSource(Value *Ptr) {
|
||||
assert(getRawSource()->getType() == Ptr->getType() &&
|
||||
"setSource called with pointer of wrong type!");
|
||||
setArgOperand(ARG_SOURCE, Ptr);
|
||||
}
|
||||
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::memcpy:
|
||||
case Intrinsic::memmove:
|
||||
case Intrinsic::memcpy_element_unordered_atomic:
|
||||
case Intrinsic::memmove_element_unordered_atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// This class represents any memcpy intrinsic
|
||||
/// i.e. llvm.element.unordered.atomic.memcpy
|
||||
/// and llvm.memcpy
|
||||
class AnyMemCpyInst : public AnyMemTransferInst {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::memcpy:
|
||||
case Intrinsic::memcpy_element_unordered_atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// This class represents any memmove intrinsic
|
||||
/// i.e. llvm.element.unordered.atomic.memmove
|
||||
/// and llvm.memmove
|
||||
class AnyMemMoveInst : public AnyMemTransferInst {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::memmove:
|
||||
case Intrinsic::memmove_element_unordered_atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents the llvm.va_start intrinsic.
|
||||
class VAStartInst : public IntrinsicInst {
|
||||
public:
|
||||
|
@ -5044,8 +5044,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||
return nullptr;
|
||||
}
|
||||
case Intrinsic::memcpy_element_unordered_atomic: {
|
||||
const ElementUnorderedAtomicMemCpyInst &MI =
|
||||
cast<ElementUnorderedAtomicMemCpyInst>(I);
|
||||
const AtomicMemCpyInst &MI = cast<AtomicMemCpyInst>(I);
|
||||
SDValue Dst = getValue(MI.getRawDest());
|
||||
SDValue Src = getValue(MI.getRawSource());
|
||||
SDValue Length = getValue(MI.getLength());
|
||||
@ -5083,7 +5082,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||
return nullptr;
|
||||
}
|
||||
case Intrinsic::memmove_element_unordered_atomic: {
|
||||
auto &MI = cast<ElementUnorderedAtomicMemMoveInst>(I);
|
||||
auto &MI = cast<AtomicMemMoveInst>(I);
|
||||
SDValue Dst = getValue(MI.getRawDest());
|
||||
SDValue Src = getValue(MI.getRawSource());
|
||||
SDValue Length = getValue(MI.getLength());
|
||||
@ -5121,7 +5120,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||
return nullptr;
|
||||
}
|
||||
case Intrinsic::memset_element_unordered_atomic: {
|
||||
auto &MI = cast<ElementUnorderedAtomicMemSetInst>(I);
|
||||
auto &MI = cast<AtomicMemSetInst>(I);
|
||||
SDValue Dst = getValue(MI.getRawDest());
|
||||
SDValue Val = getValue(MI.getValue());
|
||||
SDValue Length = getValue(MI.getLength());
|
||||
|
@ -4029,9 +4029,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
|
||||
break;
|
||||
}
|
||||
case Intrinsic::memcpy_element_unordered_atomic: {
|
||||
const ElementUnorderedAtomicMemCpyInst *MI =
|
||||
cast<ElementUnorderedAtomicMemCpyInst>(CS.getInstruction());
|
||||
;
|
||||
const AtomicMemCpyInst *MI = cast<AtomicMemCpyInst>(CS.getInstruction());
|
||||
|
||||
ConstantInt *ElementSizeCI =
|
||||
dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
|
||||
@ -4066,7 +4064,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
|
||||
break;
|
||||
}
|
||||
case Intrinsic::memmove_element_unordered_atomic: {
|
||||
auto *MI = cast<ElementUnorderedAtomicMemMoveInst>(CS.getInstruction());
|
||||
auto *MI = cast<AtomicMemMoveInst>(CS.getInstruction());
|
||||
|
||||
ConstantInt *ElementSizeCI =
|
||||
dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
|
||||
@ -4101,7 +4099,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
|
||||
break;
|
||||
}
|
||||
case Intrinsic::memset_element_unordered_atomic: {
|
||||
auto *MI = cast<ElementUnorderedAtomicMemSetInst>(CS.getInstruction());
|
||||
auto *MI = cast<AtomicMemSetInst>(CS.getInstruction());
|
||||
|
||||
ConstantInt *ElementSizeCI =
|
||||
dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
|
||||
|
@ -106,8 +106,8 @@ static Constant *getNegativeIsTrueBoolVec(ConstantDataVector *V) {
|
||||
return ConstantVector::get(BoolVec);
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::SimplifyElementUnorderedAtomicMemCpy(
|
||||
ElementUnorderedAtomicMemCpyInst *AMI) {
|
||||
Instruction *
|
||||
InstCombiner::SimplifyElementUnorderedAtomicMemCpy(AtomicMemCpyInst *AMI) {
|
||||
// Try to unfold this intrinsic into sequence of explicit atomic loads and
|
||||
// stores.
|
||||
// First check that number of elements is compile time constant.
|
||||
@ -1877,7 +1877,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
||||
if (Changed) return II;
|
||||
}
|
||||
|
||||
if (auto *AMI = dyn_cast<ElementUnorderedAtomicMemCpyInst>(II)) {
|
||||
if (auto *AMI = dyn_cast<AtomicMemCpyInst>(II)) {
|
||||
if (Constant *C = dyn_cast<Constant>(AMI->getLength()))
|
||||
if (C->isNullValue())
|
||||
return eraseInstFromFunction(*AMI);
|
||||
|
@ -789,8 +789,7 @@ private:
|
||||
Instruction *MatchBSwap(BinaryOperator &I);
|
||||
bool SimplifyStoreAtEndOfBlock(StoreInst &SI);
|
||||
|
||||
Instruction *
|
||||
SimplifyElementUnorderedAtomicMemCpy(ElementUnorderedAtomicMemCpyInst *AMI);
|
||||
Instruction *SimplifyElementUnorderedAtomicMemCpy(AtomicMemCpyInst *AMI);
|
||||
Instruction *SimplifyMemTransfer(MemIntrinsic *MI);
|
||||
Instruction *SimplifyMemSet(MemSetInst *MI);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user