1; RUN: llc < %s -mtriple=ve | FileCheck %s 2 3;;; Test both ‘lshr’ and `ashr` instructions 4;;; 5;;; ‘lshr’ Instruction 6;;; 7;;; Syntax: 8;;; <result> = lshr <ty> <op1>, <op2> ; yields ty:result 9;;; <result> = lshr exact <ty> <op1>, <op2> ; yields ty:result 10;;; 11;;; Overview: 12;;; The ‘lshr’ instruction (logical shift right) returns the first operand 13;;; shifted to the right a specified number of bits with zero fill. 14;;; 15;;; Arguments: 16;;; Both arguments to the ‘lshr’ instruction must be the same integer or 17;;; vector of integer type. ‘op2’ is treated as an unsigned value. 18;;; 19;;; Semantics: 20;;; This instruction always performs a logical shift right operation. The 21;;; most significant bits of the result will be filled with zero bits after 22;;; the shift. If op2 is (statically or dynamically) equal to or larger than 23;;; the number of bits in op1, this instruction returns a poison value. If 24;;; the arguments are vectors, each vector element of op1 is shifted by the 25;;; corresponding shift amount in op2. 26;;; 27;;; If the exact keyword is present, the result value of the lshr is a 28;;; poison value if any of the bits shifted out are non-zero. 29;;; 30;;; Example: 31;;; <result> = lshr i32 4, 1 ; yields i32:result = 2 32;;; <result> = lshr i32 4, 2 ; yields i32:result = 1 33;;; <result> = lshr i8 4, 3 ; yields i8:result = 0 34;;; <result> = lshr i8 -2, 1 ; yields i8:result = 0x7F 35;;; <result> = lshr i32 1, 32 ; undefined 36;;; <result> = lshr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 2> 37;;; ; yields: result=<2 x i32> < i32 0x7FFFFFFF, i32 1> 38;;; 39;;; ‘ashr’ Instruction 40;;; 41;;; Syntax: 42;;; <result> = ashr <ty> <op1>, <op2> ; yields ty:result 43;;; <result> = ashr exact <ty> <op1>, <op2> ; yields ty:result 44;;; 45;;; Overview: 46;;; The ‘ashr’ instruction (arithmetic shift right) returns the first operand 47;;; shifted to the right a specified number of bits with sign extension. 48;;; 49;;; Arguments: 50;;; Both arguments to the ‘ashr’ instruction must be the same integer or 51;;; vector of integer type. ‘op2’ is treated as an unsigned value. 52;;; 53;;; Semantics: 54;;; This instruction always performs an arithmetic shift right operation, The 55;;; most significant bits of the result will be filled with the sign bit of 56;;; op1. If op2 is (statically or dynamically) equal to or larger than the 57;;; number of bits in op1, this instruction returns a poison value. If the 58;;; arguments are vectors, each vector element of op1 is shifted by the 59;;; corresponding shift amount in op2. 60;;; 61;;; If the exact keyword is present, the result value of the ashr is a poison 62;;; value if any of the bits shifted out are non-zero. 63;;; 64;;; Example: 65;;; <result> = ashr i32 4, 1 ; yields i32:result = 2 66;;; <result> = ashr i32 4, 2 ; yields i32:result = 1 67;;; <result> = ashr i8 4, 3 ; yields i8:result = 0 68;;; <result> = ashr i8 -2, 1 ; yields i8:result = -1 69;;; <result> = ashr i32 1, 32 ; undefined 70;;; <result> = ashr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 3> 71;;; ; yields: result=<2 x i32> < i32 -1, i32 0> 72;;; 73;;; Note: 74;;; We test only i8/i16/i32/i64/i128 and unsigned of them. 75 76; Function Attrs: norecurse nounwind readnone 77define signext i8 @shl_i8_var(i8 signext %0, i8 signext %1) { 78; CHECK-LABEL: shl_i8_var: 79; CHECK: # %bb.0: 80; CHECK-NEXT: and %s1, %s1, (56)0 81; CHECK-NEXT: sra.w.sx %s0, %s0, %s1 82; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 83; CHECK-NEXT: b.l.t (, %s10) 84 %3 = sext i8 %0 to i32 85 %4 = zext i8 %1 to i32 86 %5 = ashr i32 %3, %4 87 %6 = trunc i32 %5 to i8 88 ret i8 %6 89} 90 91; Function Attrs: norecurse nounwind readnone 92define zeroext i8 @shl_u8_var(i8 zeroext %0, i8 zeroext %1) { 93; CHECK-LABEL: shl_u8_var: 94; CHECK: # %bb.0: 95; CHECK-NEXT: and %s0, %s0, (32)0 96; CHECK-NEXT: srl %s0, %s0, %s1 97; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1 98; CHECK-NEXT: b.l.t (, %s10) 99 %3 = zext i8 %0 to i32 100 %4 = zext i8 %1 to i32 101 %5 = lshr i32 %3, %4 102 %6 = trunc i32 %5 to i8 103 ret i8 %6 104} 105 106; Function Attrs: norecurse nounwind readnone 107define signext i16 @shl_i16_var(i16 signext %0, i16 signext %1) { 108; CHECK-LABEL: shl_i16_var: 109; CHECK: # %bb.0: 110; CHECK-NEXT: and %s1, %s1, (48)0 111; CHECK-NEXT: sra.w.sx %s0, %s0, %s1 112; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 113; CHECK-NEXT: b.l.t (, %s10) 114 %3 = sext i16 %0 to i32 115 %4 = zext i16 %1 to i32 116 %5 = ashr i32 %3, %4 117 %6 = trunc i32 %5 to i16 118 ret i16 %6 119} 120 121; Function Attrs: norecurse nounwind readnone 122define zeroext i16 @shl_u16_var(i16 zeroext %0, i16 zeroext %1) { 123; CHECK-LABEL: shl_u16_var: 124; CHECK: # %bb.0: 125; CHECK-NEXT: and %s0, %s0, (32)0 126; CHECK-NEXT: srl %s0, %s0, %s1 127; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1 128; CHECK-NEXT: b.l.t (, %s10) 129 %3 = zext i16 %0 to i32 130 %4 = zext i16 %1 to i32 131 %5 = lshr i32 %3, %4 132 %6 = trunc i32 %5 to i16 133 ret i16 %6 134} 135 136; Function Attrs: norecurse nounwind readnone 137define signext i32 @shl_i32_var(i32 signext %0, i32 signext %1) { 138; CHECK-LABEL: shl_i32_var: 139; CHECK: # %bb.0: 140; CHECK-NEXT: sra.w.sx %s0, %s0, %s1 141; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 142; CHECK-NEXT: b.l.t (, %s10) 143 %3 = ashr i32 %0, %1 144 ret i32 %3 145} 146 147; Function Attrs: norecurse nounwind readnone 148define zeroext i32 @shl_u32_var(i32 zeroext %0, i32 zeroext %1) { 149; CHECK-LABEL: shl_u32_var: 150; CHECK: # %bb.0: 151; CHECK-NEXT: and %s0, %s0, (32)0 152; CHECK-NEXT: srl %s0, %s0, %s1 153; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1 154; CHECK-NEXT: b.l.t (, %s10) 155 %3 = lshr i32 %0, %1 156 ret i32 %3 157} 158 159; Function Attrs: norecurse nounwind readnone 160define i64 @shl_i64_var(i64 %0, i64 %1) { 161; CHECK-LABEL: shl_i64_var: 162; CHECK: # %bb.0: 163; CHECK-NEXT: sra.l %s0, %s0, %s1 164; CHECK-NEXT: b.l.t (, %s10) 165 %3 = ashr i64 %0, %1 166 ret i64 %3 167} 168 169; Function Attrs: norecurse nounwind readnone 170define i64 @shl_u64_var(i64 %0, i64 %1) { 171; CHECK-LABEL: shl_u64_var: 172; CHECK: # %bb.0: 173; CHECK-NEXT: srl %s0, %s0, %s1 174; CHECK-NEXT: b.l.t (, %s10) 175 %3 = lshr i64 %0, %1 176 ret i64 %3 177} 178 179; Function Attrs: norecurse nounwind readnone 180define i128 @shl_i128_var(i128 %0, i128 %1) { 181; CHECK-LABEL: shl_i128_var: 182; CHECK: .LBB{{[0-9]+}}_2: 183; CHECK-NEXT: adds.w.sx %s2, %s2, (0)1 184; CHECK-NEXT: lea %s3, __ashrti3@lo 185; CHECK-NEXT: and %s3, %s3, (32)0 186; CHECK-NEXT: lea.sl %s12, __ashrti3@hi(, %s3) 187; CHECK-NEXT: bsic %s10, (, %s12) 188; CHECK-NEXT: or %s11, 0, %s9 189 %3 = ashr i128 %0, %1 190 ret i128 %3 191} 192 193; Function Attrs: norecurse nounwind readnone 194define i128 @shl_u128_var(i128 %0, i128 %1) { 195; CHECK-LABEL: shl_u128_var: 196; CHECK: .LBB{{[0-9]+}}_2: 197; CHECK-NEXT: and %s2, %s2, (32)0 198; CHECK-NEXT: lea %s3, __lshrti3@lo 199; CHECK-NEXT: and %s3, %s3, (32)0 200; CHECK-NEXT: lea.sl %s12, __lshrti3@hi(, %s3) 201; CHECK-NEXT: bsic %s10, (, %s12) 202; CHECK-NEXT: or %s11, 0, %s9 203 %3 = lshr i128 %0, %1 204 ret i128 %3 205} 206 207; Function Attrs: norecurse nounwind readnone 208define signext i8 @shl_const_i8(i8 signext %0) { 209; CHECK-LABEL: shl_const_i8: 210; CHECK: # %bb.0: 211; CHECK-NEXT: and %s0, %s0, (56)0 212; CHECK-NEXT: sra.w.sx %s0, (62)1, %s0 213; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 214; CHECK-NEXT: b.l.t (, %s10) 215 %2 = zext i8 %0 to i32 216 %3 = ashr i32 -4, %2 217 %4 = trunc i32 %3 to i8 218 ret i8 %4 219} 220 221; Function Attrs: norecurse nounwind readnone 222define zeroext i8 @shl_const_u8(i8 zeroext %0) { 223; CHECK-LABEL: shl_const_u8: 224; CHECK: # %bb.0: 225; CHECK-NEXT: sra.w.sx %s0, (62)1, %s0 226; CHECK-NEXT: and %s0, %s0, (56)0 227; CHECK-NEXT: b.l.t (, %s10) 228 %2 = zext i8 %0 to i32 229 %3 = ashr i32 -4, %2 230 %4 = trunc i32 %3 to i8 231 ret i8 %4 232} 233 234; Function Attrs: norecurse nounwind readnone 235define signext i16 @shl_const_i16(i16 signext %0) { 236; CHECK-LABEL: shl_const_i16: 237; CHECK: # %bb.0: 238; CHECK-NEXT: and %s0, %s0, (48)0 239; CHECK-NEXT: sra.w.sx %s0, (62)1, %s0 240; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 241; CHECK-NEXT: b.l.t (, %s10) 242 %2 = zext i16 %0 to i32 243 %3 = ashr i32 -4, %2 244 %4 = trunc i32 %3 to i16 245 ret i16 %4 246} 247 248; Function Attrs: norecurse nounwind readnone 249define zeroext i16 @shl_const_u16(i16 zeroext %0) { 250; CHECK-LABEL: shl_const_u16: 251; CHECK: # %bb.0: 252; CHECK-NEXT: sra.w.sx %s0, (62)1, %s0 253; CHECK-NEXT: and %s0, %s0, (48)0 254; CHECK-NEXT: b.l.t (, %s10) 255 %2 = zext i16 %0 to i32 256 %3 = ashr i32 -4, %2 257 %4 = trunc i32 %3 to i16 258 ret i16 %4 259} 260 261; Function Attrs: norecurse nounwind readnone 262define signext i32 @shl_const_i32(i32 signext %0) { 263; CHECK-LABEL: shl_const_i32: 264; CHECK: # %bb.0: 265; CHECK-NEXT: sra.w.sx %s0, (62)1, %s0 266; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 267; CHECK-NEXT: b.l.t (, %s10) 268 %2 = ashr i32 -4, %0 269 ret i32 %2 270} 271 272; Function Attrs: norecurse nounwind readnone 273define zeroext i32 @shl_const_u32(i32 zeroext %0) { 274; CHECK-LABEL: shl_const_u32: 275; CHECK: # %bb.0: 276; CHECK-NEXT: sra.w.sx %s0, (62)1, %s0 277; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1 278; CHECK-NEXT: b.l.t (, %s10) 279 %2 = ashr i32 -4, %0 280 ret i32 %2 281} 282 283; Function Attrs: norecurse nounwind readnone 284define i64 @shl_const_i64(i64 %0) { 285; CHECK-LABEL: shl_const_i64: 286; CHECK: # %bb.0: 287; CHECK-NEXT: sra.l %s0, (62)1, %s0 288; CHECK-NEXT: b.l.t (, %s10) 289 %2 = ashr i64 -4, %0 290 ret i64 %2 291} 292 293; Function Attrs: norecurse nounwind readnone 294define i64 @shl_const_u64(i64 %0) { 295; CHECK-LABEL: shl_const_u64: 296; CHECK: # %bb.0: 297; CHECK-NEXT: sra.l %s0, (62)1, %s0 298; CHECK-NEXT: b.l.t (, %s10) 299 %2 = ashr i64 -4, %0 300 ret i64 %2 301} 302 303; Function Attrs: norecurse nounwind readnone 304define i128 @shl_const_i128(i128 %0) { 305; CHECK-LABEL: shl_const_i128: 306; CHECK: .LBB{{[0-9]+}}_2: 307; CHECK-NEXT: adds.w.sx %s2, %s0, (0)1 308; CHECK-NEXT: lea %s0, __ashrti3@lo 309; CHECK-NEXT: and %s0, %s0, (32)0 310; CHECK-NEXT: lea.sl %s12, __ashrti3@hi(, %s0) 311; CHECK-NEXT: or %s0, -4, (0)1 312; CHECK-NEXT: or %s1, -1, (0)1 313; CHECK-NEXT: bsic %s10, (, %s12) 314; CHECK-NEXT: or %s11, 0, %s9 315 %2 = ashr i128 -4, %0 316 ret i128 %2 317} 318 319; Function Attrs: norecurse nounwind readnone 320define i128 @shl_const_u128(i128 %0) { 321; CHECK-LABEL: shl_const_u128: 322; CHECK: .LBB{{[0-9]+}}_2: 323; CHECK-NEXT: adds.w.sx %s2, %s0, (0)1 324; CHECK-NEXT: lea %s0, __ashrti3@lo 325; CHECK-NEXT: and %s0, %s0, (32)0 326; CHECK-NEXT: lea.sl %s12, __ashrti3@hi(, %s0) 327; CHECK-NEXT: or %s0, -4, (0)1 328; CHECK-NEXT: or %s1, -1, (0)1 329; CHECK-NEXT: bsic %s10, (, %s12) 330; CHECK-NEXT: or %s11, 0, %s9 331 %2 = ashr i128 -4, %0 332 ret i128 %2 333} 334 335; Function Attrs: norecurse nounwind readnone 336define signext i8 @shl_i8_const(i8 signext %0) { 337; CHECK-LABEL: shl_i8_const: 338; CHECK: # %bb.0: 339; CHECK-NEXT: sra.w.sx %s0, %s0, 3 340; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 341; CHECK-NEXT: b.l.t (, %s10) 342 %2 = ashr i8 %0, 3 343 ret i8 %2 344} 345 346; Function Attrs: norecurse nounwind readnone 347define zeroext i8 @shl_u8_const(i8 zeroext %0) { 348; CHECK-LABEL: shl_u8_const: 349; CHECK: # %bb.0: 350; CHECK-NEXT: and %s0, %s0, (32)0 351; CHECK-NEXT: srl %s0, %s0, 3 352; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1 353; CHECK-NEXT: b.l.t (, %s10) 354 %2 = lshr i8 %0, 3 355 ret i8 %2 356} 357 358; Function Attrs: norecurse nounwind readnone 359define signext i16 @shl_i16_const(i16 signext %0) { 360; CHECK-LABEL: shl_i16_const: 361; CHECK: # %bb.0: 362; CHECK-NEXT: sra.w.sx %s0, %s0, 7 363; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 364; CHECK-NEXT: b.l.t (, %s10) 365 %2 = ashr i16 %0, 7 366 ret i16 %2 367} 368 369; Function Attrs: norecurse nounwind readnone 370define zeroext i16 @shl_u16_const(i16 zeroext %0) { 371; CHECK-LABEL: shl_u16_const: 372; CHECK: # %bb.0: 373; CHECK-NEXT: and %s0, %s0, (32)0 374; CHECK-NEXT: srl %s0, %s0, 7 375; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1 376; CHECK-NEXT: b.l.t (, %s10) 377 %2 = lshr i16 %0, 7 378 ret i16 %2 379} 380 381; Function Attrs: norecurse nounwind readnone 382define signext i32 @shl_i32_const(i32 signext %0) { 383; CHECK-LABEL: shl_i32_const: 384; CHECK: # %bb.0: 385; CHECK-NEXT: sra.w.sx %s0, %s0, 15 386; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 387; CHECK-NEXT: b.l.t (, %s10) 388 %2 = ashr i32 %0, 15 389 ret i32 %2 390} 391 392; Function Attrs: norecurse nounwind readnone 393define zeroext i32 @shl_u32_const(i32 zeroext %0) { 394; CHECK-LABEL: shl_u32_const: 395; CHECK: # %bb.0: 396; CHECK-NEXT: and %s0, %s0, (32)0 397; CHECK-NEXT: srl %s0, %s0, 15 398; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1 399; CHECK-NEXT: b.l.t (, %s10) 400 %2 = lshr i32 %0, 15 401 ret i32 %2 402} 403 404; Function Attrs: norecurse nounwind readnone 405define i64 @shl_i64_const(i64 %0) { 406; CHECK-LABEL: shl_i64_const: 407; CHECK: # %bb.0: 408; CHECK-NEXT: sra.l %s0, %s0, 63 409; CHECK-NEXT: b.l.t (, %s10) 410 %2 = ashr i64 %0, 63 411 ret i64 %2 412} 413 414; Function Attrs: norecurse nounwind readnone 415define i64 @shl_u64_const(i64 %0) { 416; CHECK-LABEL: shl_u64_const: 417; CHECK: # %bb.0: 418; CHECK-NEXT: srl %s0, %s0, 63 419; CHECK-NEXT: b.l.t (, %s10) 420 %2 = lshr i64 %0, 63 421 ret i64 %2 422} 423 424; Function Attrs: norecurse nounwind readnone 425define i128 @shl_i128_const(i128 %0) { 426; CHECK-LABEL: shl_i128_const: 427; CHECK: # %bb.0: 428; CHECK-NEXT: sra.l %s0, %s1, 63 429; CHECK-NEXT: or %s1, 0, %s0 430; CHECK-NEXT: b.l.t (, %s10) 431 %2 = ashr i128 %0, 127 432 ret i128 %2 433} 434 435; Function Attrs: norecurse nounwind readnone 436define i128 @shl_u128_const(i128 %0) { 437; CHECK-LABEL: shl_u128_const: 438; CHECK: # %bb.0: 439; CHECK-NEXT: srl %s0, %s1, 63 440; CHECK-NEXT: or %s1, 0, (0)1 441; CHECK-NEXT: b.l.t (, %s10) 442 %2 = lshr i128 %0, 127 443 ret i128 %2 444} 445