Skip to content

Commit 582d463

Browse files
committed
[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
1 parent f388d17 commit 582d463

File tree

4 files changed

+34
-19
lines changed

4 files changed

+34
-19
lines changed

llvm/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,16 @@ class BaseIndexOffset {
6262

6363
// Returns true if `Other` (with size `OtherSize`) can be proven to be fully
6464
// contained in `*this` (with size `Size`).
65-
bool contains(int64_t Size, const BaseIndexOffset &Other, int64_t OtherSize,
66-
const SelectionDAG &DAG) const {
67-
int64_t Offset;
68-
return contains(Size, Other, OtherSize, DAG, Offset);
65+
bool contains(const SelectionDAG &DAG, int64_t BitSize,
66+
const BaseIndexOffset &Other, int64_t OtherBitSize,
67+
int64_t &BitOffset) const;
68+
69+
bool contains(const SelectionDAG &DAG, int64_t BitSize,
70+
const BaseIndexOffset &Other, int64_t OtherBitSize) const {
71+
int64_t BitOffset;
72+
return contains(DAG, BitSize, Other, OtherBitSize, BitOffset);
6973
}
7074

71-
bool contains(int64_t Size, const BaseIndexOffset &Other, int64_t OtherSize,
72-
const SelectionDAG &DAG, int64_t &Offset) const;
73-
7475
// Returns true `BasePtr0` and `BasePtr1` can be proven to alias/not alias, in
7576
// which case `IsAlias` is set to true/false.
7677
static bool computeAliasing(const BaseIndexOffset &BasePtr0,

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15427,13 +15427,13 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
1542715427
!ST1->getBasePtr().isUndef()) {
1542815428
const BaseIndexOffset STBase = BaseIndexOffset::match(ST, DAG);
1542915429
const BaseIndexOffset ChainBase = BaseIndexOffset::match(ST1, DAG);
15430-
unsigned STByteSize = ST->getMemoryVT().getSizeInBits() / 8;
15431-
unsigned ChainByteSize = ST1->getMemoryVT().getSizeInBits() / 8;
15430+
unsigned STBitSize = ST->getMemoryVT().getSizeInBits();
15431+
unsigned ChainBitSize = ST1->getMemoryVT().getSizeInBits();
1543215432
// If this is a store who's preceding store to a subset of the current
1543315433
// location and no one other node is chained to that store we can
1543415434
// effectively drop the store. Do not remove stores to undef as they may
1543515435
// be used as data sinks.
15436-
if (STBase.contains(STByteSize, ChainBase, ChainByteSize, DAG)) {
15436+
if (STBase.contains(DAG, STBitSize, ChainBase, ChainBitSize)) {
1543715437
CombineTo(ST1, ST1->getChain());
1543815438
return SDValue();
1543915439
}
@@ -15442,17 +15442,17 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
1544215442
// able to fold ST's value into the preceding stored value. As we know
1544315443
// the other uses of ST1's chain are unconcerned with ST, this folding
1544415444
// will not affect those nodes.
15445-
int64_t Offset;
15446-
if (ChainBase.contains(ChainByteSize, STBase, STByteSize, DAG,
15447-
Offset)) {
15445+
int64_t BitOffset;
15446+
if (ChainBase.contains(DAG, ChainBitSize, STBase, STBitSize,
15447+
BitOffset)) {
1544815448
SDValue ChainValue = ST1->getValue();
1544915449
if (auto *C1 = dyn_cast<ConstantSDNode>(ChainValue)) {
1545015450
if (auto *C = dyn_cast<ConstantSDNode>(Value)) {
1545115451
APInt Val = C1->getAPIntValue();
15452-
APInt InsertVal = C->getAPIntValue().zextOrTrunc(STByteSize * 8);
15452+
APInt InsertVal = C->getAPIntValue().zextOrTrunc(STBitSize);
1545315453
// FIXME: Handle Big-endian mode.
1545415454
if (!DAG.getDataLayout().isBigEndian()) {
15455-
Val.insertBits(InsertVal, Offset * 8);
15455+
Val.insertBits(InsertVal, BitOffset);
1545615456
SDValue NewSDVal =
1545715457
DAG.getConstant(Val, SDLoc(C), ChainValue.getValueType(),
1545815458
C1->isTargetOpcode(), C1->isOpaque());

llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,19 @@ bool BaseIndexOffset::computeAliasing(const BaseIndexOffset &BasePtr0,
135135
return false; // Cannot determine whether the pointers alias.
136136
}
137137

138-
bool BaseIndexOffset::contains(int64_t Size, const BaseIndexOffset &Other,
139-
int64_t OtherSize, const SelectionDAG &DAG,
140-
int64_t &Offset) const {
138+
bool BaseIndexOffset::contains(const SelectionDAG &DAG, int64_t BitSize,
139+
const BaseIndexOffset &Other,
140+
int64_t OtherBitSize, int64_t &BitOffset) const {
141+
int64_t Offset;
141142
if (!equalBaseIndex(Other, DAG, Offset))
142143
return false;
143144
if (Offset >= 0) {
144145
// Other is after *this:
145146
// [-------*this---------]
146147
// [---Other--]
147148
// ==Offset==>
148-
return Offset + OtherSize <= Size;
149+
BitOffset = 8 * Offset;
150+
return BitOffset + OtherBitSize <= BitSize;
149151
}
150152
// Other starts strictly before *this, it cannot be fully contained.
151153
// [-------*this---------]

llvm/test/CodeGen/X86/constant-combines.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,15 @@ entry:
3838
store float %8, float* %0, align 4
3939
ret void
4040
}
41+
42+
43+
define void @bitstore_fold() {
44+
; CHECK-LABEL: bitstore_fold:
45+
; CHECK: # %bb.0: # %BB
46+
; CHECK-NEXT: movl $-2, 0
47+
; CHECK-NEXT: retq
48+
BB:
49+
store i32 -1, i32* null
50+
store i1 false, i1* null
51+
ret void
52+
}

0 commit comments

Comments
 (0)