Skip to content

Commit 3fc9349

Browse files
JamesbarfordAmanieu
authored andcommitted
fix - neon type signed unsigned conversions
1 parent 1d71dc6 commit 3fc9349

File tree

7 files changed

+826
-824
lines changed

7 files changed

+826
-824
lines changed

Diff for: crates/core_arch/src/aarch64/neon/generated.rs

+337-331
Large diffs are not rendered by default.

Diff for: crates/core_arch/src/arm_shared/neon/generated.rs

+413-434
Large diffs are not rendered by default.

Diff for: crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml

+17-14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ arch_cfgs:
55
# Generate big endian shuffles
66
auto_big_endian: true
77

8+
# We do not want to automatically generate signed/unsigned casts
9+
auto_llvm_sign_conversion: false
10+
811
# Repeatedly used anchors
912
# #[stable(feature = "neon_intrinsics", since = "1.59.0")]
1013
neon-stable: &neon-stable
@@ -1004,7 +1007,7 @@ intrinsics:
10041007
links:
10051008
- link: "llvm.aarch64.neon.facgt.{type[3]}.{type[1]}"
10061009
arch: aarch64,arm64ec
1007-
- '_vcagth_f16(a, b).as_unsigned() as u16'
1010+
- '_vcagth_f16(a, b) as u16'
10081011

10091012
- name: "vcage{neon_type[0].no}"
10101013
doc: "Floating-point absolute compare greater than or equal"
@@ -1064,7 +1067,7 @@ intrinsics:
10641067
links:
10651068
- link: "llvm.aarch64.neon.facge.{type[3]}.{type[1]}"
10661069
arch: aarch64,arm64ec
1067-
- "_vcageh_f16(a, b).as_unsigned() as u16"
1070+
- "_vcageh_f16(a, b) as u16"
10681071

10691072
- name: "vcalt{neon_type[0].no}"
10701073
doc: "Floating-point absolute compare less than"
@@ -1314,7 +1317,7 @@ intrinsics:
13141317
links:
13151318
- link: "llvm.aarch64.neon.vcvtfxu2fp.{type[1]}.{type[0]}"
13161319
arch: aarch64,arm64ec
1317-
- FnCall: ["_vcvt{type[2]}_n_{type[1]}_{type[0]}", [a.as_signed(), N]]
1320+
- FnCall: ["_vcvt{type[2]}_n_{type[1]}_{type[0]}", [a, N]]
13181321

13191322

13201323
- name: "vcvt{type[2]}_n_{type[1]}_{type[0]}"
@@ -1406,7 +1409,7 @@ intrinsics:
14061409
links:
14071410
- link: "llvm.aarch64.neon.vcvtfxu2fp.{neon_type[1]}.{neon_type[0]}"
14081411
arch: aarch64,arm64ec
1409-
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a.as_signed()", N]]
1412+
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a", N]]
14101413

14111414
- name: "vcvt{type[2]}"
14121415
doc: "Fixed-point convert to floating-point"
@@ -1432,7 +1435,7 @@ intrinsics:
14321435
links:
14331436
- link: "llvm.aarch64.neon.vcvtfxu2fp.{type[1]}.{type[0]}"
14341437
arch: aarch64,arm64ec
1435-
- FnCall: ["_vcvt{type[2]}", ["a.as_signed()", N]]
1438+
- FnCall: ["_vcvt{type[2]}", ["a", N]]
14361439

14371440
- name: "vcvt{type[2]}"
14381441
doc: "Fixed-point convert to floating-point"
@@ -6023,7 +6026,7 @@ intrinsics:
60236026
links:
60246027
- link: "llvm.aarch64.neon.uaddlv.{type[2]}.{neon_type[0]}"
60256028
arch: aarch64,arm64ec
6026-
- FnCall: ['_vaddlv{neon_type[0].no}', ['a.as_signed()']]
6029+
- FnCall: ['_vaddlv{neon_type[0].no}', ['a']]
60276030

60286031
- name: "vaddlv{neon_type[0].no}"
60296032
doc: Unsigned Add Long across Vector
@@ -6041,7 +6044,7 @@ intrinsics:
60416044
links:
60426045
- link: "llvm.aarch64.neon.uaddlv.{type[2]}.{neon_type[0]}"
60436046
arch: aarch64,arm64ec
6044-
- FnCall: ['_vaddlv{neon_type[0].no}', ['a.as_signed()']]
6047+
- FnCall: ['_vaddlv{neon_type[0].no}', ['a']]
60456048

60466049
- name: "vsubw_high{neon_type[1].noq}"
60476050
doc: Signed Subtract Wide
@@ -8704,7 +8707,7 @@ intrinsics:
87048707
links:
87058708
- link: "llvm.aarch64.neon.uqshrn.i32"
87068709
arch: aarch64,arm64ec
8707-
- FnCall: ["_vqshrnd_n_u64", ["a.as_signed()", N]]
8710+
- FnCall: ["_vqshrnd_n_u64", ["a", N]]
87088711

87098712
- name: "vqshrn{type[0]}"
87108713
doc: "Unsigned saturating shift right narrow"
@@ -9845,9 +9848,9 @@ intrinsics:
98459848
arch: aarch64,arm64ec
98469849
- FnCall:
98479850
- "_vsm3tt{type[0]}"
9848-
- - "a.as_signed()"
9849-
- "b.as_signed()"
9850-
- "c.as_signed()"
9851+
- - "a"
9852+
- "b"
9853+
- "c"
98519854
- "IMM2 as i64"
98529855

98539856
- name: "vxarq_u64"
@@ -9877,8 +9880,8 @@ intrinsics:
98779880
arch: aarch64,arm64ec
98789881
- FnCall:
98799882
- "_vxarq_u64"
9880-
- - "a.as_signed()"
9881-
- "b.as_signed()"
9883+
- - "a"
9884+
- "b"
98829885
- "IMM6 as i64"
98839886

98849887
- name: "vrnd32x{neon_type.no}"
@@ -13979,7 +13982,7 @@ intrinsics:
1397913982
links:
1398013983
- link: "llvm.aarch64.neon.uaddlv.i32.{neon_type[0]}"
1398113984
arch: aarch64,arm64ec
13982-
- Identifier: ["_vaddlv{neon_type[0].no}(a.as_signed()).as_unsigned() as u16", Symbol]
13985+
- Identifier: ["_vaddlv{neon_type[0].no}(a) as u16", Symbol]
1398313986

1398413987
- name: "vmaxv{neon_type[0].no}"
1398513988
doc: "Horizontal vector max."

Diff for: crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml

+23-25
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,7 @@ intrinsics:
11391139
links:
11401140
- link: "llvm.arm.neon.vcvtfxu2fp.{neon_type[1]}.{neon_type[0]}"
11411141
arch: arm
1142-
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a.as_signed()", N]]
1142+
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a", N]]
11431143

11441144
- name: "vcvt{neon_type[1].N}_{neon_type[0]}"
11451145
doc: "Fixed-point convert to floating-point"
@@ -1166,7 +1166,7 @@ intrinsics:
11661166
links:
11671167
- link: "llvm.aarch64.neon.vcvtfxu2fp.{neon_type[1]}.{neon_type[0]}"
11681168
arch: aarch64,arm64ec
1169-
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a.as_signed()", N]]
1169+
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a", N]]
11701170

11711171
- name: "vcvt{neon_type[1].N}_{neon_type[0]}"
11721172
doc: "Fixed-point convert to floating-point"
@@ -1197,7 +1197,7 @@ intrinsics:
11971197
arch: arm
11981198
- link: "llvm.aarch64.neon.vcvtfxu2fp.{neon_type[1]}.{neon_type[0]}"
11991199
arch: aarch64,arm64ec
1200-
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a.as_signed()", N]]
1200+
- FnCall: ["_vcvt{neon_type[1].N}_{neon_type[0]}", ["a", N]]
12011201

12021202

12031203
- name: "vcvt{neon_type[1].N}_{neon_type[0]}"
@@ -8486,9 +8486,9 @@ intrinsics:
84868486
safety:
84878487
unsafe: [neon]
84888488
types:
8489-
- [uint16x8_t, uint8x8_t, 'N >= 1 && N <= 8', 'const { uint16x8_t([-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16]) }.as_signed()']
8490-
- [uint32x4_t, uint16x4_t, 'N >= 1 && N <= 16', 'const { uint32x4_t([-N as u32, -N as u32, -N as u32, -N as u32]) }.as_signed()']
8491-
- [uint64x2_t, uint32x2_t, 'N >= 1 && N <= 32', 'const { uint64x2_t([-N as u64, -N as u64]) }.as_signed()']
8489+
- [uint16x8_t, uint8x8_t, 'N >= 1 && N <= 8', 'const { uint16x8_t([-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16]) }']
8490+
- [uint32x4_t, uint16x4_t, 'N >= 1 && N <= 16', 'const { uint32x4_t([-N as u32, -N as u32, -N as u32, -N as u32]) }']
8491+
- [uint64x2_t, uint32x2_t, 'N >= 1 && N <= 32', 'const { uint64x2_t([-N as u64, -N as u64]) }']
84928492
compose:
84938493
- FnCall: [static_assert!, ["{type[2]}"]]
84948494
- LLVMLink:
@@ -8499,7 +8499,7 @@ intrinsics:
84998499
links:
85008500
- link: "llvm.arm.neon.vqshiftnu.{neon_type[1]}"
85018501
arch: arm
8502-
- FnCall: ["_vqshrn_n_{neon_type[0]}", ["a.as_signed()", "{type[3]}"]]
8502+
- FnCall: ["_vqshrn_n_{neon_type[0]}", ["a", "{type[3]}"]]
85038503

85048504
- name: "vqshrn_n_{neon_type[0]}"
85058505
doc: "Unsigned saturating shift right narrow"
@@ -8527,7 +8527,7 @@ intrinsics:
85278527
links:
85288528
- link: "llvm.aarch64.neon.uqshrn.{neon_type[1]}"
85298529
arch: aarch64,arm64ec
8530-
- FnCall: ["_vqshrn_n_{neon_type[0]}", ["a.as_signed()", N]]
8530+
- FnCall: ["_vqshrn_n_{neon_type[0]}", ["a", N]]
85318531

85328532
- name: "vqshrun_n_{neon_type[0]}"
85338533
doc: "Signed saturating shift right unsigned narrow"
@@ -10987,9 +10987,9 @@ intrinsics:
1098710987
safety:
1098810988
unsafe: [neon]
1098910989
types:
10990-
- [uint16x8_t, uint8x8_t, '8', 'const { uint16x8_t([-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16]) }.as_signed()']
10991-
- [uint32x4_t, uint16x4_t, '16', 'const { uint32x4_t([-N as u32, -N as u32, -N as u32, -N as u32]) }.as_signed()']
10992-
- [uint64x2_t, uint32x2_t, '32', 'const { uint64x2_t([-N as u64, -N as u64]) }.as_signed()']
10990+
- [uint16x8_t, uint8x8_t, '8', 'const { uint16x8_t([-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16]) }']
10991+
- [uint32x4_t, uint16x4_t, '16', 'const { uint32x4_t([-N as u32, -N as u32, -N as u32, -N as u32]) }']
10992+
- [uint64x2_t, uint32x2_t, '32', 'const { uint64x2_t([-N as u64, -N as u64]) }']
1099310993
compose:
1099410994
- FnCall: [static_assert!, ['N >= 1 && N <= {type[2]}']]
1099510995
- LLVMLink:
@@ -11000,7 +11000,7 @@ intrinsics:
1100011000
links:
1100111001
- link: "llvm.arm.neon.vqrshiftnu.{neon_type[1]}"
1100211002
arch: arm
11003-
- FnCall: ["_vqrshrn_n{neon_type[0].noq}", ["a.as_signed()", "{type[3]}"]]
11003+
- FnCall: ["_vqrshrn_n{neon_type[0].noq}", ["a", "{type[3]}"]]
1100411004

1100511005
- name: "vqrshrn_n_{neon_type[0]}"
1100611006
doc: "Unsigned signed saturating rounded shift right narrow"
@@ -11028,7 +11028,7 @@ intrinsics:
1102811028
links:
1102911029
- link: "llvm.aarch64.neon.uqrshrn.{neon_type[1]}"
1103011030
arch: aarch64,arm64ec
11031-
- FnCall: ["_vqrshrn_n_{neon_type[0]}", ["a.as_signed()", N]]
11031+
- FnCall: ["_vqrshrn_n_{neon_type[0]}", ["a", N]]
1103211032

1103311033
- name: "vcvt{neon_type[1].no}_{neon_type[0]}"
1103411034
doc: "Floating-point convert to unsigned fixed-point, rounding toward zero"
@@ -13167,7 +13167,7 @@ intrinsics:
1316713167
arch: aarch64,arm64ec
1316813168
- link: "llvm.arm.crc32b"
1316913169
arch: arm
13170-
- FnCall: ["___crc32b", ["crc.as_signed()", "data.as_signed() as i32"]]
13170+
- FnCall: ["___crc32b", ["crc", "data as u32"]]
1317113171

1317213172
- name: "__crc32h"
1317313173
doc: "CRC32 single round checksum for bytes (16 bits)."
@@ -13194,7 +13194,7 @@ intrinsics:
1319413194
arch: aarch64,arm64ec
1319513195
- link: "llvm.arm.crc32h"
1319613196
arch: arm
13197-
- FnCall: ["___crc32h", ["crc.as_signed()", "data.as_signed() as i32"]]
13197+
- FnCall: ["___crc32h", ["crc", "data as u32"]]
1319813198

1319913199
- name: "__crc32w"
1320013200
doc: "CRC32 single round checksum for bytes (32 bits)."
@@ -13244,7 +13244,7 @@ intrinsics:
1324413244
arch: aarch64,arm64ec
1324513245
- link: "llvm.arm.crc32cb"
1324613246
arch: arm
13247-
- FnCall: ["___crc32cb", ["crc.as_signed()", "data.as_signed() as i32"]]
13247+
- FnCall: ["___crc32cb", ["crc", "data as u32"]]
1324813248

1324913249
- name: "__crc32ch"
1325013250
doc: "CRC32-C single round checksum for bytes (16 bits)."
@@ -13271,7 +13271,7 @@ intrinsics:
1327113271
arch: aarch64,arm64ec
1327213272
- link: "llvm.arm.crc32ch"
1327313273
arch: arm
13274-
- FnCall: ["___crc32ch", ["crc.as_signed()", "data.as_signed() as i32"]]
13274+
- FnCall: ["___crc32ch", ["crc", "data as u32"]]
1327513275

1327613276
- name: "__crc32cw"
1327713277
doc: "CRC32-C single round checksum for bytes (32 bits)."
@@ -13313,10 +13313,9 @@ intrinsics:
1331313313
# As the call to `__crc32` does not get inlined, we define an LLVM binding
1331413314
# here, which is the same as above, and call it directly which results
1331513315
# in the correct instructions being generated
13316-
- Let: [a, i32, 'crc as i32']
13317-
- Let: [b, i32, '(data & 0xFFFFFFFF).as_signed() as i32']
13318-
- Let: [c, i32, '(data >> 32).as_signed() as i32']
13319-
- 'unsafe extern "unadjusted" {{ #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32w")] fn ___crc32w(crc: i32, data: i32) -> i32;}} ___crc32w(___crc32w(a, b), c).as_unsigned()'
13316+
- Let: [b, u32, '(data & 0xFFFFFFFF) as u32']
13317+
- Let: [c, u32, '(data >> 32) as u32']
13318+
- 'unsafe extern "unadjusted" {{ #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32w")] fn ___crc32w(crc: u32, data: u32) -> u32;}} ___crc32w(___crc32w(crc, b), c)'
1332013319

1332113320
- name: "__crc32cd"
1332213321
doc: "CRC32-C single round checksum for quad words (64 bits)."
@@ -13332,10 +13331,9 @@ intrinsics:
1333213331
types:
1333313332
- [u32, u64]
1333413333
compose:
13335-
- Let: [a, i32, 'crc as i32']
13336-
- Let: [b, i32, '(data & 0xFFFFFFFF).as_signed() as i32']
13337-
- Let: [c, i32, '(data >> 32).as_signed() as i32']
13338-
- 'unsafe extern "unadjusted" {{ #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32cw")] fn ___crc32cw(crc: i32, data: i32) -> i32;}} ___crc32cw(___crc32cw(a, b), c).as_unsigned() as u32'
13334+
- Let: [b, u32, '(data & 0xFFFFFFFF) as u32']
13335+
- Let: [c, u32, '(data >> 32) as u32']
13336+
- 'unsafe extern "unadjusted" {{ #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32cw")] fn ___crc32cw(crc: u32, data: u32) -> u32;}} ___crc32cw(___crc32cw(crc, b), c)'
1333913337

1334013338
- name: "vabs{neon_type.no}"
1334113339
doc: "Absolute value (wrapping)."

Diff for: crates/stdarch-gen-arm/src/context.rs

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ pub struct GlobalContext {
3939
/// Should the yaml file automagically generate big endian shuffling
4040
#[serde(default)]
4141
pub auto_big_endian: Option<bool>,
42+
43+
/// Should all LLVM wrappers convert their arguments to a signed type
44+
#[serde(default)]
45+
pub auto_llvm_sign_conversion: bool,
4246
}
4347

4448
/// Context of an intrinsic group

Diff for: crates/stdarch-gen-arm/src/expression.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl Expression {
203203
*self = intrinsic
204204
.llvm_link()
205205
.expect("got LLVMLink wildcard without a LLVM link in `compose`")
206-
.apply_conversions_to_call(fn_call.clone(), ctx.local)?
206+
.apply_conversions_to_call(fn_call.clone(), ctx)?
207207
}
208208
}
209209

Diff for: crates/stdarch-gen-arm/src/intrinsic.rs

+31-19
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,9 @@ impl LLVMLink {
548548
Ok(())
549549
}
550550

551-
/// Alters all the unsigned types from the signature, as unsupported by LLVM.
551+
/// Alters all the unsigned types from the signature. This is required where
552+
/// a signed and unsigned variant require the same binding to an exposed
553+
/// LLVM instrinsic.
552554
pub fn sanitise_uints(&mut self) {
553555
let transform = |tk: &mut TypeKind| {
554556
if let Some(BaseType::Sized(BaseTypeKind::UInt, size)) = tk.base_type() {
@@ -603,7 +605,7 @@ impl LLVMLink {
603605
pub fn apply_conversions_to_call(
604606
&self,
605607
mut fn_call: FnCall,
606-
ctx: &LocalContext,
608+
ctx: &Context,
607609
) -> context::Result<Expression> {
608610
use BaseType::{Sized, Unsized};
609611
use BaseTypeKind::{Bool, UInt};
@@ -618,6 +620,7 @@ impl LLVMLink {
618620
.map(|arg| -> context::Result<Expression> {
619621
if let Expression::Identifier(ref var_name, IdentifierType::Variable) = arg {
620622
let (kind, scope) = ctx
623+
.local
621624
.variables
622625
.get(&var_name.to_string())
623626
.ok_or_else(|| format!("invalid variable {var_name:?} being referenced"))?;
@@ -627,7 +630,11 @@ impl LLVMLink {
627630
Ok(convert("into", arg))
628631
}
629632
(Argument, Some(Sized(UInt, _) | Unsized(UInt))) => {
630-
Ok(convert("as_signed", arg))
633+
if ctx.global.auto_llvm_sign_conversion {
634+
Ok(convert("as_signed", arg))
635+
} else {
636+
Ok(arg)
637+
}
631638
}
632639
_ => Ok(arg),
633640
}
@@ -637,22 +644,25 @@ impl LLVMLink {
637644
})
638645
.try_collect()?;
639646

640-
let return_type_requires_conversion = self
641-
.signature
642-
.as_ref()
643-
.and_then(|sig| sig.return_type.as_ref())
644-
.and_then(|ty| {
645-
if let Some(Sized(Bool, bitsize)) = ty.base_type() {
646-
(*bitsize != 8).then_some(Bool)
647-
} else if let Some(Sized(UInt, _) | Unsized(UInt)) = ty.base_type() {
648-
Some(UInt)
649-
} else {
650-
None
651-
}
652-
});
647+
let return_type_conversion = if !ctx.global.auto_llvm_sign_conversion {
648+
None
649+
} else {
650+
self.signature
651+
.as_ref()
652+
.and_then(|sig| sig.return_type.as_ref())
653+
.and_then(|ty| {
654+
if let Some(Sized(Bool, bitsize)) = ty.base_type() {
655+
(*bitsize != 8).then_some(Bool)
656+
} else if let Some(Sized(UInt, _) | Unsized(UInt)) = ty.base_type() {
657+
Some(UInt)
658+
} else {
659+
None
660+
}
661+
})
662+
};
653663

654664
let fn_call = Expression::FnCall(fn_call);
655-
match return_type_requires_conversion {
665+
match return_type_conversion {
656666
Some(Bool) => Ok(convert("into", fn_call)),
657667
Some(UInt) => Ok(convert("as_unsigned", fn_call)),
658668
_ => Ok(fn_call),
@@ -1509,8 +1519,10 @@ impl Intrinsic {
15091519
}
15101520

15111521
if let Some(llvm_link) = self.llvm_link_mut() {
1512-
// Turn all Rust unsigned types into signed
1513-
llvm_link.sanitise_uints();
1522+
/* Turn all Rust unsigned types into signed if required */
1523+
if ctx.global.auto_llvm_sign_conversion {
1524+
llvm_link.sanitise_uints();
1525+
}
15141526
}
15151527

15161528
if let Some(predicate_form) = ctx.local.predicate_form() {

0 commit comments

Comments
 (0)