diff --git a/lib/Target/PowerPC/PPC32ISelSimple.cpp b/lib/Target/PowerPC/PPC32ISelSimple.cpp index a49f2538e1c..da057a65cad 100644 --- a/lib/Target/PowerPC/PPC32ISelSimple.cpp +++ b/lib/Target/PowerPC/PPC32ISelSimple.cpp @@ -1110,148 +1110,12 @@ void ISel::visitSetCondInst(SetCondInst &I) { if (canFoldSetCCIntoBranchOrSelect(&I)) return; - Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - const Type *Ty = Op0->getType(); - unsigned Class = getClassB(Ty); - unsigned Opcode = I.getOpcode(); unsigned DestReg = getReg(I); - - // If the comparison type is byte, short, or int, then we can emit a - // branchless version of the SetCC that puts 0 (false) or 1 (true) in the - // destination register. - if (Class <= cInt) { - ++NumSetCC; - MachineBasicBlock::iterator MI = BB->end(); - unsigned OpNum = getSetCCNumber(Opcode); - unsigned Op0Reg = getReg(Op0, BB, MI); - Op0Reg = ExtendOrClear(BB, MI, Op0Reg, Ty); - - // comparisons against constant zero often have shorter sequences than the - // general case, handled below. - ConstantInt *CI = dyn_cast(Op1); - if (CI && CI->getRawValue() == 0) { - switch(OpNum) { - case 0: { // eq0 - unsigned TempReg = makeAnotherReg(Type::IntTy); - BuildMI(*BB, MI, PPC::CNTLZW, 1, TempReg).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::SRWI, 2, DestReg).addReg(TempReg).addImm(5); - break; - } - case 1: { // ne0 - unsigned TempReg = makeAnotherReg(Type::IntTy); - BuildMI(*BB, MI, PPC::ADDIC, 2, TempReg).addReg(Op0Reg).addSImm(-1); - BuildMI(*BB, MI, PPC::SUBFE, 2, DestReg).addReg(TempReg).addReg(Op0Reg); - break; - } - case 2: { // lt0, always false if unsigned - if (Ty->isSigned()) - BuildMI(*BB, MI, PPC::SRWI, 2, DestReg).addReg(Op0Reg).addImm(31); - else - BuildMI(*BB, MI, PPC::LI, 1, DestReg).addSImm(0); - break; - } - case 3: { // ge0, always true if unsigned - if (Ty->isSigned()) { - unsigned TempReg = makeAnotherReg(Type::IntTy); - BuildMI(*BB, MI, PPC::SRWI, 2, TempReg).addReg(Op0Reg).addImm(31); - BuildMI(*BB, MI, PPC::XORI, 2, DestReg).addReg(TempReg).addImm(1); - } else { - BuildMI(*BB, MI, PPC::LI, 1, DestReg).addSImm(1); - } - break; - } - case 4: { // gt0, equivalent to ne0 if unsigned - unsigned Temp1 = makeAnotherReg(Type::IntTy); - unsigned Temp2 = makeAnotherReg(Type::IntTy); - if (Ty->isSigned()) { - BuildMI(*BB, MI, PPC::NEG, 2, Temp1).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::ANDC, 2, Temp2).addReg(Temp1).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::SRWI, 2, DestReg).addReg(Temp2).addImm(31); - } else { - BuildMI(*BB, MI, PPC::ADDIC, 2, Temp1).addReg(Op0Reg).addSImm(-1); - BuildMI(*BB, MI, PPC::SUBFE, 2, DestReg).addReg(Temp1).addReg(Op0Reg); - } - break; - } - case 5: { // le0, equivalent to eq0 if unsigned - unsigned Temp1 = makeAnotherReg(Type::IntTy); - unsigned Temp2 = makeAnotherReg(Type::IntTy); - if (Ty->isSigned()) { - BuildMI(*BB, MI, PPC::NEG, 2, Temp1).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::ORC, 2, Temp2).addReg(Op0Reg).addReg(Temp1); - BuildMI(*BB, MI, PPC::SRWI, 2, DestReg).addReg(Temp2).addImm(31); - } else { - BuildMI(*BB, MI, PPC::CNTLZW, 1, Temp1).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::SRWI, 2, DestReg).addReg(Temp1).addImm(5); - } - break; - } - } // switch - return; - } - unsigned Op1Reg = getReg(Op1, BB, MI); - switch(OpNum) { - case 0: { // eq - unsigned Temp1 = makeAnotherReg(Type::IntTy); - unsigned Temp2 = makeAnotherReg(Type::IntTy); - BuildMI(*BB, MI, PPC::SUBF, 2, Temp1).addReg(Op0Reg).addReg(Op1Reg); - BuildMI(*BB, MI, PPC::CNTLZW, 1, Temp2).addReg(Temp1); - BuildMI(*BB, MI, PPC::SRWI, 2, DestReg).addReg(Temp2).addImm(5); - break; - } - case 1: { // ne - unsigned Temp1 = makeAnotherReg(Type::IntTy); - unsigned Temp2 = makeAnotherReg(Type::IntTy); - BuildMI(*BB, MI, PPC::SUBF, 2, Temp1).addReg(Op0Reg).addReg(Op1Reg); - BuildMI(*BB, MI, PPC::ADDIC, 2, Temp2).addReg(Temp1).addSImm(-1); - BuildMI(*BB, MI, PPC::SUBFE, 2, DestReg).addReg(Temp2).addReg(Temp1); - break; - } - case 2: - case 4: { // lt, gt - unsigned Temp1 = makeAnotherReg(Type::IntTy); - unsigned Temp2 = makeAnotherReg(Type::IntTy); - unsigned Temp3 = makeAnotherReg(Type::IntTy); - unsigned Temp4 = makeAnotherReg(Type::IntTy); - if (OpNum == 4) std::swap(Op0Reg, Op1Reg); - if (Ty->isSigned()) { - BuildMI(*BB, MI, PPC::SUBFC, 2, Temp1).addReg(Op1Reg).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::EQV, 2, Temp2).addReg(Op1Reg).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::SRWI, 2, Temp3).addReg(Temp2).addImm(31); - BuildMI(*BB, MI, PPC::ADDZE, 1, Temp4).addReg(Temp3); - BuildMI(*BB, MI, PPC::RLWINM, 4, DestReg).addReg(Temp4).addImm(0) - .addImm(31).addImm(31); - } else { - BuildMI(*BB, MI, PPC::SUBFC, 2, Temp1).addReg(Op1Reg).addReg(Op0Reg); - BuildMI(*BB, MI, PPC::SUBFE, 2, Temp2).addReg(Temp1).addReg(Temp1); - BuildMI(*BB, MI, PPC::NEG, 2, DestReg).addReg(Temp2); - } - break; - } - case 3: - case 5: { // le, ge - unsigned Temp1 = makeAnotherReg(Type::IntTy); - unsigned Temp2 = makeAnotherReg(Type::IntTy); - unsigned Temp3 = makeAnotherReg(Type::IntTy); - if (OpNum == 3) std::swap(Op0Reg, Op1Reg); - if (Ty->isSigned()) { - BuildMI(*BB, MI, PPC::SRWI, 2, Temp1).addReg(Op0Reg).addImm(31); - BuildMI(*BB, MI, PPC::SRAWI, 2, Temp2).addReg(Op1Reg).addImm(31); - BuildMI(*BB, MI, PPC::SUBFC, 2, Temp3).addReg(Op0Reg).addReg(Op1Reg); - BuildMI(*BB, MI, PPC::ADDE, 2, DestReg).addReg(Temp2).addReg(Temp1); - } else { - BuildMI(*BB, MI, PPC::LI, 1, Temp2).addSImm(-1); - BuildMI(*BB, MI, PPC::SUBFC, 2, Temp1).addReg(Op0Reg).addReg(Op1Reg); - BuildMI(*BB, MI, PPC::SUBFZE, 1, DestReg).addReg(Temp2); - } - break; - } - } // switch - return; - } - EmitComparison(Opcode, Op0, Op1, BB, BB->end()); - + unsigned Opcode = I.getOpcode(); unsigned PPCOpcode = getPPCOpcodeForSetCCNumber(Opcode); + + // Create an iterator with which to insert the MBB for copying the false value + // and the MBB to hold the PHI instruction for this SetCC. MachineBasicBlock *thisMBB = BB; const BasicBlock *LLVM_BB = BB->getBasicBlock(); ilist::iterator It = BB; @@ -1260,32 +1124,18 @@ void ISel::visitSetCondInst(SetCondInst &I) { // thisMBB: // ... // cmpTY cr0, r1, r2 - // bCC copy1MBB - // b copy0MBB - - // FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB) - // if we could insert other, non-terminator instructions after the - // bCC. But MBB->getFirstTerminator() can't understand this. - MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB); - F->getBasicBlockList().insert(It, copy1MBB); - BuildMI(BB, PPCOpcode, 2).addReg(PPC::CR0).addMBB(copy1MBB); - MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); - F->getBasicBlockList().insert(It, copy0MBB); - BuildMI(BB, PPC::B, 1).addMBB(copy0MBB); - MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); - F->getBasicBlockList().insert(It, sinkMBB); - // Update machine-CFG edges - BB->addSuccessor(copy1MBB); - BB->addSuccessor(copy0MBB); - - // copy1MBB: // %TrueValue = li 1 - // b sinkMBB - BB = copy1MBB; + // bCC sinkMBB + EmitComparison(Opcode, I.getOperand(0), I.getOperand(1), BB, BB->end()); unsigned TrueValue = makeAnotherReg(I.getType()); BuildMI(BB, PPC::LI, 1, TrueValue).addSImm(1); - BuildMI(BB, PPC::B, 1).addMBB(sinkMBB); + MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); + BuildMI(BB, PPCOpcode, 2).addReg(PPC::CR0).addMBB(sinkMBB); + F->getBasicBlockList().insert(It, copy0MBB); + F->getBasicBlockList().insert(It, sinkMBB); // Update machine-CFG edges + BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); // copy0MBB: @@ -1298,11 +1148,11 @@ void ISel::visitSetCondInst(SetCondInst &I) { BB->addSuccessor(sinkMBB); // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ] + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] // ... BB = sinkMBB; BuildMI(BB, PPC::PHI, 4, DestReg).addReg(FalseValue) - .addMBB(copy0MBB).addReg(TrueValue).addMBB(copy1MBB); + .addMBB(copy0MBB).addReg(TrueValue).addMBB(thisMBB); } void ISel::visitSelectInst(SelectInst &SI) { @@ -1335,40 +1185,25 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB, BuildMI(*MBB, IP, PPC::CMPI, 2, PPC::CR0).addReg(CondReg).addSImm(0); Opcode = getPPCOpcodeForSetCCNumber(Instruction::SetNE); } - - // thisMBB: - // ... - // cmpTY cr0, r1, r2 - // bCC copy1MBB - // b copy0MBB + unsigned TrueValue = getReg(TrueVal, BB, BB->end()); MachineBasicBlock *thisMBB = BB; const BasicBlock *LLVM_BB = BB->getBasicBlock(); ilist::iterator It = BB; ++It; - // FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB) - // if we could insert other, non-terminator instructions after the - // bCC. But MBB->getFirstTerminator() can't understand this. - MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB); - F->getBasicBlockList().insert(It, copy1MBB); - BuildMI(BB, Opcode, 2).addReg(PPC::CR0).addMBB(copy1MBB); + // thisMBB: + // ... + // cmpTY cr0, r1, r2 + // %TrueValue = ... + // bCC sinkMBB MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); - F->getBasicBlockList().insert(It, copy0MBB); - BuildMI(BB, PPC::B, 1).addMBB(copy0MBB); MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); + BuildMI(BB, Opcode, 2).addReg(PPC::CR0).addMBB(sinkMBB); + F->getBasicBlockList().insert(It, copy0MBB); F->getBasicBlockList().insert(It, sinkMBB); // Update machine-CFG edges - BB->addSuccessor(copy1MBB); BB->addSuccessor(copy0MBB); - - // copy1MBB: - // %TrueValue = ... - // b sinkMBB - BB = copy1MBB; - unsigned TrueValue = getReg(TrueVal, BB, BB->begin()); - BuildMI(BB, PPC::B, 1).addMBB(sinkMBB); - // Update machine-CFG edges BB->addSuccessor(sinkMBB); // copy0MBB: @@ -1380,12 +1215,14 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB, BB->addSuccessor(sinkMBB); // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ] + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] // ... BB = sinkMBB; BuildMI(BB, PPC::PHI, 4, DestReg).addReg(FalseValue) - .addMBB(copy0MBB).addReg(TrueValue).addMBB(copy1MBB); + .addMBB(copy0MBB).addReg(TrueValue).addMBB(thisMBB); + // For a register pair representing a long value, define the second reg + // FIXME: Can this really be correct for selecting longs? if (getClassB(TrueVal->getType()) == cLong) BuildMI(BB, PPC::LI, 1, DestReg+1).addImm(0); return;