1; Test insertions of memory into the low byte of an i32. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5; Check a plain insertion with (or (and ... -0xff) (zext (load ....))). 6; The whole sequence can be performed by IC. 7define i32 @f1(i32 %orig, i8 *%ptr) { 8; CHECK-LABEL: f1: 9; CHECK-NOT: ni 10; CHECK: ic %r2, 0(%r3) 11; CHECK: br %r14 12 %val = load i8, i8 *%ptr 13 %ptr2 = zext i8 %val to i32 14 %ptr1 = and i32 %orig, -256 15 %or = or i32 %ptr1, %ptr2 16 ret i32 %or 17} 18 19; Like f1, but with the operands reversed. 20define i32 @f2(i32 %orig, i8 *%ptr) { 21; CHECK-LABEL: f2: 22; CHECK-NOT: ni 23; CHECK: ic %r2, 0(%r3) 24; CHECK: br %r14 25 %val = load i8, i8 *%ptr 26 %ptr2 = zext i8 %val to i32 27 %ptr1 = and i32 %orig, -256 28 %or = or i32 %ptr2, %ptr1 29 ret i32 %or 30} 31 32; Check a case where more bits than lower 8 are masked out of the 33; register value. We can use IC but must keep the original mask. 34define i32 @f3(i32 %orig, i8 *%ptr) { 35; CHECK-LABEL: f3: 36; CHECK: nill %r2, 65024 37; CHECK: ic %r2, 0(%r3) 38; CHECK: br %r14 39 %val = load i8, i8 *%ptr 40 %ptr2 = zext i8 %val to i32 41 %ptr1 = and i32 %orig, -512 42 %or = or i32 %ptr1, %ptr2 43 ret i32 %or 44} 45 46; Like f3, but with the operands reversed. 47define i32 @f4(i32 %orig, i8 *%ptr) { 48; CHECK-LABEL: f4: 49; CHECK: nill %r2, 65024 50; CHECK: ic %r2, 0(%r3) 51; CHECK: br %r14 52 %val = load i8, i8 *%ptr 53 %ptr2 = zext i8 %val to i32 54 %ptr1 = and i32 %orig, -512 55 %or = or i32 %ptr2, %ptr1 56 ret i32 %or 57} 58 59; Check a case where the low 8 bits are cleared by a shift left. 60define i32 @f5(i32 %orig, i8 *%ptr) { 61; CHECK-LABEL: f5: 62; CHECK: sll %r2, 8 63; CHECK: ic %r2, 0(%r3) 64; CHECK: br %r14 65 %val = load i8, i8 *%ptr 66 %ptr2 = zext i8 %val to i32 67 %ptr1 = shl i32 %orig, 8 68 %or = or i32 %ptr1, %ptr2 69 ret i32 %or 70} 71 72; Like f5, but with the operands reversed. 73define i32 @f6(i32 %orig, i8 *%ptr) { 74; CHECK-LABEL: f6: 75; CHECK: sll %r2, 8 76; CHECK: ic %r2, 0(%r3) 77; CHECK: br %r14 78 %val = load i8, i8 *%ptr 79 %ptr2 = zext i8 %val to i32 80 %ptr1 = shl i32 %orig, 8 81 %or = or i32 %ptr2, %ptr1 82 ret i32 %or 83} 84 85; Check insertions into a constant. 86define i32 @f7(i32 %orig, i8 *%ptr) { 87; CHECK-LABEL: f7: 88; CHECK: lhi %r2, 256 89; CHECK: ic %r2, 0(%r3) 90; CHECK: br %r14 91 %val = load i8, i8 *%ptr 92 %ptr2 = zext i8 %val to i32 93 %or = or i32 %ptr2, 256 94 ret i32 %or 95} 96 97; Like f7, but with the operands reversed. 98define i32 @f8(i32 %orig, i8 *%ptr) { 99; CHECK-LABEL: f8: 100; CHECK: lhi %r2, 256 101; CHECK: ic %r2, 0(%r3) 102; CHECK: br %r14 103 %val = load i8, i8 *%ptr 104 %ptr2 = zext i8 %val to i32 105 %or = or i32 256, %ptr2 106 ret i32 %or 107} 108 109; Check the high end of the IC range. 110define i32 @f9(i32 %orig, i8 *%src) { 111; CHECK-LABEL: f9: 112; CHECK: ic %r2, 4095(%r3) 113; CHECK: br %r14 114 %ptr = getelementptr i8, i8 *%src, i64 4095 115 %val = load i8, i8 *%ptr 116 %src2 = zext i8 %val to i32 117 %src1 = and i32 %orig, -256 118 %or = or i32 %src2, %src1 119 ret i32 %or 120} 121 122; Check the next byte up, which should use ICY instead of IC. 123define i32 @f10(i32 %orig, i8 *%src) { 124; CHECK-LABEL: f10: 125; CHECK: icy %r2, 4096(%r3) 126; CHECK: br %r14 127 %ptr = getelementptr i8, i8 *%src, i64 4096 128 %val = load i8, i8 *%ptr 129 %src2 = zext i8 %val to i32 130 %src1 = and i32 %orig, -256 131 %or = or i32 %src2, %src1 132 ret i32 %or 133} 134 135; Check the high end of the ICY range. 136define i32 @f11(i32 %orig, i8 *%src) { 137; CHECK-LABEL: f11: 138; CHECK: icy %r2, 524287(%r3) 139; CHECK: br %r14 140 %ptr = getelementptr i8, i8 *%src, i64 524287 141 %val = load i8, i8 *%ptr 142 %src2 = zext i8 %val to i32 143 %src1 = and i32 %orig, -256 144 %or = or i32 %src2, %src1 145 ret i32 %or 146} 147 148; Check the next byte up, which needs separate address logic. 149; Other sequences besides this one would be OK. 150define i32 @f12(i32 %orig, i8 *%src) { 151; CHECK-LABEL: f12: 152; CHECK: agfi %r3, 524288 153; CHECK: ic %r2, 0(%r3) 154; CHECK: br %r14 155 %ptr = getelementptr i8, i8 *%src, i64 524288 156 %val = load i8, i8 *%ptr 157 %src2 = zext i8 %val to i32 158 %src1 = and i32 %orig, -256 159 %or = or i32 %src2, %src1 160 ret i32 %or 161} 162 163; Check the high end of the negative ICY range. 164define i32 @f13(i32 %orig, i8 *%src) { 165; CHECK-LABEL: f13: 166; CHECK: icy %r2, -1(%r3) 167; CHECK: br %r14 168 %ptr = getelementptr i8, i8 *%src, i64 -1 169 %val = load i8, i8 *%ptr 170 %src2 = zext i8 %val to i32 171 %src1 = and i32 %orig, -256 172 %or = or i32 %src2, %src1 173 ret i32 %or 174} 175 176; Check the low end of the ICY range. 177define i32 @f14(i32 %orig, i8 *%src) { 178; CHECK-LABEL: f14: 179; CHECK: icy %r2, -524288(%r3) 180; CHECK: br %r14 181 %ptr = getelementptr i8, i8 *%src, i64 -524288 182 %val = load i8, i8 *%ptr 183 %src2 = zext i8 %val to i32 184 %src1 = and i32 %orig, -256 185 %or = or i32 %src2, %src1 186 ret i32 %or 187} 188 189; Check the next byte down, which needs separate address logic. 190; Other sequences besides this one would be OK. 191define i32 @f15(i32 %orig, i8 *%src) { 192; CHECK-LABEL: f15: 193; CHECK: agfi %r3, -524289 194; CHECK: ic %r2, 0(%r3) 195; CHECK: br %r14 196 %ptr = getelementptr i8, i8 *%src, i64 -524289 197 %val = load i8, i8 *%ptr 198 %src2 = zext i8 %val to i32 199 %src1 = and i32 %orig, -256 200 %or = or i32 %src2, %src1 201 ret i32 %or 202} 203 204; Check that IC allows an index. 205define i32 @f16(i32 %orig, i8 *%src, i64 %index) { 206; CHECK-LABEL: f16: 207; CHECK: ic %r2, 4095({{%r4,%r3|%r3,%r4}}) 208; CHECK: br %r14 209 %ptr1 = getelementptr i8, i8 *%src, i64 %index 210 %ptr2 = getelementptr i8, i8 *%ptr1, i64 4095 211 %val = load i8, i8 *%ptr2 212 %src2 = zext i8 %val to i32 213 %src1 = and i32 %orig, -256 214 %or = or i32 %src2, %src1 215 ret i32 %or 216} 217 218; Check that ICY allows an index. 219define i32 @f17(i32 %orig, i8 *%src, i64 %index) { 220; CHECK-LABEL: f17: 221; CHECK: icy %r2, 4096({{%r4,%r3|%r3,%r4}}) 222; CHECK: br %r14 223 %ptr1 = getelementptr i8, i8 *%src, i64 %index 224 %ptr2 = getelementptr i8, i8 *%ptr1, i64 4096 225 %val = load i8, i8 *%ptr2 226 %src2 = zext i8 %val to i32 227 %src1 = and i32 %orig, -256 228 %or = or i32 %src2, %src1 229 ret i32 %or 230} 231