rust/src/test/codegen
bors 1d601d6ff1 Auto merge of #74695 - alexcrichton:more-wasm-float-cast-fixes, r=nagisa
rustc: Improving safe wasm float->int casts

This commit improves code generation for WebAssembly targets when
translating floating to integer casts. This improvement is only relevant
when the `nontrapping-fptoint` feature is not enabled, but the feature
is not enabled by default right now. Additionally this improvement only
affects safe casts since unchecked casts were improved in #74659.

Some more background for this issue is present on #73591, but the
general gist of the issue is that in LLVM the `fptosi` and `fptoui`
instructions are defined to return an `undef` value if they execute on
out-of-bounds values; they notably do not trap. To implement these
instructions for WebAssembly the LLVM backend must therefore generate
quite a few instructions before executing `i32.trunc_f32_s` (for
example) because this WebAssembly instruction traps on out-of-bounds
values. This codegen into wasm instructions happens very late in the
code generator, so what ends up happening is that rustc inserts its own
codegen to implement Rust's saturating semantics, and then LLVM also
inserts its own codegen to make sure that the `fptosi` instruction
doesn't trap. Overall this means that a function like this:

    #[no_mangle]
    pub unsafe extern "C" fn cast(x: f64) -> u32 {
        x as u32
    }

will generate this WebAssembly today:

    (func $cast (type 0) (param f64) (result i32)
      (local i32 i32)
      local.get 0
      f64.const 0x1.fffffffep+31 (;=4.29497e+09;)
      f64.gt
      local.set 1
      block  ;; label = @1
        block  ;; label = @2
          local.get 0
          f64.const 0x0p+0 (;=0;)
          local.get 0
          f64.const 0x0p+0 (;=0;)
          f64.gt
          select
          local.tee 0
          f64.const 0x1p+32 (;=4.29497e+09;)
          f64.lt
          local.get 0
          f64.const 0x0p+0 (;=0;)
          f64.ge
          i32.and
          i32.eqz
          br_if 0 (;@2;)
          local.get 0
          i32.trunc_f64_u
          local.set 2
          br 1 (;@1;)
        end
        i32.const 0
        local.set 2
      end
      i32.const -1
      local.get 2
      local.get 1
      select)

This PR improves the situation by updating the code generation for
float-to-int conversions in rustc, specifically only for WebAssembly
targets and only for some situations (float-to-u8 still has not great
codegen). The fix here is to use basic blocks and control flow to avoid
speculatively executing `fptosi`, and instead LLVM's raw intrinsic for
the WebAssembly instruction is used instead. This effectively extends
the support added in #74659 to checked casts. After this commit the
codegen for the above Rust function looks like:

    (func $cast (type 0) (param f64) (result i32)
      (local i32)
      block  ;; label = @1
        local.get 0
        f64.const 0x0p+0 (;=0;)
        f64.ge
        local.tee 1
        i32.const 1
        i32.xor
        br_if 0 (;@1;)
        local.get 0
        f64.const 0x1.fffffffep+31 (;=4.29497e+09;)
        f64.le
        i32.eqz
        br_if 0 (;@1;)
        local.get 0
        i32.trunc_f64_u
        return
      end
      i32.const -1
      i32.const 0
      local.get 1
      select)

For reference, in Rust 1.44, which did not have saturating
float-to-integer casts, the codegen LLVM would emit is:

    (func $cast (type 0) (param f64) (result i32)
      block  ;; label = @1
        local.get 0
        f64.const 0x1p+32 (;=4.29497e+09;)
        f64.lt
        local.get 0
        f64.const 0x0p+0 (;=0;)
        f64.ge
        i32.and
        i32.eqz
        br_if 0 (;@1;)
        local.get 0
        i32.trunc_f64_u
        return
      end
      i32.const 0)

So we're relatively close to the original codegen, although it's
slightly different because the semantics of the function changed where
we're emulating the `i32.trunc_sat_f32_s` instruction rather than always
replacing out-of-bounds values with zero.

There is still work that could be done to improve casts such as `f32` to
`u8`. That form of cast still uses the `fptosi` instruction which
generates lots of branch-y code. This seems less important to tackle now
though. In the meantime this should take care of most use cases of
floating-point conversion and as a result I'm going to speculate that
this...

Closes #73591
2020-08-03 23:57:50 +00:00
..
auxiliary Remove licenses 2018-12-25 21:08:33 -07:00
avr compiletest: Support ignoring tests requiring missing LLVM components 2020-08-02 20:35:24 +03:00
dllimports Added ignore-sgx for appropriate tests 2019-05-16 14:29:12 -07:00
intrinsics Added ui tests for volatile and nearby intrinsics 2020-07-13 00:47:09 -04:00
non-terminate Gate llvm.sideeffect under -Z insert-sideeffect 2019-09-28 07:13:53 +08:00
remap_path_prefix Add hash of source files in debug info 2020-04-02 14:13:19 -07:00
riscv-abi test: codegen: Add riscv abi llvm intrinsics test 2020-06-04 12:02:03 +01:00
simd-intrinsic Update the minimum external LLVM to 7 2019-12-02 11:36:21 -08:00
src-hash-algorithm Add hash of source files in debug info 2020-04-02 14:13:19 -07:00
abi-efiapi.rs compiletest: Support ignoring tests requiring missing LLVM components 2020-08-02 20:35:24 +03:00
abi-main-signature-16bit-c-int.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
abi-main-signature-32bit-c-int.rs Update codegen tests with unnamed arguments 2020-01-07 21:28:22 +01:00
abi-sysv64.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
abi-x86-interrupt.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
abi-x86_64_sysv.rs Remove licenses 2018-12-25 21:08:33 -07:00
adjustments.rs codegen: use "_N" (like for other locals) instead of "argN", for argument names. 2019-09-13 19:25:05 +03:00
align-enum.rs Disable MIR optimization for alignment codegen tests 2020-05-16 17:15:24 -07:00
align-struct.rs Disable MIR optimization for alignment codegen tests 2020-05-16 17:15:24 -07:00
alloc-optimisation.rs Gate llvm.sideeffect under -Z insert-sideeffect 2019-09-28 07:13:53 +08:00
asm-multiple-options.rs Add codegen test for multiple asm! options 2020-06-20 11:12:42 -07:00
asm-options.rs Add tests for asm! 2020-05-18 14:41:32 +01:00
async-fn-debug-msvc.rs Split out async fn and generator test 2020-06-24 15:08:59 -07:00
async-fn-debug.rs Split out async fn and generator test 2020-06-24 15:08:59 -07:00
atomic-operations.rs Test codegen of compare_exchange operations 2020-07-17 00:00:00 +00:00
bool-cmp.rs Update bool-cmp.rs codegen 2020-01-07 21:28:22 +01:00
box-maybe-uninit.rs stabilize core parts of MaybeUninit and deprecate mem::uninitialized in the future 2019-05-20 10:44:02 +02:00
c-variadic-copy.rs Expose VaListImpl as the Rust equivalent of __va_list_tag and implement Clone for it. 2019-06-17 16:04:49 -07:00
c-variadic-opt.rs Expose VaListImpl as the Rust equivalent of __va_list_tag and implement Clone for it. 2019-06-17 16:04:49 -07:00
c-variadic.rs Use call instead of invoke for functions that cannot unwind 2020-04-15 05:45:21 -04:00
call-llvm-intrinsics.rs test: codegen: Add riscv abi llvm intrinsics test 2020-06-04 12:02:03 +01:00
call-metadata.rs Remove licenses 2018-12-25 21:08:33 -07:00
catch-unwind.rs test: codegen: skip catch-unwind on riscv64 2020-06-04 12:15:26 +01:00
cdylib-external-inline-fns.rs Fix exports with #[inline(always)] 2020-06-15 09:40:56 +01:00
cfguard-checks.rs Stabilize control-flow-guard codegen option 2020-07-14 15:27:42 +01:00
cfguard-disabled.rs Stabilize control-flow-guard codegen option 2020-07-14 15:27:42 +01:00
cfguard-nochecks.rs Stabilize control-flow-guard codegen option 2020-07-14 15:27:42 +01:00
cfguard-non-msvc.rs Stabilize control-flow-guard codegen option 2020-07-14 15:27:42 +01:00
coercions.rs Remove licenses 2018-12-25 21:08:33 -07:00
consts.rs Fix codegen and mir-opt tests 2020-04-20 21:18:20 +02:00
dealloc-no-unwind.rs Gate llvm.sideeffect under -Z insert-sideeffect 2019-09-28 07:13:53 +08:00
debug-column-msvc.rs Test that column information is not emitted for MSVC targets 2020-02-26 21:45:34 +01:00
debug-column.rs Use byte offsets when emitting debuginfo columns 2020-02-26 21:45:34 +01:00
debug-linkage-name.rs Omit DW_AT_linkage_name when it is the same as DW_AT_name 2020-05-27 18:36:32 +02:00
drop.rs Revert "Defer creating drop trees in MIR lowering until leaving that scope" 2020-06-04 11:34:42 -04:00
enum-bounds-check.rs Remove licenses 2018-12-25 21:08:33 -07:00
enum-debug-clike.rs Update the minimum external LLVM to 8 2020-04-14 12:44:41 -07:00
enum-debug-niche-2.rs Update the minimum external LLVM to 8 2020-04-14 12:44:41 -07:00
enum-debug-niche.rs Update the minimum external LLVM to 8 2020-04-14 12:44:41 -07:00
enum-debug-tagged.rs Update the minimum external LLVM to 8 2020-04-14 12:44:41 -07:00
enum-discriminant-value.rs debuginfo: Use is unsigned flag when emitting enumerators 2020-03-05 20:13:01 +01:00
export-no-mangle.rs Fix whitespace 2020-06-15 09:40:57 +01:00
external-no-mangle-fns.rs Fix exports with #[inline(always)] 2020-06-15 09:40:56 +01:00
external-no-mangle-statics.rs Upgrade Emscripten targets to use upstream LLVM backend 2019-10-16 17:06:48 -07:00
fastcall-inreg.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
fatptr.rs Remove licenses 2018-12-25 21:08:33 -07:00
ffi-const.rs Add tests for #[ffi_const] and #[ffi_pure] function attributes 2020-05-20 01:16:11 +02:00
ffi-out-of-bounds-loads.rs Add some skip flags 2020-05-08 00:51:13 +09:00
ffi-pure.rs Add tests for #[ffi_const] and #[ffi_pure] function attributes 2020-05-20 01:16:11 +02:00
ffi-returns-twice.rs Fix attribute check 2019-02-23 15:48:40 +01:00
float_math.rs Remove licenses 2018-12-25 21:08:33 -07:00
fn-impl-trait-self.rs Add codegen test 2019-03-31 20:09:30 -04:00
foo.s Add global_asm tests 2017-04-12 19:12:50 -05:00
force-frame-pointers.rs Update the minimum external LLVM to 8 2020-04-14 12:44:41 -07:00
force-unwind-tables.rs Add missing : after *llvm-version 2020-07-19 11:03:04 +00:00
function-arguments.rs Update codegen tests with unnamed arguments 2020-01-07 21:28:22 +01:00
gdb_debug_script_load.rs Disable gdb pretty printer global section on wasm targets 2019-12-04 20:15:21 -08:00
generator-debug-msvc.rs Split out async fn and generator test 2020-06-24 15:08:59 -07:00
generator-debug.rs Split out async fn and generator test 2020-06-24 15:08:59 -07:00
generic-debug.rs Remove unnecessary ignore-tidy-linelength 2019-04-23 11:42:14 +01:00
global_asm.rs Remove licenses 2018-12-25 21:08:33 -07:00
global_asm_include.rs Remove licenses 2018-12-25 21:08:33 -07:00
global_asm_x2.rs Remove licenses 2018-12-25 21:08:33 -07:00
i686-macosx-deployment-target.rs choose a more specific LLVM target on OS X when necessary 2019-05-07 11:09:39 -04:00
i686-no-macosx-deployment-target.rs default to $ARCH-apple-macosx10.7.0 LLVM triple for darwin targets 2019-05-13 17:04:59 -04:00
inline-always-works-always.rs Support revisions for codegen tests 2019-01-24 20:13:51 +02:00
instrument-mcount.rs Update the minimum external LLVM to 8 2020-04-14 12:44:41 -07:00
integer-cmp.rs Small improvement for Ord implementation of integers 2019-08-29 03:52:18 +00:00
integer-overflow.rs Added a codegen test for a recent optimization for overflow-checks=on 2020-05-24 16:20:02 -04:00
internalize-closures.rs test: support both (legacy and v0) choices of mangling. 2019-05-31 18:24:53 +03:00
intrinsic-no-unnamed-attr.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-13018.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-15953.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-32031.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-32364.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-34947-pow-i32.rs Gate llvm.sideeffect under -Z insert-sideeffect 2019-09-28 07:13:53 +08:00
issue-37945.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-44056-macos-tls-align.rs Ignore changes when debug assertions are enabled. 2020-07-09 10:41:33 -07:00
issue-45222.rs Disable failing codegen test 2020-02-08 18:47:41 -05:00
issue-45466.rs ignore some codegen tests in debug mode 2019-07-15 16:56:43 +02:00
issue-47278.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-47442.rs Remove licenses 2018-12-25 21:08:33 -07:00
issue-56267-2.rs rustc_codegen_llvm: don't overalign loads of pair operands. 2018-11-29 00:37:38 +02:00
issue-56267.rs Fix alignment of stores to scalar pair 2018-11-28 00:31:03 +01:00
issue-56927.rs better lint names 2020-02-18 22:49:47 +01:00
issue-58881.rs Fix LLVM IR generated for C-variadic arguments 2019-03-31 17:37:37 +00:00
issue-69101-bounds-check.rs Slightly improve panic messages when range indices are out of bounds 2020-07-20 00:40:42 +02:00
lifetime_start_end.rs Remove licenses 2018-12-25 21:08:33 -07:00
link-dead-code.rs test: support both (legacy and v0) choices of mangling. 2019-05-31 18:24:53 +03:00
link_section.rs Upgrade Emscripten targets to use upstream LLVM backend 2019-10-16 17:06:48 -07:00
loads.rs Remove licenses 2018-12-25 21:08:33 -07:00
local-generics-in-exe-internalized.rs test: support both (legacy and v0) choices of mangling. 2019-05-31 18:24:53 +03:00
lto-removes-invokes.rs Remove licenses 2018-12-25 21:08:33 -07:00
mainsubprogram.rs Adjust codegen tests for DISPFlagMainSubprogram 2019-07-09 21:55:29 +02:00
mainsubprogramstart.rs Adjust codegen tests for DISPFlagMainSubprogram 2019-07-09 21:55:29 +02:00
match-optimizes-away.rs Remove licenses 2018-12-25 21:08:33 -07:00
match.rs Introduce MIR optimizations for simplifying x? on Results. 2019-11-21 20:05:16 +01:00
mir_zst_stores.rs Remove licenses 2018-12-25 21:08:33 -07:00
naked-functions.rs Suppress debuginfo on naked function arguments 2020-07-27 18:27:15 -04:00
no-assumes-on-casts.rs Remove licenses 2018-12-25 21:08:33 -07:00
no-dllimport-w-cross-lang-lto.rs Stabilize linker-plugin based LTO. 2019-02-12 15:10:29 +01:00
no-output-asm-is-volatile.rs Update tests to use llvm_asm! 2020-03-26 15:49:22 +00:00
no-plt.rs Remove licenses 2018-12-25 21:08:33 -07:00
noreturn-uninhabited.rs Remove unnecessary ignore-tidy-linelength 2019-04-23 11:42:14 +01:00
noreturnflag.rs Remove unnecessary ignore-tidy-linelength 2019-04-23 11:42:14 +01:00
nounwind.rs Remove double trailing newlines 2019-04-22 16:57:01 +01:00
nrvo.rs Test that NRVO elides the call to memcpy 2020-05-17 10:24:06 -07:00
optimize-attr-1.rs [mir-opt] Turn on the ConstProp pass by default 2019-11-11 20:57:26 -05:00
packed.rs Update the minimum external LLVM to 7 2019-12-02 11:36:21 -08:00
panic-abort-windows.rs Added ignore-sgx for appropriate tests 2019-05-16 14:29:12 -07:00
personality_lifetimes.rs Re-enable Emscripten's exception handling support 2019-10-25 15:16:36 -07:00
pgo-instrumentation.rs Relax checks in pgo-instrumentation codegen test 2019-07-15 14:01:26 +02:00
README.md add link to FileCheck docs 2019-08-26 20:40:30 +02:00
refs.rs codegen: use "_N" (like for other locals) instead of "argN", for argument names. 2019-09-13 19:25:05 +03:00
repeat-trusted-len.rs fix a codegen test 2020-03-14 14:05:26 +01:00
repr-transparent-aggregates-1.rs Ignoring test case: [codegen] repr-transparent-aggregates-1.rs for aarch64 2020-07-01 16:02:10 +01:00
repr-transparent-aggregates-2.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
repr-transparent-aggregates-3.rs stabilize transparent_enums 2020-01-20 11:18:05 +01:00
repr-transparent-sysv64.rs Update codegen tests with unnamed arguments 2020-01-07 21:28:22 +01:00
repr-transparent.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
sanitizer-memory-track-orgins.rs compiletest: Add directives to detect sanitizer support 2020-06-13 14:24:30 +02:00
sanitizer-no-sanitize-inlining.rs Rollup merge of #73044 - tmiasko:compiletest-san, r=nikomatsakis 2020-06-19 14:29:22 +02:00
sanitizer-no-sanitize.rs compiletest: Add directives to detect sanitizer support 2020-06-13 14:24:30 +02:00
sanitizer-recover.rs Prepare for LLVM 11 2020-06-25 18:52:41 -07:00
scalar-pair-bool.rs codegen: use "_N" (like for other locals) instead of "argN", for argument names. 2019-09-13 19:25:05 +03:00
set-discriminant-invalid.rs use abort instead of unreachable 2019-12-06 00:10:01 +01:00
slice-init.rs Remove licenses 2018-12-25 21:08:33 -07:00
slice-iter-len-eq-zero.rs Help LLVM better optimize slice::Iter(Mut)::len 2019-06-15 21:15:25 -07:00
slice-position-bounds-check.rs Remove licenses 2018-12-25 21:08:33 -07:00
sparc-struct-abi.rs Remove licenses 2018-12-25 21:08:33 -07:00
stack-probes.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
staticlib-external-inline-fns.rs Fix exports with #[inline(always)] 2020-06-15 09:40:56 +01:00
stores.rs Update the minimum external LLVM to 7 2019-12-02 11:36:21 -08:00
swap-small-types.rs ignore some codegen tests in debug mode 2019-07-15 16:56:43 +02:00
target-cpu-on-functions.rs test: support both (legacy and v0) choices of mangling. 2019-05-31 18:24:53 +03:00
target-feature-multiple.rs cmdline: Make target features individually overridable 2020-05-11 02:04:53 +03:00
target-feature-on-functions.rs Remove licenses 2018-12-25 21:08:33 -07:00
try-panic-abort.rs Simplify the try intrinsic by using a callback in the catch block 2020-03-05 17:36:50 +00:00
try_identity.rs Introduce MIR optimizations for simplifying x? on Results. 2019-11-21 20:05:16 +01:00
unchecked-float-casts.rs Improve codegen for unchecked float casts on wasm 2020-07-22 15:05:05 -07:00
union-abi.rs Update codegen tests with unnamed arguments 2020-01-07 21:28:22 +01:00
unwind-extern-exports.rs Re-enable Emscripten's exception handling support 2019-10-25 15:16:36 -07:00
unwind-extern-imports.rs Re-enable Emscripten's exception handling support 2019-10-25 15:16:36 -07:00
var-names.rs rustc_codegen_llvm: give names to non-alloca variable values. 2019-09-06 16:57:20 +03:00
vec-clear.rs we can enable one more codegen test in debug mode now 2020-06-16 16:01:30 -04:00
vec-iter-collect-len.rs Gate llvm.sideeffect under -Z insert-sideeffect 2019-09-28 07:13:53 +08:00
vec-optimizes-away.rs we can enable one more codegen test in debug mode now 2020-06-16 16:01:30 -04:00
vtabletype.rs Remove unnecessary ignore-tidy-linelength 2019-04-23 11:42:14 +01:00
wasm_casts_nontrapping.rs Add codegen tests 2020-07-02 09:32:09 +02:00
wasm_casts_trapping.rs rustc: Improving safe wasm float->int casts 2020-07-28 10:17:11 -07:00
x86_64-macosx-deployment-target.rs choose a more specific LLVM target on OS X when necessary 2019-05-07 11:09:39 -04:00
x86_64-no-macosx-deployment-target.rs default to $ARCH-apple-macosx10.7.0 LLVM triple for darwin targets 2019-05-13 17:04:59 -04:00
x86_mmx.rs test: codegen: skip tests inappropriate for riscv64 2020-06-04 12:02:03 +01:00
zip.rs Remove licenses 2018-12-25 21:08:33 -07:00

The files here use the LLVM FileCheck framework, documented at https://llvm.org/docs/CommandGuide/FileCheck.html.