mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 06:30:39 +00:00
Fix PR19144: Incorrect offset generated for int-to-fp conversion at -O0.
When converting a signed 32-bit integer to double-precision floating point on hardware without a lfiwax instruction, we have to instead use a lfd followed by fcfid. We were erroneously offsetting the address by 4 bytes in preparation for either a lfiwax or lfiwzx when generating the lfd. This fixes that silly error. This was not caught in the test suite since the conversion tests were run with -mcpu=pwr7, which implies availability of lfiwax. I've added another test case for older hardware that checks the code we expect in the absence of lfiwax and other flavors of fcfid. There are fewer tests in this test case because we punt to DAG selection in more cases on older hardware. (We must generate complex fiddly sequences in those cases, and there is marginal benefit in duplicating that logic in fast-isel.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204155 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
610469f4c2
commit
d4585b941a
@ -898,11 +898,13 @@ unsigned PPCFastISel::PPCMoveToFPReg(MVT SrcVT, unsigned SrcReg,
|
||||
unsigned LoadOpc = PPC::LFD;
|
||||
|
||||
if (SrcVT == MVT::i32) {
|
||||
Addr.Offset = 4;
|
||||
if (!IsSigned)
|
||||
if (!IsSigned) {
|
||||
LoadOpc = PPC::LFIWZX;
|
||||
else if (PPCSubTarget.hasLFIWAX())
|
||||
Addr.Offset = 4;
|
||||
} else if (PPCSubTarget.hasLFIWAX()) {
|
||||
LoadOpc = PPC::LFIWAX;
|
||||
Addr.Offset = 4;
|
||||
}
|
||||
}
|
||||
|
||||
const TargetRegisterClass *RC = &PPC::F8RCRegClass;
|
||||
|
153
test/CodeGen/PowerPC/fast-isel-conversion-p5.ll
Normal file
153
test/CodeGen/PowerPC/fast-isel-conversion-p5.ll
Normal file
@ -0,0 +1,153 @@
|
||||
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr5 | FileCheck %s --check-prefix=ELF64
|
||||
|
||||
; Test sitofp
|
||||
|
||||
define void @sitofp_double_i32(i32 %a, double %b) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: sitofp_double_i32
|
||||
%b.addr = alloca double, align 8
|
||||
%conv = sitofp i32 %a to double
|
||||
; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
|
||||
; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
|
||||
; ELF64: fcfid
|
||||
store double %conv, double* %b.addr, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sitofp_double_i64(i64 %a, double %b) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: sitofp_double_i64
|
||||
%b.addr = alloca double, align 8
|
||||
%conv = sitofp i64 %a to double
|
||||
; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
|
||||
; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
|
||||
; ELF64: fcfid
|
||||
store double %conv, double* %b.addr, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sitofp_double_i16(i16 %a, double %b) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: sitofp_double_i16
|
||||
%b.addr = alloca double, align 8
|
||||
%conv = sitofp i16 %a to double
|
||||
; ELF64: extsh
|
||||
; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
|
||||
; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
|
||||
; ELF64: fcfid
|
||||
store double %conv, double* %b.addr, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sitofp_double_i8(i8 %a, double %b) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: sitofp_double_i8
|
||||
%b.addr = alloca double, align 8
|
||||
%conv = sitofp i8 %a to double
|
||||
; ELF64: extsb
|
||||
; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
|
||||
; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
|
||||
; ELF64: fcfid
|
||||
store double %conv, double* %b.addr, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; Test fptosi
|
||||
|
||||
define void @fptosi_float_i32(float %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptosi_float_i32
|
||||
%b.addr = alloca i32, align 4
|
||||
%conv = fptosi float %a to i32
|
||||
; ELF64: fctiwz
|
||||
; ELF64: stfd
|
||||
; ELF64: lwa
|
||||
store i32 %conv, i32* %b.addr, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @fptosi_float_i64(float %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptosi_float_i64
|
||||
%b.addr = alloca i64, align 4
|
||||
%conv = fptosi float %a to i64
|
||||
; ELF64: fctidz
|
||||
; ELF64: stfd
|
||||
; ELF64: ld
|
||||
store i64 %conv, i64* %b.addr, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @fptosi_double_i32(double %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptosi_double_i32
|
||||
%b.addr = alloca i32, align 8
|
||||
%conv = fptosi double %a to i32
|
||||
; ELF64: fctiwz
|
||||
; ELF64: stfd
|
||||
; ELF64: lwa
|
||||
store i32 %conv, i32* %b.addr, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @fptosi_double_i64(double %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptosi_double_i64
|
||||
%b.addr = alloca i64, align 8
|
||||
%conv = fptosi double %a to i64
|
||||
; ELF64: fctidz
|
||||
; ELF64: stfd
|
||||
; ELF64: ld
|
||||
store i64 %conv, i64* %b.addr, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; Test fptoui
|
||||
|
||||
define void @fptoui_float_i32(float %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptoui_float_i32
|
||||
%b.addr = alloca i32, align 4
|
||||
%conv = fptoui float %a to i32
|
||||
; ELF64: fctidz
|
||||
; ELF64: stfd
|
||||
; ELF64: lwz
|
||||
store i32 %conv, i32* %b.addr, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @fptoui_float_i64(float %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptoui_float_i64
|
||||
%b.addr = alloca i64, align 4
|
||||
%conv = fptoui float %a to i64
|
||||
; ELF64: fctiduz
|
||||
; ELF64: stfd
|
||||
; ELF64: ld
|
||||
store i64 %conv, i64* %b.addr, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @fptoui_double_i32(double %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptoui_double_i32
|
||||
%b.addr = alloca i32, align 8
|
||||
%conv = fptoui double %a to i32
|
||||
; ELF64: fctidz
|
||||
; ELF64: stfd
|
||||
; ELF64: lwz
|
||||
store i32 %conv, i32* %b.addr, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @fptoui_double_i64(double %a) nounwind ssp {
|
||||
entry:
|
||||
; ELF64: fptoui_double_i64
|
||||
%b.addr = alloca i64, align 8
|
||||
%conv = fptoui double %a to i64
|
||||
; ELF64: fctiduz
|
||||
; ELF64: stfd
|
||||
; ELF64: ld
|
||||
store i64 %conv, i64* %b.addr, align 8
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue
Block a user