+SDOperand SparcV8TargetLowering::
+LowerOperation(SDOperand Op, SelectionDAG &DAG) {
+ switch (Op.getOpcode()) {
+ default: assert(0 && "Should not custom lower this!");
+ case ISD::GlobalAddress: {
+ GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+ SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
+ SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, GA);
+ SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, GA);
+ return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi);
+ }
+ case ISD::ConstantPool: {
+ Constant *C = cast<ConstantPoolSDNode>(Op)->get();
+ SDOperand CP = DAG.getTargetConstantPool(C, MVT::i32);
+ SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, CP);
+ SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, CP);
+ return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi);
+ }
+ case ISD::FP_TO_SINT:
+ // Convert the fp value to integer in an FP register.
+ assert(Op.getValueType() == MVT::i32);
+ Op = DAG.getNode(V8ISD::FTOI, MVT::f32, Op.getOperand(0));
+ return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Op);
+ case ISD::SINT_TO_FP: {
+ assert(Op.getOperand(0).getValueType() == MVT::i32);
+ SDOperand Tmp = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Op.getOperand(0));
+ // Convert the int value to FP in an FP register.
+ return DAG.getNode(V8ISD::ITOF, Op.getValueType(), Tmp);
+ }
+ case ISD::BR_CC: {
+ SDOperand Chain = Op.getOperand(0);
+ SDOperand CC = Op.getOperand(1);
+ SDOperand LHS = Op.getOperand(2);
+ SDOperand RHS = Op.getOperand(3);
+ SDOperand Dest = Op.getOperand(4);
+
+ // Get the condition flag.
+ if (LHS.getValueType() == MVT::i32) {
+ std::vector<MVT::ValueType> VTs;
+ VTs.push_back(MVT::i32);
+ VTs.push_back(MVT::Flag);
+ std::vector<SDOperand> Ops;
+ Ops.push_back(LHS);
+ Ops.push_back(RHS);
+ SDOperand Cond = DAG.getNode(V8ISD::CMPICC, VTs, Ops);
+ return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond);
+ } else {
+ std::vector<MVT::ValueType> VTs;
+ VTs.push_back(MVT::i32);
+ VTs.push_back(MVT::Flag);
+ std::vector<SDOperand> Ops;
+ Ops.push_back(LHS);
+ Ops.push_back(RHS);
+ SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, VTs, Ops);
+ return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond);
+ }
+ }
+ case ISD::SELECT_CC: {
+ SDOperand LHS = Op.getOperand(0);
+ SDOperand RHS = Op.getOperand(1);
+ unsigned CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
+ SDOperand TrueVal = Op.getOperand(2);
+ SDOperand FalseVal = Op.getOperand(3);
+
+ unsigned Opc;
+ Opc = LHS.getValueType() == MVT::i32 ? V8ISD::CMPICC : V8ISD::CMPFCC;
+ std::vector<MVT::ValueType> VTs;
+ VTs.push_back(LHS.getValueType());
+ VTs.push_back(MVT::Flag);
+ std::vector<SDOperand> Ops;
+ Ops.push_back(LHS);
+ Ops.push_back(RHS);
+ SDOperand CompareFlag = DAG.getNode(Opc, VTs, Ops).getValue(1);
+
+ Opc = LHS.getValueType() == MVT::i32 ?
+ V8ISD::SELECT_ICC : V8ISD::SELECT_FCC;
+ return DAG.getNode(Opc, TrueVal.getValueType(), TrueVal, FalseVal,
+ DAG.getConstant(CC, MVT::i32), CompareFlag);
+ }
+ }
+}
+
+MachineBasicBlock *
+SparcV8TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
+ MachineBasicBlock *BB) {
+ unsigned BROpcode;
+ // Figure out the conditional branch opcode to use for this select_cc.
+ switch (MI->getOpcode()) {
+ default: assert(0 && "Unknown SELECT_CC!");
+ case V8::SELECT_CC_Int_ICC:
+ case V8::SELECT_CC_FP_ICC:
+ case V8::SELECT_CC_DFP_ICC:
+ // Integer compare.
+ switch ((ISD::CondCode)MI->getOperand(3).getImmedValue()) {
+ default: assert(0 && "Unknown integer condition code!");
+ case ISD::SETEQ: BROpcode = V8::BE; break;
+ case ISD::SETNE: BROpcode = V8::BNE; break;
+ case ISD::SETLT: BROpcode = V8::BL; break;
+ case ISD::SETGT: BROpcode = V8::BG; break;
+ case ISD::SETLE: BROpcode = V8::BLE; break;
+ case ISD::SETGE: BROpcode = V8::BGE; break;
+ case ISD::SETULT: BROpcode = V8::BCS; break;
+ case ISD::SETULE: BROpcode = V8::BLEU; break;
+ case ISD::SETUGT: BROpcode = V8::BGU; break;
+ case ISD::SETUGE: BROpcode = V8::BCC; break;
+ }
+ break;
+ case V8::SELECT_CC_Int_FCC:
+ case V8::SELECT_CC_FP_FCC:
+ case V8::SELECT_CC_DFP_FCC:
+ // FP compare.
+ switch ((ISD::CondCode)MI->getOperand(3).getImmedValue()) {
+ default: assert(0 && "Unknown fp condition code!");
+ case ISD::SETEQ: BROpcode = V8::FBE; break;
+ case ISD::SETNE: BROpcode = V8::FBNE; break;
+ case ISD::SETLT: BROpcode = V8::FBL; break;
+ case ISD::SETGT: BROpcode = V8::FBG; break;
+ case ISD::SETLE: BROpcode = V8::FBLE; break;
+ case ISD::SETGE: BROpcode = V8::FBGE; break;
+ case ISD::SETULT: BROpcode = V8::FBUL; break;
+ case ISD::SETULE: BROpcode = V8::FBULE; break;
+ case ISD::SETUGT: BROpcode = V8::FBUG; break;
+ case ISD::SETUGE: BROpcode = V8::FBUGE; break;
+ case ISD::SETUO: BROpcode = V8::FBU; break;
+ case ISD::SETO: BROpcode = V8::FBO; break;
+ case ISD::SETONE: BROpcode = V8::FBLG; break;
+ case ISD::SETUEQ: BROpcode = V8::FBUE; break;
+ }
+ break;
+ }
+
+ // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
+ // control-flow pattern. The incoming instruction knows the destination vreg
+ // to set, the condition code register to branch on, the true/false values to
+ // select between, and a branch opcode to use.
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ ilist<MachineBasicBlock>::iterator It = BB;
+ ++It;
+
+ // thisMBB:
+ // ...
+ // TrueVal = ...
+ // [f]bCC copy1MBB
+ // fallthrough --> copy0MBB
+ MachineBasicBlock *thisMBB = BB;
+ MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
+ BuildMI(BB, BROpcode, 1).addMBB(sinkMBB);
+ MachineFunction *F = BB->getParent();
+ F->getBasicBlockList().insert(It, copy0MBB);
+ F->getBasicBlockList().insert(It, sinkMBB);
+ // Update machine-CFG edges
+ BB->addSuccessor(copy0MBB);
+ BB->addSuccessor(sinkMBB);
+
+ // copy0MBB:
+ // %FalseValue = ...
+ // # fallthrough to sinkMBB
+ BB = copy0MBB;
+
+ // Update machine-CFG edges
+ BB->addSuccessor(sinkMBB);
+
+ // sinkMBB:
+ // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
+ // ...
+ BB = sinkMBB;
+ BuildMI(BB, V8::PHI, 4, MI->getOperand(0).getReg())
+ .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
+ .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
+
+ delete MI; // The pseudo instruction is gone now.
+ return BB;
+}
+