llvm.org GIT mirror llvm / 886b940
Merging r204155: ------------------------------------------------------------------------ r204155 | wschmidt | 2014-03-18 10:32:50 -0400 (Tue, 18 Mar 2014) | 16 lines 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/branches/release_34@205824 91177308-0d34-0410-b5e6-96231b3b80d8 Tom Stellard 6 years ago
2 changed file(s) with 158 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
891891 unsigned LoadOpc = PPC::LFD;
892892
893893 if (SrcVT == MVT::i32) {
894 Addr.Offset = 4;
895 if (!IsSigned)
894 if (!IsSigned) {
896895 LoadOpc = PPC::LFIWZX;
897 else if (PPCSubTarget.hasLFIWAX())
896 Addr.Offset = 4;
897 } else if (PPCSubTarget.hasLFIWAX()) {
898898 LoadOpc = PPC::LFIWAX;
899 Addr.Offset = 4;
900 }
899901 }
900902
901903 const TargetRegisterClass *RC = &PPC::F8RCRegClass;
0 ; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr5 | FileCheck %s --check-prefix=ELF64
1
2 ; Test sitofp
3
4 define void @sitofp_double_i32(i32 %a, double %b) nounwind ssp {
5 entry:
6 ; ELF64: sitofp_double_i32
7 %b.addr = alloca double, align 8
8 %conv = sitofp i32 %a to double
9 ; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
10 ; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
11 ; ELF64: fcfid
12 store double %conv, double* %b.addr, align 8
13 ret void
14 }
15
16 define void @sitofp_double_i64(i64 %a, double %b) nounwind ssp {
17 entry:
18 ; ELF64: sitofp_double_i64
19 %b.addr = alloca double, align 8
20 %conv = sitofp i64 %a to double
21 ; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
22 ; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
23 ; ELF64: fcfid
24 store double %conv, double* %b.addr, align 8
25 ret void
26 }
27
28 define void @sitofp_double_i16(i16 %a, double %b) nounwind ssp {
29 entry:
30 ; ELF64: sitofp_double_i16
31 %b.addr = alloca double, align 8
32 %conv = sitofp i16 %a to double
33 ; ELF64: extsh
34 ; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
35 ; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
36 ; ELF64: fcfid
37 store double %conv, double* %b.addr, align 8
38 ret void
39 }
40
41 define void @sitofp_double_i8(i8 %a, double %b) nounwind ssp {
42 entry:
43 ; ELF64: sitofp_double_i8
44 %b.addr = alloca double, align 8
45 %conv = sitofp i8 %a to double
46 ; ELF64: extsb
47 ; ELF64: std {{[0-9]+}}, -[[OFFSET:[0-9]+]](1)
48 ; ELF64: lfd {{[0-9]+}}, -[[OFFSET]](1)
49 ; ELF64: fcfid
50 store double %conv, double* %b.addr, align 8
51 ret void
52 }
53
54 ; Test fptosi
55
56 define void @fptosi_float_i32(float %a) nounwind ssp {
57 entry:
58 ; ELF64: fptosi_float_i32
59 %b.addr = alloca i32, align 4
60 %conv = fptosi float %a to i32
61 ; ELF64: fctiwz
62 ; ELF64: stfd
63 ; ELF64: lwa
64 store i32 %conv, i32* %b.addr, align 4
65 ret void
66 }
67
68 define void @fptosi_float_i64(float %a) nounwind ssp {
69 entry:
70 ; ELF64: fptosi_float_i64
71 %b.addr = alloca i64, align 4
72 %conv = fptosi float %a to i64
73 ; ELF64: fctidz
74 ; ELF64: stfd
75 ; ELF64: ld
76 store i64 %conv, i64* %b.addr, align 4
77 ret void
78 }
79
80 define void @fptosi_double_i32(double %a) nounwind ssp {
81 entry:
82 ; ELF64: fptosi_double_i32
83 %b.addr = alloca i32, align 8
84 %conv = fptosi double %a to i32
85 ; ELF64: fctiwz
86 ; ELF64: stfd
87 ; ELF64: lwa
88 store i32 %conv, i32* %b.addr, align 8
89 ret void
90 }
91
92 define void @fptosi_double_i64(double %a) nounwind ssp {
93 entry:
94 ; ELF64: fptosi_double_i64
95 %b.addr = alloca i64, align 8
96 %conv = fptosi double %a to i64
97 ; ELF64: fctidz
98 ; ELF64: stfd
99 ; ELF64: ld
100 store i64 %conv, i64* %b.addr, align 8
101 ret void
102 }
103
104 ; Test fptoui
105
106 define void @fptoui_float_i32(float %a) nounwind ssp {
107 entry:
108 ; ELF64: fptoui_float_i32
109 %b.addr = alloca i32, align 4
110 %conv = fptoui float %a to i32
111 ; ELF64: fctidz
112 ; ELF64: stfd
113 ; ELF64: lwz
114 store i32 %conv, i32* %b.addr, align 4
115 ret void
116 }
117
118 define void @fptoui_float_i64(float %a) nounwind ssp {
119 entry:
120 ; ELF64: fptoui_float_i64
121 %b.addr = alloca i64, align 4
122 %conv = fptoui float %a to i64
123 ; ELF64: fctiduz
124 ; ELF64: stfd
125 ; ELF64: ld
126 store i64 %conv, i64* %b.addr, align 4
127 ret void
128 }
129
130 define void @fptoui_double_i32(double %a) nounwind ssp {
131 entry:
132 ; ELF64: fptoui_double_i32
133 %b.addr = alloca i32, align 8
134 %conv = fptoui double %a to i32
135 ; ELF64: fctidz
136 ; ELF64: stfd
137 ; ELF64: lwz
138 store i32 %conv, i32* %b.addr, align 8
139 ret void
140 }
141
142 define void @fptoui_double_i64(double %a) nounwind ssp {
143 entry:
144 ; ELF64: fptoui_double_i64
145 %b.addr = alloca i64, align 8
146 %conv = fptoui double %a to i64
147 ; ELF64: fctiduz
148 ; ELF64: stfd
149 ; ELF64: ld
150 store i64 %conv, i64* %b.addr, align 8
151 ret void
152 }