bool SystemZDAGToDAGISel::SelectAddrRI12(SDNode *Op, SDValue& Addr, SDValue &Base, SDValue &Disp, bool is12BitOnly) { SystemZRRIAddressMode AM20(/*isRI*/true), AM12(/*isRI*/true); bool Done = false; if (!Addr.hasOneUse()) { unsigned Opcode = Addr.getOpcode(); if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) { // If we are able to fold N into addressing mode, then we'll allow it even // if N has multiple uses. In general, addressing computation is used as // addresses by all of its uses. But watch out for CopyToReg uses, that // means the address computation is liveout. It will be computed by a LA // so we want to avoid computing the address twice. for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), UE = Addr.getNode()->use_end(); UI != UE; ++UI) { if (UI->getOpcode() == ISD::CopyToReg) { MatchAddressBase(Addr, AM12); Done = true; break; } } } } if (!Done && MatchAddress(Addr, AM12, /* is12Bit */ true)) return false; // Check, whether we can match stuff using 20-bit displacements if (!Done && !is12BitOnly && !MatchAddress(Addr, AM20, /* is12Bit */ false)) if (AM12.Disp == 0 && AM20.Disp != 0) return false; DEBUG(errs() << "MatchAddress (final): "; AM12.dump()); EVT VT = Addr.getValueType(); if (AM12.BaseType == SystemZRRIAddressMode::RegBase) { if (!AM12.Base.Reg.getNode()) AM12.Base.Reg = CurDAG->getRegister(0, VT); } assert(AM12.IndexReg.getNode() == 0 && "Invalid reg-imm address mode!"); getAddressOperandsRI(AM12, Base, Disp); return true; }
/// Returns true if the address can be represented by a base register plus /// index register plus a signed 20-bit displacement [base + idx + imm]. bool SystemZDAGToDAGISel::SelectAddrRRI20(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Disp, SDValue &Index) { SystemZRRIAddressMode AM; bool Done = false; if (!Addr.hasOneUse()) { unsigned Opcode = Addr.getOpcode(); if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) { // If we are able to fold N into addressing mode, then we'll allow it even // if N has multiple uses. In general, addressing computation is used as // addresses by all of its uses. But watch out for CopyToReg uses, that // means the address computation is liveout. It will be computed by a LA // so we want to avoid computing the address twice. for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), UE = Addr.getNode()->use_end(); UI != UE; ++UI) { if (UI->getOpcode() == ISD::CopyToReg) { MatchAddressBase(Addr, AM); Done = true; break; } } } } if (!Done && MatchAddress(Addr, AM, /* is12Bit */ false)) return false; DEBUG(errs() << "MatchAddress (final): "; AM.dump()); EVT VT = Addr.getValueType(); if (AM.BaseType == SystemZRRIAddressMode::RegBase) { if (!AM.Base.Reg.getNode()) AM.Base.Reg = CurDAG->getRegister(0, VT); } if (!AM.IndexReg.getNode()) AM.IndexReg = CurDAG->getRegister(0, VT); getAddressOperands(AM, Base, Disp, Index); return true; }
// Note: branch conditions, by definition, only have a chain user. // This is why it should not be saved in a map for recall. Value* ARMIREmitter::visitBRCOND(const SDNode *N) { // Get the address const ConstantSDNode *DestNode = dyn_cast<ConstantSDNode>(N->getOperand(0)); if (!DestNode) { printError("visitBRCOND: Not a constant integer for branch!"); return NULL; } uint64_t DestInt = DestNode->getSExtValue(); uint64_t PC = Dec->getDisassembler()->getDebugOffset(N->getDebugLoc()); // Note: pipeline is 8 bytes uint64_t Tgt = PC + 8 + DestInt; Function *F = IRB->GetInsertBlock()->getParent(); BasicBlock *CurBB = IRB->GetInsertBlock(); BasicBlock *BBTgt = Dec->getOrCreateBasicBlock(Tgt, F); // Parse the branch condition code const ConstantSDNode *CCNode = dyn_cast<ConstantSDNode>(N->getOperand(1)); if (!CCNode) { printError("visitBRCOND: Condition code is not a constant integer!"); return NULL; } ARMCC::CondCodes ARMcc = ARMCC::CondCodes(CCNode->getZExtValue()); // Unconditional branch if (ARMcc == ARMCC::AL) { Instruction *Br = IRB->CreateBr(BBTgt); Br->setDebugLoc(N->getDebugLoc()); return Br; } // If not a conditional branch, find the successor block and look at CC BasicBlock *NextBB = NULL; Function::iterator BI = F->begin(), BE= F->end(); while (BI != BE && BI->getName() != CurBB->getName()) ++BI; ++BI; if (BI == BE) { // NOTE: This should never happen... NextBB = Dec->getOrCreateBasicBlock("end", F); } else { NextBB = &(*BI); } SDNode *CPSR = N->getOperand(2)->getOperand(1).getNode(); SDNode *CMPNode = NULL; for (SDNode::use_iterator I = CPSR->use_begin(), E = CPSR->use_end(); I != E; ++I) { if (I->getOpcode() == ISD::CopyToReg) { CMPNode = I->getOperand(2).getNode(); } } if (CMPNode == NULL) { errs() << "ARMIREmitter ERROR: Could not find CMP SDNode for ARMBRCond!\n"; return NULL; } Value *Cmp = NULL; Value *LHS = visit(CMPNode->getOperand(0).getNode()); Value *RHS = visit(CMPNode->getOperand(1).getNode()); // See ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC); in ARMISelLowering.cpp // TODO: Add support for conditions that handle floating point switch(ARMcc) { default: printError("Unknown condition code"); return NULL; case ARMCC::EQ: Cmp = IRB->CreateICmpEQ(LHS, RHS); break; case ARMCC::NE: Cmp = IRB->CreateICmpNE(LHS, RHS); break; case ARMCC::HS: // HS - unsigned higher or same (or carry set) Cmp = IRB->CreateICmpUGE(LHS, RHS); break; case ARMCC::LO: // LO - unsigned lower (or carry clear) Cmp = IRB->CreateICmpULT(LHS, RHS); break; case ARMCC::MI: // MI - minus (negative) printError("Condition code MI is not handled at this time!"); return NULL; // break; case ARMCC::PL: // PL - plus (positive or zero) printError("Condition code PL is not handled at this time!"); return NULL; // break; case ARMCC::VS: // VS - V Set (signed overflow) printError("Condition code VS is not handled at this time!"); return NULL; // break; case ARMCC::VC: // VC - V clear (no signed overflow) printError("Condition code VC is not handled at this time!"); return NULL; // break; case ARMCC::HI: // HI - unsigned higher Cmp = IRB->CreateICmpUGT(LHS, RHS); break; case ARMCC::LS: // LS - unsigned lower or same Cmp = IRB->CreateICmpULE(LHS, RHS); break; case ARMCC::GE: // GE - signed greater or equal Cmp = IRB->CreateICmpSGE(LHS, RHS); break; case ARMCC::LT: // LT - signed less than Cmp = IRB->CreateICmpSLT(LHS, RHS); break; case ARMCC::GT: // GT - signed greater than Cmp = IRB->CreateICmpSGT(LHS, RHS); break; case ARMCC::LE: // LE - signed less than or equal Cmp = IRB->CreateICmpSLE(LHS, RHS); break; } (dyn_cast<Instruction>(Cmp))->setDebugLoc(N->getOperand(2)->getDebugLoc()); // Conditional branch Instruction *Br = IRB->CreateCondBr(Cmp, BBTgt, NextBB); Br->setDebugLoc(N->getDebugLoc()); return Br; }