1; Test insertions of i32s into the low half of an i64. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5; Insertion of an i32 can be done using LR. 6define i64 @f1(i64 %a, i32 %b) { 7; CHECK-LABEL: f1: 8; CHECK-NOT: {{%r[23]}} 9; CHECK: lr %r2, %r3 10; CHECK: br %r14 11 %low = zext i32 %b to i64 12 %high = and i64 %a, -4294967296 13 %res = or i64 %high, %low 14 ret i64 %res 15} 16 17; ... and again with the operands reversed. 18define i64 @f2(i64 %a, i32 %b) { 19; CHECK-LABEL: f2: 20; CHECK-NOT: {{%r[23]}} 21; CHECK: lr %r2, %r3 22; CHECK: br %r14 23 %low = zext i32 %b to i64 24 %high = and i64 %a, -4294967296 25 %res = or i64 %low, %high 26 ret i64 %res 27} 28 29; Like f1, but with "in register" zero extension. 30define i64 @f3(i64 %a, i64 %b) { 31; CHECK-LABEL: f3: 32; CHECK-NOT: {{%r[23]}} 33; CHECK: lr %r2, %r3 34; CHECK: br %r14 35 %low = and i64 %b, 4294967295 36 %high = and i64 %a, -4294967296 37 %res = or i64 %high, %low 38 ret i64 %res 39} 40 41; ... and again with the operands reversed. 42define i64 @f4(i64 %a, i64 %b) { 43; CHECK-LABEL: f4: 44; CHECK-NOT: {{%r[23]}} 45; CHECK: lr %r2, %r3 46; CHECK: br %r14 47 %low = and i64 %b, 4294967295 48 %high = and i64 %a, -4294967296 49 %res = or i64 %low, %high 50 ret i64 %res 51} 52 53; Unary operations can be done directly into the low half. 54define i64 @f5(i64 %a, i32 %b) { 55; CHECK-LABEL: f5: 56; CHECK-NOT: {{%r[23]}} 57; CHECK: lcr %r2, %r3 58; CHECK: br %r14 59 %neg = sub i32 0, %b 60 %low = zext i32 %neg to i64 61 %high = and i64 %a, -4294967296 62 %res = or i64 %high, %low 63 ret i64 %res 64} 65 66; ...likewise three-operand binary operations like RLL. 67define i64 @f6(i64 %a, i32 %b) { 68; CHECK-LABEL: f6: 69; CHECK-NOT: {{%r[23]}} 70; CHECK: rll %r2, %r3, 1 71; CHECK: br %r14 72 %parta = shl i32 %b, 1 73 %partb = lshr i32 %b, 31 74 %rot = or i32 %parta, %partb 75 %low = zext i32 %rot to i64 76 %high = and i64 %a, -4294967296 77 %res = or i64 %low, %high 78 ret i64 %res 79} 80 81; Loads can be done directly into the low half. The range of L is checked 82; in the move tests. 83define i64 @f7(i64 %a, i32 *%src) { 84; CHECK-LABEL: f7: 85; CHECK-NOT: {{%r[23]}} 86; CHECK: l %r2, 0(%r3) 87; CHECK: br %r14 88 %b = load i32, i32 *%src 89 %low = zext i32 %b to i64 90 %high = and i64 %a, -4294967296 91 %res = or i64 %high, %low 92 ret i64 %res 93} 94 95; ...likewise extending loads. 96define i64 @f8(i64 %a, i8 *%src) { 97; CHECK-LABEL: f8: 98; CHECK-NOT: {{%r[23]}} 99; CHECK: lb %r2, 0(%r3) 100; CHECK: br %r14 101 %byte = load i8, i8 *%src 102 %b = sext i8 %byte to i32 103 %low = zext i32 %b to i64 104 %high = and i64 %a, -4294967296 105 %res = or i64 %high, %low 106 ret i64 %res 107} 108 109; Check a case like f1 in which there is no AND. We simply know from context 110; that the upper half of one OR operand and the lower half of the other are 111; both clear. 112define i64 @f9(i64 %a, i32 %b) { 113; CHECK-LABEL: f9: 114; CHECK: sllg %r2, %r2, 32 115; CHECK: lr %r2, %r3 116; CHECK: br %r14 117 %shift = shl i64 %a, 32 118 %low = zext i32 %b to i64 119 %or = or i64 %shift, %low 120 ret i64 %or 121} 122 123; ...and again with the operands reversed. 124define i64 @f10(i64 %a, i32 %b) { 125; CHECK-LABEL: f10: 126; CHECK: sllg %r2, %r2, 32 127; CHECK: lr %r2, %r3 128; CHECK: br %r14 129 %shift = shl i64 %a, 32 130 %low = zext i32 %b to i64 131 %or = or i64 %low, %shift 132 ret i64 %or 133} 134 135; Like f9, but with "in register" zero extension. 136define i64 @f11(i64 %a, i64 %b) { 137; CHECK-LABEL: f11: 138; CHECK: lr %r2, %r3 139; CHECK: br %r14 140 %shift = shl i64 %a, 32 141 %low = and i64 %b, 4294967295 142 %or = or i64 %shift, %low 143 ret i64 %or 144} 145 146; ...and again with the operands reversed. 147define i64 @f12(i64 %a, i64 %b) { 148; CHECK-LABEL: f12: 149; CHECK: lr %r2, %r3 150; CHECK: br %r14 151 %shift = shl i64 %a, 32 152 %low = and i64 %b, 4294967295 153 %or = or i64 %low, %shift 154 ret i64 %or 155} 156 157; Like f9, but for larger shifts than 32. 158define i64 @f13(i64 %a, i32 %b) { 159; CHECK-LABEL: f13: 160; CHECK: sllg %r2, %r2, 60 161; CHECK: lr %r2, %r3 162; CHECK: br %r14 163 %shift = shl i64 %a, 60 164 %low = zext i32 %b to i64 165 %or = or i64 %shift, %low 166 ret i64 %or 167} 168 169; We previously wrongly removed the upper AND as dead. 170define i64 @f14(i64 %a, i64 %b) { 171; CHECK-LABEL: f14: 172; CHECK: risbg {{%r[0-5]}}, %r2, 6, 134, 0 173; CHECK: br %r14 174 %and1 = and i64 %a, 144115188075855872 175 %and2 = and i64 %b, 15 176 %or = or i64 %and1, %and2 177 %res = icmp eq i64 %or, 0 178 %ext = sext i1 %res to i64 179 ret i64 %ext 180} 181 182; Check another representation of f8. 183define i64 @f15(i64 %a, i8 *%src) { 184; CHECK-LABEL: f15: 185; CHECK-NOT: {{%r[23]}} 186; CHECK: lb %r2, 0(%r3) 187; CHECK: br %r14 188 %byte = load i8, i8 *%src 189 %b = sext i8 %byte to i64 190 %low = and i64 %b, 4294967295 191 %high = and i64 %a, -4294967296 192 %res = or i64 %high, %low 193 ret i64 %res 194} 195