[llvm] [GlobalISel] Use GINodeEquiv for `G_PTRADD` as `add` (PR #214109)
Demetrius Kanios via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 4 17:54:58 PDT 2026
https://github.com/QuantumSegfault created https://github.com/llvm/llvm-project/pull/214109
None
>From 9860fc14eea4e0fba246f6ba024231518db2ac8e Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Tue, 4 Aug 2026 17:53:49 -0700
Subject: [PATCH] WIP: Try using DAG `add` instead of custom selction for
G_PTRMASK
---
.../Target/GlobalISel/SelectionDAGCompat.td | 1 +
.../GISel/AArch64InstructionSelector.cpp | 15 ---
.../AMDGPU/AMDGPUInstructionSelector.cpp | 115 ------------------
.../Target/AMDGPU/AMDGPUInstructionSelector.h | 1 -
.../RISCV/GISel/RISCVInstructionSelector.cpp | 8 --
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 56 ---------
6 files changed, 1 insertion(+), 195 deletions(-)
diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index e06c96fa837df..1a7e99f126426 100644
--- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -82,6 +82,7 @@ def : GINodeEquiv<G_UREM, urem>;
def : GINodeEquiv<G_SDIVREM, sdivrem>;
def : GINodeEquiv<G_UDIVREM, udivrem>;
def : GINodeEquiv<G_AND, and>;
+def : GINodeEquiv<G_PTRMASK, and>;
def : GINodeEquiv<G_OR, or>;
def : GINodeEquiv<G_XOR, xor>;
def : GINodeEquiv<G_SHL, shl>;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 0c2f3f97ec07d..aaa39f6e8a738 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -3208,21 +3208,6 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
case TargetOpcode::G_USUBO:
return selectOverflowOp(I, MRI);
- case TargetOpcode::G_PTRMASK: {
- Register MaskReg = I.getOperand(2).getReg();
- std::optional<int64_t> MaskVal = getIConstantVRegSExtVal(MaskReg, MRI);
- // TODO: Implement arbitrary cases
- if (!MaskVal || !isShiftedMask_64(*MaskVal))
- return false;
-
- uint64_t Mask = *MaskVal;
- I.setDesc(TII.get(AArch64::ANDXri));
- I.getOperand(2).ChangeToImmediate(
- AArch64_AM::encodeLogicalImmediate(Mask, 64));
-
- constrainSelectedInstRegOperands(I, TII, TRI, RBI);
- return true;
- }
case TargetOpcode::G_PTRTOINT:
case TargetOpcode::G_TRUNC: {
const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 22b8b10554928..bda4b91c2a053 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -3271,119 +3271,6 @@ bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
}
-bool AMDGPUInstructionSelector::selectG_PTRMASK(MachineInstr &I) const {
- Register DstReg = I.getOperand(0).getReg();
- Register SrcReg = I.getOperand(1).getReg();
- Register MaskReg = I.getOperand(2).getReg();
- LLT Ty = MRI->getType(DstReg);
- LLT MaskTy = MRI->getType(MaskReg);
- MachineBasicBlock *BB = I.getParent();
- const DebugLoc &DL = I.getDebugLoc();
-
- const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
- const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
- const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
- const bool IsVGPR = DstRB->getID() == AMDGPU::VGPRRegBankID;
- if (DstRB != SrcRB) // Should only happen for hand written MIR.
- return false;
-
- // Try to avoid emitting a bit operation when we only need to touch half of
- // the 64-bit pointer.
- APInt MaskOnes = VT->getKnownOnes(MaskReg).zext(64);
- const APInt MaskHi32 = APInt::getHighBitsSet(64, 32);
- const APInt MaskLo32 = APInt::getLowBitsSet(64, 32);
-
- const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
- const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
-
- if (!IsVGPR && Ty.getSizeInBits() == 64 &&
- !CanCopyLow32 && !CanCopyHi32) {
- auto MIB = BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_AND_B64), DstReg)
- .addReg(SrcReg)
- .addReg(MaskReg)
- .setOperandDead(3); // Dead scc
- I.eraseFromParent();
- constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
- return true;
- }
-
- unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
- const TargetRegisterClass &RegRC
- = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
-
- const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(Ty, *DstRB);
- const TargetRegisterClass *SrcRC = TRI.getRegClassForTypeOnBank(Ty, *SrcRB);
- const TargetRegisterClass *MaskRC =
- TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
-
- if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
- !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
- !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
- return false;
-
- if (Ty.getSizeInBits() == 32) {
- assert(MaskTy.getSizeInBits() == 32 &&
- "ptrmask should have been narrowed during legalize");
-
- auto NewOp = BuildMI(*BB, &I, DL, TII.get(NewOpc), DstReg)
- .addReg(SrcReg)
- .addReg(MaskReg);
-
- if (!IsVGPR)
- NewOp.setOperandDead(3); // Dead scc
- I.eraseFromParent();
- return true;
- }
-
- Register HiReg = MRI->createVirtualRegister(&RegRC);
- Register LoReg = MRI->createVirtualRegister(&RegRC);
-
- // Extract the subregisters from the source pointer.
- BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), LoReg)
- .addReg(SrcReg, {}, AMDGPU::sub0);
- BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), HiReg)
- .addReg(SrcReg, {}, AMDGPU::sub1);
-
- Register MaskedLo, MaskedHi;
-
- if (CanCopyLow32) {
- // If all the bits in the low half are 1, we only need a copy for it.
- MaskedLo = LoReg;
- } else {
- // Extract the mask subregister and apply the and.
- Register MaskLo = MRI->createVirtualRegister(&RegRC);
- MaskedLo = MRI->createVirtualRegister(&RegRC);
-
- BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), MaskLo)
- .addReg(MaskReg, {}, AMDGPU::sub0);
- BuildMI(*BB, &I, DL, TII.get(NewOpc), MaskedLo)
- .addReg(LoReg)
- .addReg(MaskLo);
- }
-
- if (CanCopyHi32) {
- // If all the bits in the high half are 1, we only need a copy for it.
- MaskedHi = HiReg;
- } else {
- Register MaskHi = MRI->createVirtualRegister(&RegRC);
- MaskedHi = MRI->createVirtualRegister(&RegRC);
-
- BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), MaskHi)
- .addReg(MaskReg, {}, AMDGPU::sub1);
- BuildMI(*BB, &I, DL, TII.get(NewOpc), MaskedHi)
- .addReg(HiReg)
- .addReg(MaskHi);
- }
-
- BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
- .addReg(MaskedLo)
- .addImm(AMDGPU::sub0)
- .addReg(MaskedHi)
- .addImm(AMDGPU::sub1);
- I.eraseFromParent();
- return true;
-}
-
/// Return the register to use for the index value, and the subregister to use
/// for the indirectly accessed register.
static std::pair<Register, unsigned>
@@ -4671,8 +4558,6 @@ bool AMDGPUInstructionSelector::select(MachineInstr &I) {
return selectG_BRCOND(I);
case TargetOpcode::G_GLOBAL_VALUE:
return selectG_GLOBAL_VALUE(I);
- case TargetOpcode::G_PTRMASK:
- return selectG_PTRMASK(I);
case TargetOpcode::G_EXTRACT_VECTOR_ELT:
return selectG_EXTRACT_VECTOR_ELT(I);
case TargetOpcode::G_INSERT_VECTOR_ELT:
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
index 1f9531ce2fa13..c5778d313ed2f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
@@ -141,7 +141,6 @@ class AMDGPUInstructionSelector final : public InstructionSelector {
bool selectG_SELECT(MachineInstr &I) const;
bool selectG_BRCOND(MachineInstr &I) const;
bool selectG_GLOBAL_VALUE(MachineInstr &I) const;
- bool selectG_PTRMASK(MachineInstr &I) const;
bool selectG_EXTRACT_VECTOR_ELT(MachineInstr &I) const;
bool selectG_INSERT_VECTOR_ELT(MachineInstr &I) const;
bool selectBufferLoadLds(MachineInstr &MI) const;
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 16af89c715861..c468aa369d92c 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -1505,14 +1505,6 @@ void RISCVInstructionSelector::preISelLower(MachineInstr &MI) {
MRI->setType(DstReg, sXLen);
break;
}
- case TargetOpcode::G_PTRMASK: {
- Register DstReg = MI.getOperand(0).getReg();
- const LLT sXLen = LLT::scalar(STI.getXLen());
- replacePtrWithInt(MI.getOperand(1));
- MI.setDesc(TII.get(TargetOpcode::G_AND));
- MRI->setType(DstReg, sXLen);
- break;
- }
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index f798cfe9641be..d1ccae1c01814 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1288,8 +1288,6 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
return selectBitcast(ResVReg, ResType, I);
case TargetOpcode::G_ADDRSPACE_CAST:
return selectAddrSpaceCast(ResVReg, ResType, I);
- case TargetOpcode::G_PTRMASK:
- return selectPtrMask(ResVReg, ResType, I);
case TargetOpcode::G_PTR_ADD: {
// Currently, we get G_PTR_ADD only applied to global variables.
assert(I.getOperand(1).isReg() && I.getOperand(2).isReg());
@@ -2936,60 +2934,6 @@ bool SPIRVInstructionSelector::selectAddrSpaceCast(Register ResVReg,
return false;
}
-// G_PTRMASK - Apply a bitmask to a pointer value.
-// Result = Ptr & Mask
-// We need to convert the pointer to an integer, perform the AND operation,
-// and convert back to a pointer.
-bool SPIRVInstructionSelector::selectPtrMask(Register ResVReg,
- SPIRVTypeInst ResType,
- MachineInstr &I) const {
- if (STI.isLogicalSPIRV())
- return diagnoseUnsupported(
- I, "G_PTRMASK is not supported with logical SPIR-V");
- MachineBasicBlock &BB = *I.getParent();
- MachineFunction &MF = *BB.getParent();
- const DebugLoc &DL = I.getDebugLoc();
-
- Register PtrReg = I.getOperand(1).getReg();
- Register MaskReg = I.getOperand(2).getReg();
-
- SPIRVTypeInst MaskType = GR.getSPIRVTypeForVReg(MaskReg);
-
- // Convert pointer to integer.
- Register PtrAsInt = MRI->createVirtualRegister(GR.getRegClass(MaskType));
- GR.assignSPIRVTypeToVReg(MaskType, PtrAsInt, MF);
-
- BuildMI(BB, I, DL, TII.get(SPIRV::OpConvertPtrToU))
- .addDef(PtrAsInt)
- .addUse(GR.getSPIRVTypeID(MaskType))
- .addUse(PtrReg)
- .constrainAllUses(TII, TRI, RBI);
-
- // Perform bitwise AND.
- Register MaskedInt = MRI->createVirtualRegister(GR.getRegClass(MaskType));
- GR.assignSPIRVTypeToVReg(MaskType, MaskedInt, MF);
-
- unsigned AndOpcode = GR.getScalarOrVectorComponentCount(MaskType) > 1
- ? SPIRV::OpBitwiseAndV
- : SPIRV::OpBitwiseAndS;
-
- BuildMI(BB, I, DL, TII.get(AndOpcode))
- .addDef(MaskedInt)
- .addUse(GR.getSPIRVTypeID(MaskType))
- .addUse(PtrAsInt)
- .addUse(MaskReg)
- .constrainAllUses(TII, TRI, RBI);
-
- // Convert integer back to pointer.
- BuildMI(BB, I, DL, TII.get(SPIRV::OpConvertUToPtr))
- .addDef(ResVReg)
- .addUse(GR.getSPIRVTypeID(ResType))
- .addUse(MaskedInt)
- .constrainAllUses(TII, TRI, RBI);
-
- return true;
-}
-
static unsigned getFCmpOpcode(unsigned PredNum) {
auto Pred = static_cast<CmpInst::Predicate>(PredNum);
switch (Pred) {
More information about the llvm-commits
mailing list