Skip to content

Commit d82809e

Browse files
committed
[llvm] Use ABI instead of preferred alignment for const prop checks
We'd hit an assertion checking proper alignment for an i8 when building chromium because we used the prefered alignment (which is 4 bytes) instead of the ABI alignment (which is 1 byte). The ABI alignment should be used because that's the actual alignment needed to load a constant from the vtable. This also updates the two `virtual-const-prop-small-alignment-*` to explicitly give ABI alignments for i64s.
1 parent 5d2e1c0 commit d82809e

File tree

4 files changed

+121
-7
lines changed

4 files changed

+121
-7
lines changed

llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1845,7 +1845,7 @@ bool DevirtModule::tryVirtualConstProp(
18451845
if (BitWidth > 64)
18461846
return false;
18471847

1848-
Align TypeAlignment = M.getDataLayout().getPrefTypeAlign(RetType);
1848+
Align TypeAlignment = M.getDataLayout().getABIIntegerTypeAlignment(BitWidth);
18491849

18501850
// Make sure that each function is defined, does not access memory, takes at
18511851
// least one argument, does not use its first argument (which we assume is
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
;; Demonstrate that the ABI alignment is used over the preferred alignment.
2+
;;
3+
;; In both runs, pointers are 32-bit but we can only store the function returing
4+
;; the 64-bit constant in the vtable if the ABI alignment for an i64 is 32 since
5+
;; we cannot guarantee a 64-bit ABI alignment if the vtable is 32-bit aligned.
6+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:32:64" %s | FileCheck %s --check-prefixes=COMMON,ABI32
7+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:64" %s | FileCheck %s --check-prefixes=COMMON,ABI64
8+
9+
; ABI32: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [8 x i8] }
10+
; ABI32-SAME: [8 x i8] c"\05\00\00\00\00\00\00\00"
11+
; ABI64: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [0 x i8] }
12+
; ABI64-SAME: zeroinitializer
13+
; COMMON-SAME: }, !type [[T:![0-9]+]]
14+
@vt6 = constant [2 x ptr] [
15+
ptr @vf10i8,
16+
ptr @vf5i64
17+
], !type !1
18+
19+
; ABI32: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [8 x i8] }
20+
; ABI32-SAME: [8 x i8] c"\06\00\00\00\00\00\00\00"
21+
; ABI64: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [0 x i8] }
22+
; ABI64-SAME: zeroinitializer
23+
; COMMON-SAME: }, !type [[T]]
24+
@vt7 = constant [2 x ptr] [
25+
ptr @vf9i8,
26+
ptr @vf6i64
27+
], !type !1
28+
29+
define i1 @vf0i1(ptr %this) readnone {
30+
ret i1 0
31+
}
32+
33+
define i1 @vf1i1(ptr %this) readnone {
34+
ret i1 1
35+
}
36+
37+
define i8 @vf0i8(ptr %this) readnone {
38+
ret i8 2
39+
}
40+
41+
define i8 @vf1i8(ptr %this) readnone {
42+
ret i8 3
43+
}
44+
45+
define i32 @vf1i32(ptr %this) readnone {
46+
ret i32 1
47+
}
48+
49+
define i32 @vf2i32(ptr %this) readnone {
50+
ret i32 2
51+
}
52+
53+
define i32 @vf3i32(ptr %this) readnone {
54+
ret i32 3
55+
}
56+
57+
define i32 @vf4i32(ptr %this) readnone {
58+
ret i32 4
59+
}
60+
61+
define i64 @vf5i64(ptr %this) readnone {
62+
ret i64 5
63+
}
64+
65+
define i64 @vf6i64(ptr %this) readnone {
66+
ret i64 6
67+
}
68+
69+
define i8 @vf9i8(ptr %this) readnone {
70+
ret i8 10
71+
}
72+
73+
define i8 @vf10i8(ptr %this) readnone {
74+
ret i8 11
75+
}
76+
77+
; COMMON-LABEL: define i8 @call0(
78+
define i8 @call0(ptr %obj) {
79+
%vtable = load ptr, ptr %obj
80+
%p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid")
81+
call void @llvm.assume(i1 %p)
82+
%fptrptr = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 0
83+
%fptr = load ptr, ptr %fptrptr
84+
%result = call i8 %fptr(ptr %obj)
85+
ret i8 %result
86+
; COMMON: [[VTGEP:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -1
87+
; COMMON: [[VTLOAD:%[^ ]*]] = load i8, ptr [[VTGEP]]
88+
; COMMON: ret i8 [[VTLOAD]]
89+
}
90+
91+
; COMMON-LABEL: define i64 @call1(
92+
define i64 @call1(ptr %obj) {
93+
%vtable = load ptr, ptr %obj
94+
%p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid")
95+
call void @llvm.assume(i1 %p)
96+
%fptrptr = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 1
97+
%fptr = load ptr, ptr %fptrptr
98+
%result = call i64 %fptr(ptr %obj)
99+
ret i64 %result
100+
; ABI32: [[VTGEP:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 8
101+
; ABI32-NEXT: [[VTLOAD:%[^ ]*]] = load i64, ptr [[VTGEP]]
102+
; ABI64: [[VTGEP:%[^ ]*]] = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 1
103+
; ABI64-NEXT: [[FUNC:%[^ ]*]] = load ptr, ptr [[VTGEP]], align 4
104+
; ABI64-NEXT: [[VTLOAD:%[^ ]*]] = call i64 [[FUNC]](ptr %obj)
105+
; COMMON-NEXT: ret i64 [[VTLOAD]]
106+
}
107+
108+
; COMMON: [[T]] = !{i32 4, !"typeid"}
109+
110+
!1 = !{i32 0, !"typeid"}

llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-32.ll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s
2-
31
;; This target uses 32-bit sized and aligned pointers.
4-
target datalayout = "e-p:32:32"
2+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:64" %s | FileCheck %s
3+
4+
;; The tests should be the exact same even with different preferred alignments since
5+
;; the ABI alignment is used.
6+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:128" %s | FileCheck %s
57

68
;; Constant propagation should be agnostic towards sections.
79
;; Also the new global should be in the original vtable's section.

llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-64.ll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s
2-
31
;; This target uses 64-bit sized and aligned pointers.
4-
target datalayout = "e-p:64:64"
2+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:64:64-i64:64:64" %s | FileCheck %s
3+
4+
;; The tests should be the exact same even with different preferred alignments since
5+
;; the ABI alignment is used.
6+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:64:64-i64:64:128" %s | FileCheck %s
57

68
;; Constant propagation should be agnostic towards sections.
79
;; Also the new global should be in the original vtable's section.

0 commit comments

Comments
 (0)