[llvm] r239169 - Revert r238473, "Thumb2: Modify codegen for memcpy intrinsic to prefer LDM/STM."
Peter Collingbourne
peter at pcc.me.uk
Fri Jun 5 11:01:28 PDT 2015
Author: pcc
Date: Fri Jun 5 13:01:28 2015
New Revision: 239169
URL: http://llvm.org/viewvc/llvm-project?rev=239169&view=rev
Log:
Revert r238473, "Thumb2: Modify codegen for memcpy intrinsic to prefer LDM/STM."
as it caused miscompilations and assertion failures (PR23768,
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150601/280380.html).
Modified:
llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
llvm/trunk/lib/Target/ARM/ARMISelLowering.h
llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
llvm/trunk/lib/Target/ARM/ARMSelectionDAGInfo.cpp
llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
llvm/trunk/lib/Target/ARM/Thumb2SizeReduction.cpp
llvm/trunk/test/CodeGen/Thumb/ldm-stm-base-materialization.ll
llvm/trunk/test/CodeGen/Thumb/thumb-memcpy-ldm-stm.ll
Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Jun 5 13:01:28 2015
@@ -1125,7 +1125,6 @@ const char *ARMTargetLowering::getTarget
case ARMISD::VORRIMM: return "ARMISD::VORRIMM";
case ARMISD::VBICIMM: return "ARMISD::VBICIMM";
case ARMISD::VBSL: return "ARMISD::VBSL";
- case ARMISD::MCOPY: return "ARMISD::MCOPY";
case ARMISD::VLD2DUP: return "ARMISD::VLD2DUP";
case ARMISD::VLD3DUP: return "ARMISD::VLD3DUP";
case ARMISD::VLD4DUP: return "ARMISD::VLD4DUP";
@@ -7676,59 +7675,8 @@ ARMTargetLowering::EmitInstrWithCustomIn
}
}
-/// \brief Lowers MCOPY to either LDMIA/STMIA or LDMIA_UPD/STMID_UPD depending
-/// on whether the result is used. This is done as a post-isel lowering instead
-/// of as a custom inserter because we need the use list from the SDNode.
-static void LowerMCOPY(const ARMSubtarget *Subtarget, MachineInstr *MI,
- SDNode *Node) {
- bool isThumb1 = Subtarget->isThumb1Only();
- bool isThumb2 = Subtarget->isThumb2();
- const ARMBaseInstrInfo *TII = Subtarget->getInstrInfo();
-
- DebugLoc dl = MI->getDebugLoc();
- MachineBasicBlock *BB = MI->getParent();
- MachineFunction *MF = BB->getParent();
- MachineRegisterInfo &MRI = MF->getRegInfo();
-
- MachineInstrBuilder LD, ST;
- if (isThumb1 || Node->hasAnyUseOfValue(1)) {
- LD = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA_UPD
- : isThumb1 ? ARM::tLDMIA_UPD
- : ARM::LDMIA_UPD))
- .addOperand(MI->getOperand(1));
- } else {
- LD = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));
- }
-
- if (isThumb1 || Node->hasAnyUseOfValue(0)) {
- ST = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA_UPD
- : isThumb1 ? ARM::tSTMIA_UPD
- : ARM::STMIA_UPD))
- .addOperand(MI->getOperand(0));
- } else {
- ST = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));
- }
-
- LD.addOperand(MI->getOperand(3)).addImm(ARMCC::AL).addReg(0);
- ST.addOperand(MI->getOperand(2)).addImm(ARMCC::AL).addReg(0);
-
- for (unsigned I = 0; I != MI->getOperand(4).getImm(); ++I) {
- unsigned TmpReg = MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
- : &ARM::GPRRegClass);
- LD.addReg(TmpReg, RegState::Define);
- ST.addReg(TmpReg, RegState::Kill);
- }
-
- MI->eraseFromParent();
-}
-
void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI,
SDNode *Node) const {
- if (MI->getOpcode() == ARM::MCOPY) {
- LowerMCOPY(Subtarget, MI, Node);
- return;
- }
-
const MCInstrDesc *MCID = &MI->getDesc();
// Adjust potentially 's' setting instructions after isel, i.e. ADC, SBC, RSB,
// RSC. Coming out of isel, they have an implicit CPSR def, but the optional
Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Fri Jun 5 13:01:28 2015
@@ -189,10 +189,6 @@ namespace llvm {
// Vector bitwise select
VBSL,
- // Pseudo-instruction representing a memory copy using ldm/stm
- // instructions.
- MCOPY,
-
// Vector load N-element structure to all lanes:
VLD2DUP = ISD::FIRST_TARGET_MEMORY_OPCODE,
VLD3DUP,
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Fri Jun 5 13:01:28 2015
@@ -73,10 +73,6 @@ def SDT_ARMBFI : SDTypeProfile<1, 3, [SD
def SDT_ARMVMAXNM : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisFP<1>, SDTCisFP<2>]>;
def SDT_ARMVMINNM : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisFP<1>, SDTCisFP<2>]>;
-def SDT_ARMMCOPY : SDTypeProfile<2, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
- SDTCisVT<2, i32>, SDTCisVT<3, i32>,
- SDTCisVT<4, i32>]>;
-
def SDTBinaryArithWithFlags : SDTypeProfile<2, 2,
[SDTCisSameAs<0, 2>,
SDTCisSameAs<0, 3>,
@@ -183,10 +179,6 @@ def ARMbfi : SDNode<"ARMISD::B
def ARMvmaxnm : SDNode<"ARMISD::VMAXNM", SDT_ARMVMAXNM, []>;
def ARMvminnm : SDNode<"ARMISD::VMINNM", SDT_ARMVMINNM, []>;
-def ARMmcopy : SDNode<"ARMISD::MCOPY", SDT_ARMMCOPY,
- [SDNPHasChain, SDNPInGlue, SDNPOutGlue,
- SDNPMayStore, SDNPMayLoad]>;
-
//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
//
@@ -4586,13 +4578,6 @@ let usesCustomInserter = 1 in {
[(ARMcopystructbyval GPR:$dst, GPR:$src, imm:$size, imm:$alignment)]>;
}
-let hasPostISelHook = 1 in {
- def MCOPY : PseudoInst<
- (outs GPR:$newdst, GPR:$newsrc), (ins GPR:$dst, GPR:$src, i32imm:$nreg),
- NoItinerary,
- [(set GPR:$newdst, GPR:$newsrc, (ARMmcopy GPR:$dst, GPR:$src, imm:$nreg))]>;
-}
-
def ldrex_1 : PatFrag<(ops node:$ptr), (int_arm_ldrex node:$ptr), [{
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
}]>;
Modified: llvm/trunk/lib/Target/ARM/ARMSelectionDAGInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSelectionDAGInfo.cpp?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMSelectionDAGInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMSelectionDAGInfo.cpp Fri Jun 5 13:01:28 2015
@@ -164,38 +164,41 @@ ARMSelectionDAGInfo::EmitTargetCodeForMe
unsigned VTSize = 4;
unsigned i = 0;
// Emit a maximum of 4 loads in Thumb1 since we have fewer registers
- const unsigned MaxLoadsInLDM = Subtarget.isThumb1Only() ? 4 : 6;
+ const unsigned MAX_LOADS_IN_LDM = Subtarget.isThumb1Only() ? 4 : 6;
SDValue TFOps[6];
SDValue Loads[6];
uint64_t SrcOff = 0, DstOff = 0;
- // FIXME: We should invent a VMCOPY pseudo-instruction that lowers to
- // VLDM/VSTM and make this code emit it when appropriate. This would reduce
- // pressure on the general purpose registers. However this seems harder to map
- // onto the register allocator's view of the world.
+ // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
+ // same number of stores. The loads and stores will get combined into
+ // ldm/stm later on.
+ while (EmittedNumMemOps < NumMemOps) {
+ for (i = 0;
+ i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
+ Loads[i] = DAG.getLoad(VT, dl, Chain,
+ DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
+ DAG.getConstant(SrcOff, dl, MVT::i32)),
+ SrcPtrInfo.getWithOffset(SrcOff), isVolatile,
+ false, false, 0);
+ TFOps[i] = Loads[i].getValue(1);
+ SrcOff += VTSize;
+ }
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ makeArrayRef(TFOps, i));
+
+ for (i = 0;
+ i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
+ TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
+ DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
+ DAG.getConstant(DstOff, dl, MVT::i32)),
+ DstPtrInfo.getWithOffset(DstOff),
+ isVolatile, false, 0);
+ DstOff += VTSize;
+ }
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ makeArrayRef(TFOps, i));
- // The number of MCOPY pseudo-instructions to emit. We use up to MaxLoadsInLDM
- // registers per mcopy, which will get lowered into ldm/stm later on. This is
- // a lower bound on the number of MCOPY operations we must emit.
- unsigned NumMCOPYs = (NumMemOps + MaxLoadsInLDM - 1) / MaxLoadsInLDM;
-
- SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other, MVT::Glue);
-
- for (unsigned I = 0; I != NumMCOPYs; ++I) {
- // Evenly distribute registers among MCOPY operations to reduce register
- // pressure.
- unsigned NextEmittedNumMemOps = NumMemOps * (I + 1) / NumMCOPYs;
- unsigned NumRegs = NextEmittedNumMemOps - EmittedNumMemOps;
-
- Dst = DAG.getNode(ARMISD::MCOPY, dl, VTs, Chain, Dst, Src,
- DAG.getConstant(NumRegs, dl, MVT::i32));
- Src = Dst.getValue(1);
- Chain = Dst.getValue(2);
-
- DstPtrInfo = DstPtrInfo.getWithOffset(NumRegs * VTSize);
- SrcPtrInfo = SrcPtrInfo.getWithOffset(NumRegs * VTSize);
-
- EmittedNumMemOps = NextEmittedNumMemOps;
+ EmittedNumMemOps += i;
}
if (BytesLeft == 0)
Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Fri Jun 5 13:01:28 2015
@@ -744,21 +744,10 @@ void ARMInstPrinter::printRegisterList(c
const MCSubtargetInfo &STI,
raw_ostream &O) {
O << "{";
-
- // The backend may have given us a register list in non-ascending order. Sort
- // it now.
- std::vector<MCOperand> RegOps(MI->size() - OpNum);
- std::copy(MI->begin() + OpNum, MI->end(), RegOps.begin());
- std::sort(RegOps.begin(), RegOps.end(),
- [this](const MCOperand &O1, const MCOperand &O2) -> bool {
- return MRI.getEncodingValue(O1.getReg()) <
- MRI.getEncodingValue(O2.getReg());
- });
-
- for (unsigned i = 0, e = RegOps.size(); i != e; ++i) {
- if (i != 0)
+ for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
+ if (i != OpNum)
O << ", ";
- printRegName(O, RegOps[i].getReg());
+ printRegName(O, MI->getOperand(i).getReg());
}
O << "}";
}
Modified: llvm/trunk/lib/Target/ARM/Thumb2SizeReduction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb2SizeReduction.cpp?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb2SizeReduction.cpp (original)
+++ llvm/trunk/lib/Target/ARM/Thumb2SizeReduction.cpp Fri Jun 5 13:01:28 2015
@@ -125,10 +125,7 @@ namespace {
{ ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
{ ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 0,1,0 },
{ ARM::t2LDMIA_UPD,ARM::tLDMIA_UPD,ARM::tPOP,0, 0, 1, 1, 1,1, 0,1,0 },
- // ARM::t2STMIA (with no basereg writeback) has no Thumb1 equivalent.
- // tSTMIA_UPD is a change in semantics which can only be used if the base
- // register is killed. This difference is correctly handled elsewhere.
- { ARM::t2STMIA, ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
+ // ARM::t2STM (with no basereg writeback) has no Thumb1 equivalent
{ ARM::t2STMIA_UPD,ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
{ ARM::t2STMDB_UPD, 0, ARM::tPUSH, 0, 0, 1, 1, 1,1, 0,1,0 }
};
@@ -435,14 +432,6 @@ Thumb2SizeReduce::ReduceLoadStore(Machin
isLdStMul = true;
break;
}
- case ARM::t2STMIA: {
- // If the base register is killed, we don't care what its value is after the
- // instruction, so we can use an updating STMIA.
- if (!MI->getOperand(0).isKill())
- return false;
-
- break;
- }
case ARM::t2LDMIA_RET: {
unsigned BaseReg = MI->getOperand(1).getReg();
if (BaseReg != ARM::SP)
@@ -500,12 +489,6 @@ Thumb2SizeReduce::ReduceLoadStore(Machin
// Add the 16-bit load / store instruction.
DebugLoc dl = MI->getDebugLoc();
MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, TII->get(Opc));
-
- // tSTMIA_UPD takes a defining register operand. We've already checked that
- // the register is killed, so mark it as dead here.
- if (Entry.WideOpc == ARM::t2STMIA)
- MIB.addReg(MI->getOperand(0).getReg(), RegState::Define | RegState::Dead);
-
if (!isLdStMul) {
MIB.addOperand(MI->getOperand(0));
MIB.addOperand(MI->getOperand(1));
Modified: llvm/trunk/test/CodeGen/Thumb/ldm-stm-base-materialization.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/ldm-stm-base-materialization.ll?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb/ldm-stm-base-materialization.ll (original)
+++ llvm/trunk/test/CodeGen/Thumb/ldm-stm-base-materialization.ll Fri Jun 5 13:01:28 2015
@@ -6,89 +6,22 @@ target triple = "thumbv6m-none--eabi"
@b = external global i32*
; Function Attrs: nounwind
-define void @foo24() #0 {
+define void @foo() #0 {
entry:
-; CHECK-LABEL: foo24:
-; CHECK: ldr r[[LB:[0-9]]], .LCPI
-; CHECK: adds r[[NLB:[0-9]]], r[[LB]], #4
-; CHECK: ldr r[[SB:[0-9]]], .LCPI
-; CHECK: adds r[[NSB:[0-9]]], r[[SB]], #4
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]]}
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]]}
- %0 = load i32*, i32** @a, align 4
- %arrayidx = getelementptr inbounds i32, i32* %0, i32 1
- %1 = bitcast i32* %arrayidx to i8*
- %2 = load i32*, i32** @b, align 4
- %arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1
- %3 = bitcast i32* %arrayidx1 to i8*
- tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %3, i32 24, i32 4, i1 false)
- ret void
-}
-
-define void @foo28() #0 {
-entry:
-; CHECK-LABEL: foo28:
-; CHECK: ldr r[[LB:[0-9]]], .LCPI
-; CHECK: adds r[[NLB:[0-9]]], r[[LB]], #4
-; CHECK: ldr r[[SB:[0-9]]], .LCPI
-; CHECK: adds r[[NSB:[0-9]]], r[[SB]], #4
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]]}
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]], r[[R4:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]], r[[R4]]}
- %0 = load i32*, i32** @a, align 4
- %arrayidx = getelementptr inbounds i32, i32* %0, i32 1
- %1 = bitcast i32* %arrayidx to i8*
- %2 = load i32*, i32** @b, align 4
- %arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1
- %3 = bitcast i32* %arrayidx1 to i8*
- tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %3, i32 28, i32 4, i1 false)
- ret void
-}
-
-define void @foo32() #0 {
-entry:
-; CHECK-LABEL: foo32:
-; CHECK: ldr r[[LB:[0-9]]], .LCPI
-; CHECK: adds r[[NLB:[0-9]]], r[[LB]], #4
+; CHECK-LABEL: foo:
; CHECK: ldr r[[SB:[0-9]]], .LCPI
-; CHECK: adds r[[NSB:[0-9]]], r[[SB]], #4
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]], r[[R4:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]], r[[R4]]}
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]], r[[R4:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]], r[[R4]]}
- %0 = load i32*, i32** @a, align 4
- %arrayidx = getelementptr inbounds i32, i32* %0, i32 1
- %1 = bitcast i32* %arrayidx to i8*
- %2 = load i32*, i32** @b, align 4
- %arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1
- %3 = bitcast i32* %arrayidx1 to i8*
- tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %3, i32 32, i32 4, i1 false)
- ret void
-}
-
-define void @foo36() #0 {
-entry:
-; CHECK-LABEL: foo36:
; CHECK: ldr r[[LB:[0-9]]], .LCPI
; CHECK: adds r[[NLB:[0-9]]], r[[LB]], #4
-; CHECK: ldr r[[SB:[0-9]]], .LCPI
+; CHECK-NEXT: ldm r[[NLB]],
; CHECK: adds r[[NSB:[0-9]]], r[[SB]], #4
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]]}
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]]}
-; CHECK-NEXT: ldm r[[NLB]]!, {r[[R1:[0-9]]], r[[R2:[0-9]]], r[[R3:[0-9]]]}
-; CHECK-NEXT: stm r[[NSB]]!, {r[[R1]], r[[R2]], r[[R3]]}
+; CHECK-NEXT: stm r[[NSB]]
%0 = load i32*, i32** @a, align 4
%arrayidx = getelementptr inbounds i32, i32* %0, i32 1
%1 = bitcast i32* %arrayidx to i8*
%2 = load i32*, i32** @b, align 4
%arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1
%3 = bitcast i32* %arrayidx1 to i8*
- tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %3, i32 36, i32 4, i1 false)
+ tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %3, i32 24, i32 4, i1 false)
ret void
}
Modified: llvm/trunk/test/CodeGen/Thumb/thumb-memcpy-ldm-stm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/thumb-memcpy-ldm-stm.ll?rev=239169&r1=239168&r2=239169&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb/thumb-memcpy-ldm-stm.ll (original)
+++ llvm/trunk/test/CodeGen/Thumb/thumb-memcpy-ldm-stm.ll Fri Jun 5 13:01:28 2015
@@ -7,8 +7,8 @@ define void @t1() #0 {
entry:
; CHECK-LABEL: t1:
; CHECK: ldr r[[LB:[0-9]]],
-; CHECK-NEXT: ldr r[[SB:[0-9]]],
; CHECK-NEXT: ldm r[[LB]]!,
+; CHECK-NEXT: ldr r[[SB:[0-9]]],
; CHECK-NEXT: stm r[[SB]]!,
; CHECK-NEXT: ldrb {{.*}}, [r[[LB]]]
; CHECK-NEXT: strb {{.*}}, [r[[SB]]]
@@ -21,8 +21,8 @@ define void @t2() #0 {
entry:
; CHECK-LABEL: t2:
; CHECK: ldr r[[LB:[0-9]]],
-; CHECK-NEXT: ldr r[[SB:[0-9]]],
; CHECK-NEXT: ldm r[[LB]]!,
+; CHECK-NEXT: ldr r[[SB:[0-9]]],
; CHECK-NEXT: stm r[[SB]]!,
; CHECK-NEXT: ldrh {{.*}}, [r[[LB]]]
; CHECK-NEXT: ldrb {{.*}}, [r[[LB]], #2]
More information about the llvm-commits
mailing list