bool AMDGPULegalizerInfo::legalizeAddrSpaceCast( MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder) const { MachineFunction &MF = MIRBuilder.getMF(); MIRBuilder.setInstr(MI); unsigned Dst = MI.getOperand(0).getReg(); unsigned Src = MI.getOperand(1).getReg(); LLT DstTy = MRI.getType(Dst); LLT SrcTy = MRI.getType(Src); unsigned DestAS = DstTy.getAddressSpace(); unsigned SrcAS = SrcTy.getAddressSpace(); // TODO: Avoid reloading from the queue ptr for each cast, or at least each // vector element. assert(!DstTy.isVector()); const AMDGPUTargetMachine &TM = static_cast<const AMDGPUTargetMachine &>(MF.getTarget()); const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); if (ST.getTargetLowering()->isNoopAddrSpaceCast(SrcAS, DestAS)) { MI.setDesc(MIRBuilder.getTII().get(TargetOpcode::G_BITCAST)); return true; } if (SrcAS == AMDGPUAS::FLAT_ADDRESS) { assert(DestAS == AMDGPUAS::LOCAL_ADDRESS || DestAS == AMDGPUAS::PRIVATE_ADDRESS); unsigned NullVal = TM.getNullPointerValue(DestAS); auto SegmentNull = MIRBuilder.buildConstant(DstTy, NullVal); auto FlatNull = MIRBuilder.buildConstant(SrcTy, 0); unsigned PtrLo32 = MRI.createGenericVirtualRegister(DstTy); // Extract low 32-bits of the pointer. MIRBuilder.buildExtract(PtrLo32, Src, 0); unsigned CmpRes = MRI.createGenericVirtualRegister(LLT::scalar(1)); MIRBuilder.buildICmp(CmpInst::ICMP_NE, CmpRes, Src, FlatNull.getReg(0)); MIRBuilder.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0)); MI.eraseFromParent(); return true; } assert(SrcAS == AMDGPUAS::LOCAL_ADDRESS || SrcAS == AMDGPUAS::PRIVATE_ADDRESS); auto SegmentNull = MIRBuilder.buildConstant(SrcTy, TM.getNullPointerValue(SrcAS)); auto FlatNull = MIRBuilder.buildConstant(DstTy, TM.getNullPointerValue(DestAS)); unsigned ApertureReg = getSegmentAperture(DestAS, MRI, MIRBuilder); unsigned CmpRes = MRI.createGenericVirtualRegister(LLT::scalar(1)); MIRBuilder.buildICmp(CmpInst::ICMP_NE, CmpRes, Src, SegmentNull.getReg(0)); unsigned BuildPtr = MRI.createGenericVirtualRegister(DstTy); // Coerce the type of the low half of the result so we can use merge_values. unsigned SrcAsInt = MRI.createGenericVirtualRegister(LLT::scalar(32)); MIRBuilder.buildInstr(TargetOpcode::G_PTRTOINT) .addDef(SrcAsInt) .addUse(Src); // TODO: Should we allow mismatched types but matching sizes in merges to // avoid the ptrtoint? MIRBuilder.buildMerge(BuildPtr, {SrcAsInt, ApertureReg}); MIRBuilder.buildSelect(Dst, CmpRes, BuildPtr, FlatNull.getReg(0)); MI.eraseFromParent(); return true; }
void LegalizerInfo::computeTables() { assert(TablesInitialized == false); for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) { const unsigned Opcode = FirstOp + OpcodeIdx; for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size(); ++TypeIdx) { // 0. Collect information specified through the setAction API, i.e. // for specific bit sizes. // For scalar types: SizeAndActionsVec ScalarSpecifiedActions; // For pointer types: std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions; // For vector types: std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions; for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) { const LLT Type = LLT2Action.first; const LegalizeAction Action = LLT2Action.second; auto SizeAction = std::make_pair(Type.getSizeInBits(), Action); if (Type.isPointer()) AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back( SizeAction); else if (Type.isVector()) ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()] .push_back(SizeAction); else ScalarSpecifiedActions.push_back(SizeAction); } // 1. Handle scalar types { // Decide how to handle bit sizes for which no explicit specification // was given. SizeChangeStrategy S = &unsupportedForDifferentSizes; if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() && ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr) S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx]; std::sort(ScalarSpecifiedActions.begin(), ScalarSpecifiedActions.end()); checkPartialSizeAndActionsVector(ScalarSpecifiedActions); setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions)); } // 2. Handle pointer types for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) { std::sort(PointerSpecifiedActions.second.begin(), PointerSpecifiedActions.second.end()); checkPartialSizeAndActionsVector(PointerSpecifiedActions.second); // For pointer types, we assume that there isn't a meaningfull way // to change the number of bits used in the pointer. setPointerAction( Opcode, TypeIdx, PointerSpecifiedActions.first, unsupportedForDifferentSizes(PointerSpecifiedActions.second)); } // 3. Handle vector types SizeAndActionsVec ElementSizesSeen; for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) { std::sort(VectorSpecifiedActions.second.begin(), VectorSpecifiedActions.second.end()); const uint16_t ElementSize = VectorSpecifiedActions.first; ElementSizesSeen.push_back({ElementSize, Legal}); checkPartialSizeAndActionsVector(VectorSpecifiedActions.second); // For vector types, we assume that the best way to adapt the number // of elements is to the next larger number of elements type for which // the vector type is legal, unless there is no such type. In that case, // legalize towards a vector type with a smaller number of elements. SizeAndActionsVec NumElementsActions; for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) { assert(BitsizeAndAction.first % ElementSize == 0); const uint16_t NumElements = BitsizeAndAction.first / ElementSize; NumElementsActions.push_back({NumElements, BitsizeAndAction.second}); } setVectorNumElementAction( Opcode, TypeIdx, ElementSize, moreToWiderTypesAndLessToWidest(NumElementsActions)); } std::sort(ElementSizesSeen.begin(), ElementSizesSeen.end()); SizeChangeStrategy VectorElementSizeChangeStrategy = &unsupportedForDifferentSizes; if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() && VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr) VectorElementSizeChangeStrategy = VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx]; setScalarInVectorAction( Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen)); } } TablesInitialized = true; }