Skip to content

Commit 8fdc3ff

Browse files
author
Dinar Temirbulatov
committed
[DAGCombine] Allow scalable type dead store elimination.
Add support to allow removing a dead store for scalable types. Avoid to remove scalable type store in favor of fixed type store, since scalable type size is unknown at the compile time. Differential Revision: https://reviews.llvm.org/D142100
1 parent aef05b5 commit 8fdc3ff

File tree

2 files changed

+81
-20
lines changed

2 files changed

+81
-20
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19923,22 +19923,32 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
1992319923

1992419924
if (OptLevel != CodeGenOpt::None && ST1->hasOneUse() &&
1992519925
!ST1->getBasePtr().isUndef() &&
19926-
// BaseIndexOffset and the code below requires knowing the size
19927-
// of a vector, so bail out if MemoryVT is scalable.
19928-
!ST->getMemoryVT().isScalableVector() &&
19929-
!ST1->getMemoryVT().isScalableVector() &&
1993019926
ST->getAddressSpace() == ST1->getAddressSpace()) {
19931-
const BaseIndexOffset STBase = BaseIndexOffset::match(ST, DAG);
19932-
const BaseIndexOffset ChainBase = BaseIndexOffset::match(ST1, DAG);
19933-
unsigned STBitSize = ST->getMemoryVT().getFixedSizeInBits();
19934-
unsigned ChainBitSize = ST1->getMemoryVT().getFixedSizeInBits();
19935-
// If this is a store who's preceding store to a subset of the current
19936-
// location and no one other node is chained to that store we can
19937-
// effectively drop the store. Do not remove stores to undef as they may
19938-
// be used as data sinks.
19939-
if (STBase.contains(DAG, STBitSize, ChainBase, ChainBitSize)) {
19940-
CombineTo(ST1, ST1->getChain());
19941-
return SDValue();
19927+
// If we consider two stores and one smaller in size is a scalable
19928+
// vector type and another one a bigger size store with a fixed type,
19929+
// then we could not allow the scalable store removal because we don't
19930+
// know its final size in the end.
19931+
if (ST->getMemoryVT().isScalableVector() ||
19932+
ST1->getMemoryVT().isScalableVector()) {
19933+
if (ST1->getBasePtr() == Ptr &&
19934+
TypeSize::isKnownLE(ST1->getMemoryVT().getStoreSize(),
19935+
ST->getMemoryVT().getStoreSize())) {
19936+
CombineTo(ST1, ST1->getChain());
19937+
return SDValue();
19938+
}
19939+
} else {
19940+
const BaseIndexOffset STBase = BaseIndexOffset::match(ST, DAG);
19941+
const BaseIndexOffset ChainBase = BaseIndexOffset::match(ST1, DAG);
19942+
// If this is a store who's preceding store to a subset of the current
19943+
// location and no one other node is chained to that store we can
19944+
// effectively drop the store. Do not remove stores to undef as they
19945+
// may be used as data sinks.
19946+
if (STBase.contains(DAG, ST->getMemoryVT().getFixedSizeInBits(),
19947+
ChainBase,
19948+
ST1->getMemoryVT().getFixedSizeInBits())) {
19949+
CombineTo(ST1, ST1->getChain());
19950+
return SDValue();
19951+
}
1994219952
}
1994319953
}
1994419954
}

llvm/test/CodeGen/AArch64/sve-redundant-store.ll

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,69 @@
88
; *p = 1;
99
; *(svint32_t *)p = v;
1010
; }
11-
12-
; Update me: Until dead store elimination is improved in DAGCombine, this will contain a redundant store.
13-
;
1411
define void @redundant_store(ptr nocapture %p, <vscale x 4 x i32> %v) {
1512
; CHECK-LABEL: redundant_store:
1613
; CHECK: // %bb.0:
17-
; CHECK-NEXT: mov w8, #1
1814
; CHECK-NEXT: ptrue p0.s
19-
; CHECK-NEXT: str w8, [x0]
2015
; CHECK-NEXT: st1w { z0.s }, p0, [x0]
2116
; CHECK-NEXT: ret
2217
store i32 1, ptr %p, align 4
2318
store <vscale x 4 x i32> %v, <vscale x 4 x i32>* %p, align 16
2419
ret void
2520
}
21+
22+
define void @two_scalable_same_size(ptr writeonly %ptr, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
23+
; CHECK-LABEL: two_scalable_same_size:
24+
; CHECK: // %bb.0: // %entry
25+
; CHECK-NEXT: ptrue p0.s
26+
; CHECK-NEXT: st1w { z1.s }, p0, [x0]
27+
; CHECK-NEXT: ret
28+
entry:
29+
store <vscale x 4 x i32> %a, ptr %ptr
30+
store <vscale x 4 x i32> %b, ptr %ptr
31+
ret void
32+
}
33+
34+
; make sure that scalable store is present, becuase we don't know its final size.
35+
define void @keep_scalable_store(ptr writeonly %ptr, ptr %a, <vscale x 4 x i32> %b) {
36+
; CHECK-LABEL: keep_scalable_store:
37+
; CHECK: // %bb.0: // %entry
38+
; CHECK-NEXT: ldp q2, q1, [x1]
39+
; CHECK-NEXT: ptrue p0.s
40+
; CHECK-NEXT: st1w { z0.s }, p0, [x0]
41+
; CHECK-NEXT: stp q2, q1, [x0]
42+
; CHECK-NEXT: ret
43+
entry:
44+
%0 = load <8 x i32>, ptr %a
45+
store <vscale x 4 x i32> %b, ptr %ptr
46+
store <8 x i32> %0, ptr %ptr
47+
ret void
48+
}
49+
50+
define void @two_scalable_keep_stores(ptr writeonly %ptr, <vscale x 4 x i32> %a, <vscale x 4 x i64> %b) {
51+
; CHECK-LABEL: two_scalable_keep_stores:
52+
; CHECK: // %bb.0: // %entry
53+
; CHECK-NEXT: ptrue p0.d
54+
; CHECK-NEXT: ptrue p1.s
55+
; CHECK-NEXT: st1d { z2.d }, p0, [x0, #1, mul vl]
56+
; CHECK-NEXT: st1d { z1.d }, p0, [x0]
57+
; CHECK-NEXT: st1w { z0.s }, p1, [x0]
58+
; CHECK-NEXT: ret
59+
entry:
60+
store <vscale x 4 x i64> %b, ptr %ptr
61+
store <vscale x 4 x i32> %a, ptr %ptr
62+
ret void
63+
}
64+
65+
define void @two_scalable_remove_store(ptr writeonly %ptr, <vscale x 4 x i32> %a, <vscale x 4 x i64> %b) {
66+
; CHECK-LABEL: two_scalable_remove_store:
67+
; CHECK: // %bb.0: // %entry
68+
; CHECK-NEXT: ptrue p0.d
69+
; CHECK-NEXT: st1d { z2.d }, p0, [x0, #1, mul vl]
70+
; CHECK-NEXT: st1d { z1.d }, p0, [x0]
71+
; CHECK-NEXT: ret
72+
entry:
73+
store <vscale x 4 x i32> %a, ptr %ptr
74+
store <vscale x 4 x i64> %b, ptr %ptr
75+
ret void
76+
}

0 commit comments

Comments
 (0)