[RISCV] Support folding constant addresses in SelectAddrRegImm.

We already handled this by folding an ADDI in the post-isel peephole.
My goal is to remove that peephole so this adds the functionality
to isel.
This commit is contained in:
Craig Topper 2022-07-09 11:54:52 -07:00
parent 40866b74bd
commit 9c6a2200e2
1 changed files with 50 additions and 0 deletions

View File

@ -1887,6 +1887,53 @@ bool RISCVDAGToDAGISel::SelectFrameAddrRegImm(SDValue Addr, SDValue &Base,
return false;
}
// Fold constant addresses.
static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL,
const MVT VT, const RISCVSubtarget *Subtarget,
SDValue Addr, SDValue &Base, SDValue &Offset) {
if (!isa<ConstantSDNode>(Addr))
return false;
int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
// If the constant is a simm12, we can fold the whole constant and use X0 as
// the base. If the constant can be materialized with LUI+simm12, use LUI as
// the base. We can't use generateInstSeq because it favors LUI+ADDIW.
int64_t Lo12 = SignExtend64<12>(CVal);
int64_t Hi = (uint64_t)CVal - (uint64_t)Lo12;
if (!Subtarget->is64Bit() || isInt<32>(Hi)) {
if (Hi) {
int64_t Hi20 = (Hi >> 12) & 0xfffff;
Base = SDValue(
CurDAG->getMachineNode(RISCV::LUI, DL, VT,
CurDAG->getTargetConstant(Hi20, DL, VT)),
0);
} else {
Base = CurDAG->getRegister(RISCV::X0, VT);
}
Offset = CurDAG->getTargetConstant(Lo12, DL, VT);
return true;
}
// Ask how constant materialization would handle this constant.
RISCVMatInt::InstSeq Seq =
RISCVMatInt::generateInstSeq(CVal, Subtarget->getFeatureBits());
// If the last instruction would be an ADDI, we can fold its immediate and
// emit the rest of the sequence as the base.
if (Seq.back().Opc != RISCV::ADDI)
return false;
Lo12 = Seq.back().Imm;
// Drop the last instruction.
Seq.pop_back();
assert(!Seq.empty() && "Expected more instructions in sequence");
Base = SDValue(selectImmSeq(CurDAG, DL, VT, Seq), 0);
Offset = CurDAG->getTargetConstant(Lo12, DL, VT);
return true;
}
bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
SDValue &Offset) {
if (SelectAddrFrameIndex(Addr, Base, Offset))
@ -1952,6 +1999,9 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
}
}
if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset))
return true;
Base = Addr;
Offset = CurDAG->getTargetConstant(0, DL, VT);
return true;