[PR29121] Don't fold if it would produce atomic vector loads or stores

The instcombine code which folds loads and stores into their use types can trip up if the use is a bitcast to a type which we can't directly load or store in the IR. In principle, such types shouldn't exist, but in practice they do today. This is a workaround to avoid a bug while we work towards the long term goal.

Differential Revision: https://reviews.llvm.org/D24365

llvm-svn: 288415
This commit is contained in:
Philip Reames 2016-12-01 20:17:06 +00:00
parent bf1a70f1c9
commit 89e92d21b4
2 changed files with 48 additions and 14 deletions

View File

@ -308,6 +308,11 @@ Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) {
return visitAllocSite(AI);
}
// Are we allowed to form a atomic load or store of this type?
static bool isSupportedAtomicType(Type *Ty) {
return Ty->isIntegerTy() || Ty->isPointerTy() || Ty->isFloatingPointTy();
}
/// \brief Helper to combine a load to a new type.
///
/// This just does the work of combining a load to a new type. It handles
@ -319,6 +324,9 @@ Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) {
/// point the \c InstCombiner currently is using.
static LoadInst *combineLoadToNewType(InstCombiner &IC, LoadInst &LI, Type *NewTy,
const Twine &Suffix = "") {
assert((!LI.isAtomic() || isSupportedAtomicType(NewTy)) &&
"can't fold an atomic load to requested type");
Value *Ptr = LI.getPointerOperand();
unsigned AS = LI.getPointerAddressSpace();
SmallVector<std::pair<unsigned, MDNode *>, 8> MD;
@ -400,6 +408,9 @@ static LoadInst *combineLoadToNewType(InstCombiner &IC, LoadInst &LI, Type *NewT
///
/// Returns the newly created store instruction.
static StoreInst *combineStoreToNewValue(InstCombiner &IC, StoreInst &SI, Value *V) {
assert((!SI.isAtomic() || isSupportedAtomicType(V->getType())) &&
"can't fold an atomic store of requested type");
Value *Ptr = SI.getPointerOperand();
unsigned AS = SI.getPointerAddressSpace();
SmallVector<std::pair<unsigned, MDNode *>, 8> MD;
@ -514,14 +525,14 @@ static Instruction *combineLoadToOperationType(InstCombiner &IC, LoadInst &LI) {
// as long as those are noops (i.e., the source or dest type have the same
// bitwidth as the target's pointers).
if (LI.hasOneUse())
if (auto* CI = dyn_cast<CastInst>(LI.user_back())) {
if (CI->isNoopCast(DL)) {
LoadInst *NewLoad = combineLoadToNewType(IC, LI, CI->getDestTy());
CI->replaceAllUsesWith(NewLoad);
IC.eraseInstFromFunction(*CI);
return &LI;
}
}
if (auto* CI = dyn_cast<CastInst>(LI.user_back()))
if (CI->isNoopCast(DL))
if (!LI.isAtomic() || isSupportedAtomicType(CI->getDestTy())) {
LoadInst *NewLoad = combineLoadToNewType(IC, LI, CI->getDestTy());
CI->replaceAllUsesWith(NewLoad);
IC.eraseInstFromFunction(*CI);
return &LI;
}
// FIXME: We should also canonicalize loads of vectors when their elements are
// cast to other types.
@ -1026,14 +1037,17 @@ static bool combineStoreToValueType(InstCombiner &IC, StoreInst &SI) {
// Fold away bit casts of the stored value by storing the original type.
if (auto *BC = dyn_cast<BitCastInst>(V)) {
V = BC->getOperand(0);
combineStoreToNewValue(IC, SI, V);
return true;
if (!SI.isAtomic() || isSupportedAtomicType(V->getType())) {
combineStoreToNewValue(IC, SI, V);
return true;
}
}
if (Value *U = likeBitCastFromVector(IC, V)) {
combineStoreToNewValue(IC, SI, U);
return true;
}
if (Value *U = likeBitCastFromVector(IC, V))
if (!SI.isAtomic() || isSupportedAtomicType(U->getType())) {
combineStoreToNewValue(IC, SI, U);
return true;
}
// FIXME: We should also canonicalize stores of vectors when their elements
// are cast to other types.

View File

@ -267,3 +267,23 @@ define void @pr27490b(i8** %p1, i8** %p2) {
store atomic i8* %l, i8** %p2 seq_cst, align 8
ret void
}
;; At the moment, we can't form atomic vectors by folding since these are
;; not representable in the IR. This was pr29121. The right long term
;; solution is to extend the IR to handle this case.
define <2 x float> @no_atomic_vector_load(i64* %p) {
; CHECK-LABEL @no_atomic_vector_load
; CHECK: load atomic i64, i64* %p unordered, align 8
%load = load atomic i64, i64* %p unordered, align 8
%.cast = bitcast i64 %load to <2 x float>
ret <2 x float> %.cast
}
define void @no_atomic_vector_store(<2 x float> %p, i8* %p2) {
; CHECK-LABEL: @no_atomic_vector_store
; CHECK: store atomic i64 %1, i64* %2 unordered, align 8
%1 = bitcast <2 x float> %p to i64
%2 = bitcast i8* %p2 to i64*
store atomic i64 %1, i64* %2 unordered, align 8
ret void
}