diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -282,6 +282,7 @@ bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCtlz() const override; + bool hasBitTest(SDValue X, SDValue Y) const override; bool shouldFoldConstantShiftPairToMask(const SDNode *N, CombineLevel Level) const override; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -1174,6 +1174,16 @@ return Subtarget.hasMips32(); } +bool MipsTargetLowering::hasBitTest(SDValue X, SDValue Y) const { + // We can use ANDI+SLTIU as a bit test. Y contains the bit position. + // For MIPSR2 or later, we may be able to use the `ext` instruction or its' + // double-word variants. + if (auto *C = dyn_cast(Y)) + return C->getAPIntValue().ule(15); + + return false; +} + bool MipsTargetLowering::shouldFoldConstantShiftPairToMask( const SDNode *N, CombineLevel Level) const { if (N->getOperand(0).getValueType().isVector()) diff --git a/llvm/test/CodeGen/Mips/bittest.ll b/llvm/test/CodeGen/Mips/bittest.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Mips/bittest.ll @@ -0,0 +1,659 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips2 | FileCheck %s \ +; RUN: -check-prefix=MIPS +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32 | FileCheck %s \ +; RUN: -check-prefix=MIPS +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r2 | FileCheck %s \ +; RUN: -check-prefix=MIPS32R2 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r3 | FileCheck %s \ +; RUN: -check-prefix=MIPS32R2 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r5 | FileCheck %s \ +; RUN: -check-prefix=MIPS32R2 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r6 | FileCheck %s \ +; RUN: -check-prefix=MIPS32R6 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips3 | FileCheck %s \ +; RUN: -check-prefix=MIPS64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips4 | FileCheck %s \ +; RUN: -check-prefix=MIPS64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64 | FileCheck %s \ +; RUN: -check-prefix=MIPS64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r2 | FileCheck %s \ +; RUN: -check-prefix=MIPS64R2 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r3 | FileCheck %s \ +; RUN: -check-prefix=MIPS64R2 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r5 | FileCheck %s \ +; RUN: -check-prefix=MIPS64R2 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r6 | FileCheck %s \ +; RUN: -check-prefix=MIPS64R6 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r3 -mattr=+micromips | FileCheck %s \ +; RUN: -check-prefix=MM32R3 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r6 -mattr=+micromips | FileCheck %s \ +; RUN: -check-prefix=MM32R6 + +define signext i32 @bittest_10_i32(i32 signext %a) nounwind { +; MIPS-LABEL: bittest_10_i32: +; MIPS: # %bb.0: +; MIPS-NEXT: andi $1, $4, 1024 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: sltiu $2, $1, 1 +; +; MIPS32R2-LABEL: bittest_10_i32: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: andi $1, $4, 1024 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: sltiu $2, $1, 1 +; +; MIPS32R6-LABEL: bittest_10_i32: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: andi $1, $4, 1024 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: sltiu $2, $1, 1 +; +; MIPS64-LABEL: bittest_10_i32: +; MIPS64: # %bb.0: +; MIPS64-NEXT: andi $1, $4, 1024 +; MIPS64-NEXT: sltiu $1, $1, 1 +; MIPS64-NEXT: dsll $1, $1, 32 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: dsrl $2, $1, 32 +; +; MIPS64R2-LABEL: bittest_10_i32: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: andi $1, $4, 1024 +; MIPS64R2-NEXT: sltiu $1, $1, 1 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: dext $2, $1, 0, 32 +; +; MIPS64R6-LABEL: bittest_10_i32: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: andi $1, $4, 1024 +; MIPS64R6-NEXT: sltiu $1, $1, 1 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: dext $2, $1, 0, 32 +; +; MM32R3-LABEL: bittest_10_i32: +; MM32R3: # %bb.0: +; MM32R3-NEXT: andi $1, $4, 1024 +; MM32R3-NEXT: jr $ra +; MM32R3-NEXT: sltiu $2, $1, 1 +; +; MM32R6-LABEL: bittest_10_i32: +; MM32R6: # %bb.0: +; MM32R6-NEXT: andi $1, $4, 1024 +; MM32R6-NEXT: sltiu $2, $1, 1 +; MM32R6-NEXT: jrc $ra + %shr = lshr i32 %a, 10 + %not = xor i32 %shr, -1 + %and = and i32 %not, 1 + ret i32 %and +} + +define signext i32 @bittest_15_i32(i32 signext %a) nounwind { +; MIPS-LABEL: bittest_15_i32: +; MIPS: # %bb.0: +; MIPS-NEXT: andi $1, $4, 32768 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: sltiu $2, $1, 1 +; +; MIPS32R2-LABEL: bittest_15_i32: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: andi $1, $4, 32768 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: sltiu $2, $1, 1 +; +; MIPS32R6-LABEL: bittest_15_i32: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: andi $1, $4, 32768 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: sltiu $2, $1, 1 +; +; MIPS64-LABEL: bittest_15_i32: +; MIPS64: # %bb.0: +; MIPS64-NEXT: andi $1, $4, 32768 +; MIPS64-NEXT: sltiu $1, $1, 1 +; MIPS64-NEXT: dsll $1, $1, 32 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: dsrl $2, $1, 32 +; +; MIPS64R2-LABEL: bittest_15_i32: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: andi $1, $4, 32768 +; MIPS64R2-NEXT: sltiu $1, $1, 1 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: dext $2, $1, 0, 32 +; +; MIPS64R6-LABEL: bittest_15_i32: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: andi $1, $4, 32768 +; MIPS64R6-NEXT: sltiu $1, $1, 1 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: dext $2, $1, 0, 32 +; +; MM32R3-LABEL: bittest_15_i32: +; MM32R3: # %bb.0: +; MM32R3-NEXT: andi16 $2, $4, 32768 +; MM32R3-NEXT: jr $ra +; MM32R3-NEXT: sltiu $2, $2, 1 +; +; MM32R6-LABEL: bittest_15_i32: +; MM32R6: # %bb.0: +; MM32R6-NEXT: andi16 $2, $4, 32768 +; MM32R6-NEXT: sltiu $2, $2, 1 +; MM32R6-NEXT: jrc $ra + %shr = lshr i32 %a, 15 + %not = xor i32 %shr, -1 + %and = and i32 %not, 1 + ret i32 %and +} + +define signext i32 @bittest_16_i32(i32 signext %a) nounwind { +; MIPS-LABEL: bittest_16_i32: +; MIPS: # %bb.0: +; MIPS-NEXT: srl $1, $4, 16 +; MIPS-NEXT: not $1, $1 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: andi $2, $1, 1 +; +; MIPS32R2-LABEL: bittest_16_i32: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: srl $1, $4, 16 +; MIPS32R2-NEXT: not $1, $1 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: andi $2, $1, 1 +; +; MIPS32R6-LABEL: bittest_16_i32: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: srl $1, $4, 16 +; MIPS32R6-NEXT: not $1, $1 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: andi $2, $1, 1 +; +; MIPS64-LABEL: bittest_16_i32: +; MIPS64: # %bb.0: +; MIPS64-NEXT: srl $1, $4, 16 +; MIPS64-NEXT: not $1, $1 +; MIPS64-NEXT: andi $1, $1, 1 +; MIPS64-NEXT: dsll $1, $1, 32 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: dsrl $2, $1, 32 +; +; MIPS64R2-LABEL: bittest_16_i32: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: srl $1, $4, 16 +; MIPS64R2-NEXT: not $1, $1 +; MIPS64R2-NEXT: andi $1, $1, 1 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: dext $2, $1, 0, 32 +; +; MIPS64R6-LABEL: bittest_16_i32: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: srl $1, $4, 16 +; MIPS64R6-NEXT: not $1, $1 +; MIPS64R6-NEXT: andi $1, $1, 1 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: dext $2, $1, 0, 32 +; +; MM32R3-LABEL: bittest_16_i32: +; MM32R3: # %bb.0: +; MM32R3-NEXT: srl $2, $4, 16 +; MM32R3-NEXT: not16 $2, $2 +; MM32R3-NEXT: andi16 $2, $2, 1 +; MM32R3-NEXT: jrc $ra +; +; MM32R6-LABEL: bittest_16_i32: +; MM32R6: # %bb.0: +; MM32R6-NEXT: srl $2, $4, 16 +; MM32R6-NEXT: not16 $2, $2 +; MM32R6-NEXT: andi16 $2, $2, 1 +; MM32R6-NEXT: jrc $ra + %shr = lshr i32 %a, 16 + %not = xor i32 %shr, -1 + %and = and i32 %not, 1 + ret i32 %and +} + +define signext i32 @bittest_31_i32(i32 signext %a) nounwind { +; MIPS-LABEL: bittest_31_i32: +; MIPS: # %bb.0: +; MIPS-NEXT: not $1, $4 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: srl $2, $1, 31 +; +; MIPS32R2-LABEL: bittest_31_i32: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: not $1, $4 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: srl $2, $1, 31 +; +; MIPS32R6-LABEL: bittest_31_i32: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: not $1, $4 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: srl $2, $1, 31 +; +; MIPS64-LABEL: bittest_31_i32: +; MIPS64: # %bb.0: +; MIPS64-NEXT: not $1, $4 +; MIPS64-NEXT: srl $1, $1, 31 +; MIPS64-NEXT: dsll $1, $1, 32 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: dsrl $2, $1, 32 +; +; MIPS64R2-LABEL: bittest_31_i32: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: not $1, $4 +; MIPS64R2-NEXT: srl $1, $1, 31 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: dext $2, $1, 0, 32 +; +; MIPS64R6-LABEL: bittest_31_i32: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: not $1, $4 +; MIPS64R6-NEXT: srl $1, $1, 31 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: dext $2, $1, 0, 32 +; +; MM32R3-LABEL: bittest_31_i32: +; MM32R3: # %bb.0: +; MM32R3-NEXT: not16 $2, $4 +; MM32R3-NEXT: jr $ra +; MM32R3-NEXT: srl $2, $2, 31 +; +; MM32R6-LABEL: bittest_31_i32: +; MM32R6: # %bb.0: +; MM32R6-NEXT: not16 $2, $4 +; MM32R6-NEXT: srl $2, $2, 31 +; MM32R6-NEXT: jrc $ra + %shr = lshr i32 %a, 31 + %not = xor i32 %shr, -1 + %and = and i32 %not, 1 + ret i32 %and +} + +define i64 @bittest_10_i64(i64 %a) nounwind { +; MIPS-LABEL: bittest_10_i64: +; MIPS: # %bb.0: +; MIPS-NEXT: andi $1, $5, 1024 +; MIPS-NEXT: sltiu $3, $1, 1 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: addiu $2, $zero, 0 +; +; MIPS32R2-LABEL: bittest_10_i64: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: andi $1, $5, 1024 +; MIPS32R2-NEXT: sltiu $3, $1, 1 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: addiu $2, $zero, 0 +; +; MIPS32R6-LABEL: bittest_10_i64: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: andi $1, $5, 1024 +; MIPS32R6-NEXT: sltiu $3, $1, 1 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: addiu $2, $zero, 0 +; +; MIPS64-LABEL: bittest_10_i64: +; MIPS64: # %bb.0: +; MIPS64-NEXT: andi $1, $4, 1024 +; MIPS64-NEXT: sltiu $1, $1, 1 +; MIPS64-NEXT: dsll $1, $1, 32 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: dsrl $2, $1, 32 +; +; MIPS64R2-LABEL: bittest_10_i64: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: andi $1, $4, 1024 +; MIPS64R2-NEXT: sltiu $1, $1, 1 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: dext $2, $1, 0, 32 +; +; MIPS64R6-LABEL: bittest_10_i64: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: andi $1, $4, 1024 +; MIPS64R6-NEXT: sltiu $1, $1, 1 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: dext $2, $1, 0, 32 +; +; MM32R3-LABEL: bittest_10_i64: +; MM32R3: # %bb.0: +; MM32R3-NEXT: andi $1, $5, 1024 +; MM32R3-NEXT: li16 $2, 0 +; MM32R3-NEXT: jr $ra +; MM32R3-NEXT: sltiu $3, $1, 1 +; +; MM32R6-LABEL: bittest_10_i64: +; MM32R6: # %bb.0: +; MM32R6-NEXT: andi $1, $5, 1024 +; MM32R6-NEXT: sltiu $3, $1, 1 +; MM32R6-NEXT: li16 $2, 0 +; MM32R6-NEXT: jrc $ra + %shr = lshr i64 %a, 10 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +} + +define i64 @bittest_15_i64(i64 %a) nounwind { +; MIPS-LABEL: bittest_15_i64: +; MIPS: # %bb.0: +; MIPS-NEXT: andi $1, $5, 32768 +; MIPS-NEXT: sltiu $3, $1, 1 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: addiu $2, $zero, 0 +; +; MIPS32R2-LABEL: bittest_15_i64: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: andi $1, $5, 32768 +; MIPS32R2-NEXT: sltiu $3, $1, 1 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: addiu $2, $zero, 0 +; +; MIPS32R6-LABEL: bittest_15_i64: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: andi $1, $5, 32768 +; MIPS32R6-NEXT: sltiu $3, $1, 1 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: addiu $2, $zero, 0 +; +; MIPS64-LABEL: bittest_15_i64: +; MIPS64: # %bb.0: +; MIPS64-NEXT: andi $1, $4, 32768 +; MIPS64-NEXT: sltiu $1, $1, 1 +; MIPS64-NEXT: dsll $1, $1, 32 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: dsrl $2, $1, 32 +; +; MIPS64R2-LABEL: bittest_15_i64: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: andi $1, $4, 32768 +; MIPS64R2-NEXT: sltiu $1, $1, 1 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: dext $2, $1, 0, 32 +; +; MIPS64R6-LABEL: bittest_15_i64: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: andi $1, $4, 32768 +; MIPS64R6-NEXT: sltiu $1, $1, 1 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: dext $2, $1, 0, 32 +; +; MM32R3-LABEL: bittest_15_i64: +; MM32R3: # %bb.0: +; MM32R3-NEXT: andi16 $2, $5, 32768 +; MM32R3-NEXT: sltiu $3, $2, 1 +; MM32R3-NEXT: li16 $2, 0 +; MM32R3-NEXT: jrc $ra +; +; MM32R6-LABEL: bittest_15_i64: +; MM32R6: # %bb.0: +; MM32R6-NEXT: andi16 $2, $5, 32768 +; MM32R6-NEXT: sltiu $3, $2, 1 +; MM32R6-NEXT: li16 $2, 0 +; MM32R6-NEXT: jrc $ra + %shr = lshr i64 %a, 15 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +} + +define i64 @bittest_16_i64(i64 %a) nounwind { +; MIPS-LABEL: bittest_16_i64: +; MIPS: # %bb.0: +; MIPS-NEXT: srl $1, $5, 16 +; MIPS-NEXT: not $1, $1 +; MIPS-NEXT: andi $3, $1, 1 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: addiu $2, $zero, 0 +; +; MIPS32R2-LABEL: bittest_16_i64: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: srl $1, $5, 16 +; MIPS32R2-NEXT: not $1, $1 +; MIPS32R2-NEXT: andi $3, $1, 1 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: addiu $2, $zero, 0 +; +; MIPS32R6-LABEL: bittest_16_i64: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: srl $1, $5, 16 +; MIPS32R6-NEXT: not $1, $1 +; MIPS32R6-NEXT: andi $3, $1, 1 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: addiu $2, $zero, 0 +; +; MIPS64-LABEL: bittest_16_i64: +; MIPS64: # %bb.0: +; MIPS64-NEXT: dsrl $1, $4, 16 +; MIPS64-NEXT: daddiu $2, $zero, -1 +; MIPS64-NEXT: xor $1, $1, $2 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: andi $2, $1, 1 +; +; MIPS64R2-LABEL: bittest_16_i64: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: dsrl $1, $4, 16 +; MIPS64R2-NEXT: daddiu $2, $zero, -1 +; MIPS64R2-NEXT: xor $1, $1, $2 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: andi $2, $1, 1 +; +; MIPS64R6-LABEL: bittest_16_i64: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: dsrl $1, $4, 16 +; MIPS64R6-NEXT: daddiu $2, $zero, -1 +; MIPS64R6-NEXT: xor $1, $1, $2 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: andi $2, $1, 1 +; +; MM32R3-LABEL: bittest_16_i64: +; MM32R3: # %bb.0: +; MM32R3-NEXT: srl $2, $5, 16 +; MM32R3-NEXT: not16 $2, $2 +; MM32R3-NEXT: andi16 $3, $2, 1 +; MM32R3-NEXT: li16 $2, 0 +; MM32R3-NEXT: jrc $ra +; +; MM32R6-LABEL: bittest_16_i64: +; MM32R6: # %bb.0: +; MM32R6-NEXT: srl $2, $5, 16 +; MM32R6-NEXT: not16 $2, $2 +; MM32R6-NEXT: andi16 $3, $2, 1 +; MM32R6-NEXT: li16 $2, 0 +; MM32R6-NEXT: jrc $ra + %shr = lshr i64 %a, 16 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +} + +define i64 @bittest_31_i64(i64 %a) nounwind { +; MIPS-LABEL: bittest_31_i64: +; MIPS: # %bb.0: +; MIPS-NEXT: not $1, $5 +; MIPS-NEXT: srl $3, $1, 31 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: addiu $2, $zero, 0 +; +; MIPS32R2-LABEL: bittest_31_i64: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: not $1, $5 +; MIPS32R2-NEXT: srl $3, $1, 31 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: addiu $2, $zero, 0 +; +; MIPS32R6-LABEL: bittest_31_i64: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: not $1, $5 +; MIPS32R6-NEXT: srl $3, $1, 31 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: addiu $2, $zero, 0 +; +; MIPS64-LABEL: bittest_31_i64: +; MIPS64: # %bb.0: +; MIPS64-NEXT: dsrl $1, $4, 31 +; MIPS64-NEXT: daddiu $2, $zero, -1 +; MIPS64-NEXT: xor $1, $1, $2 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: andi $2, $1, 1 +; +; MIPS64R2-LABEL: bittest_31_i64: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: dsrl $1, $4, 31 +; MIPS64R2-NEXT: daddiu $2, $zero, -1 +; MIPS64R2-NEXT: xor $1, $1, $2 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: andi $2, $1, 1 +; +; MIPS64R6-LABEL: bittest_31_i64: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: dsrl $1, $4, 31 +; MIPS64R6-NEXT: daddiu $2, $zero, -1 +; MIPS64R6-NEXT: xor $1, $1, $2 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: andi $2, $1, 1 +; +; MM32R3-LABEL: bittest_31_i64: +; MM32R3: # %bb.0: +; MM32R3-NEXT: not16 $2, $5 +; MM32R3-NEXT: srl $3, $2, 31 +; MM32R3-NEXT: li16 $2, 0 +; MM32R3-NEXT: jrc $ra +; +; MM32R6-LABEL: bittest_31_i64: +; MM32R6: # %bb.0: +; MM32R6-NEXT: not16 $2, $5 +; MM32R6-NEXT: srl $3, $2, 31 +; MM32R6-NEXT: li16 $2, 0 +; MM32R6-NEXT: jrc $ra + %shr = lshr i64 %a, 31 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +} + +define i64 @bittest_32_i64(i64 %a) nounwind { +; MIPS-LABEL: bittest_32_i64: +; MIPS: # %bb.0: +; MIPS-NEXT: not $1, $4 +; MIPS-NEXT: andi $3, $1, 1 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: addiu $2, $zero, 0 +; +; MIPS32R2-LABEL: bittest_32_i64: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: not $1, $4 +; MIPS32R2-NEXT: andi $3, $1, 1 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: addiu $2, $zero, 0 +; +; MIPS32R6-LABEL: bittest_32_i64: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: not $1, $4 +; MIPS32R6-NEXT: andi $3, $1, 1 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: addiu $2, $zero, 0 +; +; MIPS64-LABEL: bittest_32_i64: +; MIPS64: # %bb.0: +; MIPS64-NEXT: dsrl $1, $4, 32 +; MIPS64-NEXT: daddiu $2, $zero, -1 +; MIPS64-NEXT: xor $1, $1, $2 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: andi $2, $1, 1 +; +; MIPS64R2-LABEL: bittest_32_i64: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: dsrl $1, $4, 32 +; MIPS64R2-NEXT: daddiu $2, $zero, -1 +; MIPS64R2-NEXT: xor $1, $1, $2 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: andi $2, $1, 1 +; +; MIPS64R6-LABEL: bittest_32_i64: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: dsrl $1, $4, 32 +; MIPS64R6-NEXT: daddiu $2, $zero, -1 +; MIPS64R6-NEXT: xor $1, $1, $2 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: andi $2, $1, 1 +; +; MM32R3-LABEL: bittest_32_i64: +; MM32R3: # %bb.0: +; MM32R3-NEXT: not16 $2, $4 +; MM32R3-NEXT: andi16 $3, $2, 1 +; MM32R3-NEXT: li16 $2, 0 +; MM32R3-NEXT: jrc $ra +; +; MM32R6-LABEL: bittest_32_i64: +; MM32R6: # %bb.0: +; MM32R6-NEXT: not16 $2, $4 +; MM32R6-NEXT: andi16 $3, $2, 1 +; MM32R6-NEXT: li16 $2, 0 +; MM32R6-NEXT: jrc $ra + %shr = lshr i64 %a, 32 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +} + +define i64 @bittest_63_i64(i64 %a) nounwind { +; MIPS-LABEL: bittest_63_i64: +; MIPS: # %bb.0: +; MIPS-NEXT: not $1, $4 +; MIPS-NEXT: srl $3, $1, 31 +; MIPS-NEXT: jr $ra +; MIPS-NEXT: addiu $2, $zero, 0 +; +; MIPS32R2-LABEL: bittest_63_i64: +; MIPS32R2: # %bb.0: +; MIPS32R2-NEXT: not $1, $4 +; MIPS32R2-NEXT: srl $3, $1, 31 +; MIPS32R2-NEXT: jr $ra +; MIPS32R2-NEXT: addiu $2, $zero, 0 +; +; MIPS32R6-LABEL: bittest_63_i64: +; MIPS32R6: # %bb.0: +; MIPS32R6-NEXT: not $1, $4 +; MIPS32R6-NEXT: srl $3, $1, 31 +; MIPS32R6-NEXT: jr $ra +; MIPS32R6-NEXT: addiu $2, $zero, 0 +; +; MIPS64-LABEL: bittest_63_i64: +; MIPS64: # %bb.0: +; MIPS64-NEXT: daddiu $1, $zero, -1 +; MIPS64-NEXT: xor $1, $4, $1 +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: dsrl $2, $1, 63 +; +; MIPS64R2-LABEL: bittest_63_i64: +; MIPS64R2: # %bb.0: +; MIPS64R2-NEXT: daddiu $1, $zero, -1 +; MIPS64R2-NEXT: xor $1, $4, $1 +; MIPS64R2-NEXT: jr $ra +; MIPS64R2-NEXT: dsrl $2, $1, 63 +; +; MIPS64R6-LABEL: bittest_63_i64: +; MIPS64R6: # %bb.0: +; MIPS64R6-NEXT: daddiu $1, $zero, -1 +; MIPS64R6-NEXT: xor $1, $4, $1 +; MIPS64R6-NEXT: jr $ra +; MIPS64R6-NEXT: dsrl $2, $1, 63 +; +; MM32R3-LABEL: bittest_63_i64: +; MM32R3: # %bb.0: +; MM32R3-NEXT: not16 $2, $4 +; MM32R3-NEXT: srl $3, $2, 31 +; MM32R3-NEXT: li16 $2, 0 +; MM32R3-NEXT: jrc $ra +; +; MM32R6-LABEL: bittest_63_i64: +; MM32R6: # %bb.0: +; MM32R6-NEXT: not16 $2, $4 +; MM32R6-NEXT: srl $3, $2, 31 +; MM32R6-NEXT: li16 $2, 0 +; MM32R6-NEXT: jrc $ra + %shr = lshr i64 %a, 63 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +}