+void ISel::visitSelectInst(SelectInst &SI) {
+ unsigned DestReg = getReg(SI);
+ MachineBasicBlock::iterator MII = BB->end();
+ emitSelectOperation(BB, MII, SI.getCondition(), SI.getTrueValue(),
+ SI.getFalseValue(), DestReg);
+}
+
+/// emitSelect - Common code shared between visitSelectInst and the constant
+/// expression support.
+void ISel::emitSelectOperation(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator IP,
+ Value *Cond, Value *TrueVal, Value *FalseVal,
+ unsigned DestReg) {
+ unsigned SelectClass = getClassB(TrueVal->getType());
+
+ // We don't support 8-bit conditional moves. If we have incoming constants,
+ // transform them into 16-bit constants to avoid having a run-time conversion.
+ if (SelectClass == cByte) {
+ if (Constant *T = dyn_cast<Constant>(TrueVal))
+ TrueVal = ConstantExpr::getCast(T, Type::ShortTy);
+ if (Constant *F = dyn_cast<Constant>(FalseVal))
+ FalseVal = ConstantExpr::getCast(F, Type::ShortTy);
+ }
+
+
+ unsigned Opcode;
+ if (SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(Cond)) {
+ // We successfully folded the setcc into the select instruction.
+
+ unsigned OpNum = getSetCCNumber(SCI->getOpcode());
+ OpNum = EmitComparison(OpNum, SCI->getOperand(0), SCI->getOperand(1), MBB,
+ IP);
+
+ const Type *CompTy = SCI->getOperand(0)->getType();
+ bool isSigned = CompTy->isSigned() && getClassB(CompTy) != cFP;
+
+ // LLVM -> X86 signed X86 unsigned
+ // ----- ---------- ------------
+ // seteq -> cmovNE cmovNE
+ // setne -> cmovE cmovE
+ // setlt -> cmovGE cmovAE
+ // setge -> cmovL cmovB
+ // setgt -> cmovLE cmovBE
+ // setle -> cmovG cmovA
+ // ----
+ // cmovNS // Used by comparison with 0 optimization
+ // cmovS
+
+ switch (SelectClass) {
+ default: assert(0 && "Unknown value class!");
+ case cFP: {
+ // Annoyingly, we don't have a full set of floating point conditional
+ // moves. :(
+ static const unsigned OpcodeTab[2][8] = {
+ { X86::FCMOVNE, X86::FCMOVE, X86::FCMOVAE, X86::FCMOVB,
+ X86::FCMOVBE, X86::FCMOVA, 0, 0 },
+ { X86::FCMOVNE, X86::FCMOVE, 0, 0, 0, 0, 0, 0 },
+ };
+ Opcode = OpcodeTab[isSigned][OpNum];
+
+ // If opcode == 0, we hit a case that we don't support. Output a setcc
+ // and compare the result against zero.
+ if (Opcode == 0) {
+ unsigned CompClass = getClassB(CompTy);
+ unsigned CondReg;
+ if (CompClass != cLong || OpNum < 2) {
+ CondReg = makeAnotherReg(Type::BoolTy);
+ // Handle normal comparisons with a setcc instruction...
+ BuildMI(*MBB, IP, SetCCOpcodeTab[isSigned][OpNum], 0, CondReg);
+ } else {
+ // Long comparisons end up in the BL register.
+ CondReg = X86::BL;
+ }
+
+ BuildMI(*MBB, IP, X86::TEST8rr, 2).addReg(CondReg).addReg(CondReg);
+ Opcode = X86::FCMOVE;
+ }
+ break;
+ }
+ case cByte:
+ case cShort: {
+ static const unsigned OpcodeTab[2][8] = {
+ { X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVAE16rr, X86::CMOVB16rr,
+ X86::CMOVBE16rr, X86::CMOVA16rr, 0, 0 },
+ { X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVGE16rr, X86::CMOVL16rr,
+ X86::CMOVLE16rr, X86::CMOVG16rr, X86::CMOVNS16rr, X86::CMOVS16rr },
+ };
+ Opcode = OpcodeTab[isSigned][OpNum];
+ break;
+ }
+ case cInt:
+ case cLong: {
+ static const unsigned OpcodeTab[2][8] = {
+ { X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVAE32rr, X86::CMOVB32rr,
+ X86::CMOVBE32rr, X86::CMOVA32rr, 0, 0 },
+ { X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVGE32rr, X86::CMOVL32rr,
+ X86::CMOVLE32rr, X86::CMOVG32rr, X86::CMOVNS32rr, X86::CMOVS32rr },
+ };
+ Opcode = OpcodeTab[isSigned][OpNum];
+ break;
+ }
+ }
+ } else {
+ // Get the value being branched on, and use it to set the condition codes.
+ unsigned CondReg = getReg(Cond, MBB, IP);
+ BuildMI(*MBB, IP, X86::TEST8rr, 2).addReg(CondReg).addReg(CondReg);
+ switch (SelectClass) {
+ default: assert(0 && "Unknown value class!");
+ case cFP: Opcode = X86::FCMOVE; break;
+ case cByte:
+ case cShort: Opcode = X86::CMOVE16rr; break;
+ case cInt:
+ case cLong: Opcode = X86::CMOVE32rr; break;
+ }
+ }
+
+ unsigned TrueReg = getReg(TrueVal, MBB, IP);
+ unsigned FalseReg = getReg(FalseVal, MBB, IP);
+ unsigned RealDestReg = DestReg;
+
+
+ // Annoyingly enough, X86 doesn't HAVE 8-bit conditional moves. Because of
+ // this, we have to promote the incoming values to 16 bits, perform a 16-bit
+ // cmove, then truncate the result.
+ if (SelectClass == cByte) {
+ DestReg = makeAnotherReg(Type::ShortTy);
+ if (getClassB(TrueVal->getType()) == cByte) {
+ // Promote the true value, by storing it into AL, and reading from AX.
+ BuildMI(*MBB, IP, X86::MOV8rr, 1, X86::AL).addReg(TrueReg);
+ BuildMI(*MBB, IP, X86::MOV8ri, 1, X86::AH).addImm(0);
+ TrueReg = makeAnotherReg(Type::ShortTy);
+ BuildMI(*MBB, IP, X86::MOV16rr, 1, TrueReg).addReg(X86::AX);
+ }
+ if (getClassB(FalseVal->getType()) == cByte) {
+ // Promote the true value, by storing it into CL, and reading from CX.
+ BuildMI(*MBB, IP, X86::MOV8rr, 1, X86::CL).addReg(FalseReg);
+ BuildMI(*MBB, IP, X86::MOV8ri, 1, X86::CH).addImm(0);
+ FalseReg = makeAnotherReg(Type::ShortTy);
+ BuildMI(*MBB, IP, X86::MOV16rr, 1, FalseReg).addReg(X86::CX);
+ }
+ }
+
+ BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(TrueReg).addReg(FalseReg);
+
+ switch (SelectClass) {
+ case cByte:
+ // We did the computation with 16-bit registers. Truncate back to our
+ // result by copying into AX then copying out AL.
+ BuildMI(*MBB, IP, X86::MOV16rr, 1, X86::AX).addReg(DestReg);
+ BuildMI(*MBB, IP, X86::MOV8rr, 1, RealDestReg).addReg(X86::AL);
+ break;
+ case cLong:
+ // Move the upper half of the value as well.
+ BuildMI(*MBB, IP, Opcode, 2,DestReg+1).addReg(TrueReg+1).addReg(FalseReg+1);
+ break;
+ }
+}