Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -58,6 +58,15 @@ return false; }]>; +def PowerOf2LO_i32 : PatLeaf<(imm), [{ + if (N->getValueType(0) == MVT::i32) { + uint64_t Imm = N->getZExtValue(); + return isPowerOf2_32(Imm) && (Imm & 0xffffffff) == Imm; + } + else + return false; +}]>; + def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ return cast(N->getOperand(1))->getVT().bitsLT(MVT::i32); }]>; @@ -392,10 +401,11 @@ } class CBranchBitNum shift = 1> : + RegisterOperand RO, PatFrag ImmShift, Operand ImmOp, + bits<64> shift = 1> : InstSE<(outs), (ins RO:$rs, ImmOp:$p, opnd:$offset), !strconcat(opstr, "\t$rs, $p, $offset"), - [(brcond (i32 (cond_op (and RO:$rs, (shl shift, immZExt5_64:$p)), 0)), + [(brcond (i32 (cond_op (and RO:$rs, (shl shift, ImmShift:$p)), 0)), bb:$offset)], II_BBIT, FrmI, opstr> { let isBranch = 1; let isTerminator = 1; @@ -415,16 +425,23 @@ } // Branch on Bit Clear /+32 -def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd, +def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd, immZExt5_64, uimm5_64_report_uimm6>, BBIT_FM<0x32>, ASE_CNMIPS; -def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, uimm5_64, - 0x100000000>, BBIT_FM<0x36>, ASE_CNMIPS; +def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, immZExt5_64, + uimm5_64, 0x100000000>, BBIT_FM<0x36>, ASE_CNMIPS; // Branch on Bit Set /+32 -def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd, +def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd, immZExt5_64, uimm5_64_report_uimm6>, BBIT_FM<0x3a>, ASE_CNMIPS; -def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, uimm5_64, - 0x100000000>, BBIT_FM<0x3e>, ASE_CNMIPS; +def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, immZExt5_64, + uimm5_64, 0x100000000>, BBIT_FM<0x3e>, ASE_CNMIPS; + +let isCodeGenOnly = 1 in + def BBIT0_i32 : CBranchBitNum<"bbit0", brtarget, seteq, GPR32Opnd, immZExt5, + uimm5_report_uimm6>, BBIT_FM<0x32>, ASE_CNMIPS; +let isCodeGenOnly = 1 in + def BBIT1_i32 : CBranchBitNum<"bbit1", brtarget, setne, GPR32Opnd, immZExt5, + uimm5_report_uimm6>, BBIT_FM<0x3a>, ASE_CNMIPS; // Multiply Doubleword to GPR def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>, @@ -703,6 +720,10 @@ (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; +def : MipsPat<(brcond (i32 (seteq (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst), + (BBIT0_i32 i32:$lhs, (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; +def : MipsPat<(brcond (i32 (setne (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst), + (BBIT1_i32 i32:$lhs, (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; // Atomic load patterns. def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>; Index: lib/Target/Mips/MipsSEInstrInfo.cpp =================================================================== --- lib/Target/Mips/MipsSEInstrInfo.cpp +++ lib/Target/Mips/MipsSEInstrInfo.cpp @@ -455,6 +455,8 @@ case Mips::BBIT1: return Mips::BBIT0; case Mips::BBIT032: return Mips::BBIT132; case Mips::BBIT132: return Mips::BBIT032; + case Mips::BBIT0_i32: return Mips::BBIT1_i32; + case Mips::BBIT1_i32: return Mips::BBIT0_i32; } } @@ -547,7 +549,8 @@ Opc == Mips::BGEZC64 || Opc == Mips::BLTZC64 || Opc == Mips::BLEZC64 || Opc == Mips::BC || Opc == Mips::BBIT0 || Opc == Mips::BBIT1 || Opc == Mips::BBIT032 || - Opc == Mips::BBIT132) ? Opc : 0; + Opc == Mips::BBIT132 || Opc == Mips::BBIT0_i32 || + Opc == Mips::BBIT1_i32) ? Opc : 0; } void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, Index: test/CodeGen/Mips/octeon.ll =================================================================== --- test/CodeGen/Mips/octeon.ll +++ test/CodeGen/Mips/octeon.ll @@ -164,3 +164,59 @@ endif: ret i64 12 } + +; long long var = 7; +; void bbit0i32 () { +; if ((var & 0x2)) { +; printf("bbit0i32"); +; } +; } +; +; void bbit1i32() { +; if (!(var & 0x2)) { +; printf("bbit1i32"); +; } +; } + +@var = local_unnamed_addr global i64 7, align 8 +@.str = private unnamed_addr constant [9 x i8] c"bbit0i32\00", align 1 +@.str.1 = private unnamed_addr constant [9 x i8] c"bbit1i32\00", align 1 + +define void @bbit0i32() local_unnamed_addr { +entry: +; OCTEON: bbit0 $1, 1, [[BB0:(\$|\.L)BB[0-9_]+]] +; OCTEON-PIC-NOT: b {{[[:space:]].*}} +; OCTEON-NOT: j {{[[:space:]].*}} + %0 = load i64, i64* @var, align 8 + %and = and i64 %0, 2 + %tobool = icmp eq i64 %and, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +} + +declare i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr + +define void @bbit1i32() local_unnamed_addr { +entry: +; OCTEON: bbit1 $1, 1, [[BB0:(\$|\.L)BB[0-9_]+]] +; OCTEON-PIC-NOT: b {{[[:space:]].*}} +; OCTEON-NOT: j {{[[:space:]].*}} + %0 = load i64, i64* @var, align 8 + %and = and i64 %0, 2 + %tobool = icmp eq i64 %and, 0 + br i1 %tobool, label %if.then, label %if.end + +if.then: ; preds = %entry + %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i64 0, i64 0)) + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +} +