[XCore] Make use of the target independent global address offset folding.

This let us to remove some custom code that matched constant offsets
from globals at instruction selection time as a special addressing mode.
No intended functionality change.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181126 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Osborne 2013-05-04 17:24:33 +00:00
parent 40827bc716
commit 6ffbf6ea8f
6 changed files with 41 additions and 98 deletions

View File

@ -97,9 +97,6 @@ static DecodeStatus DecodeRRegsRegisterClass(MCInst &Inst,
static DecodeStatus DecodeBitpOperand(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMEMiiOperand(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus Decode2RInstruction(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@ -242,13 +239,6 @@ static DecodeStatus DecodeBitpOperand(MCInst &Inst, unsigned Val,
return MCDisassembler::Success;
}
static DecodeStatus DecodeMEMiiOperand(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(Val));
Inst.addOperand(MCOperand::CreateImm(0));
return MCDisassembler::Success;
}
static DecodeStatus
Decode2OpInstruction(unsigned Insn, unsigned &Op1, unsigned &Op2) {
unsigned Combined = fieldFromInstruction(Insn, 6, 5);

View File

@ -84,14 +84,3 @@ printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
assert(Op.isExpr() && "unknown operand kind in printOperand");
printExpr(Op.getExpr(), O);
}
void XCoreInstPrinter::
printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
printOperand(MI, opNum, O);
if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0)
return;
O << "+";
printOperand(MI, opNum+1, O);
}

View File

@ -68,8 +68,6 @@ namespace {
// Complex Pattern Selectors.
bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectADDRdpii(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectADDRcpii(SDValue Addr, SDValue &Base, SDValue &Offset);
virtual const char *getPassName() const {
return "XCore DAG->DAG Pattern Instruction Selection";
@ -110,48 +108,6 @@ bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
return false;
}
bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Addr, SDValue &Base,
SDValue &Offset) {
if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
Base = Addr.getOperand(0);
Offset = CurDAG->getTargetConstant(0, MVT::i32);
return true;
}
if (Addr.getOpcode() == ISD::ADD) {
ConstantSDNode *CN = 0;
if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
&& (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
&& (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
// Constant word offset from a object in the data region
Base = Addr.getOperand(0).getOperand(0);
Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
return true;
}
}
return false;
}
bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Addr, SDValue &Base,
SDValue &Offset) {
if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
Base = Addr.getOperand(0);
Offset = CurDAG->getTargetConstant(0, MVT::i32);
return true;
}
if (Addr.getOpcode() == ISD::ADD) {
ConstantSDNode *CN = 0;
if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
&& (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
&& (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
// Constant word offset from a object in the data region
Base = Addr.getOperand(0).getOperand(0);
Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
return true;
}
}
return false;
}
SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
DebugLoc dl = N->getDebugLoc();
switch (N->getOpcode()) {

View File

@ -36,6 +36,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
const char *XCoreTargetLowering::
@ -241,9 +243,20 @@ getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV,
SDValue XCoreTargetLowering::
LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const
{
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
SDValue GA = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(), MVT::i32);
return getGlobalAddressWrapper(GA, GV, DAG);
DebugLoc DL = Op.getDebugLoc();
const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
const GlobalValue *GV = GN->getGlobal();
int64_t Offset = GN->getOffset();
// We can only fold positive offsets that are a multiple of the word size.
int64_t FoldedOffset = std::max(Offset & ~3, 0LL);
SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset);
GA = getGlobalAddressWrapper(GA, GV, DAG);
// Handle the rest of the offset.
if (Offset != FoldedOffset) {
SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, MVT::i32);
GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining);
}
return GA;
}
static inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) {
@ -319,10 +332,19 @@ lowerLoadWordFromAlignedBasePlusOffset(DebugLoc DL, SDValue Chain, SDValue Base,
// Lower to pair of consecutive word aligned loads plus some bit shifting.
int32_t HighOffset = RoundUpToAlignment(Offset, 4);
int32_t LowOffset = HighOffset - 4;
SDValue LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
DAG.getConstant(LowOffset, MVT::i32));
SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
DAG.getConstant(HighOffset, MVT::i32));
SDValue LowAddr, HighAddr;
if (GlobalAddressSDNode *GASD =
dyn_cast<GlobalAddressSDNode>(Base.getNode())) {
LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
LowOffset);
HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
HighOffset);
} else {
LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
DAG.getConstant(LowOffset, MVT::i32));
HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
DAG.getConstant(HighOffset, MVT::i32));
}
SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, MVT::i32);
SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, MVT::i32);
@ -1553,12 +1575,6 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
}
}
bool XCoreTargetLowering::
isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
// The XCore target isn't yet aware of offsets.
return false;
}
//===----------------------------------------------------------------------===//
// XCore Inline Assembly Support
//===----------------------------------------------------------------------===//

View File

@ -106,8 +106,6 @@ namespace llvm {
virtual bool isLegalAddressingMode(const AddrMode &AM,
Type *Ty) const;
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
private:
const XCoreTargetMachine &TM;
const XCoreSubtarget &Subtarget;

View File

@ -174,15 +174,9 @@ def pclabel : Operand<i32>;
// Addressing modes
def ADDRspii : ComplexPattern<i32, 2, "SelectADDRspii", [add, frameindex], []>;
def ADDRdpii : ComplexPattern<i32, 2, "SelectADDRdpii", [add, dprelwrapper],
[]>;
def ADDRcpii : ComplexPattern<i32, 2, "SelectADDRcpii", [add, cprelwrapper],
[]>;
// Address operands
def MEMii : Operand<i32> {
let PrintMethod = "printMemOperand";
let DecoderMethod = "DecodeMEMiiOperand";
let MIOperandInfo = (ops i32imm, i32imm);
}
@ -515,29 +509,29 @@ def LMUL_l6r : _FL6R<
//let Uses = [DP] in ...
let neverHasSideEffects = 1, isReMaterializable = 1 in
def LDAWDP_ru6: _FRU6<0b011000, (outs RRegs:$a), (ins MEMii:$b),
def LDAWDP_ru6: _FRU6<0b011000, (outs RRegs:$a), (ins i32imm:$b),
"ldaw $a, dp[$b]", []>;
let isReMaterializable = 1 in
def LDAWDP_lru6: _FLRU6<0b011000, (outs RRegs:$a), (ins MEMii:$b),
def LDAWDP_lru6: _FLRU6<0b011000, (outs RRegs:$a), (ins i32imm:$b),
"ldaw $a, dp[$b]",
[(set RRegs:$a, ADDRdpii:$b)]>;
[(set RRegs:$a, (dprelwrapper tglobaladdr:$b))]>;
let mayLoad=1 in
def LDWDP_ru6: _FRU6<0b010110, (outs RRegs:$a), (ins MEMii:$b),
def LDWDP_ru6: _FRU6<0b010110, (outs RRegs:$a), (ins i32imm:$b),
"ldw $a, dp[$b]", []>;
def LDWDP_lru6: _FLRU6<0b010110, (outs RRegs:$a), (ins MEMii:$b),
def LDWDP_lru6: _FLRU6<0b010110, (outs RRegs:$a), (ins i32imm:$b),
"ldw $a, dp[$b]",
[(set RRegs:$a, (load ADDRdpii:$b))]>;
[(set RRegs:$a, (load (dprelwrapper tglobaladdr:$b)))]>;
let mayStore=1 in
def STWDP_ru6 : _FRU6<0b010100, (outs), (ins RRegs:$a, MEMii:$b),
def STWDP_ru6 : _FRU6<0b010100, (outs), (ins RRegs:$a, i32imm:$b),
"stw $a, dp[$b]", []>;
def STWDP_lru6 : _FLRU6<0b010100, (outs), (ins RRegs:$a, MEMii:$b),
def STWDP_lru6 : _FLRU6<0b010100, (outs), (ins RRegs:$a, i32imm:$b),
"stw $a, dp[$b]",
[(store RRegs:$a, ADDRdpii:$b)]>;
[(store RRegs:$a, (dprelwrapper tglobaladdr:$b))]>;
//let Uses = [CP] in ..
let mayLoad = 1, isReMaterializable = 1, neverHasSideEffects = 1 in
@ -626,12 +620,12 @@ def BRFU_lu6 : _FLU6<0b0111001100, (outs), (ins brtarget:$a), "bu $a", []>;
//let Uses = [CP] in ...
let Defs = [R11], neverHasSideEffects = 1, isReMaterializable = 1 in
def LDAWCP_u6: _FU6<0b0111111101, (outs), (ins MEMii:$a), "ldaw r11, cp[$a]",
def LDAWCP_u6: _FU6<0b0111111101, (outs), (ins i32imm:$a), "ldaw r11, cp[$a]",
[]>;
let Defs = [R11], isReMaterializable = 1 in
def LDAWCP_lu6: _FLU6<0b0111111101, (outs), (ins MEMii:$a), "ldaw r11, cp[$a]",
[(set R11, ADDRcpii:$a)]>;
def LDAWCP_lu6: _FLU6<0b0111111101, (outs), (ins i32imm:$a), "ldaw r11, cp[$a]",
[(set R11, (cprelwrapper tglobaladdr:$a))]>;
let Defs = [R11] in
defm GETSR : FU6_LU6_np<0b0111111100, "getsr r11,">;