1; Test 128-bit addition in which the second operand is variable. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s 4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s 5 6declare i128 *@foo() 7 8; Test register addition. 9define void @f1(i128 *%ptr) { 10; CHECK-LABEL: f1: 11; CHECK: algr 12; CHECK: alcgr 13; CHECK: br %r14 14 %value = load i128, i128 *%ptr 15 %add = add i128 %value, %value 16 store i128 %add, i128 *%ptr 17 ret void 18} 19 20; Test memory addition with no offset. Making the load of %a volatile 21; should force the memory operand to be %b. 22define void @f2(i128 *%aptr, i64 %addr) { 23; CHECK-LABEL: f2: 24; CHECK: alg {{%r[0-5]}}, 8(%r3) 25; CHECK: alcg {{%r[0-5]}}, 0(%r3) 26; CHECK: br %r14 27 %bptr = inttoptr i64 %addr to i128 * 28 %a = load volatile i128, i128 *%aptr 29 %b = load i128, i128 *%bptr 30 %add = add i128 %a, %b 31 store i128 %add, i128 *%aptr 32 ret void 33} 34 35; Test the highest aligned offset that is in range of both ALG and ALCG. 36define void @f3(i128 *%aptr, i64 %base) { 37; CHECK-LABEL: f3: 38; CHECK: alg {{%r[0-5]}}, 524280(%r3) 39; CHECK: alcg {{%r[0-5]}}, 524272(%r3) 40; CHECK: br %r14 41 %addr = add i64 %base, 524272 42 %bptr = inttoptr i64 %addr to i128 * 43 %a = load volatile i128, i128 *%aptr 44 %b = load i128, i128 *%bptr 45 %add = add i128 %a, %b 46 store i128 %add, i128 *%aptr 47 ret void 48} 49 50; Test the next doubleword up, which requires separate address logic for ALG. 51define void @f4(i128 *%aptr, i64 %base) { 52; CHECK-LABEL: f4: 53; CHECK: lay [[BASE:%r[1-5]]], 524280(%r3) 54; CHECK: alg {{%r[0-5]}}, 8([[BASE]]) 55; CHECK: alcg {{%r[0-5]}}, 524280(%r3) 56; CHECK: br %r14 57 %addr = add i64 %base, 524280 58 %bptr = inttoptr i64 %addr to i128 * 59 %a = load volatile i128, i128 *%aptr 60 %b = load i128, i128 *%bptr 61 %add = add i128 %a, %b 62 store i128 %add, i128 *%aptr 63 ret void 64} 65 66; Test the next doubleword after that, which requires separate logic for 67; both instructions. 68define void @f5(i128 *%aptr, i64 %base) { 69; CHECK-LABEL: f5: 70; CHECK: alg {{%r[0-5]}}, 8({{%r[1-5]}}) 71; CHECK: alcg {{%r[0-5]}}, 0({{%r[1-5]}}) 72; CHECK: br %r14 73 %addr = add i64 %base, 524288 74 %bptr = inttoptr i64 %addr to i128 * 75 %a = load volatile i128, i128 *%aptr 76 %b = load i128, i128 *%bptr 77 %add = add i128 %a, %b 78 store i128 %add, i128 *%aptr 79 ret void 80} 81 82; Test the lowest displacement that is in range of both ALG and ALCG. 83define void @f6(i128 *%aptr, i64 %base) { 84; CHECK-LABEL: f6: 85; CHECK: alg {{%r[0-5]}}, -524280(%r3) 86; CHECK: alcg {{%r[0-5]}}, -524288(%r3) 87; CHECK: br %r14 88 %addr = add i64 %base, -524288 89 %bptr = inttoptr i64 %addr to i128 * 90 %a = load volatile i128, i128 *%aptr 91 %b = load i128, i128 *%bptr 92 %add = add i128 %a, %b 93 store i128 %add, i128 *%aptr 94 ret void 95} 96 97; Test the next doubleword down, which is out of range of the ALCG. 98define void @f7(i128 *%aptr, i64 %base) { 99; CHECK-LABEL: f7: 100; CHECK: alg {{%r[0-5]}}, -524288(%r3) 101; CHECK: alcg {{%r[0-5]}}, 0({{%r[1-5]}}) 102; CHECK: br %r14 103 %addr = add i64 %base, -524296 104 %bptr = inttoptr i64 %addr to i128 * 105 %a = load volatile i128, i128 *%aptr 106 %b = load i128, i128 *%bptr 107 %add = add i128 %a, %b 108 store i128 %add, i128 *%aptr 109 ret void 110} 111 112; Check that additions of spilled values can use ALG and ALCG rather than 113; ALGR and ALCGR. 114define void @f8(i128 *%ptr0) { 115; CHECK-LABEL: f8: 116; CHECK: brasl %r14, foo@PLT 117; CHECK: alg {{%r[0-9]+}}, {{[0-9]+}}(%r15) 118; CHECK: alcg {{%r[0-9]+}}, {{[0-9]+}}(%r15) 119; CHECK: br %r14 120 %ptr1 = getelementptr i128, i128 *%ptr0, i128 2 121 %ptr2 = getelementptr i128, i128 *%ptr0, i128 4 122 %ptr3 = getelementptr i128, i128 *%ptr0, i128 6 123 %ptr4 = getelementptr i128, i128 *%ptr0, i128 8 124 %ptr5 = getelementptr i128, i128 *%ptr0, i128 10 125 126 %val0 = load i128, i128 *%ptr0 127 %val1 = load i128, i128 *%ptr1 128 %val2 = load i128, i128 *%ptr2 129 %val3 = load i128, i128 *%ptr3 130 %val4 = load i128, i128 *%ptr4 131 %val5 = load i128, i128 *%ptr5 132 133 %retptr = call i128 *@foo() 134 135 %ret = load i128, i128 *%retptr 136 %add0 = add i128 %ret, %val0 137 %add1 = add i128 %add0, %val1 138 %add2 = add i128 %add1, %val2 139 %add3 = add i128 %add2, %val3 140 %add4 = add i128 %add3, %val4 141 %add5 = add i128 %add4, %val5 142 store i128 %add5, i128 *%retptr 143 144 ret void 145} 146