OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the TargetLoweringX8632 class, which | 10 // This file implements the TargetLoweringX8632 class, which |
(...skipping 2079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2090 } else if (Dest->getType() == IceType_i64) { | 2090 } else if (Dest->getType() == IceType_i64) { |
2091 // Use a helper for converting floating-point values to 64-bit | 2091 // Use a helper for converting floating-point values to 64-bit |
2092 // integers. SSE2 appears to have no way to convert from xmm | 2092 // integers. SSE2 appears to have no way to convert from xmm |
2093 // registers to something like the edx:eax register pair, and | 2093 // registers to something like the edx:eax register pair, and |
2094 // gcc and clang both want to use x87 instructions complete with | 2094 // gcc and clang both want to use x87 instructions complete with |
2095 // temporary manipulation of the status word. This helper is | 2095 // temporary manipulation of the status word. This helper is |
2096 // not needed for x86-64. | 2096 // not needed for x86-64. |
2097 split64(Dest); | 2097 split64(Dest); |
2098 const SizeT MaxSrcs = 1; | 2098 const SizeT MaxSrcs = 1; |
2099 Type SrcType = Inst->getSrc(0)->getType(); | 2099 Type SrcType = Inst->getSrc(0)->getType(); |
2100 InstCall *Call = makeHelperCall( | 2100 InstCall *Call = makeHelperCall(isFloat32Asserting32Or64(SrcType) |
2101 isFloat32Asserting32Or64(SrcType) ? "cvtftosi64" : "cvtdtosi64", Dest, | 2101 ? "__Sz_fptosi_f32_i64" |
Mircea Trofin
2015/02/28 00:45:35
Do we expect to use these strings anywhere else, s
Jim Stichnoth
2015/02/28 02:35:44
Good point. It's likely that these and more will
Mircea Trofin
2015/02/28 03:28:56
Why would the use during lowering be faster?
Jim Stichnoth
2015/02/28 04:44:28
I'm assuming that copying a constant IceString (i.
| |
2102 MaxSrcs); | 2102 : "__Sz_fptosi_f64_i64", |
2103 // TODO: Call the correct compiler-rt helper function. | 2103 Dest, MaxSrcs); |
2104 Call->addArg(Inst->getSrc(0)); | 2104 Call->addArg(Inst->getSrc(0)); |
2105 lowerCall(Call); | 2105 lowerCall(Call); |
2106 } else { | 2106 } else { |
2107 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 2107 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
2108 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type | 2108 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
2109 Variable *T_1 = makeReg(IceType_i32); | 2109 Variable *T_1 = makeReg(IceType_i32); |
2110 Variable *T_2 = makeReg(Dest->getType()); | 2110 Variable *T_2 = makeReg(Dest->getType()); |
2111 _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si); | 2111 _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si); |
2112 _mov(T_2, T_1); // T_1 and T_2 may have different integer types | 2112 _mov(T_2, T_1); // T_1 and T_2 may have different integer types |
2113 if (Dest->getType() == IceType_i1) | 2113 if (Dest->getType() == IceType_i1) |
2114 _and(T_2, Ctx->getConstantInt1(1)); | 2114 _and(T_2, Ctx->getConstantInt1(1)); |
2115 _mov(Dest, T_2); | 2115 _mov(Dest, T_2); |
2116 } | 2116 } |
2117 break; | 2117 break; |
2118 case InstCast::Fptoui: | 2118 case InstCast::Fptoui: |
2119 if (isVectorType(Dest->getType())) { | 2119 if (isVectorType(Dest->getType())) { |
2120 assert(Dest->getType() == IceType_v4i32 && | 2120 assert(Dest->getType() == IceType_v4i32 && |
2121 Inst->getSrc(0)->getType() == IceType_v4f32); | 2121 Inst->getSrc(0)->getType() == IceType_v4f32); |
2122 const SizeT MaxSrcs = 1; | 2122 const SizeT MaxSrcs = 1; |
2123 InstCall *Call = makeHelperCall("Sz_fptoui_v4f32", Dest, MaxSrcs); | 2123 InstCall *Call = makeHelperCall("__Sz_fptoui_4xi32_f32", Dest, MaxSrcs); |
2124 Call->addArg(Inst->getSrc(0)); | 2124 Call->addArg(Inst->getSrc(0)); |
2125 lowerCall(Call); | 2125 lowerCall(Call); |
2126 } else if (Dest->getType() == IceType_i64 || | 2126 } else if (Dest->getType() == IceType_i64 || |
2127 Dest->getType() == IceType_i32) { | 2127 Dest->getType() == IceType_i32) { |
2128 // Use a helper for both x86-32 and x86-64. | 2128 // Use a helper for both x86-32 and x86-64. |
2129 split64(Dest); | 2129 split64(Dest); |
2130 const SizeT MaxSrcs = 1; | 2130 const SizeT MaxSrcs = 1; |
2131 Type DestType = Dest->getType(); | 2131 Type DestType = Dest->getType(); |
2132 Type SrcType = Inst->getSrc(0)->getType(); | 2132 Type SrcType = Inst->getSrc(0)->getType(); |
2133 IceString DstSubstring = (isInt32Asserting32Or64(DestType) ? "32" : "64"); | 2133 IceString TargetString; |
2134 IceString SrcSubstring = (isFloat32Asserting32Or64(SrcType) ? "f" : "d"); | 2134 if (isInt32Asserting32Or64(DestType)) { |
2135 // Possibilities are cvtftoui32, cvtdtoui32, cvtftoui64, cvtdtoui64 | 2135 TargetString = isFloat32Asserting32Or64(SrcType) |
2136 IceString TargetString = "cvt" + SrcSubstring + "toui" + DstSubstring; | 2136 ? "__Sz_fptoui_f32_i32" |
2137 // TODO: Call the correct compiler-rt helper function. | 2137 : "__Sz_fptoui_f64_i32"; |
2138 } else { | |
2139 TargetString = isFloat32Asserting32Or64(SrcType) | |
2140 ? "__Sz_fptoui_f32_i64" | |
2141 : "__Sz_fptoui_f64_i64"; | |
2142 } | |
2138 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); | 2143 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); |
2139 Call->addArg(Inst->getSrc(0)); | 2144 Call->addArg(Inst->getSrc(0)); |
2140 lowerCall(Call); | 2145 lowerCall(Call); |
2141 return; | 2146 return; |
2142 } else { | 2147 } else { |
2143 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 2148 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
2144 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type | 2149 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
2145 Variable *T_1 = makeReg(IceType_i32); | 2150 Variable *T_1 = makeReg(IceType_i32); |
2146 Variable *T_2 = makeReg(Dest->getType()); | 2151 Variable *T_2 = makeReg(Dest->getType()); |
2147 _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si); | 2152 _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si); |
2148 _mov(T_2, T_1); // T_1 and T_2 may have different integer types | 2153 _mov(T_2, T_1); // T_1 and T_2 may have different integer types |
2149 if (Dest->getType() == IceType_i1) | 2154 if (Dest->getType() == IceType_i1) |
2150 _and(T_2, Ctx->getConstantInt1(1)); | 2155 _and(T_2, Ctx->getConstantInt1(1)); |
2151 _mov(Dest, T_2); | 2156 _mov(Dest, T_2); |
2152 } | 2157 } |
2153 break; | 2158 break; |
2154 case InstCast::Sitofp: | 2159 case InstCast::Sitofp: |
2155 if (isVectorType(Dest->getType())) { | 2160 if (isVectorType(Dest->getType())) { |
2156 assert(Dest->getType() == IceType_v4f32 && | 2161 assert(Dest->getType() == IceType_v4f32 && |
2157 Inst->getSrc(0)->getType() == IceType_v4i32); | 2162 Inst->getSrc(0)->getType() == IceType_v4i32); |
2158 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 2163 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
2159 Variable *T = makeReg(Dest->getType()); | 2164 Variable *T = makeReg(Dest->getType()); |
2160 _cvt(T, Src0RM, InstX8632Cvt::Dq2ps); | 2165 _cvt(T, Src0RM, InstX8632Cvt::Dq2ps); |
2161 _movp(Dest, T); | 2166 _movp(Dest, T); |
2162 } else if (Inst->getSrc(0)->getType() == IceType_i64) { | 2167 } else if (Inst->getSrc(0)->getType() == IceType_i64) { |
2163 // Use a helper for x86-32. | 2168 // Use a helper for x86-32. |
2164 const SizeT MaxSrcs = 1; | 2169 const SizeT MaxSrcs = 1; |
2165 Type DestType = Dest->getType(); | 2170 Type DestType = Dest->getType(); |
2166 InstCall *Call = makeHelperCall( | 2171 InstCall *Call = makeHelperCall(isFloat32Asserting32Or64(DestType) |
2167 isFloat32Asserting32Or64(DestType) ? "cvtsi64tof" : "cvtsi64tod", | 2172 ? "__Sz_sitofp_i64_f32" |
2168 Dest, MaxSrcs); | 2173 : "__Sz_sitofp_i64_f64", |
2174 Dest, MaxSrcs); | |
2169 // TODO: Call the correct compiler-rt helper function. | 2175 // TODO: Call the correct compiler-rt helper function. |
2170 Call->addArg(Inst->getSrc(0)); | 2176 Call->addArg(Inst->getSrc(0)); |
2171 lowerCall(Call); | 2177 lowerCall(Call); |
2172 return; | 2178 return; |
2173 } else { | 2179 } else { |
2174 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 2180 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
2175 // Sign-extend the operand. | 2181 // Sign-extend the operand. |
2176 // t1.i32 = movsx Src0RM; t2 = Cvt t1.i32; Dest = t2 | 2182 // t1.i32 = movsx Src0RM; t2 = Cvt t1.i32; Dest = t2 |
2177 Variable *T_1 = makeReg(IceType_i32); | 2183 Variable *T_1 = makeReg(IceType_i32); |
2178 Variable *T_2 = makeReg(Dest->getType()); | 2184 Variable *T_2 = makeReg(Dest->getType()); |
2179 if (Src0RM->getType() == IceType_i32) | 2185 if (Src0RM->getType() == IceType_i32) |
2180 _mov(T_1, Src0RM); | 2186 _mov(T_1, Src0RM); |
2181 else | 2187 else |
2182 _movsx(T_1, Src0RM); | 2188 _movsx(T_1, Src0RM); |
2183 _cvt(T_2, T_1, InstX8632Cvt::Si2ss); | 2189 _cvt(T_2, T_1, InstX8632Cvt::Si2ss); |
2184 _mov(Dest, T_2); | 2190 _mov(Dest, T_2); |
2185 } | 2191 } |
2186 break; | 2192 break; |
2187 case InstCast::Uitofp: { | 2193 case InstCast::Uitofp: { |
2188 Operand *Src0 = Inst->getSrc(0); | 2194 Operand *Src0 = Inst->getSrc(0); |
2189 if (isVectorType(Src0->getType())) { | 2195 if (isVectorType(Src0->getType())) { |
2190 assert(Dest->getType() == IceType_v4f32 && | 2196 assert(Dest->getType() == IceType_v4f32 && |
2191 Src0->getType() == IceType_v4i32); | 2197 Src0->getType() == IceType_v4i32); |
2192 const SizeT MaxSrcs = 1; | 2198 const SizeT MaxSrcs = 1; |
2193 InstCall *Call = makeHelperCall("Sz_uitofp_v4i32", Dest, MaxSrcs); | 2199 InstCall *Call = makeHelperCall("__Sz_uitofp_4xi32_4xf32", Dest, MaxSrcs); |
2194 Call->addArg(Src0); | 2200 Call->addArg(Src0); |
2195 lowerCall(Call); | 2201 lowerCall(Call); |
2196 } else if (Src0->getType() == IceType_i64 || | 2202 } else if (Src0->getType() == IceType_i64 || |
2197 Src0->getType() == IceType_i32) { | 2203 Src0->getType() == IceType_i32) { |
2198 // Use a helper for x86-32 and x86-64. Also use a helper for | 2204 // Use a helper for x86-32 and x86-64. Also use a helper for |
2199 // i32 on x86-32. | 2205 // i32 on x86-32. |
2200 const SizeT MaxSrcs = 1; | 2206 const SizeT MaxSrcs = 1; |
2201 Type DestType = Dest->getType(); | 2207 Type DestType = Dest->getType(); |
2202 IceString SrcSubstring = | 2208 IceString TargetString; |
2203 (isInt32Asserting32Or64(Src0->getType()) ? "32" : "64"); | 2209 if (isInt32Asserting32Or64(Src0->getType())) { |
2204 IceString DstSubstring = (isFloat32Asserting32Or64(DestType) ? "f" : "d"); | 2210 TargetString = isFloat32Asserting32Or64(DestType) |
2205 // Possibilities are cvtui32tof, cvtui32tod, cvtui64tof, cvtui64tod | 2211 ? "__Sz_uitofp_i32_f32" |
2206 IceString TargetString = "cvtui" + SrcSubstring + "to" + DstSubstring; | 2212 : "__Sz_uitofp_i32_f64"; |
2207 // TODO: Call the correct compiler-rt helper function. | 2213 } else { |
2214 TargetString = isFloat32Asserting32Or64(DestType) | |
2215 ? "__Sz_uitofp_i64_f32" | |
2216 : "__Sz_uitofp_i64_f64"; | |
2217 } | |
2208 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); | 2218 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); |
2209 Call->addArg(Src0); | 2219 Call->addArg(Src0); |
2210 lowerCall(Call); | 2220 lowerCall(Call); |
2211 return; | 2221 return; |
2212 } else { | 2222 } else { |
2213 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2223 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
2214 // Zero-extend the operand. | 2224 // Zero-extend the operand. |
2215 // t1.i32 = movzx Src0RM; t2 = Cvt t1.i32; Dest = t2 | 2225 // t1.i32 = movzx Src0RM; t2 = Cvt t1.i32; Dest = t2 |
2216 Variable *T_1 = makeReg(IceType_i32); | 2226 Variable *T_1 = makeReg(IceType_i32); |
2217 Variable *T_2 = makeReg(Dest->getType()); | 2227 Variable *T_2 = makeReg(Dest->getType()); |
(...skipping 11 matching lines...) Expand all Loading... | |
2229 if (Dest->getType() == Src0->getType()) { | 2239 if (Dest->getType() == Src0->getType()) { |
2230 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); | 2240 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); |
2231 lowerAssign(Assign); | 2241 lowerAssign(Assign); |
2232 return; | 2242 return; |
2233 } | 2243 } |
2234 switch (Dest->getType()) { | 2244 switch (Dest->getType()) { |
2235 default: | 2245 default: |
2236 llvm_unreachable("Unexpected Bitcast dest type"); | 2246 llvm_unreachable("Unexpected Bitcast dest type"); |
2237 case IceType_i8: { | 2247 case IceType_i8: { |
2238 assert(Src0->getType() == IceType_v8i1); | 2248 assert(Src0->getType() == IceType_v8i1); |
2239 InstCall *Call = makeHelperCall("Sz_bitcast_v8i1_to_i8", Dest, 1); | 2249 InstCall *Call = makeHelperCall("__Sz_bitcast_8xi1_i8", Dest, 1); |
2240 Call->addArg(Src0); | 2250 Call->addArg(Src0); |
2241 lowerCall(Call); | 2251 lowerCall(Call); |
2242 } break; | 2252 } break; |
2243 case IceType_i16: { | 2253 case IceType_i16: { |
2244 assert(Src0->getType() == IceType_v16i1); | 2254 assert(Src0->getType() == IceType_v16i1); |
2245 InstCall *Call = makeHelperCall("Sz_bitcast_v16i1_to_i16", Dest, 1); | 2255 InstCall *Call = makeHelperCall("__Sz_bitcast_16xi1_i16", Dest, 1); |
2246 Call->addArg(Src0); | 2256 Call->addArg(Src0); |
2247 lowerCall(Call); | 2257 lowerCall(Call); |
2248 } break; | 2258 } break; |
2249 case IceType_i32: | 2259 case IceType_i32: |
2250 case IceType_f32: { | 2260 case IceType_f32: { |
2251 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2261 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
2252 Type DestType = Dest->getType(); | 2262 Type DestType = Dest->getType(); |
2253 Type SrcType = Src0RM->getType(); | 2263 Type SrcType = Src0RM->getType(); |
2254 (void)DestType; | 2264 (void)DestType; |
2255 assert((DestType == IceType_i32 && SrcType == IceType_f32) || | 2265 assert((DestType == IceType_i32 && SrcType == IceType_f32) || |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2323 // SpillLo is considered a "use" of Spill so define Spill before it | 2333 // SpillLo is considered a "use" of Spill so define Spill before it |
2324 // is used. | 2334 // is used. |
2325 Context.insert(InstFakeDef::create(Func, Spill)); | 2335 Context.insert(InstFakeDef::create(Func, Spill)); |
2326 _store(T_Lo, SpillLo); | 2336 _store(T_Lo, SpillLo); |
2327 _mov(T_Hi, hiOperand(Src0)); | 2337 _mov(T_Hi, hiOperand(Src0)); |
2328 _store(T_Hi, SpillHi); | 2338 _store(T_Hi, SpillHi); |
2329 _movq(Dest, Spill); | 2339 _movq(Dest, Spill); |
2330 } break; | 2340 } break; |
2331 case IceType_v8i1: { | 2341 case IceType_v8i1: { |
2332 assert(Src0->getType() == IceType_i8); | 2342 assert(Src0->getType() == IceType_i8); |
2333 InstCall *Call = makeHelperCall("Sz_bitcast_i8_to_v8i1", Dest, 1); | 2343 InstCall *Call = makeHelperCall("__Sz_bitcast_i8_8xi1", Dest, 1); |
2334 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); | 2344 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
2335 // Arguments to functions are required to be at least 32 bits wide. | 2345 // Arguments to functions are required to be at least 32 bits wide. |
2336 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2346 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
2337 Call->addArg(Src0AsI32); | 2347 Call->addArg(Src0AsI32); |
2338 lowerCall(Call); | 2348 lowerCall(Call); |
2339 } break; | 2349 } break; |
2340 case IceType_v16i1: { | 2350 case IceType_v16i1: { |
2341 assert(Src0->getType() == IceType_i16); | 2351 assert(Src0->getType() == IceType_i16); |
2342 InstCall *Call = makeHelperCall("Sz_bitcast_i16_to_v16i1", Dest, 1); | 2352 InstCall *Call = makeHelperCall("__Sz_bitcast_i16_16xi1", Dest, 1); |
2343 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); | 2353 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
2344 // Arguments to functions are required to be at least 32 bits wide. | 2354 // Arguments to functions are required to be at least 32 bits wide. |
2345 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2355 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
2346 Call->addArg(Src0AsI32); | 2356 Call->addArg(Src0AsI32); |
2347 lowerCall(Call); | 2357 lowerCall(Call); |
2348 } break; | 2358 } break; |
2349 case IceType_v8i16: | 2359 case IceType_v8i16: |
2350 case IceType_v16i8: | 2360 case IceType_v16i8: |
2351 case IceType_v4i32: | 2361 case IceType_v4i32: |
2352 case IceType_v4f32: { | 2362 case IceType_v4f32: { |
(...skipping 2413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4766 case FT_Asm: | 4776 case FT_Asm: |
4767 case FT_Iasm: { | 4777 case FT_Iasm: { |
4768 OstreamLocker L(Ctx); | 4778 OstreamLocker L(Ctx); |
4769 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 4779 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
4770 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 4780 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
4771 } break; | 4781 } break; |
4772 } | 4782 } |
4773 } | 4783 } |
4774 | 4784 |
4775 } // end of namespace Ice | 4785 } // end of namespace Ice |
OLD | NEW |