OLD | NEW |
1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// | 1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// |
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 /// \file | 10 /// \file |
(...skipping 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1259 Str << "\t" | 1259 Str << "\t" |
1260 "cwtd"; | 1260 "cwtd"; |
1261 break; | 1261 break; |
1262 case IceType_i32: | 1262 case IceType_i32: |
1263 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); | 1263 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); |
1264 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx); | 1264 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx); |
1265 Str << "\t" | 1265 Str << "\t" |
1266 "cltd"; | 1266 "cltd"; |
1267 break; | 1267 break; |
1268 case IceType_i64: | 1268 case IceType_i64: |
1269 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx); | 1269 assert(InstX86Base<Machine>::Traits::Is64Bit); |
| 1270 assert(SrcReg == InstX86Base<Machine>::Traits::getRaxOrDie()); |
| 1271 assert(DestReg == InstX86Base<Machine>::Traits::getRdxOrDie()); |
1270 Str << "\t" | 1272 Str << "\t" |
1271 "cdto"; | 1273 "cqo"; |
1272 break; | 1274 break; |
1273 } | 1275 } |
1274 } | 1276 } |
1275 | 1277 |
1276 template <class Machine> | 1278 template <class Machine> |
1277 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const { | 1279 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const { |
1278 typename InstX86Base<Machine>::Traits::Assembler *Asm = | 1280 typename InstX86Base<Machine>::Traits::Assembler *Asm = |
1279 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); | 1281 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); |
1280 assert(this->getSrcSize() == 1); | 1282 assert(this->getSrcSize() == 1); |
1281 Operand *Src0 = this->getSrc(0); | 1283 Operand *Src0 = this->getSrc(0); |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 // acceptable type. | 2124 // acceptable type. |
2123 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister) | 2125 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister) |
2124 ->emit(Func); | 2126 ->emit(Func); |
2125 } else { | 2127 } else { |
2126 Src0->emit(Func); | 2128 Src0->emit(Func); |
2127 } | 2129 } |
2128 Str << ", "; | 2130 Str << ", "; |
2129 this->getDest()->emit(Func); | 2131 this->getDest()->emit(Func); |
2130 } | 2132 } |
2131 | 2133 |
2132 inline bool isIntegerConstant(const Operand *Op) { | |
2133 return llvm::isa<ConstantInteger32>(Op) || llvm::isa<ConstantInteger64>(Op); | |
2134 } | |
2135 | |
2136 template <class Machine> void InstX86Mov<Machine>::emit(const Cfg *Func) const { | 2134 template <class Machine> void InstX86Mov<Machine>::emit(const Cfg *Func) const { |
2137 if (!BuildDefs::dump()) | 2135 if (!BuildDefs::dump()) |
2138 return; | 2136 return; |
2139 Ostream &Str = Func->getContext()->getStrEmit(); | 2137 Ostream &Str = Func->getContext()->getStrEmit(); |
2140 assert(this->getSrcSize() == 1); | 2138 assert(this->getSrcSize() == 1); |
2141 Operand *Src = this->getSrc(0); | 2139 Operand *Src = this->getSrc(0); |
2142 Type SrcTy = Src->getType(); | 2140 Type SrcTy = Src->getType(); |
2143 Type DestTy = this->getDest()->getType(); | 2141 Type DestTy = this->getDest()->getType(); |
2144 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 && | 2142 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 && |
2145 isIntegerConstant(Src)) { | 2143 llvm::isa<ConstantInteger64>(Src)) { |
2146 Str << "\t" | 2144 Str << "\t" |
2147 "movabs\t"; | 2145 "movabs" |
| 2146 "\t"; |
2148 } else { | 2147 } else { |
2149 Str << "\t" | 2148 Str << "\t" |
2150 "mov" << (!isScalarFloatingType(DestTy) | 2149 "mov" << (!isScalarFloatingType(DestTy) |
2151 ? this->getWidthString(DestTy) | 2150 ? this->getWidthString(DestTy) |
2152 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy] | 2151 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy] |
2153 .SdSsString) << "\t"; | 2152 .SdSsString) << "\t"; |
2154 } | 2153 } |
2155 // For an integer truncation operation, src is wider than dest. In this case, | 2154 // For an integer truncation operation, src is wider than dest. In this case, |
2156 // we use a mov instruction whose data width matches the narrower dest. | 2155 // we use a mov instruction whose data width matches the narrower dest. |
2157 // TODO: This assert disallows usages such as copying a floating | 2156 // TODO: This assert disallows usages such as copying a floating |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2207 assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) == | 2206 assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) == |
2208 Target->typeWidthInBytesOnStack(Src->getType())); | 2207 Target->typeWidthInBytesOnStack(Src->getType())); |
2209 if (Dest->hasReg()) { | 2208 if (Dest->hasReg()) { |
2210 if (isScalarFloatingType(DestTy)) { | 2209 if (isScalarFloatingType(DestTy)) { |
2211 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter); | 2210 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter); |
2212 return; | 2211 return; |
2213 } else { | 2212 } else { |
2214 assert(isScalarIntegerType(DestTy)); | 2213 assert(isScalarIntegerType(DestTy)); |
2215 // Widen DestTy for truncation (see above note). We should only do this | 2214 // Widen DestTy for truncation (see above note). We should only do this |
2216 // when both Src and Dest are integer types. | 2215 // when both Src and Dest are integer types. |
2217 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 && | 2216 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64) { |
2218 isIntegerConstant(Src)) { | |
2219 uint64_t Value = -1; | |
2220 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) { | 2217 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) { |
2221 Value = C64->getValue(); | 2218 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>() |
2222 } else { | 2219 ->movabs(InstX86Base<Machine>::Traits::getEncodedGPR( |
2223 Value = llvm::cast<ConstantInteger32>(Src)->getValue(); | 2220 Dest->getRegNum()), |
| 2221 C64->getValue()); |
| 2222 return; |
2224 } | 2223 } |
2225 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>() | |
2226 ->movabs( | |
2227 InstX86Base<Machine>::Traits::getEncodedGPR(Dest->getRegNum()), | |
2228 Value); | |
2229 return; | |
2230 } | 2224 } |
2231 if (isScalarIntegerType(SrcTy)) { | 2225 if (isScalarIntegerType(SrcTy)) { |
2232 SrcTy = DestTy; | 2226 SrcTy = DestTy; |
2233 } | 2227 } |
2234 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter); | 2228 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter); |
2235 return; | 2229 return; |
2236 } | 2230 } |
2237 } else { | 2231 } else { |
2238 // Dest must be Stack and Src *could* be a register. Use Src's type to | 2232 // Dest must be Stack and Src *could* be a register. Use Src's type to |
2239 // decide on the emitters. | 2233 // decide on the emitters. |
(...skipping 13 matching lines...) Expand all Loading... |
2253 // Src can be a register or immediate. | 2247 // Src can be a register or immediate. |
2254 assert(isScalarIntegerType(SrcTy)); | 2248 assert(isScalarIntegerType(SrcTy)); |
2255 emitIASAddrOpTyGPR<Machine>(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); | 2249 emitIASAddrOpTyGPR<Machine>(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); |
2256 return; | 2250 return; |
2257 } | 2251 } |
2258 return; | 2252 return; |
2259 } | 2253 } |
2260 } | 2254 } |
2261 | 2255 |
2262 template <class Machine> | 2256 template <class Machine> |
| 2257 void InstX86Movd<Machine>::emit(const Cfg *Func) const { |
| 2258 if (!BuildDefs::dump()) |
| 2259 return; |
| 2260 assert(this->getSrcSize() == 1); |
| 2261 Variable *Dest = this->getDest(); |
| 2262 Operand *Src = this->getSrc(0); |
| 2263 |
| 2264 if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) { |
| 2265 assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64); |
| 2266 assert(Dest->getType() != Src->getType()); |
| 2267 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2268 Str << "\t" |
| 2269 "movq" |
| 2270 "\t"; |
| 2271 Src->emit(Func); |
| 2272 Str << ", "; |
| 2273 Dest->emit(Func); |
| 2274 return; |
| 2275 } |
| 2276 |
| 2277 InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd>::emit(Func); |
| 2278 } |
| 2279 |
| 2280 template <class Machine> |
2263 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const { | 2281 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const { |
2264 typename InstX86Base<Machine>::Traits::Assembler *Asm = | 2282 typename InstX86Base<Machine>::Traits::Assembler *Asm = |
2265 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); | 2283 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); |
2266 assert(this->getSrcSize() == 1); | 2284 assert(this->getSrcSize() == 1); |
2267 const Variable *Dest = this->getDest(); | 2285 const Variable *Dest = this->getDest(); |
2268 auto *Target = InstX86Base<Machine>::getTarget(Func); | 2286 auto *Target = InstX86Base<Machine>::getTarget(Func); |
2269 // For insert/extract element (one of Src/Dest is an Xmm vector and the other | 2287 // For insert/extract element (one of Src/Dest is an Xmm vector and the other |
2270 // is an int type). | 2288 // is an int type). |
2271 if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) { | 2289 if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) { |
2272 if (SrcVar->getType() == IceType_i32 || | 2290 if (SrcVar->getType() == IceType_i32 || |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2352 | 2370 |
2353 template <class Machine> | 2371 template <class Machine> |
2354 void InstX86Movq<Machine>::emit(const Cfg *Func) const { | 2372 void InstX86Movq<Machine>::emit(const Cfg *Func) const { |
2355 if (!BuildDefs::dump()) | 2373 if (!BuildDefs::dump()) |
2356 return; | 2374 return; |
2357 Ostream &Str = Func->getContext()->getStrEmit(); | 2375 Ostream &Str = Func->getContext()->getStrEmit(); |
2358 assert(this->getSrcSize() == 1); | 2376 assert(this->getSrcSize() == 1); |
2359 assert(this->getDest()->getType() == IceType_i64 || | 2377 assert(this->getDest()->getType() == IceType_i64 || |
2360 this->getDest()->getType() == IceType_f64); | 2378 this->getDest()->getType() == IceType_f64); |
2361 Str << "\t" | 2379 Str << "\t" |
2362 "movq\t"; | 2380 "movq" |
| 2381 "\t"; |
2363 this->getSrc(0)->emit(Func); | 2382 this->getSrc(0)->emit(Func); |
2364 Str << ", "; | 2383 Str << ", "; |
2365 this->getDest()->emit(Func); | 2384 this->getDest()->emit(Func); |
2366 } | 2385 } |
2367 | 2386 |
2368 template <class Machine> | 2387 template <class Machine> |
2369 void InstX86Movq<Machine>::emitIAS(const Cfg *Func) const { | 2388 void InstX86Movq<Machine>::emitIAS(const Cfg *Func) const { |
2370 assert(this->getSrcSize() == 1); | 2389 assert(this->getSrcSize() == 1); |
2371 assert(this->getDest()->getType() == IceType_i64 || | 2390 assert(this->getDest()->getType() == IceType_i64 || |
2372 this->getDest()->getType() == IceType_f64); | 2391 this->getDest()->getType() == IceType_f64); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2405 // use the full register for Dest to avoid having an OperandSizeOverride | 2424 // use the full register for Dest to avoid having an OperandSizeOverride |
2406 // prefix. It also allows us to only dispatch on SrcTy. | 2425 // prefix. It also allows us to only dispatch on SrcTy. |
2407 Type SrcTy = Src->getType(); | 2426 Type SrcTy = Src->getType(); |
2408 assert(typeWidthInBytes(Dest->getType()) > 1); | 2427 assert(typeWidthInBytes(Dest->getType()) > 1); |
2409 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); | 2428 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
2410 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src, | 2429 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src, |
2411 this->Emitter); | 2430 this->Emitter); |
2412 } | 2431 } |
2413 | 2432 |
2414 template <class Machine> | 2433 template <class Machine> |
| 2434 void InstX86Movzx<Machine>::emit(const Cfg *Func) const { |
| 2435 if (!BuildDefs::dump()) |
| 2436 return; |
| 2437 if (InstX86Base<Machine>::Traits::Is64Bit) { |
| 2438 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a |
| 2439 // mov %eXX, %eXX. The processor will still do a movzx[bw]q. |
| 2440 assert(this->getSrcSize() == 1); |
| 2441 const Operand *Src = this->getSrc(0); |
| 2442 const Variable *Dest = this->Dest; |
| 2443 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) { |
| 2444 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2445 Str << "\t" |
| 2446 "mov" |
| 2447 "\t"; |
| 2448 Src->emit(Func); |
| 2449 Str << ", "; |
| 2450 Dest->asType(IceType_i32, InstX86Base<Machine>::Traits::getGprForType( |
| 2451 IceType_i32, Dest->getRegNum())) |
| 2452 ->emit(Func); |
| 2453 Str << " /* movzx */"; |
| 2454 return; |
| 2455 } |
| 2456 } |
| 2457 InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx>::emit(Func); |
| 2458 } |
| 2459 |
| 2460 template <class Machine> |
2415 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const { | 2461 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const { |
2416 assert(this->getSrcSize() == 1); | 2462 assert(this->getSrcSize() == 1); |
2417 const Variable *Dest = this->getDest(); | 2463 const Variable *Dest = this->getDest(); |
2418 const Operand *Src = this->getSrc(0); | 2464 const Operand *Src = this->getSrc(0); |
2419 Type SrcTy = Src->getType(); | 2465 Type SrcTy = Src->getType(); |
2420 assert(typeWidthInBytes(Dest->getType()) > 1); | 2466 assert(typeWidthInBytes(Dest->getType()) > 1); |
2421 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); | 2467 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
2422 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src, | 2468 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src, |
2423 this->Emitter); | 2469 this->Emitter); |
2424 } | 2470 } |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3034 return; | 3080 return; |
3035 Ostream &Str = Func->getContext()->getStrDump(); | 3081 Ostream &Str = Func->getContext()->getStrDump(); |
3036 Str << "IACA_END"; | 3082 Str << "IACA_END"; |
3037 } | 3083 } |
3038 | 3084 |
3039 } // end of namespace X86Internal | 3085 } // end of namespace X86Internal |
3040 | 3086 |
3041 } // end of namespace Ice | 3087 } // end of namespace Ice |
3042 | 3088 |
3043 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H | 3089 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H |
OLD | NEW |