; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s ; Test that the "returned" attribute is optimized effectively. target triple = "wasm32-unknown-unknown" %class.Apple = type { i8 } declare noalias ptr @_Znwm(i32) declare ptr @_ZN5AppleC1Ev(ptr returned) define ptr @_Z3foov() { ; CHECK-LABEL: _Z3foov: ; CHECK: .functype _Z3foov () -> (i32) ; CHECK-NEXT: # %bb.0: # %entry ; CHECK-NEXT: i32.const $push0=, 1 ; CHECK-NEXT: call $push1=, _Znwm, $pop0 ; CHECK-NEXT: call $push2=, _ZN5AppleC1Ev, $pop1 ; CHECK-NEXT: return $pop2 entry: %call = tail call noalias ptr @_Znwm(i32 1) %call1 = tail call ptr @_ZN5AppleC1Ev(ptr %call) ret ptr %call } declare ptr @memcpy(ptr returned, ptr, i32) define ptr @_Z3barPvS_l(ptr %p, ptr %s, i32 %n) { ; CHECK-LABEL: _Z3barPvS_l: ; CHECK: .functype _Z3barPvS_l (i32, i32, i32) -> (i32) ; CHECK-NEXT: # %bb.0: # %entry ; CHECK-NEXT: call $push0=, memcpy, $0, $1, $2 ; CHECK-NEXT: return $pop0 entry: %call = tail call ptr @memcpy(ptr %p, ptr %s, i32 %n) ret ptr %p } ; Test that the optimization isn't performed on constant arguments. @global = external global i32 @addr = global ptr @global define void @test_constant_arg() { ; CHECK-LABEL: test_constant_arg: ; CHECK: .functype test_constant_arg () -> () ; CHECK-NEXT: # %bb.0: ; CHECK-NEXT: i32.const $push0=, global ; CHECK-NEXT: call $drop=, returns_arg, $pop0 ; CHECK-NEXT: return %call = call ptr @returns_arg(ptr @global) ret void } declare ptr @returns_arg(ptr returned) ; Test that the optimization isn't performed on arguments without the ; "returned" attribute. declare i32 @do_something(i32 returned, i32, double) declare void @do_something_with_i32(i32) declare void @do_something_with_double(double) define void @test_other_skipped(i32 %a, i32 %b, double %c) { ; CHECK-LABEL: test_other_skipped: ; CHECK: .functype test_other_skipped (i32, i32, f64) -> () ; CHECK-NEXT: # %bb.0: ; CHECK-NEXT: call $drop=, do_something, $0, $1, $2 ; CHECK-NEXT: call do_something_with_i32, $1 ; CHECK-NEXT: call do_something_with_double, $2 ; CHECK-NEXT: return %call = call i32 @do_something(i32 %a, i32 %b, double %c) call void @do_something_with_i32(i32 %b) call void @do_something_with_double(double %c) ret void } ; Test that the optimization is performed on arguments other than the first. declare i32 @do_something_else(i32, i32 returned) define i32 @test_second_arg(i32 %a, i32 %b) { ; CHECK-LABEL: test_second_arg: ; CHECK: .functype test_second_arg (i32, i32) -> (i32) ; CHECK-NEXT: # %bb.0: ; CHECK-NEXT: call $push0=, do_something_else, $0, $1 ; CHECK-NEXT: return $pop0 %call = call i32 @do_something_else(i32 %a, i32 %b) ret i32 %b }