1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck %s -check-prefixes=CHECK,RV32I 4; RUN: llc -mtriple=riscv32 -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 108define i32 @packh_i32(i32 %a, i32 %b) nounwind { 109; RV32I-LABEL: packh_i32: 110; RV32I: # %bb.0: 111; RV32I-NEXT: andi a0, a0, 255 112; RV32I-NEXT: slli a1, a1, 24 113; RV32I-NEXT: srli a1, a1, 16 114; RV32I-NEXT: or a0, a1, a0 115; RV32I-NEXT: ret 116; 117; RV32ZBKB-LABEL: packh_i32: 118; RV32ZBKB: # %bb.0: 119; RV32ZBKB-NEXT: packh a0, a0, a1 120; RV32ZBKB-NEXT: ret 121 %and = and i32 %a, 255 122 %and1 = shl i32 %b, 8 123 %shl = and i32 %and1, 65280 124 %or = or i32 %shl, %and 125 ret i32 %or 126} 127 128define i32 @packh_i32_2(i32 %a, i32 %b) nounwind { 129; RV32I-LABEL: packh_i32_2: 130; RV32I: # %bb.0: 131; RV32I-NEXT: andi a0, a0, 255 132; RV32I-NEXT: andi a1, a1, 255 133; RV32I-NEXT: slli a1, a1, 8 134; RV32I-NEXT: or a0, a1, a0 135; RV32I-NEXT: ret 136; 137; RV32ZBKB-LABEL: packh_i32_2: 138; RV32ZBKB: # %bb.0: 139; RV32ZBKB-NEXT: packh a0, a0, a1 140; RV32ZBKB-NEXT: ret 141 %and = and i32 %a, 255 142 %and1 = and i32 %b, 255 143 %shl = shl i32 %and1, 8 144 %or = or i32 %shl, %and 145 ret i32 %or 146} 147 148define i64 @packh_i64(i64 %a, i64 %b) nounwind { 149; RV32I-LABEL: packh_i64: 150; RV32I: # %bb.0: 151; RV32I-NEXT: andi a0, a0, 255 152; RV32I-NEXT: slli a2, a2, 24 153; RV32I-NEXT: srli a2, a2, 16 154; RV32I-NEXT: or a0, a2, a0 155; RV32I-NEXT: li a1, 0 156; RV32I-NEXT: ret 157; 158; RV32ZBKB-LABEL: packh_i64: 159; RV32ZBKB: # %bb.0: 160; RV32ZBKB-NEXT: packh a0, a0, a2 161; RV32ZBKB-NEXT: li a1, 0 162; RV32ZBKB-NEXT: ret 163 %and = and i64 %a, 255 164 %and1 = shl i64 %b, 8 165 %shl = and i64 %and1, 65280 166 %or = or i64 %shl, %and 167 ret i64 %or 168} 169 170define i64 @packh_i64_2(i64 %a, i64 %b) nounwind { 171; RV32I-LABEL: packh_i64_2: 172; RV32I: # %bb.0: 173; RV32I-NEXT: andi a0, a0, 255 174; RV32I-NEXT: andi a1, a2, 255 175; RV32I-NEXT: slli a1, a1, 8 176; RV32I-NEXT: or a0, a1, a0 177; RV32I-NEXT: li a1, 0 178; RV32I-NEXT: ret 179; 180; RV32ZBKB-LABEL: packh_i64_2: 181; RV32ZBKB: # %bb.0: 182; RV32ZBKB-NEXT: packh a0, a0, a2 183; RV32ZBKB-NEXT: li a1, 0 184; RV32ZBKB-NEXT: ret 185 %and = and i64 %a, 255 186 %and1 = and i64 %b, 255 187 %shl = shl i64 %and1, 8 188 %or = or i64 %shl, %and 189 ret i64 %or 190} 191 192 193define zeroext i16 @packh_i16(i8 zeroext %a, i8 zeroext %b) nounwind { 194; RV32I-LABEL: packh_i16: 195; RV32I: # %bb.0: 196; RV32I-NEXT: slli a1, a1, 8 197; RV32I-NEXT: or a0, a1, a0 198; RV32I-NEXT: ret 199; 200; RV32ZBKB-LABEL: packh_i16: 201; RV32ZBKB: # %bb.0: 202; RV32ZBKB-NEXT: packh a0, a0, a1 203; RV32ZBKB-NEXT: ret 204 %zext = zext i8 %a to i16 205 %zext1 = zext i8 %b to i16 206 %shl = shl i16 %zext1, 8 207 %or = or i16 %shl, %zext 208 ret i16 %or 209} 210 211 212define zeroext i16 @packh_i16_2(i8 zeroext %0, i8 zeroext %1, i8 zeroext %2) { 213; RV32I-LABEL: packh_i16_2: 214; RV32I: # %bb.0: 215; RV32I-NEXT: add a0, a1, a0 216; RV32I-NEXT: slli a0, a0, 8 217; RV32I-NEXT: or a0, a0, a2 218; RV32I-NEXT: slli a0, a0, 16 219; RV32I-NEXT: srli a0, a0, 16 220; RV32I-NEXT: ret 221; 222; RV32ZBKB-LABEL: packh_i16_2: 223; RV32ZBKB: # %bb.0: 224; RV32ZBKB-NEXT: add a0, a1, a0 225; RV32ZBKB-NEXT: packh a0, a2, a0 226; RV32ZBKB-NEXT: ret 227 %4 = add i8 %1, %0 228 %5 = zext i8 %4 to i16 229 %6 = shl i16 %5, 8 230 %7 = zext i8 %2 to i16 231 %8 = or i16 %6, %7 232 ret i16 %8 233} 234 235define void @packh_i16_3(i8 zeroext %0, i8 zeroext %1, i8 zeroext %2, ptr %p) { 236; RV32I-LABEL: packh_i16_3: 237; RV32I: # %bb.0: 238; RV32I-NEXT: add a0, a1, a0 239; RV32I-NEXT: slli a0, a0, 8 240; RV32I-NEXT: or a0, a0, a2 241; RV32I-NEXT: sh a0, 0(a3) 242; RV32I-NEXT: ret 243; 244; RV32ZBKB-LABEL: packh_i16_3: 245; RV32ZBKB: # %bb.0: 246; RV32ZBKB-NEXT: add a0, a1, a0 247; RV32ZBKB-NEXT: packh a0, a2, a0 248; RV32ZBKB-NEXT: sh a0, 0(a3) 249; RV32ZBKB-NEXT: ret 250 %4 = add i8 %1, %0 251 %5 = zext i8 %4 to i16 252 %6 = shl i16 %5, 8 253 %7 = zext i8 %2 to i16 254 %8 = or i16 %6, %7 255 store i16 %8, ptr %p 256 ret void 257} 258 259define i32 @zexth_i32(i32 %a) nounwind { 260; RV32I-LABEL: zexth_i32: 261; RV32I: # %bb.0: 262; RV32I-NEXT: slli a0, a0, 16 263; RV32I-NEXT: srli a0, a0, 16 264; RV32I-NEXT: ret 265; 266; RV32ZBKB-LABEL: zexth_i32: 267; RV32ZBKB: # %bb.0: 268; RV32ZBKB-NEXT: zext.h a0, a0 269; RV32ZBKB-NEXT: ret 270 %and = and i32 %a, 65535 271 ret i32 %and 272} 273 274define i64 @zexth_i64(i64 %a) nounwind { 275; RV32I-LABEL: zexth_i64: 276; RV32I: # %bb.0: 277; RV32I-NEXT: slli a0, a0, 16 278; RV32I-NEXT: srli a0, a0, 16 279; RV32I-NEXT: li a1, 0 280; RV32I-NEXT: ret 281; 282; RV32ZBKB-LABEL: zexth_i64: 283; RV32ZBKB: # %bb.0: 284; RV32ZBKB-NEXT: zext.h a0, a0 285; RV32ZBKB-NEXT: li a1, 0 286; RV32ZBKB-NEXT: ret 287 %and = and i64 %a, 65535 288 ret i64 %and 289} 290 291define i32 @zext_i16_to_i32(i16 %a) nounwind { 292; RV32I-LABEL: zext_i16_to_i32: 293; RV32I: # %bb.0: 294; RV32I-NEXT: slli a0, a0, 16 295; RV32I-NEXT: srli a0, a0, 16 296; RV32I-NEXT: ret 297; 298; RV32ZBKB-LABEL: zext_i16_to_i32: 299; RV32ZBKB: # %bb.0: 300; RV32ZBKB-NEXT: zext.h a0, a0 301; RV32ZBKB-NEXT: ret 302 %1 = zext i16 %a to i32 303 ret i32 %1 304} 305 306define i64 @zext_i16_to_i64(i16 %a) nounwind { 307; RV32I-LABEL: zext_i16_to_i64: 308; RV32I: # %bb.0: 309; RV32I-NEXT: slli a0, a0, 16 310; RV32I-NEXT: srli a0, a0, 16 311; RV32I-NEXT: li a1, 0 312; RV32I-NEXT: ret 313; 314; RV32ZBKB-LABEL: zext_i16_to_i64: 315; RV32ZBKB: # %bb.0: 316; RV32ZBKB-NEXT: zext.h a0, a0 317; RV32ZBKB-NEXT: li a1, 0 318; RV32ZBKB-NEXT: ret 319 %1 = zext i16 %a to i64 320 ret i64 %1 321} 322