void NVPTXFloatMCExpr::PrintImpl(raw_ostream &OS) const { bool Ignored; unsigned NumHex; APFloat APF = getAPFloat(); switch (Kind) { default: llvm_unreachable("Invalid kind!"); case VK_NVPTX_SINGLE_PREC_FLOAT: OS << "0f"; NumHex = 8; APF.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &Ignored); break; case VK_NVPTX_DOUBLE_PREC_FLOAT: OS << "0d"; NumHex = 16; APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &Ignored); break; } APInt API = APF.bitcastToAPInt(); std::string HexStr(utohexstr(API.getZExtValue())); if (HexStr.length() < NumHex) OS << std::string(NumHex - HexStr.length(), '0'); OS << utohexstr(API.getZExtValue()); }
void NVPTXFloatMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { bool Ignored; unsigned NumHex; APFloat APF = getAPFloat(); switch (Kind) { default: llvm_unreachable("Invalid kind!"); case VK_NVPTX_HALF_PREC_FLOAT: // ptxas does not have a way to specify half-precision floats. // Instead we have to print and load fp16 constants as .b16 OS << "0x"; NumHex = 4; APF.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored); break; case VK_NVPTX_SINGLE_PREC_FLOAT: OS << "0f"; NumHex = 8; APF.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &Ignored); break; case VK_NVPTX_DOUBLE_PREC_FLOAT: OS << "0d"; NumHex = 16; APF.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &Ignored); break; } APInt API = APF.bitcastToAPInt(); std::string HexStr(utohexstr(API.getZExtValue())); if (HexStr.length() < NumHex) OS << std::string(NumHex - HexStr.length(), '0'); OS << utohexstr(API.getZExtValue()); }
int FunctionComparator::cmpAPFloats(const APFloat &L, const APFloat &R) const { // Floats are ordered first by semantics (i.e. float, double, half, etc.), // then by value interpreted as a bitstring (aka APInt). const fltSemantics &SL = L.getSemantics(), &SR = R.getSemantics(); if (int Res = cmpNumbers(APFloat::semanticsPrecision(SL), APFloat::semanticsPrecision(SR))) return Res; if (int Res = cmpNumbers(APFloat::semanticsMaxExponent(SL), APFloat::semanticsMaxExponent(SR))) return Res; if (int Res = cmpNumbers(APFloat::semanticsMinExponent(SL), APFloat::semanticsMinExponent(SR))) return Res; if (int Res = cmpNumbers(APFloat::semanticsSizeInBits(SL), APFloat::semanticsSizeInBits(SR))) return Res; return cmpAPInts(L.bitcastToAPInt(), R.bitcastToAPInt()); }
// Create an MCInst from a MachineInstr void llvm::HexagonLowerToMC(const MachineInstr* MI, HexagonMCInst& MCI, HexagonAsmPrinter& AP) { MCI.setOpcode(MI->getOpcode()); MCI.setDesc(MI->getDesc()); for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { const MachineOperand &MO = MI->getOperand(i); MCOperand MCO; switch (MO.getType()) { default: MI->dump(); llvm_unreachable("unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) continue; MCO = MCOperand::CreateReg(MO.getReg()); break; case MachineOperand::MO_FPImmediate: { APFloat Val = MO.getFPImm()->getValueAPF(); // FP immediates are used only when setting GPRs, so they may be dealt // with like regular immediates from this point on. MCO = MCOperand::CreateImm(*Val.bitcastToAPInt().getRawData()); break; } case MachineOperand::MO_Immediate: MCO = MCOperand::CreateImm(MO.getImm()); break; case MachineOperand::MO_MachineBasicBlock: MCO = MCOperand::CreateExpr (MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), AP.OutContext)); break; case MachineOperand::MO_GlobalAddress: MCO = GetSymbolRef(MO, AP.Mang->getSymbol(MO.getGlobal()), AP); break; case MachineOperand::MO_ExternalSymbol: MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); break; case MachineOperand::MO_JumpTableIndex: MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); break; case MachineOperand::MO_ConstantPoolIndex: MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); break; case MachineOperand::MO_BlockAddress: MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP); break; } MCI.addOperand(MCO); } }
void MBlazeMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.setOpcode(MI->getOpcode()); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); MCOperand MCOp; switch (MO.getType()) { default: llvm_unreachable("unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) continue; MCOp = MCOperand::CreateReg(MO.getReg()); break; case MachineOperand::MO_Immediate: MCOp = MCOperand::CreateImm(MO.getImm()); break; case MachineOperand::MO_MachineBasicBlock: MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( MO.getMBB()->getSymbol(), Ctx)); break; case MachineOperand::MO_GlobalAddress: MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); break; case MachineOperand::MO_ExternalSymbol: MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); break; case MachineOperand::MO_JumpTableIndex: MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); break; case MachineOperand::MO_ConstantPoolIndex: MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); break; case MachineOperand::MO_BlockAddress: MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO)); break; case MachineOperand::MO_FPImmediate: { bool ignored; APFloat FVal = MO.getFPImm()->getValueAPF(); FVal.convert(APFloat::IEEEsingle, APFloat::rmTowardZero, &ignored); APInt IVal = FVal.bitcastToAPInt(); uint64_t Val = *IVal.getRawData(); MCOp = MCOperand::CreateImm(Val); break; } case MachineOperand::MO_RegisterMask: continue; } OutMI.addOperand(MCOp); } }
/// addConstantFPValue - Add constant value entry in variable DIE. bool CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { assert (MO.isFPImm() && "Invalid machine operand!"); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); APFloat FPImm = MO.getFPImm()->getValueAPF(); // Get the raw data form of the floating point. const APInt FltVal = FPImm.bitcastToAPInt(); const char *FltPtr = (const char*)FltVal.getRawData(); int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. bool LittleEndian = Asm->getTargetData().isLittleEndian(); int Incr = (LittleEndian ? 1 : -1); int Start = (LittleEndian ? 0 : NumBytes - 1); int Stop = (LittleEndian ? NumBytes : -1); // Output the constant to DWARF one byte at a time. for (; Start != Stop; Start += Incr) addUInt(Block, 0, dwarf::DW_FORM_data1, (unsigned char)0xFF & FltPtr[Start]); addBlock(Die, dwarf::DW_AT_const_value, 0, Block); return true; }
static std::string toString(const APFloat &FP) { // Print NaNs with custom payloads specially. if (FP.isNaN() && !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) && !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) { APInt AI = FP.bitcastToAPInt(); return std::string(AI.isNegative() ? "-" : "") + "nan:0x" + utohexstr(AI.getZExtValue() & (AI.getBitWidth() == 32 ? INT64_C(0x007fffff) : INT64_C(0x000fffffffffffff)), /*LowerCase=*/true); } // Use C99's hexadecimal floating-point representation. static const size_t BufBytes = 128; char buf[BufBytes]; auto Written = FP.convertToHexString( buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven); (void)Written; assert(Written != 0); assert(Written < BufBytes); return buf; }
/// This function converts a Constant* into a GenericValue. The interesting /// part is if C is a ConstantExpr. /// @brief Get a GenericValue for a Constant* GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // If its undefined, return the garbage. if (isa<UndefValue>(C)) return GenericValue(); // If the value is a ConstantExpr if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { Constant *Op0 = CE->getOperand(0); switch (CE->getOpcode()) { case Instruction::GetElementPtr: { // Compute the index GenericValue Result = getConstantValue(Op0); SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end()); uint64_t Offset = TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size()); char* tmp = (char*) Result.PointerVal; Result = PTOGV(tmp + Offset); return Result; } case Instruction::Trunc: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.trunc(BitWidth); return GV; } case Instruction::ZExt: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.zext(BitWidth); return GV; } case Instruction::SExt: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.sext(BitWidth); return GV; } case Instruction::FPTrunc: { // FIXME long double GenericValue GV = getConstantValue(Op0); GV.FloatVal = float(GV.DoubleVal); return GV; } case Instruction::FPExt:{ // FIXME long double GenericValue GV = getConstantValue(Op0); GV.DoubleVal = double(GV.FloatVal); return GV; } case Instruction::UIToFP: { GenericValue GV = getConstantValue(Op0); if (CE->getType() == Type::FloatTy) GV.FloatVal = float(GV.IntVal.roundToDouble()); else if (CE->getType() == Type::DoubleTy) GV.DoubleVal = GV.IntVal.roundToDouble(); else if (CE->getType() == Type::X86_FP80Ty) { const uint64_t zero[] = {0, 0}; APFloat apf = APFloat(APInt(80, 2, zero)); (void)apf.convertFromAPInt(GV.IntVal, false, APFloat::rmNearestTiesToEven); GV.IntVal = apf.bitcastToAPInt(); } return GV; } case Instruction::SIToFP: { GenericValue GV = getConstantValue(Op0); if (CE->getType() == Type::FloatTy) GV.FloatVal = float(GV.IntVal.signedRoundToDouble()); else if (CE->getType() == Type::DoubleTy) GV.DoubleVal = GV.IntVal.signedRoundToDouble(); else if (CE->getType() == Type::X86_FP80Ty) { const uint64_t zero[] = { 0, 0}; APFloat apf = APFloat(APInt(80, 2, zero)); (void)apf.convertFromAPInt(GV.IntVal, true, APFloat::rmNearestTiesToEven); GV.IntVal = apf.bitcastToAPInt(); } return GV; } case Instruction::FPToUI: // double->APInt conversion handles sign case Instruction::FPToSI: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); if (Op0->getType() == Type::FloatTy) GV.IntVal = APIntOps::RoundFloatToAPInt(GV.FloatVal, BitWidth); else if (Op0->getType() == Type::DoubleTy) GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth); else if (Op0->getType() == Type::X86_FP80Ty) { APFloat apf = APFloat(GV.IntVal); uint64_t v; bool ignored; (void)apf.convertToInteger(&v, BitWidth, CE->getOpcode()==Instruction::FPToSI, APFloat::rmTowardZero, &ignored); GV.IntVal = v; // endian? } return GV; } case Instruction::PtrToInt: { GenericValue GV = getConstantValue(Op0); uint32_t PtrWidth = TD->getPointerSizeInBits(); GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); return GV; } case Instruction::IntToPtr: { GenericValue GV = getConstantValue(Op0); uint32_t PtrWidth = TD->getPointerSizeInBits(); if (PtrWidth != GV.IntVal.getBitWidth()) GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); return GV; } case Instruction::BitCast: { GenericValue GV = getConstantValue(Op0); const Type* DestTy = CE->getType(); switch (Op0->getType()->getTypeID()) { default: assert(0 && "Invalid bitcast operand"); case Type::IntegerTyID: assert(DestTy->isFloatingPoint() && "invalid bitcast"); if (DestTy == Type::FloatTy) GV.FloatVal = GV.IntVal.bitsToFloat(); else if (DestTy == Type::DoubleTy) GV.DoubleVal = GV.IntVal.bitsToDouble(); break; case Type::FloatTyID: assert(DestTy == Type::Int32Ty && "Invalid bitcast"); GV.IntVal.floatToBits(GV.FloatVal); break; case Type::DoubleTyID: assert(DestTy == Type::Int64Ty && "Invalid bitcast"); GV.IntVal.doubleToBits(GV.DoubleVal); break; case Type::PointerTyID: assert(isa<PointerType>(DestTy) && "Invalid bitcast"); break; // getConstantValue(Op0) above already converted it } return GV; } case Instruction::Add: case Instruction::Sub: case Instruction::Mul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::URem: case Instruction::SRem: case Instruction::And: case Instruction::Or: case Instruction::Xor: { GenericValue LHS = getConstantValue(Op0); GenericValue RHS = getConstantValue(CE->getOperand(1)); GenericValue GV; switch (CE->getOperand(0)->getType()->getTypeID()) { default: assert(0 && "Bad add type!"); abort(); case Type::IntegerTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid integer opcode"); case Instruction::Add: GV.IntVal = LHS.IntVal + RHS.IntVal; break; case Instruction::Sub: GV.IntVal = LHS.IntVal - RHS.IntVal; break; case Instruction::Mul: GV.IntVal = LHS.IntVal * RHS.IntVal; break; case Instruction::UDiv:GV.IntVal = LHS.IntVal.udiv(RHS.IntVal); break; case Instruction::SDiv:GV.IntVal = LHS.IntVal.sdiv(RHS.IntVal); break; case Instruction::URem:GV.IntVal = LHS.IntVal.urem(RHS.IntVal); break; case Instruction::SRem:GV.IntVal = LHS.IntVal.srem(RHS.IntVal); break; case Instruction::And: GV.IntVal = LHS.IntVal & RHS.IntVal; break; case Instruction::Or: GV.IntVal = LHS.IntVal | RHS.IntVal; break; case Instruction::Xor: GV.IntVal = LHS.IntVal ^ RHS.IntVal; break; } break; case Type::FloatTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid float opcode"); abort(); case Instruction::Add: GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break; case Instruction::Sub: GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break; case Instruction::Mul: GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break; case Instruction::FDiv: GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break; case Instruction::FRem: GV.FloatVal = ::fmodf(LHS.FloatVal,RHS.FloatVal); break; } break; case Type::DoubleTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid double opcode"); abort(); case Instruction::Add: GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break; case Instruction::Sub: GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break; case Instruction::Mul: GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break; case Instruction::FDiv: GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break; case Instruction::FRem: GV.DoubleVal = ::fmod(LHS.DoubleVal,RHS.DoubleVal); break; } break; case Type::X86_FP80TyID: case Type::PPC_FP128TyID: case Type::FP128TyID: { APFloat apfLHS = APFloat(LHS.IntVal); switch (CE->getOpcode()) { default: assert(0 && "Invalid long double opcode"); abort(); case Instruction::Add: apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::Sub: apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::Mul: apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::FDiv: apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::FRem: apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; } } break; } return GV; } default: break; } cerr << "ConstantExpr not handled: " << *CE << "\n"; abort(); } GenericValue Result; switch (C->getType()->getTypeID()) { case Type::FloatTyID: Result.FloatVal = cast<ConstantFP>(C)->getValueAPF().convertToFloat(); break; case Type::DoubleTyID: Result.DoubleVal = cast<ConstantFP>(C)->getValueAPF().convertToDouble(); break; case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: Result.IntVal = cast <ConstantFP>(C)->getValueAPF().bitcastToAPInt(); break; case Type::IntegerTyID: Result.IntVal = cast<ConstantInt>(C)->getValue(); break; case Type::PointerTyID: if (isa<ConstantPointerNull>(C)) Result.PointerVal = 0; else if (const Function *F = dyn_cast<Function>(C)) Result = PTOGV(getPointerToFunctionOrStub(const_cast<Function*>(F))); else if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C)) Result = PTOGV(getOrEmitGlobalVariable(const_cast<GlobalVariable*>(GV))); else assert(0 && "Unknown constant pointer type!"); break; default: cerr << "ERROR: Constant unimplemented for type: " << *C->getType() << "\n"; abort(); } return Result; }
SDNode *AMDGPUDAGToDAGISel::Select(SDNode *N) { const R600InstrInfo *TII = static_cast<const R600InstrInfo*>(TM.getInstrInfo()); unsigned int Opc = N->getOpcode(); if (N->isMachineOpcode()) { return NULL; // Already selected. } switch (Opc) { default: break; case AMDGPUISD::CONST_ADDRESS: { for (SDNode::use_iterator I = N->use_begin(), Next = llvm::next(I); I != SDNode::use_end(); I = Next) { Next = llvm::next(I); if (!I->isMachineOpcode()) { continue; } unsigned Opcode = I->getMachineOpcode(); bool HasDst = TII->getOperandIdx(Opcode, AMDGPU::OpName::dst) > -1; int SrcIdx = I.getOperandNo(); int SelIdx; // Unlike MachineInstrs, SDNodes do not have results in their operand // list, so we need to increment the SrcIdx, since // R600InstrInfo::getOperandIdx is based on the MachineInstr indices. if (HasDst) { SrcIdx++; } SelIdx = TII->getSelIdx(I->getMachineOpcode(), SrcIdx); if (SelIdx < 0) { continue; } SDValue CstOffset; if (N->getValueType(0).isVector() || !SelectGlobalValueConstantOffset(N->getOperand(0), CstOffset)) continue; // Gather constants values int SrcIndices[] = { TII->getOperandIdx(Opcode, AMDGPU::OpName::src0), TII->getOperandIdx(Opcode, AMDGPU::OpName::src1), TII->getOperandIdx(Opcode, AMDGPU::OpName::src2), TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_X), TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_Y), TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_Z), TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_W), TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_X), TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_Y), TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_Z), TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_W) }; std::vector<unsigned> Consts; for (unsigned i = 0; i < sizeof(SrcIndices) / sizeof(int); i++) { int OtherSrcIdx = SrcIndices[i]; int OtherSelIdx = TII->getSelIdx(Opcode, OtherSrcIdx); if (OtherSrcIdx < 0 || OtherSelIdx < 0) { continue; } if (HasDst) { OtherSrcIdx--; OtherSelIdx--; } if (RegisterSDNode *Reg = dyn_cast<RegisterSDNode>(I->getOperand(OtherSrcIdx))) { if (Reg->getReg() == AMDGPU::ALU_CONST) { ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(I->getOperand(OtherSelIdx)); Consts.push_back(Cst->getZExtValue()); } } } ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(CstOffset); Consts.push_back(Cst->getZExtValue()); if (!TII->fitsConstReadLimitations(Consts)) continue; // Convert back to SDNode indices if (HasDst) { SrcIdx--; SelIdx--; } std::vector<SDValue> Ops; for (int i = 0, e = I->getNumOperands(); i != e; ++i) { if (i == SrcIdx) { Ops.push_back(CurDAG->getRegister(AMDGPU::ALU_CONST, MVT::f32)); } else if (i == SelIdx) { Ops.push_back(CstOffset); } else { Ops.push_back(I->getOperand(i)); } } CurDAG->UpdateNodeOperands(*I, Ops.data(), Ops.size()); } break; } case ISD::BUILD_VECTOR: { const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) { break; } unsigned RegClassID; switch(N->getValueType(0).getVectorNumElements()) { case 2: RegClassID = AMDGPU::R600_Reg64RegClassID; break; case 4: RegClassID = AMDGPU::R600_Reg128RegClassID; break; default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR"); } // BUILD_VECTOR is usually lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG // that adds a 128 bits reg copy when going through TwoAddressInstructions // pass. We want to avoid 128 bits copies as much as possible because they // can't be bundled by our scheduler. SDValue RegSeqArgs[9] = { CurDAG->getTargetConstant(RegClassID, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub0, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub1, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub2, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub3, MVT::i32) }; bool IsRegSeq = true; for (unsigned i = 0; i < N->getNumOperands(); i++) { if (dyn_cast<RegisterSDNode>(N->getOperand(i))) { IsRegSeq = false; break; } RegSeqArgs[2 * i + 1] = N->getOperand(i); } if (!IsRegSeq) break; return CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(), RegSeqArgs, 2 * N->getNumOperands() + 1); } case ISD::BUILD_PAIR: { SDValue RC, SubReg0, SubReg1; const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) { break; } if (N->getValueType(0) == MVT::i128) { RC = CurDAG->getTargetConstant(AMDGPU::SReg_128RegClassID, MVT::i32); SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, MVT::i32); SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, MVT::i32); } else if (N->getValueType(0) == MVT::i64) { RC = CurDAG->getTargetConstant(AMDGPU::VSrc_64RegClassID, MVT::i32); SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, MVT::i32); SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, MVT::i32); } else { llvm_unreachable("Unhandled value type for BUILD_PAIR"); } const SDValue Ops[] = { RC, N->getOperand(0), SubReg0, N->getOperand(1), SubReg1 }; return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SDLoc(N), N->getValueType(0), Ops); } case ISD::ConstantFP: case ISD::Constant: { const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); // XXX: Custom immediate lowering not implemented yet. Instead we use // pseudo instructions defined in SIInstructions.td if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) { break; } uint64_t ImmValue = 0; unsigned ImmReg = AMDGPU::ALU_LITERAL_X; if (N->getOpcode() == ISD::ConstantFP) { // XXX: 64-bit Immediates not supported yet assert(N->getValueType(0) != MVT::f64); ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N); APFloat Value = C->getValueAPF(); float FloatValue = Value.convertToFloat(); if (FloatValue == 0.0) { ImmReg = AMDGPU::ZERO; } else if (FloatValue == 0.5) { ImmReg = AMDGPU::HALF; } else if (FloatValue == 1.0) { ImmReg = AMDGPU::ONE; } else { ImmValue = Value.bitcastToAPInt().getZExtValue(); } } else { // XXX: 64-bit Immediates not supported yet assert(N->getValueType(0) != MVT::i64); ConstantSDNode *C = dyn_cast<ConstantSDNode>(N); if (C->getZExtValue() == 0) { ImmReg = AMDGPU::ZERO; } else if (C->getZExtValue() == 1) { ImmReg = AMDGPU::ONE_INT; } else { ImmValue = C->getZExtValue(); } } for (SDNode::use_iterator Use = N->use_begin(), Next = llvm::next(Use); Use != SDNode::use_end(); Use = Next) { Next = llvm::next(Use); std::vector<SDValue> Ops; for (unsigned i = 0; i < Use->getNumOperands(); ++i) { Ops.push_back(Use->getOperand(i)); } if (!Use->isMachineOpcode()) { if (ImmReg == AMDGPU::ALU_LITERAL_X) { // We can only use literal constants (e.g. AMDGPU::ZERO, // AMDGPU::ONE, etc) in machine opcodes. continue; } } else { if (!TII->isALUInstr(Use->getMachineOpcode()) || (TII->get(Use->getMachineOpcode()).TSFlags & R600_InstFlag::VECTOR)) { continue; } int ImmIdx = TII->getOperandIdx(Use->getMachineOpcode(), AMDGPU::OpName::literal); if (ImmIdx == -1) { continue; } if (TII->getOperandIdx(Use->getMachineOpcode(), AMDGPU::OpName::dst) != -1) { // subtract one from ImmIdx, because the DST operand is usually index // 0 for MachineInstrs, but we have no DST in the Ops vector. ImmIdx--; } // Check that we aren't already using an immediate. // XXX: It's possible for an instruction to have more than one // immediate operand, but this is not supported yet. if (ImmReg == AMDGPU::ALU_LITERAL_X) { ConstantSDNode *C = dyn_cast<ConstantSDNode>(Use->getOperand(ImmIdx)); assert(C); if (C->getZExtValue() != 0) { // This instruction is already using an immediate. continue; } // Set the immediate value Ops[ImmIdx] = CurDAG->getTargetConstant(ImmValue, MVT::i32); } } // Set the immediate register Ops[Use.getOperandNo()] = CurDAG->getRegister(ImmReg, MVT::i32); CurDAG->UpdateNodeOperands(*Use, Ops.data(), Use->getNumOperands()); } break; } } SDNode *Result = SelectCode(N); // Fold operands of selected node const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) { const R600InstrInfo *TII = static_cast<const R600InstrInfo*>(TM.getInstrInfo()); if (Result && Result->isMachineOpcode() && Result->getMachineOpcode() == AMDGPU::DOT_4) { bool IsModified = false; do { std::vector<SDValue> Ops; for(SDNode::op_iterator I = Result->op_begin(), E = Result->op_end(); I != E; ++I) Ops.push_back(*I); IsModified = FoldDotOperands(Result->getMachineOpcode(), TII, Ops); if (IsModified) { Result = CurDAG->UpdateNodeOperands(Result, Ops.data(), Ops.size()); } } while (IsModified); } if (Result && Result->isMachineOpcode() && !(TII->get(Result->getMachineOpcode()).TSFlags & R600_InstFlag::VECTOR) && TII->hasInstrModifiers(Result->getMachineOpcode())) { // Fold FNEG/FABS // TODO: Isel can generate multiple MachineInst, we need to recursively // parse Result bool IsModified = false; do { std::vector<SDValue> Ops; for(SDNode::op_iterator I = Result->op_begin(), E = Result->op_end(); I != E; ++I) Ops.push_back(*I); IsModified = FoldOperands(Result->getMachineOpcode(), TII, Ops); if (IsModified) { Result = CurDAG->UpdateNodeOperands(Result, Ops.data(), Ops.size()); } } while (IsModified); // If node has a single use which is CLAMP_R600, folds it if (Result->hasOneUse() && Result->isMachineOpcode()) { SDNode *PotentialClamp = *Result->use_begin(); if (PotentialClamp->isMachineOpcode() && PotentialClamp->getMachineOpcode() == AMDGPU::CLAMP_R600) { unsigned ClampIdx = TII->getOperandIdx(Result->getMachineOpcode(), AMDGPU::OpName::clamp); std::vector<SDValue> Ops; unsigned NumOp = Result->getNumOperands(); for (unsigned i = 0; i < NumOp; ++i) { Ops.push_back(Result->getOperand(i)); } Ops[ClampIdx - 1] = CurDAG->getTargetConstant(1, MVT::i32); Result = CurDAG->SelectNodeTo(PotentialClamp, Result->getMachineOpcode(), PotentialClamp->getVTList(), Ops.data(), NumOp); } } } } return Result; }
SDNode *AMDGPUDAGToDAGISel::Select(SDNode *N) { unsigned int Opc = N->getOpcode(); if (N->isMachineOpcode()) { return NULL; // Already selected. } switch (Opc) { default: break; case ISD::BUILD_VECTOR: { const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); if (ST.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) { break; } // BUILD_VECTOR is usually lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG // that adds a 128 bits reg copy when going through TwoAddressInstructions // pass. We want to avoid 128 bits copies as much as possible because they // can't be bundled by our scheduler. SDValue RegSeqArgs[9] = { CurDAG->getTargetConstant(AMDGPU::R600_Reg128RegClassID, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub0, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub1, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub2, MVT::i32), SDValue(), CurDAG->getTargetConstant(AMDGPU::sub3, MVT::i32) }; bool IsRegSeq = true; for (unsigned i = 0; i < N->getNumOperands(); i++) { if (dyn_cast<RegisterSDNode>(N->getOperand(i))) { IsRegSeq = false; break; } RegSeqArgs[2 * i + 1] = N->getOperand(i); } if (!IsRegSeq) break; return CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(), RegSeqArgs, 2 * N->getNumOperands() + 1); } case ISD::ConstantFP: case ISD::Constant: { const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); // XXX: Custom immediate lowering not implemented yet. Instead we use // pseudo instructions defined in SIInstructions.td if (ST.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) { break; } const R600InstrInfo *TII = static_cast<const R600InstrInfo*>(TM.getInstrInfo()); uint64_t ImmValue = 0; unsigned ImmReg = AMDGPU::ALU_LITERAL_X; if (N->getOpcode() == ISD::ConstantFP) { // XXX: 64-bit Immediates not supported yet assert(N->getValueType(0) != MVT::f64); ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N); APFloat Value = C->getValueAPF(); float FloatValue = Value.convertToFloat(); if (FloatValue == 0.0) { ImmReg = AMDGPU::ZERO; } else if (FloatValue == 0.5) { ImmReg = AMDGPU::HALF; } else if (FloatValue == 1.0) { ImmReg = AMDGPU::ONE; } else { ImmValue = Value.bitcastToAPInt().getZExtValue(); } } else { // XXX: 64-bit Immediates not supported yet assert(N->getValueType(0) != MVT::i64); ConstantSDNode *C = dyn_cast<ConstantSDNode>(N); if (C->getZExtValue() == 0) { ImmReg = AMDGPU::ZERO; } else if (C->getZExtValue() == 1) { ImmReg = AMDGPU::ONE_INT; } else { ImmValue = C->getZExtValue(); } } for (SDNode::use_iterator Use = N->use_begin(), Next = llvm::next(Use); Use != SDNode::use_end(); Use = Next) { Next = llvm::next(Use); std::vector<SDValue> Ops; for (unsigned i = 0; i < Use->getNumOperands(); ++i) { Ops.push_back(Use->getOperand(i)); } if (!Use->isMachineOpcode()) { if (ImmReg == AMDGPU::ALU_LITERAL_X) { // We can only use literal constants (e.g. AMDGPU::ZERO, // AMDGPU::ONE, etc) in machine opcodes. continue; } } else { if (!TII->isALUInstr(Use->getMachineOpcode()) || (TII->get(Use->getMachineOpcode()).TSFlags & R600_InstFlag::VECTOR)) { continue; } int ImmIdx = TII->getOperandIdx(Use->getMachineOpcode(), R600Operands::IMM); assert(ImmIdx != -1); // subtract one from ImmIdx, because the DST operand is usually index // 0 for MachineInstrs, but we have no DST in the Ops vector. ImmIdx--; // Check that we aren't already using an immediate. // XXX: It's possible for an instruction to have more than one // immediate operand, but this is not supported yet. if (ImmReg == AMDGPU::ALU_LITERAL_X) { ConstantSDNode *C = dyn_cast<ConstantSDNode>(Use->getOperand(ImmIdx)); assert(C); if (C->getZExtValue() != 0) { // This instruction is already using an immediate. continue; } // Set the immediate value Ops[ImmIdx] = CurDAG->getTargetConstant(ImmValue, MVT::i32); } } // Set the immediate register Ops[Use.getOperandNo()] = CurDAG->getRegister(ImmReg, MVT::i32); CurDAG->UpdateNodeOperands(*Use, Ops.data(), Use->getNumOperands()); } break; } } SDNode *Result = SelectCode(N); // Fold operands of selected node const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(); if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) { const R600InstrInfo *TII = static_cast<const R600InstrInfo*>(TM.getInstrInfo()); if (Result && Result->isMachineOpcode() && !(TII->get(Result->getMachineOpcode()).TSFlags & R600_InstFlag::VECTOR) && TII->isALUInstr(Result->getMachineOpcode())) { // Fold FNEG/FABS/CONST_ADDRESS // TODO: Isel can generate multiple MachineInst, we need to recursively // parse Result bool IsModified = false; do { std::vector<SDValue> Ops; for(SDNode::op_iterator I = Result->op_begin(), E = Result->op_end(); I != E; ++I) Ops.push_back(*I); IsModified = FoldOperands(Result->getMachineOpcode(), TII, Ops); if (IsModified) { Result = CurDAG->UpdateNodeOperands(Result, Ops.data(), Ops.size()); } } while (IsModified); // If node has a single use which is CLAMP_R600, folds it if (Result->hasOneUse() && Result->isMachineOpcode()) { SDNode *PotentialClamp = *Result->use_begin(); if (PotentialClamp->isMachineOpcode() && PotentialClamp->getMachineOpcode() == AMDGPU::CLAMP_R600) { unsigned ClampIdx = TII->getOperandIdx(Result->getMachineOpcode(), R600Operands::CLAMP); std::vector<SDValue> Ops; unsigned NumOp = Result->getNumOperands(); for (unsigned i = 0; i < NumOp; ++i) { Ops.push_back(Result->getOperand(i)); } Ops[ClampIdx - 1] = CurDAG->getTargetConstant(1, MVT::i32); Result = CurDAG->SelectNodeTo(PotentialClamp, Result->getMachineOpcode(), PotentialClamp->getVTList(), Ops.data(), NumOp); } } } } return Result; }
// Create an MCInst from a MachineInstr void llvm::HexagonLowerToMC(MachineInstr const* MI, MCInst& MCB, HexagonAsmPrinter& AP) { if(MI->getOpcode() == Hexagon::ENDLOOP0){ HexagonMCInstrInfo::setInnerLoop(MCB); return; } if(MI->getOpcode() == Hexagon::ENDLOOP1){ HexagonMCInstrInfo::setOuterLoop(MCB); return; } MCInst* MCI = new (AP.OutContext) MCInst; MCI->setOpcode(MI->getOpcode()); assert(MCI->getOpcode() == static_cast<unsigned>(MI->getOpcode()) && "MCI opcode should have been set on construction"); for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { const MachineOperand &MO = MI->getOperand(i); MCOperand MCO; switch (MO.getType()) { default: MI->dump(); llvm_unreachable("unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) continue; MCO = MCOperand::createReg(MO.getReg()); break; case MachineOperand::MO_FPImmediate: { APFloat Val = MO.getFPImm()->getValueAPF(); // FP immediates are used only when setting GPRs, so they may be dealt // with like regular immediates from this point on. MCO = MCOperand::createImm(*Val.bitcastToAPInt().getRawData()); break; } case MachineOperand::MO_Immediate: MCO = MCOperand::createImm(MO.getImm()); break; case MachineOperand::MO_MachineBasicBlock: MCO = MCOperand::createExpr (MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); break; case MachineOperand::MO_GlobalAddress: MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP); break; case MachineOperand::MO_ExternalSymbol: MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); break; case MachineOperand::MO_JumpTableIndex: MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); break; case MachineOperand::MO_ConstantPoolIndex: MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); break; case MachineOperand::MO_BlockAddress: MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP); break; } MCI->addOperand(MCO); } MCB.addOperand(MCOperand::createInst(MCI)); }