[arm-fast-isel] Unaligned stores of floats require special care.

rdar://10510150

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@145742 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chad Rosier 2011-12-03 02:21:57 +00:00
parent de2e27cc52
commit 9eff1e33f6
2 changed files with 40 additions and 3 deletions

View File

@ -181,7 +181,7 @@ class ARMFastISel : public FastISel {
bool ARMEmitLoad(EVT VT, unsigned &ResultReg, Address &Addr, bool isZExt,
bool allocReg);
bool ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr);
bool ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr, unsigned Alignment = 0);
bool ARMComputeAddress(const Value *Obj, Address &Addr);
void ARMSimplifyAddress(Address &Addr, EVT VT, bool useAM3);
bool ARMIsMemCpySmall(uint64_t Len);
@ -1053,7 +1053,7 @@ bool ARMFastISel::SelectLoad(const Instruction *I) {
return true;
}
bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr) {
bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr, unsigned Alignment) {
unsigned StrOpc;
bool useAM3 = false;
switch (VT.getSimpleVT().SimpleTy) {
@ -1102,9 +1102,23 @@ bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr) {
case MVT::f32:
if (!Subtarget->hasVFP2()) return false;
StrOpc = ARM::VSTRS;
// Unaligned stores need special handling.
if (Alignment && Alignment < 4) {
unsigned MoveReg = createResultReg(TLI.getRegClassFor(MVT::i32));
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(ARM::VMOVRS), MoveReg)
.addReg(SrcReg));
SrcReg = MoveReg;
VT = MVT::i32;
StrOpc = isThumb2 ? ARM::t2STRi12 : ARM::STRi12;
}
break;
case MVT::f64:
if (!Subtarget->hasVFP2()) return false;
// FIXME: Unaligned stores need special handling.
if (Alignment && Alignment < 8) {
return false;
}
StrOpc = ARM::VSTRD;
break;
}
@ -1141,7 +1155,8 @@ bool ARMFastISel::SelectStore(const Instruction *I) {
if (!ARMComputeAddress(I->getOperand(1), Addr))
return false;
if (!ARMEmitStore(VT, SrcReg, Addr)) return false;
if (!ARMEmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
return false;
return true;
}

View File

@ -158,3 +158,25 @@ define void @test4() {
; ARM: ldr r1, [r1]
; ARM: str r0, [r1]
}
; Check unaligned stores
%struct.anon = type <{ float }>
@a = common global %struct.anon* null, align 4
define void @unaligned_store(float %x, float %y) nounwind {
entry:
; ARM: @unaligned_store
; ARM: vmov r1, s0
; ARM: str r1, [r0]
; THUMB: @unaligned_store
; THUMB: vmov r1, s0
; THUMB: str r1, [r0]
%add = fadd float %x, %y
%0 = load %struct.anon** @a, align 4
%x1 = getelementptr inbounds %struct.anon* %0, i32 0, i32 0
store float %add, float* %x1, align 1
ret void
}