Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
4d66fbc4
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4d66fbc4
编写于
8月 08, 2021
作者:
A
Andreas Liljeqvist
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
enum niche allocation grows toward zero if possible
上级
641e02f3
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
82 addition
and
9 deletion
+82
-9
compiler/rustc_target/src/abi/mod.rs
compiler/rustc_target/src/abi/mod.rs
+43
-9
src/test/assembly/niche-prefer-zero.rs
src/test/assembly/niche-prefer-zero.rs
+25
-0
src/test/ui/enum-discriminant/niche-prefer-zero.rs
src/test/ui/enum-discriminant/niche-prefer-zero.rs
+14
-0
未找到文件。
compiler/rustc_target/src/abi/mod.rs
浏览文件 @
4d66fbc4
...
...
@@ -1099,19 +1099,53 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
assert
!
(
size
.bits
()
<=
128
);
let
max_value
=
size
.unsigned_int_max
();
if
count
>
max_value
{
let
niche
=
v
.end
.wrapping_add
(
1
)
..
v
.start
;
let
available
=
niche
.end
.wrapping_sub
(
niche
.start
)
&
max_value
;
if
count
>
available
{
return
None
;
}
// Compute the range of invalid values being reserved.
let
start
=
v
.end
.wrapping_add
(
1
)
&
max_value
;
let
end
=
v
.end
.wrapping_add
(
count
)
&
max_value
;
if
v
.contains
(
end
)
{
return
None
;
// Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
// Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
// This is accomplished by prefering enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
// Having `None` in niche zero can enable some special optimizations.
//
// Bound selection criteria:
// 1. Select closest to zero given wrapping semantics.
// 2. Avoid moving past zero if possible.
//
// In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
// If niche zero is already reserved, the selection of bounds are of little interest.
let
move_start
=
|
v
:
WrappingRange
|
{
let
start
=
v
.start
.wrapping_sub
(
1
)
&
max_value
;
Some
((
start
,
Scalar
{
value
,
valid_range
:
v
.with_start
(
start
)
}))
};
let
move_end
=
|
v
:
WrappingRange
|
{
let
start
=
v
.end
.wrapping_add
(
1
)
&
max_value
;
let
end
=
v
.end
.wrapping_add
(
count
)
&
max_value
;
Some
((
start
,
Scalar
{
value
,
valid_range
:
v
.with_end
(
end
)
}))
};
let
distance_end_zero
=
max_value
-
v
.end
;
if
v
.start
>
v
.end
{
// zero is unavailable because wrapping occurs
move_end
(
v
)
}
else
if
v
.start
<=
distance_end_zero
{
if
count
<=
v
.start
{
move_start
(
v
)
}
else
{
// moved past zero, use other bound
move_end
(
v
)
}
}
else
{
let
end
=
v
.end
.wrapping_add
(
count
)
&
max_value
;
let
overshot_zero
=
(
1
..=
v
.end
)
.contains
(
&
end
);
if
overshot_zero
{
// moved past zero, use other bound
move_start
(
v
)
}
else
{
move_end
(
v
)
}
}
Some
((
start
,
Scalar
{
value
,
valid_range
:
v
.with_end
(
end
)
}))
}
}
...
...
src/test/assembly/niche-prefer-zero.rs
0 → 100644
浏览文件 @
4d66fbc4
// Check that niche selection prefers zero and that jumps are optimized away.
// See https://github.com/rust-lang/rust/pull/87794
// assembly-output: emit-asm
// only-x86
// compile-flags: -Copt-level=3
#![crate_type
=
"lib"
]
#[repr(u8)]
pub
enum
Size
{
One
=
1
,
Two
=
2
,
Three
=
3
,
}
#[no_mangle]
pub
fn
handle
(
x
:
Option
<
Size
>
)
->
u8
{
match
x
{
None
=>
0
,
Some
(
size
)
=>
size
as
u8
,
}
}
// There should be no jumps in output
// CHECK-NOT: j
src/test/ui/enum-discriminant/niche-prefer-zero.rs
0 → 100644
浏览文件 @
4d66fbc4
// Check that niche selection prefers zero.
// See https://github.com/rust-lang/rust/pull/87794
// run-pass
#[repr(u8)]
pub
enum
Size
{
One
=
1
,
Two
=
2
,
Three
=
3
,
}
fn
main
()
{
// check that `None` is zero
assert_eq!
(
0
,
unsafe
{
std
::
mem
::
transmute
::
<
Option
<
Size
>
,
u8
>
(
None
)
});
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录