Skip to content

Commit f3c9e58

Browse files
committed
Analysis: Fix assertion when load alignment exceeds address space size
Apparently the maximum alignment no longer fits in 32-bits now, which overflows a 32-bit offset and would fail on the isPowerOf2 assert.
1 parent df52a22 commit f3c9e58

File tree

2 files changed

+138
-3
lines changed

2 files changed

+138
-3
lines changed

llvm/lib/Analysis/Loads.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ using namespace llvm;
2929
static bool isAligned(const Value *Base, const APInt &Offset, Align Alignment,
3030
const DataLayout &DL) {
3131
Align BA = Base->getPointerAlignment(DL);
32-
const APInt APAlign(Offset.getBitWidth(), Alignment.value());
33-
assert(APAlign.isPowerOf2() && "must be a power of 2!");
34-
return BA >= Alignment && !(Offset & (APAlign - 1));
32+
return BA >= Alignment && Offset.isAligned(BA);
3533
}
3634

3735
/// Test if V is always a pointer to allocated and suitably aligned memory for
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2+
; RUN: opt -S -passes=argpromotion < %s | FileCheck %s
3+
target datalayout = "e-p:64:64-p5:32:32-p6:128:128:128:128"
4+
5+
; Maximum alignment value of the load in a 64-bit address space
6+
; exceeds the bitwidth of the definition address space.
7+
define void @entry0() {
8+
; CHECK-LABEL: define void @entry0() {
9+
; CHECK-NEXT: bb:
10+
; CHECK-NEXT: call void @call_load_maxalign_alloca_16()
11+
; CHECK-NEXT: ret void
12+
;
13+
bb:
14+
call void @call_load_maxalign_alloca_16()
15+
ret void
16+
}
17+
18+
define internal void @call_load_maxalign_alloca_16() {
19+
; CHECK-LABEL: define internal void @call_load_maxalign_alloca_16() {
20+
; CHECK-NEXT: bb:
21+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [13 x i16], align 16, addrspace(5)
22+
; CHECK-NEXT: [[ADDRSPACECAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOCA]] to ptr
23+
; CHECK-NEXT: call void @load_maxalign0(ptr [[ADDRSPACECAST]])
24+
; CHECK-NEXT: ret void
25+
;
26+
bb:
27+
%alloca = alloca [13 x i16], align 16, addrspace(5)
28+
%addrspacecast = addrspacecast ptr addrspace(5) %alloca to ptr
29+
call void @load_maxalign0(ptr %addrspacecast)
30+
ret void
31+
}
32+
33+
define internal void @load_maxalign0(ptr %arg) {
34+
; CHECK-LABEL: define internal void @load_maxalign0
35+
; CHECK-SAME: (ptr [[ARG:%.*]]) {
36+
; CHECK-NEXT: bb:
37+
; CHECK-NEXT: br label [[BB1:%.*]]
38+
; CHECK: bb1:
39+
; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[ARG]], align 4294967296
40+
; CHECK-NEXT: ret void
41+
;
42+
bb:
43+
br label %bb1
44+
45+
bb1: ; preds = %bb
46+
%load = load i32, ptr %arg, align 4294967296
47+
ret void
48+
}
49+
50+
; Make sure the early exit alignment check isn't hiding the offset
51+
; overflow.
52+
define void @entry1() {
53+
; CHECK-LABEL: define void @entry1() {
54+
; CHECK-NEXT: bb:
55+
; CHECK-NEXT: call void @call_load_maxalign_alloca_maxalign()
56+
; CHECK-NEXT: ret void
57+
;
58+
bb:
59+
call void @call_load_maxalign_alloca_maxalign()
60+
ret void
61+
}
62+
63+
define internal void @call_load_maxalign_alloca_maxalign() {
64+
; CHECK-LABEL: define internal void @call_load_maxalign_alloca_maxalign() {
65+
; CHECK-NEXT: bb:
66+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [13 x i16], align 4294967296, addrspace(5)
67+
; CHECK-NEXT: [[ADDRSPACECAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOCA]] to ptr
68+
; CHECK-NEXT: [[ADDRSPACECAST_VAL:%.*]] = load i32, ptr [[ADDRSPACECAST]], align 4294967296
69+
; CHECK-NEXT: call void @load_maxalign1(i32 [[ADDRSPACECAST_VAL]])
70+
; CHECK-NEXT: ret void
71+
;
72+
bb:
73+
%alloca = alloca [13 x i16], align 4294967296, addrspace(5)
74+
%addrspacecast = addrspacecast ptr addrspace(5) %alloca to ptr
75+
call void @load_maxalign1(ptr %addrspacecast)
76+
ret void
77+
}
78+
79+
define internal void @load_maxalign1(ptr %arg) {
80+
; CHECK-LABEL: define internal void @load_maxalign1
81+
; CHECK-SAME: (i32 [[ARG_0_VAL:%.*]]) {
82+
; CHECK-NEXT: bb:
83+
; CHECK-NEXT: br label [[BB1:%.*]]
84+
; CHECK: bb1:
85+
; CHECK-NEXT: ret void
86+
;
87+
bb:
88+
br label %bb1
89+
90+
bb1: ; preds = %bb
91+
%load = load i32, ptr %arg, align 4294967296
92+
ret void
93+
}
94+
95+
; Alignment value exceeds pointer size, more than 1 past the end
96+
define void @entry2() {
97+
; CHECK-LABEL: define void @entry2() {
98+
; CHECK-NEXT: bb:
99+
; CHECK-NEXT: call void @call_load_maxalign_alloca_ptr128()
100+
; CHECK-NEXT: ret void
101+
;
102+
bb:
103+
call void @call_load_maxalign_alloca_ptr128()
104+
ret void
105+
}
106+
107+
define internal void @call_load_maxalign_alloca_ptr128() {
108+
; CHECK-LABEL: define internal void @call_load_maxalign_alloca_ptr128() {
109+
; CHECK-NEXT: bb:
110+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [13 x i16], align 4294967296, addrspace(6)
111+
; CHECK-NEXT: [[ADDRSPACECAST:%.*]] = addrspacecast ptr addrspace(6) [[ALLOCA]] to ptr
112+
; CHECK-NEXT: [[ADDRSPACECAST_VAL:%.*]] = load i32, ptr [[ADDRSPACECAST]], align 4294967296
113+
; CHECK-NEXT: call void @load_maxalign2(i32 [[ADDRSPACECAST_VAL]])
114+
; CHECK-NEXT: ret void
115+
;
116+
bb:
117+
%alloca = alloca [13 x i16], align 4294967296, addrspace(6)
118+
%addrspacecast = addrspacecast ptr addrspace(6) %alloca to ptr
119+
call void @load_maxalign2(ptr %addrspacecast)
120+
ret void
121+
}
122+
123+
define internal void @load_maxalign2(ptr %arg) {
124+
; CHECK-LABEL: define internal void @load_maxalign2
125+
; CHECK-SAME: (i32 [[ARG_0_VAL:%.*]]) {
126+
; CHECK-NEXT: bb:
127+
; CHECK-NEXT: br label [[BB1:%.*]]
128+
; CHECK: bb1:
129+
; CHECK-NEXT: ret void
130+
;
131+
bb:
132+
br label %bb1
133+
134+
bb1: ; preds = %bb
135+
%load = load i32, ptr %arg, align 4294967296
136+
ret void
137+
}

0 commit comments

Comments
 (0)