Skip to content

Commit 4028bb1

Browse files
authored
Local: Handle noalias_addrspace in combineMetadata (#103938)
This should act like range. Previously ConstantRangeList assumed a 64-bit range. Now query from the actual entries. This also means that the empty range has no bitwidth, so move asserts to avoid checking the bitwidth of empty ranges.
1 parent f4d7586 commit 4028bb1

File tree

7 files changed

+181
-12
lines changed

7 files changed

+181
-12
lines changed

llvm/include/llvm/IR/ConstantRangeList.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class [[nodiscard]] ConstantRangeList {
3535
ConstantRangeList(ArrayRef<ConstantRange> RangesRef) {
3636
assert(isOrderedRanges(RangesRef));
3737
for (const ConstantRange &R : RangesRef) {
38-
assert(R.getBitWidth() == getBitWidth());
38+
assert(empty() || R.getBitWidth() == getBitWidth());
3939
Ranges.push_back(R);
4040
}
4141
}
@@ -59,8 +59,9 @@ class [[nodiscard]] ConstantRangeList {
5959
/// Return true if this list contains no members.
6060
bool empty() const { return Ranges.empty(); }
6161

62-
/// Get the bit width of this ConstantRangeList.
63-
uint32_t getBitWidth() const { return 64; }
62+
/// Get the bit width of this ConstantRangeList. It is invalid to call this
63+
/// with an empty range.
64+
uint32_t getBitWidth() const { return Ranges.front().getBitWidth(); }
6465

6566
/// Return the number of ranges in this ConstantRangeList.
6667
size_t size() const { return Ranges.size(); }

llvm/include/llvm/IR/Metadata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,7 @@ class MDNode : public Metadata {
14561456
static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B);
14571457
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
14581458
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
1459+
static MDNode *getMostGenericNoaliasAddrspace(MDNode *A, MDNode *B);
14591460
static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B);
14601461
static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B);
14611462
/// Merge !prof metadata from two instructions.

llvm/lib/IR/ConstantRangeList.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ void ConstantRangeList::insert(const ConstantRange &NewRange) {
3939
return;
4040
assert(!NewRange.isFullSet() && "Do not support full set");
4141
assert(NewRange.getLower().slt(NewRange.getUpper()));
42-
assert(getBitWidth() == NewRange.getBitWidth());
4342
// Handle common cases.
4443
if (empty() || Ranges.back().getUpper().slt(NewRange.getLower())) {
4544
Ranges.push_back(NewRange);
4645
return;
4746
}
47+
48+
assert(getBitWidth() == NewRange.getBitWidth());
49+
4850
if (NewRange.getUpper().slt(Ranges.front().getLower())) {
4951
Ranges.insert(Ranges.begin(), NewRange);
5052
return;
@@ -142,14 +144,15 @@ void ConstantRangeList::subtract(const ConstantRange &SubRange) {
142144

143145
ConstantRangeList
144146
ConstantRangeList::unionWith(const ConstantRangeList &CRL) const {
145-
assert(getBitWidth() == CRL.getBitWidth() &&
146-
"ConstantRangeList bitwidths don't agree!");
147147
// Handle common cases.
148148
if (empty())
149149
return CRL;
150150
if (CRL.empty())
151151
return *this;
152152

153+
assert(getBitWidth() == CRL.getBitWidth() &&
154+
"ConstantRangeList bitwidths don't agree!");
155+
153156
ConstantRangeList Result;
154157
size_t i = 0, j = 0;
155158
// "PreviousRange" tracks the lowest unioned range that is being processed.
@@ -192,15 +195,15 @@ ConstantRangeList::unionWith(const ConstantRangeList &CRL) const {
192195

193196
ConstantRangeList
194197
ConstantRangeList::intersectWith(const ConstantRangeList &CRL) const {
195-
assert(getBitWidth() == CRL.getBitWidth() &&
196-
"ConstantRangeList bitwidths don't agree!");
197-
198198
// Handle common cases.
199199
if (empty())
200200
return *this;
201201
if (CRL.empty())
202202
return CRL;
203203

204+
assert(getBitWidth() == CRL.getBitWidth() &&
205+
"ConstantRangeList bitwidths don't agree!");
206+
204207
ConstantRangeList Result;
205208
size_t i = 0, j = 0;
206209
while (i < size() && j < CRL.size()) {

llvm/lib/IR/Metadata.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/IR/BasicBlock.h"
3030
#include "llvm/IR/Constant.h"
3131
#include "llvm/IR/ConstantRange.h"
32+
#include "llvm/IR/ConstantRangeList.h"
3233
#include "llvm/IR/Constants.h"
3334
#include "llvm/IR/DebugInfoMetadata.h"
3435
#include "llvm/IR/DebugLoc.h"
@@ -1353,6 +1354,43 @@ MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
13531354
return MDNode::get(A->getContext(), MDs);
13541355
}
13551356

1357+
MDNode *MDNode::getMostGenericNoaliasAddrspace(MDNode *A, MDNode *B) {
1358+
if (!A || !B)
1359+
return nullptr;
1360+
1361+
if (A == B)
1362+
return A;
1363+
1364+
SmallVector<ConstantRange> RangeListA, RangeListB;
1365+
for (unsigned I = 0, E = A->getNumOperands() / 2; I != E; ++I) {
1366+
auto *LowA = mdconst::extract<ConstantInt>(A->getOperand(2 * I + 0));
1367+
auto *HighA = mdconst::extract<ConstantInt>(A->getOperand(2 * I + 1));
1368+
RangeListA.push_back(ConstantRange(LowA->getValue(), HighA->getValue()));
1369+
}
1370+
1371+
for (unsigned I = 0, E = B->getNumOperands() / 2; I != E; ++I) {
1372+
auto *LowB = mdconst::extract<ConstantInt>(B->getOperand(2 * I + 0));
1373+
auto *HighB = mdconst::extract<ConstantInt>(B->getOperand(2 * I + 1));
1374+
RangeListB.push_back(ConstantRange(LowB->getValue(), HighB->getValue()));
1375+
}
1376+
1377+
ConstantRangeList CRLA(RangeListA);
1378+
ConstantRangeList CRLB(RangeListB);
1379+
ConstantRangeList Result = CRLA.intersectWith(CRLB);
1380+
if (Result.empty())
1381+
return nullptr;
1382+
1383+
SmallVector<Metadata *> MDs;
1384+
for (const ConstantRange &CR : Result) {
1385+
MDs.push_back(ConstantAsMetadata::get(
1386+
ConstantInt::get(A->getContext(), CR.getLower())));
1387+
MDs.push_back(ConstantAsMetadata::get(
1388+
ConstantInt::get(A->getContext(), CR.getUpper())));
1389+
}
1390+
1391+
return MDNode::get(A->getContext(), MDs);
1392+
}
1393+
13561394
MDNode *MDNode::getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B) {
13571395
if (!A || !B)
13581396
return nullptr;

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3391,6 +3391,11 @@ void llvm::combineMetadata(Instruction *K, const Instruction *J,
33913391
if (DoesKMove)
33923392
K->setMetadata(Kind, MDNode::getMergedProfMetadata(KMD, JMD, K, J));
33933393
break;
3394+
case LLVMContext::MD_noalias_addrspace:
3395+
if (DoesKMove)
3396+
K->setMetadata(Kind,
3397+
MDNode::getMostGenericNoaliasAddrspace(JMD, KMD));
3398+
break;
33943399
}
33953400
}
33963401
// Set !invariant.group from J if J has it. If both instructions have it
@@ -3432,7 +3437,8 @@ void llvm::combineMetadataForCSE(Instruction *K, const Instruction *J,
34323437
LLVMContext::MD_prof,
34333438
LLVMContext::MD_nontemporal,
34343439
LLVMContext::MD_noundef,
3435-
LLVMContext::MD_mmra};
3440+
LLVMContext::MD_mmra,
3441+
LLVMContext::MD_noalias_addrspace};
34363442
combineMetadata(K, J, KnownIDs, KDominatesJ);
34373443
}
34383444

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes='early-cse<memssa>' -S < %s | FileCheck %s
3+
4+
declare void @use(i1)
5+
declare void @use.ptr(ptr) memory(read)
6+
7+
define void @load_first_noalias_addrspace(ptr %p) {
8+
; CHECK-LABEL: define void @load_first_noalias_addrspace(
9+
; CHECK-SAME: ptr [[P:%.*]]) {
10+
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0:![0-9]+]], !noundef [[META0]], !noalias.addrspace [[META1:![0-9]+]]
11+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
12+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
13+
; CHECK-NEXT: ret void
14+
;
15+
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
16+
call void @use.ptr(ptr %v1)
17+
%v2 = load ptr, ptr %p
18+
call void @use.ptr(ptr %v2)
19+
ret void
20+
}
21+
22+
define void @load_both_same_noalias_addrspace(ptr %p) {
23+
; CHECK-LABEL: define void @load_both_same_noalias_addrspace(
24+
; CHECK-SAME: ptr [[P:%.*]]) {
25+
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0]], !noundef [[META0]], !noalias.addrspace [[META1]]
26+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
27+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
28+
; CHECK-NEXT: ret void
29+
;
30+
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
31+
call void @use.ptr(ptr %v1)
32+
%v2 = load ptr, ptr %p, !noalias.addrspace !0
33+
call void @use.ptr(ptr %v2)
34+
ret void
35+
}
36+
37+
define void @load_both_disjoint_noalias_addrspace(ptr %p) {
38+
; CHECK-LABEL: define void @load_both_disjoint_noalias_addrspace(
39+
; CHECK-SAME: ptr [[P:%.*]]) {
40+
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0]], !noundef [[META0]], !noalias.addrspace [[META1]]
41+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
42+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
43+
; CHECK-NEXT: ret void
44+
;
45+
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
46+
call void @use.ptr(ptr %v1)
47+
%v2 = load ptr, ptr %p, !noalias.addrspace !1
48+
call void @use.ptr(ptr %v2)
49+
ret void
50+
}
51+
52+
define void @load_both_overlap_noalias_addrspace(ptr %p) {
53+
; CHECK-LABEL: define void @load_both_overlap_noalias_addrspace(
54+
; CHECK-SAME: ptr [[P:%.*]]) {
55+
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0]], !noundef [[META0]], !noalias.addrspace [[META1]]
56+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
57+
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
58+
; CHECK-NEXT: ret void
59+
;
60+
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
61+
call void @use.ptr(ptr %v1)
62+
%v2 = load ptr, ptr %p, !noalias.addrspace !2
63+
call void @use.ptr(ptr %v2)
64+
ret void
65+
}
66+
67+
!0 = !{i32 5, i32 6}
68+
!1 = !{i32 7, i32 8}
69+
!2 = !{i32 5, i32 7}
70+
;.
71+
; CHECK: [[META0]] = !{}
72+
; CHECK: [[META1]] = !{i32 5, i32 6}
73+
;.

llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ out:
319319
define void @hoist_noalias_addrspace_both(i1 %c, ptr %p, i64 %val) {
320320
; CHECK-LABEL: @hoist_noalias_addrspace_both(
321321
; CHECK-NEXT: if:
322-
; CHECK-NEXT: [[T:%.*]] = atomicrmw add ptr [[P:%.*]], i64 [[VAL:%.*]] seq_cst, align 8
322+
; CHECK-NEXT: [[T:%.*]] = atomicrmw add ptr [[P:%.*]], i64 [[VAL:%.*]] seq_cst, align 8, !noalias.addrspace [[META7:![0-9]+]]
323323
; CHECK-NEXT: ret void
324324
;
325325
if:
@@ -361,7 +361,7 @@ out:
361361
define void @hoist_noalias_addrspace_switch(i64 %i, ptr %p, i64 %val) {
362362
; CHECK-LABEL: @hoist_noalias_addrspace_switch(
363363
; CHECK-NEXT: out:
364-
; CHECK-NEXT: [[T:%.*]] = atomicrmw add ptr [[P:%.*]], i64 [[VAL:%.*]] seq_cst, align 8
364+
; CHECK-NEXT: [[T:%.*]] = atomicrmw add ptr [[P:%.*]], i64 [[VAL:%.*]] seq_cst, align 8, !noalias.addrspace [[META7]]
365365
; CHECK-NEXT: ret void
366366
;
367367
switch i64 %i, label %bb0 [
@@ -381,6 +381,48 @@ out:
381381
ret void
382382
}
383383

384+
define void @hoist_noalias_addrspace_switch_multiple(i64 %i, ptr %p, i64 %val) {
385+
; CHECK-LABEL: @hoist_noalias_addrspace_switch_multiple(
386+
; CHECK-NEXT: out:
387+
; CHECK-NEXT: [[T:%.*]] = atomicrmw add ptr [[P:%.*]], i64 [[VAL:%.*]] seq_cst, align 8, !noalias.addrspace [[META8:![0-9]+]]
388+
; CHECK-NEXT: ret void
389+
;
390+
switch i64 %i, label %bb0 [
391+
i64 1, label %bb1
392+
i64 2, label %bb2
393+
]
394+
bb0:
395+
%t = atomicrmw add ptr %p, i64 %val seq_cst, !noalias.addrspace !7
396+
br label %out
397+
bb1:
398+
%e = atomicrmw add ptr %p, i64 %val seq_cst, !noalias.addrspace !8
399+
br label %out
400+
bb2:
401+
%f = atomicrmw add ptr %p, i64 %val seq_cst, !noalias.addrspace !9
402+
br label %out
403+
out:
404+
ret void
405+
}
406+
407+
; !noalias_addrspace is not safe to speculate as it causes immediate undefined behavior.
408+
define ptr @speculate_noalias_addrspace(i1 %c, ptr dereferenceable(8) align 8 %p) {
409+
; CHECK-LABEL: @speculate_noalias_addrspace(
410+
; CHECK-NEXT: entry:
411+
; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !nonnull [[META2]]
412+
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], ptr [[V]], ptr null
413+
; CHECK-NEXT: ret ptr [[SPEC_SELECT]]
414+
;
415+
entry:
416+
br i1 %c, label %if, label %join
417+
418+
if:
419+
%v = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !4
420+
br label %join
421+
422+
join:
423+
%phi = phi ptr [ %v, %if ], [ null, %entry ]
424+
ret ptr %phi
425+
}
384426

385427
!0 = !{ i8 0, i8 1 }
386428
!1 = !{ i8 3, i8 5 }
@@ -389,6 +431,9 @@ out:
389431
!4 = !{i32 5, i32 6}
390432
!5 = !{i32 5, i32 7}
391433
!6 = !{i32 4, i32 8}
434+
!7 = !{i32 4, i32 8, i32 20, i32 31}
435+
!8 = !{i32 2, i32 5}
436+
!9 = !{i32 2, i32 5, i32 22, i32 42, i32 45, i32 50}
392437

393438
;.
394439
; CHECK: [[RNG0]] = !{i8 0, i8 1, i8 3, i8 5}
@@ -398,4 +443,6 @@ out:
398443
; CHECK: [[RNG4]] = !{i32 0, i32 10}
399444
; CHECK: [[META5]] = !{i64 4}
400445
; CHECK: [[META6]] = !{float 2.500000e+00}
446+
; CHECK: [[META7]] = !{i32 5, i32 6}
447+
; CHECK: [[META8]] = !{i32 4, i32 5}
401448
;.

0 commit comments

Comments
 (0)