Skip to content

[RISCV] Fix more boundary cases in immediate selection for Zdinx load/store on RV32. #105874

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 3 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,6 @@ bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB,
.setMemRefs(MMOLo);

if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
// FIXME: Zdinx RV32 can not work on unaligned scalar memory.
assert(!STI->enableUnalignedScalarMem());

assert(MBBI->getOperand(2).getOffset() % 8 == 0);
MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4);
BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
Expand Down Expand Up @@ -344,7 +341,7 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB,

if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
auto Offset = MBBI->getOperand(2).getOffset();
assert(MBBI->getOperand(2).getOffset() % 8 == 0);
assert(Offset % 8 == 0);
MBBI->getOperand(2).setOffset(Offset + 4);
BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
.addReg(MBBI->getOperand(1).getReg())
Expand Down
56 changes: 44 additions & 12 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2522,7 +2522,8 @@ bool RISCVDAGToDAGISel::SelectFrameAddrRegImm(SDValue Addr, SDValue &Base,
static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL,
const MVT VT, const RISCVSubtarget *Subtarget,
SDValue Addr, SDValue &Base, SDValue &Offset,
bool IsPrefetch = false) {
bool IsPrefetch = false,
bool IsRV32Zdinx = false) {
if (!isa<ConstantSDNode>(Addr))
return false;

Expand All @@ -2536,6 +2537,8 @@ static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL,
if (!Subtarget->is64Bit() || isInt<32>(Hi)) {
if (IsPrefetch && (Lo12 & 0b11111) != 0)
return false;
if (IsRV32Zdinx && !isInt<12>(Lo12 + 4))
return false;

if (Hi) {
int64_t Hi20 = (Hi >> 12) & 0xfffff;
Expand All @@ -2560,6 +2563,8 @@ static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL,
Lo12 = Seq.back().getImm();
if (IsPrefetch && (Lo12 & 0b11111) != 0)
return false;
if (IsRV32Zdinx && !isInt<12>(Lo12 + 4))
return false;

// Drop the last instruction.
Seq.pop_back();
Expand Down Expand Up @@ -2649,20 +2654,44 @@ bool RISCVDAGToDAGISel::SelectAddrRegRegScale(SDValue Addr,
}

bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
SDValue &Offset, bool IsINX) {
SDValue &Offset, bool IsRV32Zdinx) {
if (SelectAddrFrameIndex(Addr, Base, Offset))
return true;

SDLoc DL(Addr);
MVT VT = Addr.getSimpleValueType();

if (Addr.getOpcode() == RISCVISD::ADD_LO) {
Base = Addr.getOperand(0);
Offset = Addr.getOperand(1);
return true;
// If this is non RV32Zdinx we can always fold.
if (!IsRV32Zdinx) {
Base = Addr.getOperand(0);
Offset = Addr.getOperand(1);
return true;
}

// For RV32Zdinx we need to have more than 4 byte alignment so we can add 4
// to the offset when we expand in RISCVExpandPseudoInsts.
if (auto *GA = dyn_cast<GlobalAddressSDNode>(Addr.getOperand(1))) {
const DataLayout &DL = CurDAG->getDataLayout();
Align Alignment = commonAlignment(
GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
if (Alignment > 4) {
Base = Addr.getOperand(0);
Offset = Addr.getOperand(1);
return true;
}
}
if (auto *CP = dyn_cast<ConstantPoolSDNode>(Addr.getOperand(1))) {
Align Alignment = commonAlignment(CP->getAlign(), CP->getOffset());
if (Alignment > 4) {
Base = Addr.getOperand(0);
Offset = Addr.getOperand(1);
return true;
}
}
}

int64_t RV32ZdinxRange = IsINX ? 4 : 0;
int64_t RV32ZdinxRange = IsRV32Zdinx ? 4 : 0;
if (CurDAG->isBaseWithConstantOffset(Addr)) {
int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
if (isInt<12>(CVal) && isInt<12>(CVal + RV32ZdinxRange)) {
Expand All @@ -2678,7 +2707,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
const DataLayout &DL = CurDAG->getDataLayout();
Align Alignment = commonAlignment(
GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
if (CVal == 0 || Alignment > CVal) {
if ((CVal == 0 || Alignment > CVal) &&
(!IsRV32Zdinx || Alignment > (CVal + 4))) {
int64_t CombinedOffset = CVal + GA->getOffset();
Base = Base.getOperand(0);
Offset = CurDAG->getTargetGlobalAddress(
Expand All @@ -2705,7 +2735,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
// Handle immediates in the range [-4096,-2049] or [2048, 4094]. We can use
// an ADDI for part of the offset and fold the rest into the load/store.
// This mirrors the AddiPair PatFrag in RISCVInstrInfo.td.
if (isInt<12>(CVal / 2) && isInt<12>(CVal - CVal / 2)) {
if (CVal >= -4096 && CVal <= (4094 - RV32ZdinxRange)) {
int64_t Adj = CVal < 0 ? -2048 : 2047;
Base = SDValue(
CurDAG->getMachineNode(
Expand All @@ -2724,7 +2754,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
// instructions.
if (isWorthFoldingAdd(Addr) &&
selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base,
Offset)) {
Offset, /*IsPrefetch=*/false, RV32ZdinxRange)) {
// Insert an ADD instruction with the materialized Hi52 bits.
Base = SDValue(
CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base),
Expand All @@ -2733,7 +2763,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
}
}

if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset))
if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
/*IsPrefetch=*/false, RV32ZdinxRange))
return true;

Base = Addr;
Expand Down Expand Up @@ -2791,7 +2822,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base,
}

if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base,
Offset, true)) {
Offset, /*IsPrefetch=*/true)) {
// Insert an ADD instruction with the materialized Hi52 bits.
Base = SDValue(
CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base),
Expand All @@ -2800,7 +2831,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base,
}
}

if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset, true))
if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
/*IsPrefetch=*/true))
return true;

Base = Addr;
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset,
bool IsINX = false);
bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) {
bool IsRV32Zdinx = false);
bool SelectAddrRegImmRV32Zdinx(SDValue Addr, SDValue &Base, SDValue &Offset) {
return SelectAddrRegImm(Addr, Base, Offset, true);
}
bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVInstrInfoD.td
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def SDT_RISCVSplitF64 : SDTypeProfile<2, 1, [SDTCisVT<0, i32>,
def RISCVBuildPairF64 : SDNode<"RISCVISD::BuildPairF64", SDT_RISCVBuildPairF64>;
def RISCVSplitF64 : SDNode<"RISCVISD::SplitF64", SDT_RISCVSplitF64>;

def AddrRegImmINX : ComplexPattern<iPTR, 2, "SelectAddrRegImmINX">;
def AddrRegImmINX : ComplexPattern<iPTR, 2, "SelectAddrRegImmRV32Zdinx">;

//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
Expand Down
Loading
Loading