-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[X86][GlobalISel] Support addr matching in SDAG patterns #130445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
766c7cd
[X86][GlobalISel] Support addr matching in SDAG pattern
e-kud 74a7f95
Merge remote-tracking branch 'origin/main' into global-load-2
e-kud 71586ad
Merge remote-tracking branch 'origin/main' into global-load-2
e-kud 933ccb6
Minor fixes
e-kud 4843059
Addressing comments: assert message and style
e-kud 00e6f86
Merge remote-tracking branch 'origin/main' into global-load-2
e-kud 0e33f15
Update sqrt.mir
e-kud 8ffbda9
Format
e-kud f12a77f
Merge branch 'main' into global-load-2
e-kud b6ea8a9
Merge branch 'main' into global-load-2
e-kud 5ca0f05
Refactor getPtrLoadStoreOp
e-kud 970fcb0
Merge branch 'main' into global-load-2
e-kud 3ed2ae0
Merge branch 'main' into global-load-2
e-kud File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,6 +73,9 @@ class X86InstructionSelector : public InstructionSelector { | |
| // TODO: remove after supported by Tablegen-erated instruction selection. | ||
| unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned Opc, | ||
| Align Alignment) const; | ||
| // TODO: remove once p0<->i32/i64 matching is available | ||
| unsigned getPtrLoadStoreOp(const LLT &Ty, const RegisterBank &RB, | ||
| unsigned Opc) const; | ||
|
|
||
| bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI, | ||
| MachineFunction &MF) const; | ||
|
|
@@ -119,6 +122,8 @@ class X86InstructionSelector : public InstructionSelector { | |
| bool selectSelect(MachineInstr &I, MachineRegisterInfo &MRI, | ||
| MachineFunction &MF) const; | ||
|
|
||
| ComplexRendererFns selectAddr(MachineOperand &Root) const; | ||
|
|
||
| // emit insert subreg instruction and insert it before MachineInstr &I | ||
| bool emitInsertSubreg(Register DstReg, Register SrcReg, MachineInstr &I, | ||
| MachineRegisterInfo &MRI, MachineFunction &MF) const; | ||
|
|
@@ -445,6 +450,17 @@ bool X86InstructionSelector::select(MachineInstr &I) { | |
| return false; | ||
| } | ||
|
|
||
| unsigned X86InstructionSelector::getPtrLoadStoreOp(const LLT &Ty, | ||
| const RegisterBank &RB, | ||
| unsigned Opc) const { | ||
| bool Isload = (Opc == TargetOpcode::G_LOAD); | ||
|
||
| if (Ty == LLT::pointer(0, 32) && X86::GPRRegBankID == RB.getID()) | ||
| return Isload ? X86::MOV32rm : X86::MOV32mr; | ||
| if (Ty == LLT::pointer(0, 64) && X86::GPRRegBankID == RB.getID()) | ||
| return Isload ? X86::MOV64rm : X86::MOV64mr; | ||
| return Opc; | ||
| } | ||
|
|
||
| unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty, | ||
| const RegisterBank &RB, | ||
| unsigned Opc, | ||
|
|
@@ -460,7 +476,7 @@ unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty, | |
| } else if (Ty == LLT::scalar(16)) { | ||
| if (X86::GPRRegBankID == RB.getID()) | ||
| return Isload ? X86::MOV16rm : X86::MOV16mr; | ||
| } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) { | ||
| } else if (Ty == LLT::scalar(32)) { | ||
| if (X86::GPRRegBankID == RB.getID()) | ||
| return Isload ? X86::MOV32rm : X86::MOV32mr; | ||
| if (X86::VECRRegBankID == RB.getID()) | ||
|
|
@@ -472,7 +488,7 @@ unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty, | |
| X86::MOVSSmr); | ||
| if (X86::PSRRegBankID == RB.getID()) | ||
| return Isload ? X86::LD_Fp32m : X86::ST_Fp32m; | ||
| } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) { | ||
| } else if (Ty == LLT::scalar(64)) { | ||
| if (X86::GPRRegBankID == RB.getID()) | ||
| return Isload ? X86::MOV64rm : X86::MOV64mr; | ||
| if (X86::VECRRegBankID == RB.getID()) | ||
|
|
@@ -530,30 +546,75 @@ unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty, | |
| } | ||
|
|
||
| // Fill in an address from the given instruction. | ||
| static void X86SelectAddress(const MachineInstr &I, | ||
| static bool X86SelectAddress(MachineInstr &I, const X86TargetMachine &TM, | ||
RKSimon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const MachineRegisterInfo &MRI, | ||
| X86AddressMode &AM) { | ||
| assert(I.getOperand(0).isReg() && "unsupported opperand."); | ||
| const X86Subtarget &STI, X86AddressMode &AM) { | ||
| assert(I.getOperand(0).isReg() && "unsupported operand."); | ||
| assert(MRI.getType(I.getOperand(0).getReg()).isPointer() && | ||
| "unsupported type."); | ||
|
|
||
| if (I.getOpcode() == TargetOpcode::G_PTR_ADD) { | ||
| switch (I.getOpcode()) { | ||
| default: | ||
| break; | ||
| case TargetOpcode::G_FRAME_INDEX: | ||
| AM.Base.FrameIndex = I.getOperand(1).getIndex(); | ||
| AM.BaseType = X86AddressMode::FrameIndexBase; | ||
| return true; | ||
| case TargetOpcode::G_PTR_ADD: { | ||
| if (auto COff = getIConstantVRegSExtVal(I.getOperand(2).getReg(), MRI)) { | ||
| int64_t Imm = *COff; | ||
| if (isInt<32>(Imm)) { // Check for displacement overflow. | ||
| AM.Disp = static_cast<int32_t>(Imm); | ||
| AM.Base.Reg = I.getOperand(1).getReg(); | ||
| return; | ||
| return true; | ||
| } | ||
| } | ||
| } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) { | ||
| AM.Base.FrameIndex = I.getOperand(1).getIndex(); | ||
| AM.BaseType = X86AddressMode::FrameIndexBase; | ||
| return; | ||
| break; | ||
| } | ||
| case TargetOpcode::G_GLOBAL_VALUE: { | ||
| auto GV = I.getOperand(1).getGlobal(); | ||
| if (GV->isThreadLocal()) { | ||
| return false; // TODO: we don't support TLS yet. | ||
| } | ||
| // Can't handle alternate code models yet. | ||
| if (TM.getCodeModel() != CodeModel::Small) | ||
| return false; | ||
| AM.GV = GV; | ||
| AM.GVOpFlags = STI.classifyGlobalReference(GV); | ||
|
|
||
| // TODO: The ABI requires an extra load. not supported yet. | ||
| if (isGlobalStubReference(AM.GVOpFlags)) | ||
| return false; | ||
|
|
||
| // TODO: This reference is relative to the pic base. not supported yet. | ||
| if (isGlobalRelativeToPICBase(AM.GVOpFlags)) | ||
| return false; | ||
|
|
||
| if (STI.isPICStyleRIPRel()) { | ||
| // Use rip-relative addressing. | ||
| assert(AM.Base.Reg == 0 && AM.IndexReg == 0); | ||
|
||
| AM.Base.Reg = X86::RIP; | ||
| } | ||
| return true; | ||
| } | ||
| case TargetOpcode::G_CONSTANT_POOL: { | ||
| // TODO: Need a separate move for Large model | ||
| if (TM.getCodeModel() == CodeModel::Large) | ||
| return false; | ||
|
|
||
| AM.GVOpFlags = STI.classifyLocalReference(nullptr); | ||
| if (AM.GVOpFlags == X86II::MO_GOTOFF) | ||
| AM.Base.Reg = STI.getInstrInfo()->getGlobalBaseReg(I.getMF()); | ||
| else if (STI.is64Bit()) | ||
| AM.Base.Reg = X86::RIP; | ||
| AM.CP = true; | ||
| AM.Disp = I.getOperand(1).getIndex(); | ||
| return true; | ||
| } | ||
| } | ||
| // Default behavior. | ||
| AM.Base.Reg = I.getOperand(0).getReg(); | ||
| return true; | ||
| } | ||
|
|
||
| bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I, | ||
|
|
@@ -586,36 +647,18 @@ bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I, | |
| } | ||
| } | ||
|
|
||
| unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlign()); | ||
| unsigned NewOpc = getPtrLoadStoreOp(Ty, RB, Opc); | ||
| if (NewOpc == Opc) | ||
| return false; | ||
|
|
||
| I.setDesc(TII.get(NewOpc)); | ||
| MachineInstrBuilder MIB(MF, I); | ||
| const MachineInstr *Ptr = MRI.getVRegDef(I.getOperand(1).getReg()); | ||
|
|
||
| if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) { | ||
| assert(Opc == TargetOpcode::G_LOAD && | ||
| "Only G_LOAD from constant pool is expected"); | ||
| // TODO: Need a separate move for Large model | ||
| if (TM.getCodeModel() == CodeModel::Large) | ||
| return false; | ||
|
|
||
| unsigned char OpFlag = STI.classifyLocalReference(nullptr); | ||
| Register PICBase; | ||
| if (OpFlag == X86II::MO_GOTOFF) | ||
| PICBase = TII.getGlobalBaseReg(&MF); | ||
| else if (STI.is64Bit()) | ||
| PICBase = X86::RIP; | ||
|
|
||
| I.removeOperand(1); | ||
| addConstantPoolReference(MIB, Ptr->getOperand(1).getIndex(), PICBase, | ||
| OpFlag); | ||
| return constrainSelectedInstRegOperands(I, TII, TRI, RBI); | ||
| } | ||
| MachineInstr *Ptr = MRI.getVRegDef(I.getOperand(1).getReg()); | ||
|
|
||
| X86AddressMode AM; | ||
| X86SelectAddress(*Ptr, MRI, AM); | ||
| if (!X86SelectAddress(*Ptr, TM, MRI, STI, AM)) | ||
| return false; | ||
|
|
||
| if (Opc == TargetOpcode::G_LOAD) { | ||
| I.removeOperand(1); | ||
| addFullAddress(MIB, AM); | ||
|
|
@@ -673,33 +716,10 @@ bool X86InstructionSelector::selectGlobalValue(MachineInstr &I, | |
| assert((I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE) && | ||
| "unexpected instruction"); | ||
|
|
||
| auto GV = I.getOperand(1).getGlobal(); | ||
| if (GV->isThreadLocal()) { | ||
| return false; // TODO: we don't support TLS yet. | ||
| } | ||
|
|
||
| // Can't handle alternate code models yet. | ||
| if (TM.getCodeModel() != CodeModel::Small) | ||
| return false; | ||
|
|
||
| X86AddressMode AM; | ||
| AM.GV = GV; | ||
| AM.GVOpFlags = STI.classifyGlobalReference(GV); | ||
|
|
||
| // TODO: The ABI requires an extra load. not supported yet. | ||
| if (isGlobalStubReference(AM.GVOpFlags)) | ||
| return false; | ||
|
|
||
| // TODO: This reference is relative to the pic base. not supported yet. | ||
| if (isGlobalRelativeToPICBase(AM.GVOpFlags)) | ||
| if (!X86SelectAddress(I, TM, MRI, STI, AM)) | ||
| return false; | ||
|
|
||
| if (STI.isPICStyleRIPRel()) { | ||
| // Use rip-relative addressing. | ||
| assert(AM.Base.Reg == 0 && AM.IndexReg == 0); | ||
| AM.Base.Reg = X86::RIP; | ||
| } | ||
|
|
||
| const Register DefReg = I.getOperand(0).getReg(); | ||
| LLT Ty = MRI.getType(DefReg); | ||
| unsigned NewOpc = getLeaOP(Ty, STI); | ||
|
|
@@ -1880,6 +1900,46 @@ bool X86InstructionSelector::selectSelect(MachineInstr &I, | |
| return true; | ||
| } | ||
|
|
||
| InstructionSelector::ComplexRendererFns | ||
| X86InstructionSelector::selectAddr(MachineOperand &Root) const { | ||
| MachineInstr *MI = Root.getParent(); | ||
| MachineIRBuilder MIRBuilder(*MI); | ||
|
|
||
| MachineRegisterInfo &MRI = MI->getMF()->getRegInfo(); | ||
| MachineInstr *Ptr = MRI.getVRegDef(Root.getReg()); | ||
| X86AddressMode AM; | ||
| X86SelectAddress(*Ptr, TM, MRI, STI, AM); | ||
|
|
||
| if (AM.IndexReg) | ||
| return std::nullopt; | ||
|
|
||
| return {// Base | ||
| {[=](MachineInstrBuilder &MIB) { | ||
| if (AM.BaseType == X86AddressMode::RegBase) | ||
| MIB.addUse(AM.Base.Reg); | ||
| else { | ||
| assert(AM.BaseType == X86AddressMode::FrameIndexBase && | ||
| "Unknown type of address base"); | ||
| MIB.addFrameIndex(AM.Base.FrameIndex); | ||
| } | ||
| }, | ||
| // Scale | ||
| [=](MachineInstrBuilder &MIB) { MIB.addImm(AM.Scale); }, | ||
| // Index | ||
| [=](MachineInstrBuilder &MIB) { MIB.addUse(0); }, | ||
| // Disp | ||
| [=](MachineInstrBuilder &MIB) { | ||
| if (AM.GV) | ||
| MIB.addGlobalAddress(AM.GV, AM.Disp, AM.GVOpFlags); | ||
| else if (AM.CP) | ||
| MIB.addConstantPoolIndex(AM.Disp, 0, AM.GVOpFlags); | ||
| else | ||
| MIB.addImm(AM.Disp); | ||
| }, | ||
| // Segment | ||
| [=](MachineInstrBuilder &MIB) { MIB.addUse(0); }}}; | ||
| } | ||
|
|
||
| InstructionSelector * | ||
| llvm::createX86InstructionSelector(const X86TargetMachine &TM, | ||
| const X86Subtarget &Subtarget, | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert((Opc == TargetOpcode::G_LOAD || Opc == TargetOpcode::G_STORE) && "Unknown memory opcode");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I blindly copied existing code however should've reread it.