1 ; RUN: llc < %s -mtriple=armv7 -arm-tail-calls | FileCheck %s 2 3 declare i16 @ret16(i16 returned) 4 declare i32 @ret32(i32 returned) 5 6 define i32 @test1(i32 %val) { 7 ; CHECK-LABEL: test1: 8 ; CHECK: bl {{_?}}ret16 9 %in = trunc i32 %val to i16 10 tail call i16 @ret16(i16 returned %in) 11 ret i32 %val 12 } 13 14 define i16 @test2(i32 %val) { 15 ; CHECK-LABEL: test2: 16 ; CHECK: b {{_?}}ret16 17 %in = trunc i32 %val to i16 18 tail call i16 @ret16(i16 returned %in) 19 ret i16 %in 20 } 21 22 declare {i32, i8} @take_i32_i8({i32, i8} returned) 23 define { i8, i8 } @test_nocommon_value({i32, i32} %in) { 24 ; CHECK-LABEL: test_nocommon_value: 25 ; CHECK: b {{_?}}take_i32_i8 26 27 %first = extractvalue {i32, i32} %in, 0 28 %first.trunc = trunc i32 %first to i8 29 30 %second = extractvalue {i32, i32} %in, 1 31 %second.trunc = trunc i32 %second to i8 32 33 %tmp = insertvalue {i32, i8} undef, i32 %first, 0 34 %callval = insertvalue {i32, i8} %tmp, i8 %second.trunc, 1 35 tail call {i32, i8} @take_i32_i8({i32, i8} returned %callval) 36 37 %restmp = insertvalue {i8, i8} undef, i8 %first.trunc, 0 38 %res = insertvalue {i8, i8} %restmp, i8 %second.trunc, 1 39 ret {i8, i8} %res 40 } 41 42 declare {i32, {i32, i32}} @give_i32_i32_i32() 43 define {{i32, i32}, i32} @test_structs_different_shape() { 44 ; CHECK-LABEL: test_structs_different_shape: 45 ; CHECK: b {{_?}}give_i32_i32_i32 46 %val = tail call {i32, {i32, i32}} @give_i32_i32_i32() 47 48 %first = extractvalue {i32, {i32, i32}} %val, 0 49 %second = extractvalue {i32, {i32, i32}} %val, 1, 0 50 %third = extractvalue {i32, {i32, i32}} %val, 1, 1 51 52 %restmp = insertvalue {{i32, i32}, i32} undef, i32 %first, 0, 0 53 %reseventmper = insertvalue {{i32, i32}, i32} %restmp, i32 %second, 0, 1 54 %res = insertvalue {{i32, i32}, i32} %reseventmper, i32 %third, 1 55 56 ret {{i32, i32}, i32} %res 57 } 58 59 define i32 @test_undef_asymmetry() { 60 ; CHECK: test_undef_asymmetry: 61 ; CHECK: bl {{_?}}ret32 62 ; CHECK-NOT: jmp 63 tail call i32 @ret32(i32 returned undef) 64 ret i32 2 65 } 66 67 define {{}, {{}, i32, {}}, [1 x i32]} @evil_empty_aggregates() { 68 ; CHECK-LABEL: evil_empty_aggregates: 69 ; CHECK: b {{_?}}give_i32_i32_i32 70 %agg = tail call {i32, {i32, i32}} @give_i32_i32_i32() 71 72 %first = extractvalue {i32, {i32, i32}} %agg, 0 73 %second = extractvalue {i32, {i32, i32}} %agg, 1, 0 74 75 %restmp = insertvalue {{}, {{}, i32, {}}, [1 x i32]} undef, i32 %first, 1, 1 76 %res = insertvalue {{}, {{}, i32, {}}, [1 x i32]} %restmp, i32 %second, 2, 0 77 ret {{}, {{}, i32, {}}, [1 x i32]} %res 78 } 79 80 define i32 @structure_is_unimportant() { 81 ; CHECK-LABEL: structure_is_unimportant: 82 ; CHECK: b {{_?}}give_i32_i32_i32 83 %val = tail call {i32, {i32, i32}} @give_i32_i32_i32() 84 85 %res = extractvalue {i32, {i32, i32}} %val, 0 86 ret i32 %res 87 } 88 89 declare i64 @give_i64() 90 define i64 @direct_i64_ok() { 91 ; CHECK-LABEL: direct_i64_ok: 92 ; CHECK: b {{_?}}give_i64 93 %val = tail call i64 @give_i64() 94 ret i64 %val 95 } 96 97 declare {i64, i32} @give_i64_i32() 98 define {i32, i32} @trunc_i64_not_ok() { 99 ; CHECK-LABEL: trunc_i64_not_ok: 100 ; CHECK: bl {{_?}}give_i64_i32 101 %agg = tail call {i64, i32} @give_i64_i32() 102 103 %first = extractvalue {i64, i32} %agg, 0 104 %second = extractvalue {i64, i32} %agg, 1 105 %first.trunc = trunc i64 %first to i32 106 107 %tmp = insertvalue {i32, i32} undef, i32 %first.trunc, 0 108 %ret = insertvalue {i32, i32} %tmp, i32 %second, 1 109 110 ret {i32, i32} %ret 111 } 112