Skip to content

Commit fb760c1

Browse files
committed
Fixes differences found between clang & rust
The intrinsics test was flagging differences in aarch64_be between rust in debug and clang in O2. It was found that rust was correct in debug, but incorrect in release, and in both cases were being compared against clang in O2 which was also incorrect. The vdot intrinsics were fixed and are now correct in rust for both release and debug. However the vcmla ones could not be as the issue lies with LLVM. Both the vdot and vcmla intrinsics were added to the skiplist as clang is still incorrect for both. LLVM issue: llvm/llvm-project#166190
1 parent e36ca30 commit fb760c1

File tree

6 files changed

+171
-58
lines changed

6 files changed

+171
-58
lines changed

ci/intrinsic-test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ case ${TARGET} in
5656

5757
aarch64_be-unknown-linux-gnu*)
5858
TEST_CPPFLAGS="-fuse-ld=lld"
59-
TEST_SKIP_INTRINSICS=crates/intrinsic-test/missing_aarch64.txt
59+
TEST_SKIP_INTRINSICS=crates/intrinsic-test/missing_aarch64_be.txt
6060
TEST_CXX_COMPILER="clang++"
6161
TEST_RUNNER="${CARGO_TARGET_AARCH64_BE_UNKNOWN_LINUX_GNU_RUNNER}"
6262
: "${TEST_SAMPLE_INTRINSICS_PERCENTAGE:=100}"

crates/core_arch/src/aarch64/neon/generated.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9500,10 +9500,10 @@ pub fn vdivh_f16(a: f16, b: f16) -> f16 {
95009500
#[unstable(feature = "stdarch_neon_dotprod", issue = "117224")]
95019501
pub fn vdot_laneq_s32<const LANE: i32>(a: int32x2_t, b: int8x8_t, c: int8x16_t) -> int32x2_t {
95029502
static_assert_uimm_bits!(LANE, 2);
9503+
let c: int32x4_t = vreinterpretq_s32_s8(c);
95039504
unsafe {
9504-
let c: int32x4_t = transmute(c);
95059505
let c: int32x2_t = simd_shuffle!(c, c, [LANE as u32, LANE as u32]);
9506-
vdot_s32(a, b, transmute(c))
9506+
vdot_s32(a, b, vreinterpret_s8_s32(c))
95079507
}
95089508
}
95099509
#[doc = "Dot product arithmetic (indexed)"]
@@ -9515,11 +9515,11 @@ pub fn vdot_laneq_s32<const LANE: i32>(a: int32x2_t, b: int8x8_t, c: int8x16_t)
95159515
#[unstable(feature = "stdarch_neon_dotprod", issue = "117224")]
95169516
pub fn vdotq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int8x16_t, c: int8x16_t) -> int32x4_t {
95179517
static_assert_uimm_bits!(LANE, 2);
9518+
let c: int32x4_t = vreinterpretq_s32_s8(c);
95189519
unsafe {
9519-
let c: int32x4_t = transmute(c);
95209520
let c: int32x4_t =
95219521
simd_shuffle!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
9522-
vdotq_s32(a, b, transmute(c))
9522+
vdotq_s32(a, b, vreinterpretq_s8_s32(c))
95239523
}
95249524
}
95259525
#[doc = "Dot product arithmetic (indexed)"]
@@ -9531,10 +9531,10 @@ pub fn vdotq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int8x16_t, c: int8x16_t
95319531
#[unstable(feature = "stdarch_neon_dotprod", issue = "117224")]
95329532
pub fn vdot_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint8x8_t, c: uint8x16_t) -> uint32x2_t {
95339533
static_assert_uimm_bits!(LANE, 2);
9534+
let c: uint32x4_t = vreinterpretq_u32_u8(c);
95349535
unsafe {
9535-
let c: uint32x4_t = transmute(c);
95369536
let c: uint32x2_t = simd_shuffle!(c, c, [LANE as u32, LANE as u32]);
9537-
vdot_u32(a, b, transmute(c))
9537+
vdot_u32(a, b, vreinterpret_u8_u32(c))
95389538
}
95399539
}
95409540
#[doc = "Dot product arithmetic (indexed)"]
@@ -9546,11 +9546,11 @@ pub fn vdot_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint8x8_t, c: uint8x16_
95469546
#[unstable(feature = "stdarch_neon_dotprod", issue = "117224")]
95479547
pub fn vdotq_laneq_u32<const LANE: i32>(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t {
95489548
static_assert_uimm_bits!(LANE, 2);
9549+
let c: uint32x4_t = vreinterpretq_u32_u8(c);
95499550
unsafe {
9550-
let c: uint32x4_t = transmute(c);
95519551
let c: uint32x4_t =
95529552
simd_shuffle!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
9553-
vdotq_u32(a, b, transmute(c))
9553+
vdotq_u32(a, b, vreinterpretq_u8_u32(c))
95549554
}
95559555
}
95569556
#[doc = "Set all vector lanes to the same value"]
@@ -28283,10 +28283,10 @@ pub fn vuqadds_s32(a: i32, b: u32) -> i32 {
2828328283
#[unstable(feature = "stdarch_neon_i8mm", issue = "117223")]
2828428284
pub fn vusdot_laneq_s32<const LANE: i32>(a: int32x2_t, b: uint8x8_t, c: int8x16_t) -> int32x2_t {
2828528285
static_assert_uimm_bits!(LANE, 2);
28286+
let c: int32x4_t = vreinterpretq_s32_s8(c);
2828628287
unsafe {
28287-
let c: int32x4_t = transmute(c);
2828828288
let c: int32x2_t = simd_shuffle!(c, c, [LANE as u32, LANE as u32]);
28289-
vusdot_s32(a, b, transmute(c))
28289+
vusdot_s32(a, b, vreinterpret_s8_s32(c))
2829028290
}
2829128291
}
2829228292
#[doc = "Dot product index form with unsigned and signed integers"]
@@ -28298,11 +28298,11 @@ pub fn vusdot_laneq_s32<const LANE: i32>(a: int32x2_t, b: uint8x8_t, c: int8x16_
2829828298
#[unstable(feature = "stdarch_neon_i8mm", issue = "117223")]
2829928299
pub fn vusdotq_laneq_s32<const LANE: i32>(a: int32x4_t, b: uint8x16_t, c: int8x16_t) -> int32x4_t {
2830028300
static_assert_uimm_bits!(LANE, 2);
28301+
let c: int32x4_t = vreinterpretq_s32_s8(c);
2830128302
unsafe {
28302-
let c: int32x4_t = transmute(c);
2830328303
let c: int32x4_t =
2830428304
simd_shuffle!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
28305-
vusdotq_s32(a, b, transmute(c))
28305+
vusdotq_s32(a, b, vreinterpretq_s8_s32(c))
2830628306
}
2830728307
}
2830828308
#[doc = "Unzip vectors"]

crates/core_arch/src/arm_shared/neon/generated.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9201,10 +9201,10 @@ pub fn vcvtq_u32_f32(a: float32x4_t) -> uint32x4_t {
92019201
)]
92029202
pub fn vdot_lane_s32<const LANE: i32>(a: int32x2_t, b: int8x8_t, c: int8x8_t) -> int32x2_t {
92039203
static_assert_uimm_bits!(LANE, 1);
9204+
let c: int32x2_t = vreinterpret_s32_s8(c);
92049205
unsafe {
9205-
let c: int32x2_t = transmute(c);
92069206
let c: int32x2_t = simd_shuffle!(c, c, [LANE as u32, LANE as u32]);
9207-
vdot_s32(a, b, transmute(c))
9207+
vdot_s32(a, b, vreinterpret_s8_s32(c))
92089208
}
92099209
}
92109210
#[doc = "Dot product arithmetic (indexed)"]
@@ -9228,11 +9228,11 @@ pub fn vdot_lane_s32<const LANE: i32>(a: int32x2_t, b: int8x8_t, c: int8x8_t) ->
92289228
)]
92299229
pub fn vdotq_lane_s32<const LANE: i32>(a: int32x4_t, b: int8x16_t, c: int8x8_t) -> int32x4_t {
92309230
static_assert_uimm_bits!(LANE, 1);
9231+
let c: int32x2_t = vreinterpret_s32_s8(c);
92319232
unsafe {
9232-
let c: int32x2_t = transmute(c);
92339233
let c: int32x4_t =
92349234
simd_shuffle!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
9235-
vdotq_s32(a, b, transmute(c))
9235+
vdotq_s32(a, b, vreinterpretq_s8_s32(c))
92369236
}
92379237
}
92389238
#[doc = "Dot product arithmetic (indexed)"]
@@ -9256,10 +9256,10 @@ pub fn vdotq_lane_s32<const LANE: i32>(a: int32x4_t, b: int8x16_t, c: int8x8_t)
92569256
)]
92579257
pub fn vdot_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint8x8_t, c: uint8x8_t) -> uint32x2_t {
92589258
static_assert_uimm_bits!(LANE, 1);
9259+
let c: uint32x2_t = vreinterpret_u32_u8(c);
92599260
unsafe {
9260-
let c: uint32x2_t = transmute(c);
92619261
let c: uint32x2_t = simd_shuffle!(c, c, [LANE as u32, LANE as u32]);
9262-
vdot_u32(a, b, transmute(c))
9262+
vdot_u32(a, b, vreinterpret_u8_u32(c))
92639263
}
92649264
}
92659265
#[doc = "Dot product arithmetic (indexed)"]
@@ -9283,11 +9283,11 @@ pub fn vdot_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint8x8_t, c: uint8x8_t)
92839283
)]
92849284
pub fn vdotq_lane_u32<const LANE: i32>(a: uint32x4_t, b: uint8x16_t, c: uint8x8_t) -> uint32x4_t {
92859285
static_assert_uimm_bits!(LANE, 1);
9286+
let c: uint32x2_t = vreinterpret_u32_u8(c);
92869287
unsafe {
9287-
let c: uint32x2_t = transmute(c);
92889288
let c: uint32x4_t =
92899289
simd_shuffle!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
9290-
vdotq_u32(a, b, transmute(c))
9290+
vdotq_u32(a, b, vreinterpretq_u8_u32(c))
92919291
}
92929292
}
92939293
#[doc = "Dot product arithmetic (vector)"]
@@ -71710,10 +71710,10 @@ pub fn vsubw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t {
7171071710
)]
7171171711
pub fn vsudot_lane_s32<const LANE: i32>(a: int32x2_t, b: int8x8_t, c: uint8x8_t) -> int32x2_t {
7171271712
static_assert_uimm_bits!(LANE, 1);
71713+
let c: uint32x2_t = vreinterpret_u32_u8(c);
7171371714
unsafe {
71714-
let c: uint32x2_t = transmute(c);
7171571715
let c: uint32x2_t = simd_shuffle!(c, c, [LANE as u32, LANE as u32]);
71716-
vusdot_s32(a, transmute(c), b)
71716+
vusdot_s32(a, vreinterpret_u8_u32(c), b)
7171771717
}
7171871718
}
7171971719
#[doc = "Dot product index form with signed and unsigned integers"]
@@ -71737,11 +71737,11 @@ pub fn vsudot_lane_s32<const LANE: i32>(a: int32x2_t, b: int8x8_t, c: uint8x8_t)
7173771737
)]
7173871738
pub fn vsudotq_lane_s32<const LANE: i32>(a: int32x4_t, b: int8x16_t, c: uint8x8_t) -> int32x4_t {
7173971739
static_assert_uimm_bits!(LANE, 1);
71740+
let c: uint32x2_t = vreinterpret_u32_u8(c);
7174071741
unsafe {
71741-
let c: uint32x2_t = transmute(c);
7174271742
let c: uint32x4_t =
7174371743
simd_shuffle!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
71744-
vusdotq_s32(a, transmute(c), b)
71744+
vusdotq_s32(a, vreinterpretq_u8_u32(c), b)
7174571745
}
7174671746
}
7174771747
#[doc = "Table look-up"]
@@ -73630,10 +73630,10 @@ pub fn vtstq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
7363073630
)]
7363173631
pub fn vusdot_lane_s32<const LANE: i32>(a: int32x2_t, b: uint8x8_t, c: int8x8_t) -> int32x2_t {
7363273632
static_assert_uimm_bits!(LANE, 1);
73633+
let c: int32x2_t = vreinterpret_s32_s8(c);
7363373634
unsafe {
73634-
let c: int32x2_t = transmute(c);
7363573635
let c: int32x2_t = simd_shuffle!(c, c, [LANE as u32, LANE as u32]);
73636-
vusdot_s32(a, b, transmute(c))
73636+
vusdot_s32(a, b, vreinterpret_s8_s32(c))
7363773637
}
7363873638
}
7363973639
#[doc = "Dot product index form with unsigned and signed integers"]
@@ -73657,11 +73657,11 @@ pub fn vusdot_lane_s32<const LANE: i32>(a: int32x2_t, b: uint8x8_t, c: int8x8_t)
7365773657
)]
7365873658
pub fn vusdotq_lane_s32<const LANE: i32>(a: int32x4_t, b: uint8x16_t, c: int8x8_t) -> int32x4_t {
7365973659
static_assert_uimm_bits!(LANE, 1);
73660+
let c: int32x2_t = vreinterpret_s32_s8(c);
7366073661
unsafe {
73661-
let c: int32x2_t = transmute(c);
7366273662
let c: int32x4_t =
7366373663
simd_shuffle!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
73664-
vusdotq_s32(a, b, transmute(c))
73664+
vusdotq_s32(a, b, vreinterpretq_s8_s32(c))
7366573665
}
7366673666
}
7366773667
#[doc = "Dot product vector form with unsigned and signed integers"]
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Bad LLVM codegen for BE in O2 in clang, and release in rust (https://github.com/llvm/llvm-project/issues/166190)
2+
vcmla_lane_f16
3+
vcmla_laneq_f16
4+
vcmla_rot180_lane_f16
5+
vcmla_rot180_laneq_f16
6+
vcmla_rot270_lane_f16
7+
vcmla_rot270_laneq_f16
8+
vcmla_rot90_lane_f16
9+
vcmla_rot90_laneq_f16
10+
vcmlaq_lane_f16
11+
vcmlaq_laneq_f16
12+
vcmlaq_laneq_f32
13+
vcmlaq_rot180_lane_f16
14+
vcmlaq_rot180_laneq_f16
15+
vcmlaq_rot180_laneq_f32
16+
vcmlaq_rot270_lane_f16
17+
vcmlaq_rot270_laneq_f16
18+
vcmlaq_rot270_laneq_f32
19+
vcmlaq_rot90_lane_f16
20+
vcmlaq_rot90_laneq_f16
21+
vcmlaq_rot90_laneq_f32
22+
# Bad codegen for BE in O2 in clang, correct in rust. Same cause as above issue.
23+
vdot_lane_s32
24+
vdot_lane_u32
25+
vdot_laneq_s32
26+
vdot_laneq_u32
27+
vdotq_lane_s32
28+
vdotq_lane_u32
29+
vdotq_laneq_s32
30+
vdotq_laneq_u32
31+
vsudot_lane_s32
32+
vsudot_laneq_s32
33+
vsudotq_lane_s32
34+
vsudotq_laneq_s32
35+
vusdot_lane_s32
36+
vusdot_laneq_s32
37+
vusdotq_lane_s32
38+
vusdotq_laneq_s32
39+
40+
# Below are in common to missing_aarch64.txt
41+
42+
# Not implemented in stdarch yet
43+
vbfdot_f32
44+
vbfdot_lane_f32
45+
vbfdot_laneq_f32
46+
vbfdotq_f32
47+
vbfdotq_lane_f32
48+
vbfdotq_laneq_f32
49+
vbfmlalbq_f32
50+
vbfmlalbq_lane_f32
51+
vbfmlalbq_laneq_f32
52+
vbfmlaltq_f32
53+
vbfmlaltq_lane_f32
54+
vbfmlaltq_laneq_f32
55+
vbfmmlaq_f32
56+
57+
58+
# Implemented in stdarch, but missing in Clang.
59+
vrnd32xq_f64
60+
vrnd32zq_f64
61+
vrnd64xq_f64
62+
vrnd64zq_f64
63+
vamin_f32
64+
vaminq_f32
65+
vaminq_f64
66+
vamax_f32
67+
vamaxq_f32
68+
vamaxq_f64
69+
# LLVM select error, and missing in Clang.
70+
vrnd32x_f64
71+
vrnd32z_f64
72+
vrnd64x_f64
73+
vrnd64z_f64
74+
vluti2_lane_p16
75+
vluti2_lane_p8
76+
vluti2_lane_s16
77+
vluti2_lane_s8
78+
vluti2_lane_u16
79+
vluti2_lane_u8
80+
vluti2q_lane_p16
81+
vluti2q_lane_p8
82+
vluti2q_lane_s16
83+
vluti2q_lane_s8
84+
vluti2q_lane_u16
85+
vluti2q_lane_u8
86+
vluti4q_lane_f16_x2
87+
vluti4q_lane_p16_x2
88+
vluti4q_lane_p8
89+
vluti4q_lane_s16_x2
90+
vluti4q_lane_s8
91+
vluti4q_lane_u16_x2
92+
vluti4q_lane_u8
93+
vluti4q_laneq_f16_x2
94+
vluti4q_laneq_p16_x2
95+
vluti4q_laneq_p8
96+
vluti4q_laneq_s16_x2
97+
vluti4q_laneq_s8
98+
vluti4q_laneq_u16_x2
99+
vluti4q_laneq_u8
100+
101+
# Broken in Clang
102+
vcvth_s16_f16
103+
# FIXME: Broken output due to missing f16 printing support in Rust
104+
vmulh_lane_f16
105+
vmulh_laneq_f16

crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5091,13 +5091,13 @@ intrinsics:
50915091
static_defs: ["const LANE: i32"]
50925092
safety: safe
50935093
types:
5094-
- [int32x2_t, uint8x8_t, int8x16_t, '[LANE as u32, LANE as u32]']
5095-
- [int32x4_t, uint8x16_t, int8x16_t, '[LANE as u32, LANE as u32, LANE as u32, LANE as u32]']
5094+
- [int32x2_t, uint8x8_t, int8x16_t, '[LANE as u32, LANE as u32]','']
5095+
- [int32x4_t, uint8x16_t, int8x16_t, '[LANE as u32, LANE as u32, LANE as u32, LANE as u32]','q']
50965096
compose:
50975097
- FnCall: [static_assert_uimm_bits!, [LANE, '2']]
5098-
- Let: [c, int32x4_t, {FnCall: [transmute, [c]]}]
5098+
- Let: [c, int32x4_t, {FnCall: ['vreinterpretq_s32_s8', [c]]}]
50995099
- Let: [c, "{neon_type[0]}", {FnCall: [simd_shuffle!, [c, c, "{type[3]}"]]}]
5100-
- FnCall: ["vusdot{neon_type[0].no}", [a, b, {FnCall: [transmute, [c]]}]]
5100+
- FnCall: ["vusdot{neon_type[0].no}", [a, b, {FnCall: ['vreinterpret{type[4]}_s8_s32', [c]]}]]
51015101

51025102
- name: "vsudot{neon_type[0].laneq_nox}"
51035103
doc: "Dot product index form with signed and unsigned integers"
@@ -5123,7 +5123,11 @@ intrinsics:
51235123
- c
51245124
- "{type[4]}"
51255125
- FnCall: [simd_shuffle!, [c, c, "{type[3]}"]]
5126-
- FnCall: ["vusdot{neon_type[0].no}", [a, {FnCall: [transmute, [c]]}, b]]
5126+
- FnCall:
5127+
- "vusdot{neon_type[0].no}"
5128+
- - a
5129+
- FnCall: [transmute, [c]]
5130+
- b
51275131

51285132
- name: "vmul{neon_type.no}"
51295133
doc: Multiply
@@ -6580,14 +6584,14 @@ intrinsics:
65806584
- FnCall: [unstable, ['feature = "stdarch_neon_dotprod"', 'issue = "117224"']]
65816585
safety: safe
65826586
types:
6583-
- [int32x2_t, int8x8_t, int8x16_t, int32x4_t, '[LANE as u32, LANE as u32]']
6584-
- [int32x4_t, int8x16_t, int8x16_t, int32x4_t, '[LANE as u32, LANE as u32, LANE as u32, LANE as u32]']
6587+
- [int32x2_t, int8x8_t, int8x16_t, int32x4_t, '[LANE as u32, LANE as u32]', '']
6588+
- [int32x4_t, int8x16_t, int8x16_t, int32x4_t, '[LANE as u32, LANE as u32, LANE as u32, LANE as u32]','q']
65856589
compose:
65866590
- FnCall: [static_assert_uimm_bits!, [LANE, '2']]
65876591
- Let:
65886592
- c
65896593
- "{neon_type[3]}"
6590-
- FnCall: [transmute, [c]]
6594+
- FnCall: ['vreinterpretq_{neon_type[0]}_{neon_type[1]}', [c]]
65916595
- Let:
65926596
- c
65936597
- "{neon_type[0]}"
@@ -6596,7 +6600,7 @@ intrinsics:
65966600
- "vdot{neon_type[0].no}"
65976601
- - a
65986602
- b
6599-
- FnCall: [transmute, [c]]
6603+
- FnCall: ['vreinterpret{type[5]}_{neon_type[1]}_{neon_type[0]}', [c]]
66006604

66016605
- name: "vdot{neon_type[0].laneq_nox}"
66026606
doc: Dot product arithmetic (indexed)
@@ -6610,14 +6614,14 @@ intrinsics:
66106614
- FnCall: [unstable, ['feature = "stdarch_neon_dotprod"', 'issue = "117224"']]
66116615
safety: safe
66126616
types:
6613-
- [uint32x2_t, uint8x8_t, uint8x16_t, uint32x4_t, '[LANE as u32, LANE as u32]']
6614-
- [uint32x4_t, uint8x16_t, uint8x16_t, uint32x4_t, '[LANE as u32, LANE as u32, LANE as u32, LANE as u32]']
6617+
- [uint32x2_t, uint8x8_t, uint8x16_t, uint32x4_t, '[LANE as u32, LANE as u32]','']
6618+
- [uint32x4_t, uint8x16_t, uint8x16_t, uint32x4_t, '[LANE as u32, LANE as u32, LANE as u32, LANE as u32]','q']
66156619
compose:
66166620
- FnCall: [static_assert_uimm_bits!, [LANE, '2']]
66176621
- Let:
66186622
- c
66196623
- "{neon_type[3]}"
6620-
- FnCall: [transmute, [c]]
6624+
- FnCall: ['vreinterpretq_{neon_type[0]}_{neon_type[1]}', [c]]
66216625
- Let:
66226626
- c
66236627
- "{neon_type[0]}"
@@ -6626,7 +6630,7 @@ intrinsics:
66266630
- "vdot{neon_type[0].no}"
66276631
- - a
66286632
- b
6629-
- FnCall: [transmute, [c]]
6633+
- FnCall: ['vreinterpret{type[5]}_{neon_type[1]}_{neon_type[0]}', [c]]
66306634

66316635
- name: "vmax{neon_type.no}"
66326636
doc: Maximum (vector)

0 commit comments

Comments
 (0)