| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,226 @@ | ||
| ; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 | ||
| ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 | ||
|
|
||
| ;; Test integers selection after integers comparison | ||
|
|
||
| define i32 @select_eq(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_eq: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: sltui $a0, $a0, 1 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_eq: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: sltui $a0, $a0, 1 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp eq i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_ne(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_ne: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: sltu $a0, $zero, $a0 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_ne: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: sltu $a0, $zero, $a0 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp ne i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_ugt(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_ugt: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sltu $a0, $a1, $a0 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_ugt: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sltu $a0, $a1, $a0 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp ugt i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_uge(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_uge: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sltu $a0, $a0, $a1 | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_uge: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sltu $a0, $a0, $a1 | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp uge i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_ult(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_ult: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sltu $a0, $a0, $a1 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_ult: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sltu $a0, $a0, $a1 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp ult i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_ule(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_ule: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sltu $a0, $a1, $a0 | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_ule: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sltu $a0, $a1, $a0 | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp ule i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_sgt(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_sgt: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slt $a0, $a1, $a0 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_sgt: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slt $a0, $a1, $a0 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp sgt i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_sge(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_sge: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slt $a0, $a0, $a1 | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_sge: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slt $a0, $a0, $a1 | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp sge i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_slt(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_slt: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slt $a0, $a0, $a1 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_slt: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slt $a0, $a0, $a1 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp slt i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } | ||
|
|
||
| define i32 @select_sle(i32 signext %a, i32 signext %b, i32 %x, i32 %y) { | ||
| ; LA32-LABEL: select_sle: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slt $a0, $a1, $a0 | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA32-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: select_sle: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slt $a0, $a1, $a0 | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: masknez $a1, $a3, $a0 | ||
| ; LA64-NEXT: maskeqz $a0, $a2, $a0 | ||
| ; LA64-NEXT: or $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %cond = icmp sle i32 %a, %b | ||
| %res = select i1 %cond, i32 %x, i32 %y | ||
| ret i32 %res | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| ; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 | ||
| ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 | ||
|
|
||
| ;; Exercise the 'shl' LLVM IR: https://llvm.org/docs/LangRef.html#shl-instruction | ||
|
|
||
| define i1 @shl_i1(i1 %x, i1 %y) { | ||
| ; LA32-LABEL: shl_i1: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i1: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i1 %x, %y | ||
| ret i1 %shl | ||
| } | ||
|
|
||
| define i8 @shl_i8(i8 %x, i8 %y) { | ||
| ; LA32-LABEL: shl_i8: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i8: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sll.d $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i8 %x, %y | ||
| ret i8 %shl | ||
| } | ||
|
|
||
| define i16 @shl_i16(i16 %x, i16 %y) { | ||
| ; LA32-LABEL: shl_i16: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i16: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sll.d $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i16 %x, %y | ||
| ret i16 %shl | ||
| } | ||
|
|
||
| define i32 @shl_i32(i32 %x, i32 %y) { | ||
| ; LA32-LABEL: shl_i32: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i32: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i32 %x, %y | ||
| ret i32 %shl | ||
| } | ||
|
|
||
| define i64 @shl_i64(i64 %x, i64 %y) { | ||
| ; LA32-LABEL: shl_i64: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: xori $a3, $a2, 31 | ||
| ; LA32-NEXT: srli.w $a4, $a0, 1 | ||
| ; LA32-NEXT: srl.w $a3, $a4, $a3 | ||
| ; LA32-NEXT: sll.w $a1, $a1, $a2 | ||
| ; LA32-NEXT: or $a1, $a1, $a3 | ||
| ; LA32-NEXT: addi.w $a3, $a2, -32 | ||
| ; LA32-NEXT: slti $a4, $a3, 0 | ||
| ; LA32-NEXT: maskeqz $a1, $a1, $a4 | ||
| ; LA32-NEXT: sll.w $a5, $a0, $a3 | ||
| ; LA32-NEXT: masknez $a4, $a5, $a4 | ||
| ; LA32-NEXT: or $a1, $a1, $a4 | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a2 | ||
| ; LA32-NEXT: srai.w $a2, $a3, 31 | ||
| ; LA32-NEXT: and $a0, $a2, $a0 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i64: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sll.d $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i64 %x, %y | ||
| ret i64 %shl | ||
| } | ||
|
|
||
| define i1 @shl_i1_3(i1 %x) { | ||
| ; LA32-LABEL: shl_i1_3: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i1_3: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i1 %x, 3 | ||
| ret i1 %shl | ||
| } | ||
|
|
||
| define i8 @shl_i8_3(i8 %x) { | ||
| ; LA32-LABEL: shl_i8_3: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a0, $a0, 3 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i8_3: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a0, $a0, 3 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i8 %x, 3 | ||
| ret i8 %shl | ||
| } | ||
|
|
||
| define i16 @shl_i16_3(i16 %x) { | ||
| ; LA32-LABEL: shl_i16_3: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a0, $a0, 3 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i16_3: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a0, $a0, 3 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i16 %x, 3 | ||
| ret i16 %shl | ||
| } | ||
|
|
||
| define i32 @shl_i32_3(i32 %x) { | ||
| ; LA32-LABEL: shl_i32_3: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a0, $a0, 3 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i32_3: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a0, $a0, 3 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i32 %x, 3 | ||
| ret i32 %shl | ||
| } | ||
|
|
||
| define i64 @shl_i64_3(i64 %x) { | ||
| ; LA32-LABEL: shl_i64_3: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a1, $a1, 3 | ||
| ; LA32-NEXT: srli.w $a2, $a0, 29 | ||
| ; LA32-NEXT: or $a1, $a1, $a2 | ||
| ; LA32-NEXT: slli.w $a0, $a0, 3 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: shl_i64_3: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a0, $a0, 3 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %shl = shl i64 %x, 3 | ||
| ret i64 %shl | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,264 @@ | ||
| ; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 | ||
| ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 | ||
|
|
||
| ;; Exercise the 'xor' LLVM IR: https://llvm.org/docs/LangRef.html#xor-instruction | ||
|
|
||
| define i1 @xor_i1(i1 %a, i1 %b) { | ||
| ; LA32-LABEL: xor_i1: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i1: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i1 %a, %b | ||
| ret i1 %r | ||
| } | ||
|
|
||
| define i8 @xor_i8(i8 %a, i8 %b) { | ||
| ; LA32-LABEL: xor_i8: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i8: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i8 %a, %b | ||
| ret i8 %r | ||
| } | ||
|
|
||
| define i16 @xor_i16(i16 %a, i16 %b) { | ||
| ; LA32-LABEL: xor_i16: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i16: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i16 %a, %b | ||
| ret i16 %r | ||
| } | ||
|
|
||
| define i32 @xor_i32(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: xor_i32: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i32: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i32 %a, %b | ||
| ret i32 %r | ||
| } | ||
|
|
||
| define i64 @xor_i64(i64 %a, i64 %b) { | ||
| ; LA32-LABEL: xor_i64: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xor $a0, $a0, $a2 | ||
| ; LA32-NEXT: xor $a1, $a1, $a3 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i64: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i64 %a, %b | ||
| ret i64 %r | ||
| } | ||
|
|
||
| define i1 @xor_i1_0(i1 %b) { | ||
| ; LA32-LABEL: xor_i1_0: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i1_0: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i1 4, %b | ||
| ret i1 %r | ||
| } | ||
|
|
||
| define i1 @xor_i1_5(i1 %b) { | ||
| ; LA32-LABEL: xor_i1_5: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i1_5: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i1 5, %b | ||
| ret i1 %r | ||
| } | ||
|
|
||
| define i8 @xor_i8_5(i8 %b) { | ||
| ; LA32-LABEL: xor_i8_5: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 5 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i8_5: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 5 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i8 5, %b | ||
| ret i8 %r | ||
| } | ||
|
|
||
| define i8 @xor_i8_257(i8 %b) { | ||
| ; LA32-LABEL: xor_i8_257: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i8_257: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i8 257, %b | ||
| ret i8 %r | ||
| } | ||
|
|
||
| define i16 @xor_i16_5(i16 %b) { | ||
| ; LA32-LABEL: xor_i16_5: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 5 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i16_5: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 5 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i16 5, %b | ||
| ret i16 %r | ||
| } | ||
|
|
||
| define i16 @xor_i16_0x1000(i16 %b) { | ||
| ; LA32-LABEL: xor_i16_0x1000: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: lu12i.w $a1, 1 | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i16_0x1000: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: lu12i.w $a1, 1 | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i16 4096, %b | ||
| ret i16 %r | ||
| } | ||
|
|
||
| define i16 @xor_i16_0x10001(i16 %b) { | ||
| ; LA32-LABEL: xor_i16_0x10001: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i16_0x10001: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i16 65537, %b | ||
| ret i16 %r | ||
| } | ||
|
|
||
| define i32 @xor_i32_5(i32 %b) { | ||
| ; LA32-LABEL: xor_i32_5: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 5 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i32_5: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 5 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i32 5, %b | ||
| ret i32 %r | ||
| } | ||
|
|
||
| define i32 @xor_i32_0x1000(i32 %b) { | ||
| ; LA32-LABEL: xor_i32_0x1000: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: lu12i.w $a1, 1 | ||
| ; LA32-NEXT: xor $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i32_0x1000: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: lu12i.w $a1, 1 | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i32 4096, %b | ||
| ret i32 %r | ||
| } | ||
|
|
||
| define i32 @xor_i32_0x100000001(i32 %b) { | ||
| ; LA32-LABEL: xor_i32_0x100000001: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i32_0x100000001: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i32 4294967297, %b | ||
| ret i32 %r | ||
| } | ||
|
|
||
| define i64 @xor_i64_5(i64 %b) { | ||
| ; LA32-LABEL: xor_i64_5: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: xori $a0, $a0, 5 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i64_5: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: xori $a0, $a0, 5 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i64 5, %b | ||
| ret i64 %r | ||
| } | ||
|
|
||
| define i64 @xor_i64_0x1000(i64 %b) { | ||
| ; LA32-LABEL: xor_i64_0x1000: | ||
| ; LA32: # %bb.0: # %entry | ||
| ; LA32-NEXT: lu12i.w $a2, 1 | ||
| ; LA32-NEXT: xor $a0, $a0, $a2 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: xor_i64_0x1000: | ||
| ; LA64: # %bb.0: # %entry | ||
| ; LA64-NEXT: lu12i.w $a1, 1 | ||
| ; LA64-NEXT: xor $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| entry: | ||
| %r = xor i64 4096, %b | ||
| ret i64 %r | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,255 @@ | ||
| ; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 | ||
| ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 | ||
|
|
||
| ;; This test checks that unnecessary masking of shift amount operands is | ||
| ;; eliminated during instruction selection. The test needs to ensure that the | ||
| ;; masking is not removed if it may affect the shift amount. | ||
|
|
||
| define i32 @sll_redundant_mask(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: sll_redundant_mask: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sll_redundant_mask: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = and i32 %b, 31 | ||
| %2 = shl i32 %a, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| define i32 @sll_non_redundant_mask(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: sll_non_redundant_mask: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: andi $a1, $a1, 15 | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sll_non_redundant_mask: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: andi $a1, $a1, 15 | ||
| ; LA64-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = and i32 %b, 15 | ||
| %2 = shl i32 %a, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| define i32 @srl_redundant_mask(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: srl_redundant_mask: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: srl.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: srl_redundant_mask: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: srl.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = and i32 %b, 4095 | ||
| %2 = lshr i32 %a, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| define i32 @srl_non_redundant_mask(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: srl_non_redundant_mask: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: andi $a1, $a1, 7 | ||
| ; LA32-NEXT: srl.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: srl_non_redundant_mask: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: andi $a1, $a1, 7 | ||
| ; LA64-NEXT: srl.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = and i32 %b, 7 | ||
| %2 = lshr i32 %a, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| define i32 @sra_redundant_mask(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: sra_redundant_mask: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: sra.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sra_redundant_mask: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: sra.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = and i32 %b, 65535 | ||
| %2 = ashr i32 %a, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| define i32 @sra_non_redundant_mask(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: sra_non_redundant_mask: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: andi $a1, $a1, 32 | ||
| ; LA32-NEXT: sra.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sra_non_redundant_mask: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: andi $a1, $a1, 32 | ||
| ; LA64-NEXT: sra.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = and i32 %b, 32 | ||
| %2 = ashr i32 %a, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| define i32 @sll_redundant_mask_zeros(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: sll_redundant_mask_zeros: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a1, $a1, 1 | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sll_redundant_mask_zeros: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a1, $a1, 1 | ||
| ; LA64-NEXT: sll.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = shl i32 %b, 1 | ||
| %2 = and i32 %1, 30 | ||
| %3 = shl i32 %a, %2 | ||
| ret i32 %3 | ||
| } | ||
|
|
||
| define i32 @srl_redundant_mask_zeros(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: srl_redundant_mask_zeros: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a1, $a1, 2 | ||
| ; LA32-NEXT: srl.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: srl_redundant_mask_zeros: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a1, $a1, 2 | ||
| ; LA64-NEXT: srl.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = shl i32 %b, 2 | ||
| %2 = and i32 %1, 28 | ||
| %3 = lshr i32 %a, %2 | ||
| ret i32 %3 | ||
| } | ||
|
|
||
| define i32 @sra_redundant_mask_zeros(i32 %a, i32 %b) { | ||
| ; LA32-LABEL: sra_redundant_mask_zeros: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a1, $a1, 3 | ||
| ; LA32-NEXT: sra.w $a0, $a0, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sra_redundant_mask_zeros: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a1, $a1, 3 | ||
| ; LA64-NEXT: sra.w $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = shl i32 %b, 3 | ||
| %2 = and i32 %1, 24 | ||
| %3 = ashr i32 %a, %2 | ||
| ret i32 %3 | ||
| } | ||
|
|
||
| define i64 @sll_redundant_mask_zeros_i64(i64 %a, i64 %b) { | ||
| ; LA32-LABEL: sll_redundant_mask_zeros_i64: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a2, $a2, 2 | ||
| ; LA32-NEXT: srli.w $a3, $a0, 1 | ||
| ; LA32-NEXT: andi $a4, $a2, 60 | ||
| ; LA32-NEXT: xori $a5, $a4, 31 | ||
| ; LA32-NEXT: srl.w $a3, $a3, $a5 | ||
| ; LA32-NEXT: sll.w $a1, $a1, $a2 | ||
| ; LA32-NEXT: or $a1, $a1, $a3 | ||
| ; LA32-NEXT: addi.w $a3, $a4, -32 | ||
| ; LA32-NEXT: slti $a4, $a3, 0 | ||
| ; LA32-NEXT: maskeqz $a1, $a1, $a4 | ||
| ; LA32-NEXT: sll.w $a5, $a0, $a3 | ||
| ; LA32-NEXT: masknez $a4, $a5, $a4 | ||
| ; LA32-NEXT: or $a1, $a1, $a4 | ||
| ; LA32-NEXT: sll.w $a0, $a0, $a2 | ||
| ; LA32-NEXT: srai.w $a2, $a3, 31 | ||
| ; LA32-NEXT: and $a0, $a2, $a0 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sll_redundant_mask_zeros_i64: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a1, $a1, 2 | ||
| ; LA64-NEXT: sll.d $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = shl i64 %b, 2 | ||
| %2 = and i64 %1, 60 | ||
| %3 = shl i64 %a, %2 | ||
| ret i64 %3 | ||
| } | ||
|
|
||
| define i64 @srl_redundant_mask_zeros_i64(i64 %a, i64 %b) { | ||
| ; LA32-LABEL: srl_redundant_mask_zeros_i64: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a2, $a2, 3 | ||
| ; LA32-NEXT: slli.w $a3, $a1, 1 | ||
| ; LA32-NEXT: andi $a4, $a2, 56 | ||
| ; LA32-NEXT: xori $a5, $a4, 31 | ||
| ; LA32-NEXT: sll.w $a3, $a3, $a5 | ||
| ; LA32-NEXT: srl.w $a0, $a0, $a2 | ||
| ; LA32-NEXT: or $a0, $a0, $a3 | ||
| ; LA32-NEXT: addi.w $a3, $a4, -32 | ||
| ; LA32-NEXT: slti $a4, $a3, 0 | ||
| ; LA32-NEXT: maskeqz $a0, $a0, $a4 | ||
| ; LA32-NEXT: srl.w $a5, $a1, $a3 | ||
| ; LA32-NEXT: masknez $a4, $a5, $a4 | ||
| ; LA32-NEXT: or $a0, $a0, $a4 | ||
| ; LA32-NEXT: srl.w $a1, $a1, $a2 | ||
| ; LA32-NEXT: srai.w $a2, $a3, 31 | ||
| ; LA32-NEXT: and $a1, $a2, $a1 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: srl_redundant_mask_zeros_i64: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a1, $a1, 3 | ||
| ; LA64-NEXT: srl.d $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = shl i64 %b, 3 | ||
| %2 = and i64 %1, 56 | ||
| %3 = lshr i64 %a, %2 | ||
| ret i64 %3 | ||
| } | ||
|
|
||
| define i64 @sra_redundant_mask_zeros_i64(i64 %a, i64 %b) { | ||
| ; LA32-LABEL: sra_redundant_mask_zeros_i64: | ||
| ; LA32: # %bb.0: | ||
| ; LA32-NEXT: slli.w $a3, $a2, 4 | ||
| ; LA32-NEXT: srai.w $a2, $a1, 31 | ||
| ; LA32-NEXT: andi $a4, $a3, 48 | ||
| ; LA32-NEXT: addi.w $a5, $a4, -32 | ||
| ; LA32-NEXT: slti $a6, $a5, 0 | ||
| ; LA32-NEXT: masknez $a2, $a2, $a6 | ||
| ; LA32-NEXT: sra.w $a7, $a1, $a3 | ||
| ; LA32-NEXT: maskeqz $a7, $a7, $a6 | ||
| ; LA32-NEXT: or $a2, $a7, $a2 | ||
| ; LA32-NEXT: srl.w $a0, $a0, $a3 | ||
| ; LA32-NEXT: xori $a3, $a4, 31 | ||
| ; LA32-NEXT: slli.w $a4, $a1, 1 | ||
| ; LA32-NEXT: sll.w $a3, $a4, $a3 | ||
| ; LA32-NEXT: or $a0, $a0, $a3 | ||
| ; LA32-NEXT: sra.w $a1, $a1, $a5 | ||
| ; LA32-NEXT: maskeqz $a0, $a0, $a6 | ||
| ; LA32-NEXT: masknez $a1, $a1, $a6 | ||
| ; LA32-NEXT: or $a0, $a0, $a1 | ||
| ; LA32-NEXT: move $a1, $a2 | ||
| ; LA32-NEXT: jirl $zero, $ra, 0 | ||
| ; | ||
| ; LA64-LABEL: sra_redundant_mask_zeros_i64: | ||
| ; LA64: # %bb.0: | ||
| ; LA64-NEXT: slli.d $a1, $a1, 4 | ||
| ; LA64-NEXT: sra.d $a0, $a0, $a1 | ||
| ; LA64-NEXT: jirl $zero, $ra, 0 | ||
| %1 = shl i64 %b, 4 | ||
| %2 = and i64 %1, 48 | ||
| %3 = ashr i64 %a, %2 | ||
| ret i64 %3 | ||
| } |