1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -global-isel -verify-machineinstrs < %s \ 3; RUN: | FileCheck %s -check-prefixes=CHECK,RV32I 4; RUN: llc -mtriple=riscv32 -global-isel -mattr=+zbkb -verify-machineinstrs < %s \ 5; RUN: | FileCheck %s -check-prefixes=CHECK,RV32ZBKB 6 7define i32 @pack_i32(i32 %a, i32 %b) nounwind { 8; RV32I-LABEL: pack_i32: 9; RV32I: # %bb.0: 10; RV32I-NEXT: slli a0, a0, 16 11; RV32I-NEXT: srli a0, a0, 16 12; RV32I-NEXT: slli a1, a1, 16 13; RV32I-NEXT: or a0, a1, a0 14; RV32I-NEXT: ret 15; 16; RV32ZBKB-LABEL: pack_i32: 17; RV32ZBKB: # %bb.0: 18; RV32ZBKB-NEXT: pack a0, a0, a1 19; RV32ZBKB-NEXT: ret 20 %shl = and i32 %a, 65535 21 %shl1 = shl i32 %b, 16 22 %or = or i32 %shl1, %shl 23 ret i32 %or 24} 25 26define i32 @pack_i32_2(i16 zeroext %a, i16 zeroext %b) nounwind { 27; RV32I-LABEL: pack_i32_2: 28; RV32I: # %bb.0: 29; RV32I-NEXT: slli a1, a1, 16 30; RV32I-NEXT: or a0, a1, a0 31; RV32I-NEXT: ret 32; 33; RV32ZBKB-LABEL: pack_i32_2: 34; RV32ZBKB: # %bb.0: 35; RV32ZBKB-NEXT: pack a0, a0, a1 36; RV32ZBKB-NEXT: ret 37 %zexta = zext i16 %a to i32 38 %zextb = zext i16 %b to i32 39 %shl1 = shl i32 %zextb, 16 40 %or = or i32 %shl1, %zexta 41 ret i32 %or 42} 43 44define i32 @pack_i32_3(i16 zeroext %0, i16 zeroext %1, i32 %2) { 45; RV32I-LABEL: pack_i32_3: 46; RV32I: # %bb.0: 47; RV32I-NEXT: slli a0, a0, 16 48; RV32I-NEXT: or a0, a0, a1 49; RV32I-NEXT: add a0, a0, a2 50; RV32I-NEXT: ret 51; 52; RV32ZBKB-LABEL: pack_i32_3: 53; RV32ZBKB: # %bb.0: 54; RV32ZBKB-NEXT: pack a0, a1, a0 55; RV32ZBKB-NEXT: add a0, a0, a2 56; RV32ZBKB-NEXT: ret 57 %4 = zext i16 %0 to i32 58 %5 = shl nuw i32 %4, 16 59 %6 = zext i16 %1 to i32 60 %7 = or i32 %5, %6 61 %8 = add i32 %7, %2 62 ret i32 %8 63} 64 65; As we are not matching directly i64 code patterns on RV32 some i64 patterns 66; don't have yet any matching bit manipulation instructions on RV32. 67; This test is presented here in case future expansions of the Bitmanip 68; extensions introduce instructions suitable for this pattern. 69 70define i64 @pack_i64(i64 %a, i64 %b) nounwind { 71; CHECK-LABEL: pack_i64: 72; CHECK: # %bb.0: 73; CHECK-NEXT: mv a1, a2 74; CHECK-NEXT: ret 75 %shl = and i64 %a, 4294967295 76 %shl1 = shl i64 %b, 32 77 %or = or i64 %shl1, %shl 78 ret i64 %or 79} 80 81define i64 @pack_i64_2(i32 %a, i32 %b) nounwind { 82; CHECK-LABEL: pack_i64_2: 83; CHECK: # %bb.0: 84; CHECK-NEXT: ret 85 %zexta = zext i32 %a to i64 86 %zextb = zext i32 %b to i64 87 %shl1 = shl i64 %zextb, 32 88 %or = or i64 %shl1, %zexta 89 ret i64 %or 90} 91 92define i64 @pack_i64_3(ptr %0, ptr %1) { 93; CHECK-LABEL: pack_i64_3: 94; CHECK: # %bb.0: 95; CHECK-NEXT: lw a2, 0(a0) 96; CHECK-NEXT: lw a0, 0(a1) 97; CHECK-NEXT: mv a1, a2 98; CHECK-NEXT: ret 99 %3 = load i32, ptr %0, align 4 100 %4 = zext i32 %3 to i64 101 %5 = shl i64 %4, 32 102 %6 = load i32, ptr %1, align 4 103 %7 = zext i32 %6 to i64 104 %8 = or i64 %5, %7 105 ret i64 %8 106} 107 108; FIXME: Use packh. 109define i32 @packh_i32(i32 %a, i32 %b) nounwind { 110; CHECK-LABEL: packh_i32: 111; CHECK: # %bb.0: 112; CHECK-NEXT: lui a2, 16 113; CHECK-NEXT: andi a0, a0, 255 114; CHECK-NEXT: addi a2, a2, -256 115; CHECK-NEXT: slli a1, a1, 8 116; CHECK-NEXT: and a1, a1, a2 117; CHECK-NEXT: or a0, a1, a0 118; CHECK-NEXT: ret 119 %and = and i32 %a, 255 120 %and1 = shl i32 %b, 8 121 %shl = and i32 %and1, 65280 122 %or = or i32 %shl, %and 123 ret i32 %or 124} 125 126define i32 @packh_i32_2(i32 %a, i32 %b) nounwind { 127; RV32I-LABEL: packh_i32_2: 128; RV32I: # %bb.0: 129; RV32I-NEXT: andi a0, a0, 255 130; RV32I-NEXT: andi a1, a1, 255 131; RV32I-NEXT: slli a1, a1, 8 132; RV32I-NEXT: or a0, a1, a0 133; RV32I-NEXT: ret 134; 135; RV32ZBKB-LABEL: packh_i32_2: 136; RV32ZBKB: # %bb.0: 137; RV32ZBKB-NEXT: packh a0, a0, a1 138; RV32ZBKB-NEXT: ret 139 %and = and i32 %a, 255 140 %and1 = and i32 %b, 255 141 %shl = shl i32 %and1, 8 142 %or = or i32 %shl, %and 143 ret i32 %or 144} 145 146; FIMXE: Use packh 147define i64 @packh_i64(i64 %a, i64 %b) nounwind { 148; CHECK-LABEL: packh_i64: 149; CHECK: # %bb.0: 150; CHECK-NEXT: lui a1, 16 151; CHECK-NEXT: andi a0, a0, 255 152; CHECK-NEXT: addi a1, a1, -256 153; CHECK-NEXT: slli a2, a2, 8 154; CHECK-NEXT: and a1, a2, a1 155; CHECK-NEXT: or a0, a1, a0 156; CHECK-NEXT: li a1, 0 157; CHECK-NEXT: ret 158 %and = and i64 %a, 255 159 %and1 = shl i64 %b, 8 160 %shl = and i64 %and1, 65280 161 %or = or i64 %shl, %and 162 ret i64 %or 163} 164 165; FIXME The andi+srli for RV32ZBKB should fold to 0. 166define i64 @packh_i64_2(i64 %a, i64 %b) nounwind { 167; RV32I-LABEL: packh_i64_2: 168; RV32I: # %bb.0: 169; RV32I-NEXT: andi a0, a0, 255 170; RV32I-NEXT: andi a1, a2, 255 171; RV32I-NEXT: slli a2, a1, 8 172; RV32I-NEXT: srli a1, a1, 24 173; RV32I-NEXT: or a0, a2, a0 174; RV32I-NEXT: ret 175; 176; RV32ZBKB-LABEL: packh_i64_2: 177; RV32ZBKB: # %bb.0: 178; RV32ZBKB-NEXT: andi a1, a2, 255 179; RV32ZBKB-NEXT: srli a1, a1, 24 180; RV32ZBKB-NEXT: packh a0, a0, a2 181; RV32ZBKB-NEXT: ret 182 %and = and i64 %a, 255 183 %and1 = and i64 %b, 255 184 %shl = shl i64 %and1, 8 185 %or = or i64 %shl, %and 186 ret i64 %or 187} 188 189 190define zeroext i16 @packh_i16(i8 zeroext %a, i8 zeroext %b) nounwind { 191; RV32I-LABEL: packh_i16: 192; RV32I: # %bb.0: 193; RV32I-NEXT: slli a1, a1, 8 194; RV32I-NEXT: or a0, a1, a0 195; RV32I-NEXT: ret 196; 197; RV32ZBKB-LABEL: packh_i16: 198; RV32ZBKB: # %bb.0: 199; RV32ZBKB-NEXT: packh a0, a0, a1 200; RV32ZBKB-NEXT: ret 201 %zext = zext i8 %a to i16 202 %zext1 = zext i8 %b to i16 203 %shl = shl i16 %zext1, 8 204 %or = or i16 %shl, %zext 205 ret i16 %or 206} 207 208 209define zeroext i16 @packh_i16_2(i8 zeroext %0, i8 zeroext %1, i8 zeroext %2) { 210; RV32I-LABEL: packh_i16_2: 211; RV32I: # %bb.0: 212; RV32I-NEXT: add a0, a1, a0 213; RV32I-NEXT: andi a0, a0, 255 214; RV32I-NEXT: slli a0, a0, 8 215; RV32I-NEXT: or a0, a0, a2 216; RV32I-NEXT: ret 217; 218; RV32ZBKB-LABEL: packh_i16_2: 219; RV32ZBKB: # %bb.0: 220; RV32ZBKB-NEXT: add a0, a1, a0 221; RV32ZBKB-NEXT: packh a0, a2, a0 222; RV32ZBKB-NEXT: ret 223 %4 = add i8 %1, %0 224 %5 = zext i8 %4 to i16 225 %6 = shl i16 %5, 8 226 %7 = zext i8 %2 to i16 227 %8 = or i16 %6, %7 228 ret i16 %8 229} 230 231define void @packh_i16_3(i8 zeroext %0, i8 zeroext %1, i8 zeroext %2, ptr %p) { 232; RV32I-LABEL: packh_i16_3: 233; RV32I: # %bb.0: 234; RV32I-NEXT: add a0, a1, a0 235; RV32I-NEXT: andi a0, a0, 255 236; RV32I-NEXT: slli a0, a0, 8 237; RV32I-NEXT: or a0, a0, a2 238; RV32I-NEXT: sh a0, 0(a3) 239; RV32I-NEXT: ret 240; 241; RV32ZBKB-LABEL: packh_i16_3: 242; RV32ZBKB: # %bb.0: 243; RV32ZBKB-NEXT: add a0, a1, a0 244; RV32ZBKB-NEXT: packh a0, a2, a0 245; RV32ZBKB-NEXT: sh a0, 0(a3) 246; RV32ZBKB-NEXT: ret 247 %4 = add i8 %1, %0 248 %5 = zext i8 %4 to i16 249 %6 = shl i16 %5, 8 250 %7 = zext i8 %2 to i16 251 %8 = or i16 %6, %7 252 store i16 %8, ptr %p 253 ret void 254} 255 256define i32 @zexth_i32(i32 %a) nounwind { 257; RV32I-LABEL: zexth_i32: 258; RV32I: # %bb.0: 259; RV32I-NEXT: slli a0, a0, 16 260; RV32I-NEXT: srli a0, a0, 16 261; RV32I-NEXT: ret 262; 263; RV32ZBKB-LABEL: zexth_i32: 264; RV32ZBKB: # %bb.0: 265; RV32ZBKB-NEXT: zext.h a0, a0 266; RV32ZBKB-NEXT: ret 267 %and = and i32 %a, 65535 268 ret i32 %and 269} 270 271define i64 @zexth_i64(i64 %a) nounwind { 272; RV32I-LABEL: zexth_i64: 273; RV32I: # %bb.0: 274; RV32I-NEXT: slli a0, a0, 16 275; RV32I-NEXT: srli a0, a0, 16 276; RV32I-NEXT: li a1, 0 277; RV32I-NEXT: ret 278; 279; RV32ZBKB-LABEL: zexth_i64: 280; RV32ZBKB: # %bb.0: 281; RV32ZBKB-NEXT: zext.h a0, a0 282; RV32ZBKB-NEXT: li a1, 0 283; RV32ZBKB-NEXT: ret 284 %and = and i64 %a, 65535 285 ret i64 %and 286} 287 288define i32 @zext_i16_to_i32(i16 %a) nounwind { 289; RV32I-LABEL: zext_i16_to_i32: 290; RV32I: # %bb.0: 291; RV32I-NEXT: slli a0, a0, 16 292; RV32I-NEXT: srli a0, a0, 16 293; RV32I-NEXT: ret 294; 295; RV32ZBKB-LABEL: zext_i16_to_i32: 296; RV32ZBKB: # %bb.0: 297; RV32ZBKB-NEXT: zext.h a0, a0 298; RV32ZBKB-NEXT: ret 299 %1 = zext i16 %a to i32 300 ret i32 %1 301} 302 303define i64 @zext_i16_to_i64(i16 %a) nounwind { 304; RV32I-LABEL: zext_i16_to_i64: 305; RV32I: # %bb.0: 306; RV32I-NEXT: slli a0, a0, 16 307; RV32I-NEXT: srli a0, a0, 16 308; RV32I-NEXT: li a1, 0 309; RV32I-NEXT: ret 310; 311; RV32ZBKB-LABEL: zext_i16_to_i64: 312; RV32ZBKB: # %bb.0: 313; RV32ZBKB-NEXT: zext.h a0, a0 314; RV32ZBKB-NEXT: li a1, 0 315; RV32ZBKB-NEXT: ret 316 %1 = zext i16 %a to i64 317 ret i64 %1 318} 319