1; RUN: llc < %s -mtriple=s390x-linux-gnu -verify-machineinstrs | FileCheck %s 2; RUN: llc < %s -mtriple=s390x-linux-gnu -O0 -verify-machineinstrs | FileCheck --check-prefix=CHECK-O0 %s 3 4@var = global i32 0 5 6; Test how llvm handles return type of {i16, i8}. The return value will be 7; passed in %r2 and %r3. 8; CHECK-LABEL: test: 9; CHECK: st %r2 10; CHECK: brasl %r14, gen 11; CHECK-DAG: lhr %r2, %r2 12; CHECK-DAG: lbr %[[REG1:r[0-9]+]], %r3 13; CHECK: ar %r2, %[[REG1]] 14; CHECK-O0-LABEL: test 15; CHECK-O0: st %r2 16; CHECK-O0: brasl %r14, gen 17; CHECK-O0-DAG: lhr %[[REG1:r[0-9]+]], %r2 18; CHECK-O0-DAG: lbr %[[REG2:r[0-9]+]], %r3 19; CHECK-O0: ar %[[REG1]], %[[REG2]] 20; CHECK-O0: lr %r2, %[[REG1]] 21define i16 @test(i32 %key) { 22entry: 23 %key.addr = alloca i32, align 4 24 store i32 %key, i32* %key.addr, align 4 25 %0 = load i32, i32* %key.addr, align 4 26 %call = call swiftcc { i16, i8 } @gen(i32 %0) 27 %v3 = extractvalue { i16, i8 } %call, 0 28 %v1 = sext i16 %v3 to i32 29 %v5 = extractvalue { i16, i8 } %call, 1 30 %v2 = sext i8 %v5 to i32 31 %add = add nsw i32 %v1, %v2 32 %conv = trunc i32 %add to i16 33 ret i16 %conv 34} 35 36declare swiftcc { i16, i8 } @gen(i32) 37 38; If we can't pass every return value in registers, we will pass everything 39; in memroy. The caller provides space for the return value and passes 40; the address in %r2. The first input argument will be in %r3. 41; CHECK-LABEL: test2: 42; CHECK: lr %[[REG1:r[0-9]+]], %r2 43; CHECK-DAG: la %r2, 160(%r15) 44; CHECK-DAG: lr %r3, %[[REG1]] 45; CHECK: brasl %r14, gen2 46; CHECK: l %r2, 160(%r15) 47; CHECK: a %r2, 164(%r15) 48; CHECK: a %r2, 168(%r15) 49; CHECK: a %r2, 172(%r15) 50; CHECK: a %r2, 176(%r15) 51; CHECK-O0-LABEL: test2: 52; CHECK-O0: la %[[REG1:r[0-9]+]], 168(%r15) 53; CHECK-O0: st %r2, [[SPILL1:[0-9]+]](%r15) 54; CHECK-O0: lgr %r2, %[[REG1]] 55; CHECK-O0: l %r3, [[SPILL1]](%r15) 56; CHECK-O0: brasl %r14, gen2 57; CHECK-O0-DAG: l %r{{.*}}, 184(%r15) 58; CHECK-O0-DAG: l %r{{.*}}, 180(%r15) 59; CHECK-O0-DAG: l %r{{.*}}, 176(%r15) 60; CHECK-O0-DAG: l %r{{.*}}, 172(%r15) 61; CHECK-O0-DAG: l %r{{.*}}, 168(%r15) 62; CHECK-O0: ar 63; CHECK-O0: ar 64; CHECK-O0: ar 65; CHECK-O0: ar 66; CHECK-O0: lr %r2 67define i32 @test2(i32 %key) #0 { 68entry: 69 %key.addr = alloca i32, align 4 70 store i32 %key, i32* %key.addr, align 4 71 %0 = load i32, i32* %key.addr, align 4 72 %call = call swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %0) 73 74 %v3 = extractvalue { i32, i32, i32, i32, i32 } %call, 0 75 %v5 = extractvalue { i32, i32, i32, i32, i32 } %call, 1 76 %v6 = extractvalue { i32, i32, i32, i32, i32 } %call, 2 77 %v7 = extractvalue { i32, i32, i32, i32, i32 } %call, 3 78 %v8 = extractvalue { i32, i32, i32, i32, i32 } %call, 4 79 80 %add = add nsw i32 %v3, %v5 81 %add1 = add nsw i32 %add, %v6 82 %add2 = add nsw i32 %add1, %v7 83 %add3 = add nsw i32 %add2, %v8 84 ret i32 %add3 85} 86 87; The address of the return value is passed in %r2. 88; On return, %r2 will contain the adddress that has been passed in by the caller in %r2. 89; CHECK-LABEL: gen2: 90; CHECK: st %r3, 16(%r2) 91; CHECK: st %r3, 12(%r2) 92; CHECK: st %r3, 8(%r2) 93; CHECK: st %r3, 4(%r2) 94; CHECK: st %r3, 0(%r2) 95; CHECK-O0-LABEL: gen2: 96; CHECK-O0-DAG: st %r3, 16(%r2) 97; CHECK-O0-DAG: st %r3, 12(%r2) 98; CHECK-O0-DAG: st %r3, 8(%r2) 99; CHECK-O0-DAG: st %r3, 4(%r2) 100; CHECK-O0-DAG: st %r3, 0(%r2) 101define swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %key) { 102 %Y = insertvalue { i32, i32, i32, i32, i32 } undef, i32 %key, 0 103 %Z = insertvalue { i32, i32, i32, i32, i32 } %Y, i32 %key, 1 104 %Z2 = insertvalue { i32, i32, i32, i32, i32 } %Z, i32 %key, 2 105 %Z3 = insertvalue { i32, i32, i32, i32, i32 } %Z2, i32 %key, 3 106 %Z4 = insertvalue { i32, i32, i32, i32, i32 } %Z3, i32 %key, 4 107 ret { i32, i32, i32, i32, i32 } %Z4 108} 109 110; The return value {i32, i32, i32, i32} will be returned via registers 111; %r2, %r3, %r4, %r5. 112; CHECK-LABEL: test3: 113; CHECK: brasl %r14, gen3 114; CHECK: ar %r2, %r3 115; CHECK: ar %r2, %r4 116; CHECK: ar %r2, %r5 117; CHECK-O0-LABEL: test3: 118; CHECK-O0: brasl %r14, gen3 119; CHECK-O0: ar %r2, %r3 120; CHECK-O0: ar %r2, %r4 121; CHECK-O0: ar %r2, %r5 122define i32 @test3(i32 %key) #0 { 123entry: 124 %key.addr = alloca i32, align 4 125 store i32 %key, i32* %key.addr, align 4 126 %0 = load i32, i32* %key.addr, align 4 127 %call = call swiftcc { i32, i32, i32, i32 } @gen3(i32 %0) 128 129 %v3 = extractvalue { i32, i32, i32, i32 } %call, 0 130 %v5 = extractvalue { i32, i32, i32, i32 } %call, 1 131 %v6 = extractvalue { i32, i32, i32, i32 } %call, 2 132 %v7 = extractvalue { i32, i32, i32, i32 } %call, 3 133 134 %add = add nsw i32 %v3, %v5 135 %add1 = add nsw i32 %add, %v6 136 %add2 = add nsw i32 %add1, %v7 137 ret i32 %add2 138} 139 140declare swiftcc { i32, i32, i32, i32 } @gen3(i32 %key) 141 142; The return value {float, float, float, float} will be returned via registers 143; %f0, %f2, %f4, %f6. 144; CHECK-LABEL: test4: 145; CHECK: brasl %r14, gen4 146; CHECK: aebr %f0, %f2 147; CHECK: aebr %f0, %f4 148; CHECK: aebr %f0, %f6 149; CHECK-O0-LABEL: test4: 150; CHECK-O0: brasl %r14, gen4 151; CHECK-O0: aebr %f0, %f2 152; CHECK-O0: aebr %f0, %f4 153; CHECK-O0: aebr %f0, %f6 154define float @test4(float %key) #0 { 155entry: 156 %key.addr = alloca float, align 4 157 store float %key, float* %key.addr, align 4 158 %0 = load float, float* %key.addr, align 4 159 %call = call swiftcc { float, float, float, float } @gen4(float %0) 160 161 %v3 = extractvalue { float, float, float, float } %call, 0 162 %v5 = extractvalue { float, float, float, float } %call, 1 163 %v6 = extractvalue { float, float, float, float } %call, 2 164 %v7 = extractvalue { float, float, float, float } %call, 3 165 166 %add = fadd float %v3, %v5 167 %add1 = fadd float %add, %v6 168 %add2 = fadd float %add1, %v7 169 ret float %add2 170} 171 172declare swiftcc { float, float, float, float } @gen4(float %key) 173 174; CHECK-LABEL: consume_i1_ret: 175; CHECK: brasl %r14, produce_i1_ret 176; CHECK: nilf %r2, 1 177; CHECK: nilf %r3, 1 178; CHECK: nilf %r4, 1 179; CHECK: nilf %r5, 1 180; CHECK-O0-LABEL: consume_i1_ret: 181; CHECK-O0: brasl %r14, produce_i1_ret 182; CHECK-O0: nilf %r2, 1 183; CHECK-O0: nilf %r3, 1 184; CHECK-O0: nilf %r4, 1 185; CHECK-O0: nilf %r5, 1 186define void @consume_i1_ret() { 187 %call = call swiftcc { i1, i1, i1, i1 } @produce_i1_ret() 188 %v3 = extractvalue { i1, i1, i1, i1 } %call, 0 189 %v5 = extractvalue { i1, i1, i1, i1 } %call, 1 190 %v6 = extractvalue { i1, i1, i1, i1 } %call, 2 191 %v7 = extractvalue { i1, i1, i1, i1 } %call, 3 192 %val = zext i1 %v3 to i32 193 store i32 %val, i32* @var 194 %val2 = zext i1 %v5 to i32 195 store i32 %val2, i32* @var 196 %val3 = zext i1 %v6 to i32 197 store i32 %val3, i32* @var 198 %val4 = zext i1 %v7 to i32 199 store i32 %val4, i32* @var 200 ret void 201} 202 203declare swiftcc { i1, i1, i1, i1 } @produce_i1_ret() 204