1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s 3 4;; Test generation of the bstrins.d instruction. 5;; There are 8 patterns that can be matched to bstrins.d. See performORCombine 6;; for details. 7 8;; Pattern 1 9;; R = or (and X, mask0), (and (shl Y, lsb), mask1) 10;; => 11;; R = BSTRINS X, Y, msb, lsb 12define i64 @pat1(i64 %a, i64 %b) nounwind { 13; CHECK-LABEL: pat1: 14; CHECK: # %bb.0: 15; CHECK-NEXT: bstrins.d $a0, $a1, 39, 16 16; CHECK-NEXT: ret 17 %and1 = and i64 %a, -1099511562241 ; 0xffffff000000ffff 18 %shl = shl i64 %b, 16 19 %and2 = and i64 %shl, 1099511562240 ; 0x000000ffffff0000 20 %or = or i64 %and1, %and2 21 ret i64 %or 22} 23 24define i64 @pat1_swap(i64 %a, i64 %b) nounwind { 25; CHECK-LABEL: pat1_swap: 26; CHECK: # %bb.0: 27; CHECK-NEXT: bstrins.d $a0, $a1, 39, 16 28; CHECK-NEXT: ret 29 %and1 = and i64 %a, -1099511562241 ; 0xffffff000000ffff 30 %shl = shl i64 %b, 16 31 %and2 = and i64 %shl, 1099511562240 ; 0x000000ffffff0000 32 %or = or i64 %and2, %and1 33 ret i64 %or 34} 35 36;; Pattern 2 37;; R = or (and X, mask0), (shl (and Y, mask1), lsb) 38;; => 39;; R = BSTRINS X, Y, msb, lsb 40define i64 @pat2(i64 %a, i64 %b) nounwind { 41; CHECK-LABEL: pat2: 42; CHECK: # %bb.0: 43; CHECK-NEXT: bstrins.d $a0, $a1, 39, 16 44; CHECK-NEXT: ret 45 %and1 = and i64 %a, -1099511562241 ; 0xffffff000000ffff 46 %and2 = and i64 %b, 16777215 ; 0x0000000000ffffff 47 %shl = shl i64 %and2, 16 48 %or = or i64 %and1, %shl 49 ret i64 %or 50} 51 52define i64 @pat2_swap(i64 %a, i64 %b) nounwind { 53; CHECK-LABEL: pat2_swap: 54; CHECK: # %bb.0: 55; CHECK-NEXT: bstrins.d $a0, $a1, 39, 16 56; CHECK-NEXT: ret 57 %and1 = and i64 %a, -1099511562241 ; 0xffffff000000ffff 58 %and2 = and i64 %b, 16777215 ; 0x0000000000ffffff 59 %shl = shl i64 %and2, 16 60 %or = or i64 %shl, %and1 61 ret i64 %or 62} 63 64;; Pattern 3 65;; R = or (and X, mask0), (and Y, mask1) 66;; => 67;; R = BSTRINS X, (srl (and Y, mask1), lsb), msb, lsb 68define i64 @pat3(i64 %a, i64 %b) nounwind { 69; CHECK-LABEL: pat3: 70; CHECK: # %bb.0: 71; CHECK-NEXT: andi $a1, $a1, 288 72; CHECK-NEXT: srli.d $a1, $a1, 4 73; CHECK-NEXT: bstrins.d $a0, $a1, 11, 4 74; CHECK-NEXT: ret 75 %and1 = and i64 %a, -4081 ; 0xfffffffffffff00f 76 %and2 = and i64 %b, 288 ; 0x0000000000000120 77 %or = or i64 %and1, %and2 78 ret i64 %or 79} 80 81define i64 @pat3_swap(i64 %a, i64 %b) nounwind { 82; CHECK-LABEL: pat3_swap: 83; CHECK: # %bb.0: 84; CHECK-NEXT: andi $a1, $a1, 288 85; CHECK-NEXT: srli.d $a1, $a1, 4 86; CHECK-NEXT: bstrins.d $a0, $a1, 11, 4 87; CHECK-NEXT: ret 88 %and1 = and i64 %a, -4081 ; 0xfffffffffffff00f 89 %and2 = and i64 %b, 288 ; 0x0000000000000120 90 %or = or i64 %and2, %and1 91 ret i64 %or 92} 93 94;; Pattern 4 95;; R = or (and X, mask), (shl Y, shamt) 96;; => 97;; R = BSTRINS X, Y, 63, shamt 98define i64 @pat4(i64 %a, i64 %b) nounwind { 99; CHECK-LABEL: pat4: 100; CHECK: # %bb.0: 101; CHECK-NEXT: bstrins.d $a0, $a1, 63, 8 102; CHECK-NEXT: ret 103 %and = and i64 %a, 255 104 %shl = shl i64 %b, 8 105 %or = or i64 %and, %shl 106 ret i64 %or 107} 108 109define i64 @pat4_swap(i64 %a, i64 %b) nounwind { 110; CHECK-LABEL: pat4_swap: 111; CHECK: # %bb.0: 112; CHECK-NEXT: bstrins.d $a0, $a1, 63, 8 113; CHECK-NEXT: ret 114 %and = and i64 %a, 255 115 %shl = shl i64 %b, 8 116 %or = or i64 %shl, %and 117 ret i64 %or 118} 119 120;; Pattern 5 121;; R = or (and X, mask0), const 122;; => 123;; R = BSTRINS X, (const >> lsb), msb, lsb 124define i64 @pat5(i64 %a) nounwind { 125; CHECK-LABEL: pat5: 126; CHECK: # %bb.0: 127; CHECK-NEXT: lu12i.w $a1, 74565 128; CHECK-NEXT: ori $a1, $a1, 1656 129; CHECK-NEXT: bstrins.d $a0, $a1, 47, 16 130; CHECK-NEXT: ret 131 %and = and i64 %a, 18446462598732906495 ; 0xffff00000000ffff 132 %or = or i64 %and, 20015998304256 ; 0x0000123456780000 133 ret i64 %or 134} 135 136;; Pattern 6: a = b | ((c & mask) << shamt) 137;; In this testcase b is 0x123456000000789a, but in fact we do not require b 138;; being a constant. As long as all positions in b to be overwritten by the 139;; incoming bits are known to be zero, the pattern could be matched. 140define i64 @pat6(i64 %c) nounwind { 141; CHECK-LABEL: pat6: 142; CHECK: # %bb.0: 143; CHECK-NEXT: lu12i.w $a1, 7 144; CHECK-NEXT: ori $a1, $a1, 2202 145; CHECK-NEXT: lu32i.d $a1, 284160 146; CHECK-NEXT: lu52i.d $a1, $a1, 291 147; CHECK-NEXT: bstrins.d $a1, $a0, 39, 16 148; CHECK-NEXT: move $a0, $a1 149; CHECK-NEXT: ret 150 %and = and i64 %c, 16777215 ; 0x0000000000ffffff 151 %shl = shl i64 %and, 16 152 %or = or i64 %shl, 1311767949471676570 ; 0x123456000000789a 153 ret i64 %or 154} 155 156;; Pattern 7: a = b | ((c << shamt) & shifted_mask) 157;; Similar to pattern 6. 158define i64 @pat7(i64 %c) nounwind { 159; CHECK-LABEL: pat7: 160; CHECK: # %bb.0: 161; CHECK-NEXT: lu12i.w $a1, 7 162; CHECK-NEXT: ori $a1, $a1, 2202 163; CHECK-NEXT: lu32i.d $a1, 284160 164; CHECK-NEXT: lu52i.d $a1, $a1, 291 165; CHECK-NEXT: bstrins.d $a1, $a0, 39, 16 166; CHECK-NEXT: move $a0, $a1 167; CHECK-NEXT: ret 168 %shl = shl i64 %c, 16 169 %and = and i64 %shl, 1099511562240 ; 0x000000ffffff0000 170 %or = or i64 %and, 1311767949471676570 ; 0x123456000000789a 171 ret i64 %or 172} 173 174;; Pattern 8: a = b | (c & shifted_mask) 175;; Similar to pattern 7 but without shift to c. 176define i64 @pat8(i64 %c) nounwind { 177; CHECK-LABEL: pat8: 178; CHECK: # %bb.0: 179; CHECK-NEXT: srli.d $a1, $a0, 16 180; CHECK-NEXT: lu12i.w $a0, 7 181; CHECK-NEXT: ori $a0, $a0, 2202 182; CHECK-NEXT: lu32i.d $a0, 284160 183; CHECK-NEXT: lu52i.d $a0, $a0, 291 184; CHECK-NEXT: bstrins.d $a0, $a1, 39, 16 185; CHECK-NEXT: ret 186 %and = and i64 %c, 1099511562240 ; 0x000000ffffff0000 187 %or = or i64 %and, 1311767949471676570 ; 0x123456000000789a 188 ret i64 %or 189} 190 191;; Test that bstrins.d is not generated because constant OR operand 192;; doesn't fit into bits cleared by constant AND operand. 193define i64 @no_bstrins_d(i64 %a) nounwind { 194; CHECK-LABEL: no_bstrins_d: 195; CHECK: # %bb.0: 196; CHECK-NEXT: lu12i.w $a1, 354185 197; CHECK-NEXT: lu32i.d $a1, 4660 198; CHECK-NEXT: or $a0, $a0, $a1 199; CHECK-NEXT: lu12i.w $a1, 354191 200; CHECK-NEXT: ori $a1, $a1, 4095 201; CHECK-NEXT: lu32i.d $a1, -60876 202; CHECK-NEXT: and $a0, $a0, $a1 203; CHECK-NEXT: ret 204 %and = and i64 %a, 18446462598732906495 ; 0xffff00000000ffff 205 %or = or i64 %and, 20015998341120 ; 0x0000123456789000 206 ret i64 %or 207} 208