forked from OSchip/llvm-project
ARM: check alignment before transforming ldr -> ldm (or similar).
ldm and stm instructions always require 4-byte alignment on the pointer, but we weren't checking this before trying to reduce code-size by replacing a post-indexed load/store with them. Unfortunately, we were also dropping this incormation in DAG ISel too, but that's easy enough to fix. llvm-svn: 281893
This commit is contained in:
parent
59f6f8c05d
commit
eaee28b5ca
|
@ -193,6 +193,8 @@ public:
|
||||||
#include "ARMGenDAGISel.inc"
|
#include "ARMGenDAGISel.inc"
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void transferMemOperands(SDNode *Src, SDNode *Dst);
|
||||||
|
|
||||||
/// Indexed (pre/post inc/dec) load matching code for ARM.
|
/// Indexed (pre/post inc/dec) load matching code for ARM.
|
||||||
bool tryARMIndexedLoad(SDNode *N);
|
bool tryARMIndexedLoad(SDNode *N);
|
||||||
bool tryT1IndexedLoad(SDNode *N);
|
bool tryT1IndexedLoad(SDNode *N);
|
||||||
|
@ -1471,6 +1473,12 @@ static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
|
||||||
return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
|
return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
|
||||||
|
MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
|
||||||
|
MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
|
||||||
|
cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
|
||||||
|
}
|
||||||
|
|
||||||
bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
|
bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
|
||||||
LoadSDNode *LD = cast<LoadSDNode>(N);
|
LoadSDNode *LD = cast<LoadSDNode>(N);
|
||||||
ISD::MemIndexedMode AM = LD->getAddressingMode();
|
ISD::MemIndexedMode AM = LD->getAddressingMode();
|
||||||
|
@ -1529,16 +1537,20 @@ bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
|
||||||
SDValue Base = LD->getBasePtr();
|
SDValue Base = LD->getBasePtr();
|
||||||
SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
|
SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
|
||||||
CurDAG->getRegister(0, MVT::i32), Chain };
|
CurDAG->getRegister(0, MVT::i32), Chain };
|
||||||
ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
|
SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
|
||||||
MVT::i32, MVT::Other, Ops));
|
MVT::Other, Ops);
|
||||||
|
transferMemOperands(N, New);
|
||||||
|
ReplaceNode(N, New);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
SDValue Chain = LD->getChain();
|
SDValue Chain = LD->getChain();
|
||||||
SDValue Base = LD->getBasePtr();
|
SDValue Base = LD->getBasePtr();
|
||||||
SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
|
SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
|
||||||
CurDAG->getRegister(0, MVT::i32), Chain };
|
CurDAG->getRegister(0, MVT::i32), Chain };
|
||||||
ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
|
SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
|
||||||
MVT::i32, MVT::Other, Ops));
|
MVT::Other, Ops);
|
||||||
|
transferMemOperands(N, New);
|
||||||
|
ReplaceNode(N, New);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1566,8 +1578,10 @@ bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
|
||||||
SDValue Base = LD->getBasePtr();
|
SDValue Base = LD->getBasePtr();
|
||||||
SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
|
SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
|
||||||
CurDAG->getRegister(0, MVT::i32), Chain };
|
CurDAG->getRegister(0, MVT::i32), Chain };
|
||||||
ReplaceNode(N, CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32, MVT::i32,
|
SDNode *New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32,
|
||||||
MVT::Other, Ops));
|
MVT::i32, MVT::Other, Ops);
|
||||||
|
transferMemOperands(N, New);
|
||||||
|
ReplaceNode(N, New);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1612,8 +1626,10 @@ bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
|
||||||
SDValue Base = LD->getBasePtr();
|
SDValue Base = LD->getBasePtr();
|
||||||
SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
|
SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
|
||||||
CurDAG->getRegister(0, MVT::i32), Chain };
|
CurDAG->getRegister(0, MVT::i32), Chain };
|
||||||
ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
|
SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
|
||||||
MVT::Other, Ops));
|
MVT::Other, Ops);
|
||||||
|
transferMemOperands(N, New);
|
||||||
|
ReplaceNode(N, New);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -430,6 +430,10 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||||
if (!MBB.getParent()->getFunction()->optForMinSize())
|
if (!MBB.getParent()->getFunction()->optForMinSize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!MI->hasOneMemOperand() ||
|
||||||
|
(*MI->memoperands_begin())->getAlignment() < 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
// We're creating a completely different type of load/store - LDM from LDR.
|
// We're creating a completely different type of load/store - LDM from LDR.
|
||||||
// For this reason we can't reuse the logic at the end of this function; we
|
// For this reason we can't reuse the logic at the end of this function; we
|
||||||
// have to implement the MI building here.
|
// have to implement the MI building here.
|
||||||
|
|
|
@ -98,3 +98,16 @@ false:
|
||||||
store i32* %next, i32** %addr2
|
store i32* %next, i32** %addr2
|
||||||
ret i32 %res
|
ret i32 %res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; ldm instructions fault on misaligned accesses so we mustn't convert
|
||||||
|
; this post-indexed ldr into one.
|
||||||
|
define i32* @misaligned_post(i32* %src, i32* %dest) minsize {
|
||||||
|
; CHECK-LABEL: misaligned_post:
|
||||||
|
; CHECK: ldr [[VAL:.*]], [r0], #4
|
||||||
|
; CHECK: str [[VAL]], [r1]
|
||||||
|
|
||||||
|
%val = load i32, i32* %src, align 1
|
||||||
|
store i32 %val, i32* %dest
|
||||||
|
%next = getelementptr i32, i32* %src, i32 1
|
||||||
|
ret i32* %next
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue