+ // This generates a SUBCC instruction, putting the difference in
+ // a result register, and setting a condition code.
+ //
+ // If the boolean result of the SetCC is used by anything other
+ // than a branch instruction, or if it is used outside the current
+ // basic block, the boolean must be
+ // computed and stored in the result register. Otherwise, discard
+ // the difference (by using %g0) and keep only the condition code.
+ //
+ // To compute the boolean result in a register we use a conditional
+ // move, unless the result of the SUBCC instruction can be used as
+ // the bool! This assumes that zero is FALSE and any non-zero
+ // integer is TRUE.
+ //
+ InstructionNode* parentNode = (InstructionNode*) subtreeRoot->parent();
+ Instruction* setCCInstr = subtreeRoot->getInstruction();
+
+ bool keepBoolVal = parentNode == NULL ||
+ ! AllUsesAreBranches(setCCInstr);
+ bool subValIsBoolVal = setCCInstr->getOpcode() == Instruction::SetNE;
+ bool keepSubVal = keepBoolVal && subValIsBoolVal;
+ bool computeBoolVal = keepBoolVal && ! subValIsBoolVal;
+
+ bool mustClearReg;
+ int valueToMove;
+ MachineOpCode movOpCode = 0;
+
+ // Mark the 4th operand as being a CC register, and as a def
+ // A TmpInstruction is created to represent the CC "result".
+ // Unlike other instances of TmpInstruction, this one is used
+ // by machine code of multiple LLVM instructions, viz.,
+ // the SetCC and the branch. Make sure to get the same one!
+ // Note that we do this even for FP CC registers even though they
+ // are explicit operands, because the type of the operand
+ // needs to be a floating point condition code, not an integer
+ // condition code. Think of this as casting the bool result to
+ // a FP condition code register.
+ //
+ Value* leftVal = subtreeRoot->leftChild()->getValue();
+ bool isFPCompare = leftVal->getType()->isFloatingPoint();
+
+ TmpInstruction* tmpForCC = GetTmpForCC(setCCInstr,
+ setCCInstr->getParent()->getParent(),
+ isFPCompare ? Type::FloatTy : Type::IntTy);
+ MachineCodeForInstruction::get(setCCInstr).addTemp(tmpForCC);
+
+ if (! isFPCompare)
+ {
+ // Integer condition: dest. should be %g0 or an integer register.
+ // If result must be saved but condition is not SetEQ then we need
+ // a separate instruction to compute the bool result, so discard
+ // result of SUBcc instruction anyway.
+ //
+ M = new MachineInstr(SUBcc);
+ Set3OperandsFromInstr(M, subtreeRoot, target, ! keepSubVal);
+ M->SetMachineOperandVal(3, MachineOperand::MO_CCRegister,
+ tmpForCC, /*def*/true);
+ mvec.push_back(M);
+
+ if (computeBoolVal)
+ { // recompute bool using the integer condition codes
+ movOpCode =
+ ChooseMovpccAfterSub(subtreeRoot,mustClearReg,valueToMove);
+ }
+ }
+ else
+ {
+ // FP condition: dest of FCMP should be some FCCn register
+ M = new MachineInstr(ChooseFcmpInstruction(subtreeRoot));
+ M->SetMachineOperandVal(0, MachineOperand::MO_CCRegister,
+ tmpForCC);
+ M->SetMachineOperandVal(1,MachineOperand::MO_VirtualRegister,
+ subtreeRoot->leftChild()->getValue());
+ M->SetMachineOperandVal(2,MachineOperand::MO_VirtualRegister,
+ subtreeRoot->rightChild()->getValue());
+ mvec.push_back(M);
+
+ if (computeBoolVal)
+ {// recompute bool using the FP condition codes
+ mustClearReg = true;
+ valueToMove = 1;
+ movOpCode = ChooseMovFpccInstruction(subtreeRoot);
+ }
+ }
+
+ if (computeBoolVal)
+ {
+ if (mustClearReg)
+ {// Unconditionally set register to 0
+ M = new MachineInstr(SETHI);
+ M->SetMachineOperandConst(0,MachineOperand::MO_UnextendedImmed,
+ (int64_t)0);
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
+ setCCInstr);
+ mvec.push_back(M);
+ }
+
+ // Now conditionally move `valueToMove' (0 or 1) into the register
+ // Mark the register as a use (as well as a def) because the old
+ // value should be retained if the condition is false.
+ M = new MachineInstr(movOpCode);
+ M->SetMachineOperandVal(0, MachineOperand::MO_CCRegister,
+ tmpForCC);
+ M->SetMachineOperandConst(1, MachineOperand::MO_UnextendedImmed,
+ valueToMove);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
+ setCCInstr, /*isDef*/ true,
+ /*isDefAndUse*/ true);
+ mvec.push_back(M);
+ }
+ break;
+ }
+
+ case 51: // reg: Load(reg)
+ case 52: // reg: Load(ptrreg)
+ mvec.push_back(new MachineInstr(ChooseLoadInstruction(
+ subtreeRoot->getValue()->getType())));
+ SetOperandsForMemInstr(mvec, subtreeRoot, target);
+ break;
+
+ case 55: // reg: GetElemPtr(reg)
+ case 56: // reg: GetElemPtrIdx(reg,reg)
+ // If the GetElemPtr was folded into the user (parent), it will be
+ // caught above. For other cases, we have to compute the address.
+ mvec.push_back(new MachineInstr(ADD));
+ SetOperandsForMemInstr(mvec, subtreeRoot, target);
+ break;
+
+ case 57: // reg: Alloca: Implement as 1 instruction:
+ { // add %fp, offsetFromFP -> result
+ AllocationInst* instr =
+ cast<AllocationInst>(subtreeRoot->getInstruction());
+ unsigned int tsize =
+ target.DataLayout.getTypeSize(instr->getAllocatedType());
+ assert(tsize != 0);
+ CreateCodeForFixedSizeAlloca(target, instr, tsize, 1, mvec);
+ break;