1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[DAG] Fix constant store folding to handle non-byte sizes.

Avoid crashes from zero-byte values due to sub-byte store sizes.

Reviewers: uabelho, courbet, rnk

Reviewed By: courbet

Subscribers: hiraditya, llvm-commits

Tags: #llvm

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

llvm-svn: 354884
This commit is contained in:
Nirav Dave 2019-02-26 15:02:32 +00:00
parent f7725376c2
commit 5dd611ec6e
4 changed files with 34 additions and 19 deletions

View File

@ -62,14 +62,15 @@ public:
// Returns true if `Other` (with size `OtherSize`) can be proven to be fully // Returns true if `Other` (with size `OtherSize`) can be proven to be fully
// contained in `*this` (with size `Size`). // contained in `*this` (with size `Size`).
bool contains(int64_t Size, const BaseIndexOffset &Other, int64_t OtherSize, bool contains(const SelectionDAG &DAG, int64_t BitSize,
const SelectionDAG &DAG) const { const BaseIndexOffset &Other, int64_t OtherBitSize,
int64_t Offset; int64_t &BitOffset) const;
return contains(Size, Other, OtherSize, DAG, Offset);
}
bool contains(int64_t Size, const BaseIndexOffset &Other, int64_t OtherSize, bool contains(const SelectionDAG &DAG, int64_t BitSize,
const SelectionDAG &DAG, int64_t &Offset) const; const BaseIndexOffset &Other, int64_t OtherBitSize) const {
int64_t BitOffset;
return contains(DAG, BitSize, Other, OtherBitSize, BitOffset);
}
// Returns true `BasePtr0` and `BasePtr1` can be proven to alias/not alias, in // Returns true `BasePtr0` and `BasePtr1` can be proven to alias/not alias, in
// which case `IsAlias` is set to true/false. // which case `IsAlias` is set to true/false.

View File

@ -15427,13 +15427,13 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
!ST1->getBasePtr().isUndef()) { !ST1->getBasePtr().isUndef()) {
const BaseIndexOffset STBase = BaseIndexOffset::match(ST, DAG); const BaseIndexOffset STBase = BaseIndexOffset::match(ST, DAG);
const BaseIndexOffset ChainBase = BaseIndexOffset::match(ST1, DAG); const BaseIndexOffset ChainBase = BaseIndexOffset::match(ST1, DAG);
unsigned STByteSize = ST->getMemoryVT().getSizeInBits() / 8; unsigned STBitSize = ST->getMemoryVT().getSizeInBits();
unsigned ChainByteSize = ST1->getMemoryVT().getSizeInBits() / 8; unsigned ChainBitSize = ST1->getMemoryVT().getSizeInBits();
// If this is a store who's preceding store to a subset of the current // If this is a store who's preceding store to a subset of the current
// location and no one other node is chained to that store we can // location and no one other node is chained to that store we can
// effectively drop the store. Do not remove stores to undef as they may // effectively drop the store. Do not remove stores to undef as they may
// be used as data sinks. // be used as data sinks.
if (STBase.contains(STByteSize, ChainBase, ChainByteSize, DAG)) { if (STBase.contains(DAG, STBitSize, ChainBase, ChainBitSize)) {
CombineTo(ST1, ST1->getChain()); CombineTo(ST1, ST1->getChain());
return SDValue(); return SDValue();
} }
@ -15442,17 +15442,17 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
// able to fold ST's value into the preceding stored value. As we know // able to fold ST's value into the preceding stored value. As we know
// the other uses of ST1's chain are unconcerned with ST, this folding // the other uses of ST1's chain are unconcerned with ST, this folding
// will not affect those nodes. // will not affect those nodes.
int64_t Offset; int64_t BitOffset;
if (ChainBase.contains(ChainByteSize, STBase, STByteSize, DAG, if (ChainBase.contains(DAG, ChainBitSize, STBase, STBitSize,
Offset)) { BitOffset)) {
SDValue ChainValue = ST1->getValue(); SDValue ChainValue = ST1->getValue();
if (auto *C1 = dyn_cast<ConstantSDNode>(ChainValue)) { if (auto *C1 = dyn_cast<ConstantSDNode>(ChainValue)) {
if (auto *C = dyn_cast<ConstantSDNode>(Value)) { if (auto *C = dyn_cast<ConstantSDNode>(Value)) {
APInt Val = C1->getAPIntValue(); APInt Val = C1->getAPIntValue();
APInt InsertVal = C->getAPIntValue().zextOrTrunc(STByteSize * 8); APInt InsertVal = C->getAPIntValue().zextOrTrunc(STBitSize);
// FIXME: Handle Big-endian mode. // FIXME: Handle Big-endian mode.
if (!DAG.getDataLayout().isBigEndian()) { if (!DAG.getDataLayout().isBigEndian()) {
Val.insertBits(InsertVal, Offset * 8); Val.insertBits(InsertVal, BitOffset);
SDValue NewSDVal = SDValue NewSDVal =
DAG.getConstant(Val, SDLoc(C), ChainValue.getValueType(), DAG.getConstant(Val, SDLoc(C), ChainValue.getValueType(),
C1->isTargetOpcode(), C1->isOpaque()); C1->isTargetOpcode(), C1->isOpaque());

View File

@ -135,9 +135,10 @@ bool BaseIndexOffset::computeAliasing(const BaseIndexOffset &BasePtr0,
return false; // Cannot determine whether the pointers alias. return false; // Cannot determine whether the pointers alias.
} }
bool BaseIndexOffset::contains(int64_t Size, const BaseIndexOffset &Other, bool BaseIndexOffset::contains(const SelectionDAG &DAG, int64_t BitSize,
int64_t OtherSize, const SelectionDAG &DAG, const BaseIndexOffset &Other,
int64_t &Offset) const { int64_t OtherBitSize, int64_t &BitOffset) const {
int64_t Offset;
if (!equalBaseIndex(Other, DAG, Offset)) if (!equalBaseIndex(Other, DAG, Offset))
return false; return false;
if (Offset >= 0) { if (Offset >= 0) {
@ -145,7 +146,8 @@ bool BaseIndexOffset::contains(int64_t Size, const BaseIndexOffset &Other,
// [-------*this---------] // [-------*this---------]
// [---Other--] // [---Other--]
// ==Offset==> // ==Offset==>
return Offset + OtherSize <= Size; BitOffset = 8 * Offset;
return BitOffset + OtherBitSize <= BitSize;
} }
// Other starts strictly before *this, it cannot be fully contained. // Other starts strictly before *this, it cannot be fully contained.
// [-------*this---------] // [-------*this---------]

View File

@ -38,3 +38,15 @@ entry:
store float %8, float* %0, align 4 store float %8, float* %0, align 4
ret void ret void
} }
define void @bitstore_fold() {
; CHECK-LABEL: bitstore_fold:
; CHECK: # %bb.0: # %BB
; CHECK-NEXT: movl $-2, 0
; CHECK-NEXT: retq
BB:
store i32 -1, i32* null
store i1 false, i1* null
ret void
}