Skip to content

Commit 5b41eb3

Browse files
authored
[RISCV] Fix more boundary cases in immediate selection for Zdinx load/store on RV32. (llvm#105874)
In order to support -unaligned-scalar-mem properly, we need to be more careful with immediates of global variables. We need to guarantee that adding 4 in RISCVExpandingPseudos won't overflow simm12. Since we don't know what the simm12 is until link time, the only way to guarantee this is to make sure the base address is at least 8 byte aligned. There were also several corner cases bugs in immediate folding where we would fold an immediate in the range [2044,2047] where adding 4 would overflow. These are not related to unaligned-scalar-mem.
1 parent 033e225 commit 5b41eb3

File tree

5 files changed

+387
-19
lines changed

5 files changed

+387
-19
lines changed

llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,6 @@ bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB,
291291
.setMemRefs(MMOLo);
292292

293293
if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
294-
// FIXME: Zdinx RV32 can not work on unaligned scalar memory.
295-
assert(!STI->enableUnalignedScalarMem());
296-
297294
assert(MBBI->getOperand(2).getOffset() % 8 == 0);
298295
MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4);
299296
BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
@@ -344,7 +341,7 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB,
344341

345342
if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
346343
auto Offset = MBBI->getOperand(2).getOffset();
347-
assert(MBBI->getOperand(2).getOffset() % 8 == 0);
344+
assert(Offset % 8 == 0);
348345
MBBI->getOperand(2).setOffset(Offset + 4);
349346
BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
350347
.addReg(MBBI->getOperand(1).getReg())

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,7 +2522,8 @@ bool RISCVDAGToDAGISel::SelectFrameAddrRegImm(SDValue Addr, SDValue &Base,
25222522
static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL,
25232523
const MVT VT, const RISCVSubtarget *Subtarget,
25242524
SDValue Addr, SDValue &Base, SDValue &Offset,
2525-
bool IsPrefetch = false) {
2525+
bool IsPrefetch = false,
2526+
bool IsRV32Zdinx = false) {
25262527
if (!isa<ConstantSDNode>(Addr))
25272528
return false;
25282529

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

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

25642569
// Drop the last instruction.
25652570
Seq.pop_back();
@@ -2649,20 +2654,44 @@ bool RISCVDAGToDAGISel::SelectAddrRegRegScale(SDValue Addr,
26492654
}
26502655

26512656
bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
2652-
SDValue &Offset, bool IsINX) {
2657+
SDValue &Offset, bool IsRV32Zdinx) {
26532658
if (SelectAddrFrameIndex(Addr, Base, Offset))
26542659
return true;
26552660

26562661
SDLoc DL(Addr);
26572662
MVT VT = Addr.getSimpleValueType();
26582663

26592664
if (Addr.getOpcode() == RISCVISD::ADD_LO) {
2660-
Base = Addr.getOperand(0);
2661-
Offset = Addr.getOperand(1);
2662-
return true;
2665+
// If this is non RV32Zdinx we can always fold.
2666+
if (!IsRV32Zdinx) {
2667+
Base = Addr.getOperand(0);
2668+
Offset = Addr.getOperand(1);
2669+
return true;
2670+
}
2671+
2672+
// For RV32Zdinx we need to have more than 4 byte alignment so we can add 4
2673+
// to the offset when we expand in RISCVExpandPseudoInsts.
2674+
if (auto *GA = dyn_cast<GlobalAddressSDNode>(Addr.getOperand(1))) {
2675+
const DataLayout &DL = CurDAG->getDataLayout();
2676+
Align Alignment = commonAlignment(
2677+
GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
2678+
if (Alignment > 4) {
2679+
Base = Addr.getOperand(0);
2680+
Offset = Addr.getOperand(1);
2681+
return true;
2682+
}
2683+
}
2684+
if (auto *CP = dyn_cast<ConstantPoolSDNode>(Addr.getOperand(1))) {
2685+
Align Alignment = commonAlignment(CP->getAlign(), CP->getOffset());
2686+
if (Alignment > 4) {
2687+
Base = Addr.getOperand(0);
2688+
Offset = Addr.getOperand(1);
2689+
return true;
2690+
}
2691+
}
26632692
}
26642693

2665-
int64_t RV32ZdinxRange = IsINX ? 4 : 0;
2694+
int64_t RV32ZdinxRange = IsRV32Zdinx ? 4 : 0;
26662695
if (CurDAG->isBaseWithConstantOffset(Addr)) {
26672696
int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
26682697
if (isInt<12>(CVal) && isInt<12>(CVal + RV32ZdinxRange)) {
@@ -2678,7 +2707,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
26782707
const DataLayout &DL = CurDAG->getDataLayout();
26792708
Align Alignment = commonAlignment(
26802709
GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
2681-
if (CVal == 0 || Alignment > CVal) {
2710+
if ((CVal == 0 || Alignment > CVal) &&
2711+
(!IsRV32Zdinx || Alignment > (CVal + 4))) {
26822712
int64_t CombinedOffset = CVal + GA->getOffset();
26832713
Base = Base.getOperand(0);
26842714
Offset = CurDAG->getTargetGlobalAddress(
@@ -2705,7 +2735,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
27052735
// Handle immediates in the range [-4096,-2049] or [2048, 4094]. We can use
27062736
// an ADDI for part of the offset and fold the rest into the load/store.
27072737
// This mirrors the AddiPair PatFrag in RISCVInstrInfo.td.
2708-
if (isInt<12>(CVal / 2) && isInt<12>(CVal - CVal / 2)) {
2738+
if (CVal >= -4096 && CVal <= (4094 - RV32ZdinxRange)) {
27092739
int64_t Adj = CVal < 0 ? -2048 : 2047;
27102740
Base = SDValue(
27112741
CurDAG->getMachineNode(
@@ -2724,7 +2754,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
27242754
// instructions.
27252755
if (isWorthFoldingAdd(Addr) &&
27262756
selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base,
2727-
Offset)) {
2757+
Offset, /*IsPrefetch=*/false, RV32ZdinxRange)) {
27282758
// Insert an ADD instruction with the materialized Hi52 bits.
27292759
Base = SDValue(
27302760
CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base),
@@ -2733,7 +2763,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
27332763
}
27342764
}
27352765

2736-
if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset))
2766+
if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
2767+
/*IsPrefetch=*/false, RV32ZdinxRange))
27372768
return true;
27382769

27392770
Base = Addr;
@@ -2791,7 +2822,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base,
27912822
}
27922823

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

2803-
if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset, true))
2834+
if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
2835+
/*IsPrefetch=*/true))
28042836
return true;
28052837

28062838
Base = Addr;

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
4848
bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset);
4949
bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
5050
bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset,
51-
bool IsINX = false);
52-
bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) {
51+
bool IsRV32Zdinx = false);
52+
bool SelectAddrRegImmRV32Zdinx(SDValue Addr, SDValue &Base, SDValue &Offset) {
5353
return SelectAddrRegImm(Addr, Base, Offset, true);
5454
}
5555
bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset);

llvm/lib/Target/RISCV/RISCVInstrInfoD.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def SDT_RISCVSplitF64 : SDTypeProfile<2, 1, [SDTCisVT<0, i32>,
2525
def RISCVBuildPairF64 : SDNode<"RISCVISD::BuildPairF64", SDT_RISCVBuildPairF64>;
2626
def RISCVSplitF64 : SDNode<"RISCVISD::SplitF64", SDT_RISCVSplitF64>;
2727

28-
def AddrRegImmINX : ComplexPattern<iPTR, 2, "SelectAddrRegImmINX">;
28+
def AddrRegImmINX : ComplexPattern<iPTR, 2, "SelectAddrRegImmRV32Zdinx">;
2929

3030
//===----------------------------------------------------------------------===//
3131
// Operand and SDNode transformation definitions.

0 commit comments

Comments
 (0)