1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32I %s 4; RUN: llc -relocation-model=pic -mtriple=riscv32 -verify-machineinstrs < %s \ 5; RUN: | FileCheck -check-prefix=RV32I-PIC %s 6 7declare i32 @external_function(i32) 8 9define i32 @test_call_external(i32 %a) nounwind { 10; RV32I-LABEL: test_call_external: 11; RV32I: # %bb.0: 12; RV32I-NEXT: addi sp, sp, -16 13; RV32I-NEXT: sw ra, 12(sp) 14; RV32I-NEXT: call external_function 15; RV32I-NEXT: lw ra, 12(sp) 16; RV32I-NEXT: addi sp, sp, 16 17; RV32I-NEXT: ret 18; 19; RV32I-PIC-LABEL: test_call_external: 20; RV32I-PIC: # %bb.0: 21; RV32I-PIC-NEXT: addi sp, sp, -16 22; RV32I-PIC-NEXT: sw ra, 12(sp) 23; RV32I-PIC-NEXT: call external_function@plt 24; RV32I-PIC-NEXT: lw ra, 12(sp) 25; RV32I-PIC-NEXT: addi sp, sp, 16 26; RV32I-PIC-NEXT: ret 27 %1 = call i32 @external_function(i32 %a) 28 ret i32 %1 29} 30 31declare dso_local i32 @dso_local_function(i32) 32 33define i32 @test_call_dso_local(i32 %a) nounwind { 34; RV32I-LABEL: test_call_dso_local: 35; RV32I: # %bb.0: 36; RV32I-NEXT: addi sp, sp, -16 37; RV32I-NEXT: sw ra, 12(sp) 38; RV32I-NEXT: call dso_local_function 39; RV32I-NEXT: lw ra, 12(sp) 40; RV32I-NEXT: addi sp, sp, 16 41; RV32I-NEXT: ret 42; 43; RV32I-PIC-LABEL: test_call_dso_local: 44; RV32I-PIC: # %bb.0: 45; RV32I-PIC-NEXT: addi sp, sp, -16 46; RV32I-PIC-NEXT: sw ra, 12(sp) 47; RV32I-PIC-NEXT: call dso_local_function 48; RV32I-PIC-NEXT: lw ra, 12(sp) 49; RV32I-PIC-NEXT: addi sp, sp, 16 50; RV32I-PIC-NEXT: ret 51 %1 = call i32 @dso_local_function(i32 %a) 52 ret i32 %1 53} 54 55define i32 @defined_function(i32 %a) nounwind { 56; RV32I-LABEL: defined_function: 57; RV32I: # %bb.0: 58; RV32I-NEXT: addi a0, a0, 1 59; RV32I-NEXT: ret 60; 61; RV32I-PIC-LABEL: defined_function: 62; RV32I-PIC: # %bb.0: 63; RV32I-PIC-NEXT: addi a0, a0, 1 64; RV32I-PIC-NEXT: ret 65 %1 = add i32 %a, 1 66 ret i32 %1 67} 68 69define i32 @test_call_defined(i32 %a) nounwind { 70; RV32I-LABEL: test_call_defined: 71; RV32I: # %bb.0: 72; RV32I-NEXT: addi sp, sp, -16 73; RV32I-NEXT: sw ra, 12(sp) 74; RV32I-NEXT: call defined_function 75; RV32I-NEXT: lw ra, 12(sp) 76; RV32I-NEXT: addi sp, sp, 16 77; RV32I-NEXT: ret 78; 79; RV32I-PIC-LABEL: test_call_defined: 80; RV32I-PIC: # %bb.0: 81; RV32I-PIC-NEXT: addi sp, sp, -16 82; RV32I-PIC-NEXT: sw ra, 12(sp) 83; RV32I-PIC-NEXT: call defined_function@plt 84; RV32I-PIC-NEXT: lw ra, 12(sp) 85; RV32I-PIC-NEXT: addi sp, sp, 16 86; RV32I-PIC-NEXT: ret 87 %1 = call i32 @defined_function(i32 %a) 88 ret i32 %1 89} 90 91define i32 @test_call_indirect(i32 (i32)* %a, i32 %b) nounwind { 92; RV32I-LABEL: test_call_indirect: 93; RV32I: # %bb.0: 94; RV32I-NEXT: addi sp, sp, -16 95; RV32I-NEXT: sw ra, 12(sp) 96; RV32I-NEXT: mv a2, a0 97; RV32I-NEXT: mv a0, a1 98; RV32I-NEXT: jalr a2 99; RV32I-NEXT: lw ra, 12(sp) 100; RV32I-NEXT: addi sp, sp, 16 101; RV32I-NEXT: ret 102; 103; RV32I-PIC-LABEL: test_call_indirect: 104; RV32I-PIC: # %bb.0: 105; RV32I-PIC-NEXT: addi sp, sp, -16 106; RV32I-PIC-NEXT: sw ra, 12(sp) 107; RV32I-PIC-NEXT: mv a2, a0 108; RV32I-PIC-NEXT: mv a0, a1 109; RV32I-PIC-NEXT: jalr a2 110; RV32I-PIC-NEXT: lw ra, 12(sp) 111; RV32I-PIC-NEXT: addi sp, sp, 16 112; RV32I-PIC-NEXT: ret 113 %1 = call i32 %a(i32 %b) 114 ret i32 %1 115} 116 117; Ensure that calls to fastcc functions aren't rejected. Such calls may be 118; introduced when compiling with optimisation. 119 120define fastcc i32 @fastcc_function(i32 %a, i32 %b) nounwind { 121; RV32I-LABEL: fastcc_function: 122; RV32I: # %bb.0: 123; RV32I-NEXT: add a0, a0, a1 124; RV32I-NEXT: ret 125; 126; RV32I-PIC-LABEL: fastcc_function: 127; RV32I-PIC: # %bb.0: 128; RV32I-PIC-NEXT: add a0, a0, a1 129; RV32I-PIC-NEXT: ret 130 %1 = add i32 %a, %b 131 ret i32 %1 132} 133 134define i32 @test_call_fastcc(i32 %a, i32 %b) nounwind { 135; RV32I-LABEL: test_call_fastcc: 136; RV32I: # %bb.0: 137; RV32I-NEXT: addi sp, sp, -16 138; RV32I-NEXT: sw ra, 12(sp) 139; RV32I-NEXT: sw s0, 8(sp) 140; RV32I-NEXT: mv s0, a0 141; RV32I-NEXT: call fastcc_function 142; RV32I-NEXT: mv a0, s0 143; RV32I-NEXT: lw s0, 8(sp) 144; RV32I-NEXT: lw ra, 12(sp) 145; RV32I-NEXT: addi sp, sp, 16 146; RV32I-NEXT: ret 147; 148; RV32I-PIC-LABEL: test_call_fastcc: 149; RV32I-PIC: # %bb.0: 150; RV32I-PIC-NEXT: addi sp, sp, -16 151; RV32I-PIC-NEXT: sw ra, 12(sp) 152; RV32I-PIC-NEXT: sw s0, 8(sp) 153; RV32I-PIC-NEXT: mv s0, a0 154; RV32I-PIC-NEXT: call fastcc_function@plt 155; RV32I-PIC-NEXT: mv a0, s0 156; RV32I-PIC-NEXT: lw s0, 8(sp) 157; RV32I-PIC-NEXT: lw ra, 12(sp) 158; RV32I-PIC-NEXT: addi sp, sp, 16 159; RV32I-PIC-NEXT: ret 160 %1 = call fastcc i32 @fastcc_function(i32 %a, i32 %b) 161 ret i32 %a 162} 163 164declare i32 @external_many_args(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) nounwind 165 166define i32 @test_call_external_many_args(i32 %a) nounwind { 167; RV32I-LABEL: test_call_external_many_args: 168; RV32I: # %bb.0: 169; RV32I-NEXT: addi sp, sp, -16 170; RV32I-NEXT: sw ra, 12(sp) 171; RV32I-NEXT: sw s0, 8(sp) 172; RV32I-NEXT: mv s0, a0 173; RV32I-NEXT: sw a0, 4(sp) 174; RV32I-NEXT: sw a0, 0(sp) 175; RV32I-NEXT: mv a1, a0 176; RV32I-NEXT: mv a2, a0 177; RV32I-NEXT: mv a3, a0 178; RV32I-NEXT: mv a4, a0 179; RV32I-NEXT: mv a5, a0 180; RV32I-NEXT: mv a6, a0 181; RV32I-NEXT: mv a7, a0 182; RV32I-NEXT: call external_many_args 183; RV32I-NEXT: mv a0, s0 184; RV32I-NEXT: lw s0, 8(sp) 185; RV32I-NEXT: lw ra, 12(sp) 186; RV32I-NEXT: addi sp, sp, 16 187; RV32I-NEXT: ret 188; 189; RV32I-PIC-LABEL: test_call_external_many_args: 190; RV32I-PIC: # %bb.0: 191; RV32I-PIC-NEXT: addi sp, sp, -16 192; RV32I-PIC-NEXT: sw ra, 12(sp) 193; RV32I-PIC-NEXT: sw s0, 8(sp) 194; RV32I-PIC-NEXT: mv s0, a0 195; RV32I-PIC-NEXT: sw a0, 4(sp) 196; RV32I-PIC-NEXT: sw a0, 0(sp) 197; RV32I-PIC-NEXT: mv a1, a0 198; RV32I-PIC-NEXT: mv a2, a0 199; RV32I-PIC-NEXT: mv a3, a0 200; RV32I-PIC-NEXT: mv a4, a0 201; RV32I-PIC-NEXT: mv a5, a0 202; RV32I-PIC-NEXT: mv a6, a0 203; RV32I-PIC-NEXT: mv a7, a0 204; RV32I-PIC-NEXT: call external_many_args@plt 205; RV32I-PIC-NEXT: mv a0, s0 206; RV32I-PIC-NEXT: lw s0, 8(sp) 207; RV32I-PIC-NEXT: lw ra, 12(sp) 208; RV32I-PIC-NEXT: addi sp, sp, 16 209; RV32I-PIC-NEXT: ret 210 %1 = call i32 @external_many_args(i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, 211 i32 %a, i32 %a, i32 %a, i32 %a, i32 %a) 212 ret i32 %a 213} 214 215define i32 @defined_many_args(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 %j) nounwind { 216; RV32I-LABEL: defined_many_args: 217; RV32I: # %bb.0: 218; RV32I-NEXT: lw a0, 4(sp) 219; RV32I-NEXT: addi a0, a0, 1 220; RV32I-NEXT: ret 221; 222; RV32I-PIC-LABEL: defined_many_args: 223; RV32I-PIC: # %bb.0: 224; RV32I-PIC-NEXT: lw a0, 4(sp) 225; RV32I-PIC-NEXT: addi a0, a0, 1 226; RV32I-PIC-NEXT: ret 227 %added = add i32 %j, 1 228 ret i32 %added 229} 230 231define i32 @test_call_defined_many_args(i32 %a) nounwind { 232; RV32I-LABEL: test_call_defined_many_args: 233; RV32I: # %bb.0: 234; RV32I-NEXT: addi sp, sp, -16 235; RV32I-NEXT: sw ra, 12(sp) 236; RV32I-NEXT: sw a0, 4(sp) 237; RV32I-NEXT: sw a0, 0(sp) 238; RV32I-NEXT: mv a1, a0 239; RV32I-NEXT: mv a2, a0 240; RV32I-NEXT: mv a3, a0 241; RV32I-NEXT: mv a4, a0 242; RV32I-NEXT: mv a5, a0 243; RV32I-NEXT: mv a6, a0 244; RV32I-NEXT: mv a7, a0 245; RV32I-NEXT: call defined_many_args 246; RV32I-NEXT: lw ra, 12(sp) 247; RV32I-NEXT: addi sp, sp, 16 248; RV32I-NEXT: ret 249; 250; RV32I-PIC-LABEL: test_call_defined_many_args: 251; RV32I-PIC: # %bb.0: 252; RV32I-PIC-NEXT: addi sp, sp, -16 253; RV32I-PIC-NEXT: sw ra, 12(sp) 254; RV32I-PIC-NEXT: sw a0, 4(sp) 255; RV32I-PIC-NEXT: sw a0, 0(sp) 256; RV32I-PIC-NEXT: mv a1, a0 257; RV32I-PIC-NEXT: mv a2, a0 258; RV32I-PIC-NEXT: mv a3, a0 259; RV32I-PIC-NEXT: mv a4, a0 260; RV32I-PIC-NEXT: mv a5, a0 261; RV32I-PIC-NEXT: mv a6, a0 262; RV32I-PIC-NEXT: mv a7, a0 263; RV32I-PIC-NEXT: call defined_many_args@plt 264; RV32I-PIC-NEXT: lw ra, 12(sp) 265; RV32I-PIC-NEXT: addi sp, sp, 16 266; RV32I-PIC-NEXT: ret 267 %1 = call i32 @defined_many_args(i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, 268 i32 %a, i32 %a, i32 %a, i32 %a, i32 %a) 269 ret i32 %1 270} 271