Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: src/IceInstX86BaseImpl.h

Issue 1427973003: Subzero: Refactor x86 register representation to actively use aliases. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Reformat Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceInstX8664.def ('k') | src/IceOperand.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter); 1377 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
1378 } 1378 }
1379 1379
1380 template <class Machine> 1380 template <class Machine>
1381 void InstX86Cbwdq<Machine>::emit(const Cfg *Func) const { 1381 void InstX86Cbwdq<Machine>::emit(const Cfg *Func) const {
1382 if (!BuildDefs::dump()) 1382 if (!BuildDefs::dump())
1383 return; 1383 return;
1384 Ostream &Str = Func->getContext()->getStrEmit(); 1384 Ostream &Str = Func->getContext()->getStrEmit();
1385 assert(this->getSrcSize() == 1); 1385 assert(this->getSrcSize() == 1);
1386 Operand *Src0 = this->getSrc(0); 1386 Operand *Src0 = this->getSrc(0);
1387 assert(llvm::isa<Variable>(Src0)); 1387 int32_t DestReg = this->getDest()->getRegNum();
1388 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1389 (void)DestReg;
1390 (void)SrcReg;
1388 switch (Src0->getType()) { 1391 switch (Src0->getType()) {
1389 default: 1392 default:
1390 llvm_unreachable("unexpected source type!"); 1393 llvm_unreachable("unexpected source type!");
1391 break; 1394 break;
1392 case IceType_i8: 1395 case IceType_i8:
1393 assert(llvm::cast<Variable>(Src0)->getRegNum() == 1396 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_al);
1394 InstX86Base<Machine>::Traits::RegisterSet::Reg_al); 1397 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax ||
1395 assert(this->getDest()->getRegNum() == 1398 DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ah);
1396 InstX86Base<Machine>::Traits::RegisterSet::Reg_ax);
1397 Str << "\t" 1399 Str << "\t"
1398 << "cbtw"; 1400 << "cbtw";
1399 break; 1401 break;
1400 case IceType_i16: 1402 case IceType_i16:
1401 assert(llvm::cast<Variable>(Src0)->getRegNum() == 1403 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax);
1402 InstX86Base<Machine>::Traits::RegisterSet::Reg_ax); 1404 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_dx);
1403 assert(this->getDest()->getRegNum() ==
1404 InstX86Base<Machine>::Traits::RegisterSet::Reg_dx);
1405 Str << "\t" 1405 Str << "\t"
1406 << "cwtd"; 1406 << "cwtd";
1407 break; 1407 break;
1408 case IceType_i32: 1408 case IceType_i32:
1409 assert(llvm::cast<Variable>(Src0)->getRegNum() == 1409 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1410 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 1410 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1411 assert(this->getDest()->getRegNum() ==
1412 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1413 Str << "\t" 1411 Str << "\t"
1414 << "cltd"; 1412 << "cltd";
1415 break; 1413 break;
1416 case IceType_i64: 1414 case IceType_i64:
1417 assert(this->getDest()->getRegNum() == 1415 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1418 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1419 Str << "\t" 1416 Str << "\t"
1420 << "cdto"; 1417 << "cdto";
1421 break; 1418 break;
1422 } 1419 }
1423 } 1420 }
1424 1421
1425 template <class Machine> 1422 template <class Machine>
1426 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const { 1423 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const {
1427 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1424 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1428 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 1425 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1429 assert(this->getSrcSize() == 1); 1426 assert(this->getSrcSize() == 1);
1430 Operand *Src0 = this->getSrc(0); 1427 Operand *Src0 = this->getSrc(0);
1431 assert(llvm::isa<Variable>(Src0)); 1428 int32_t DestReg = this->getDest()->getRegNum();
1429 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1430 (void)DestReg;
1431 (void)SrcReg;
1432 switch (Src0->getType()) { 1432 switch (Src0->getType()) {
1433 default: 1433 default:
1434 llvm_unreachable("unexpected source type!"); 1434 llvm_unreachable("unexpected source type!");
1435 break; 1435 break;
1436 case IceType_i8: 1436 case IceType_i8:
1437 assert(llvm::cast<Variable>(Src0)->getRegNum() == 1437 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_al);
1438 InstX86Base<Machine>::Traits::RegisterSet::Reg_al); 1438 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax ||
1439 assert(this->getDest()->getRegNum() == 1439 DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ah);
1440 InstX86Base<Machine>::Traits::RegisterSet::Reg_ax);
1441 Asm->cbw(); 1440 Asm->cbw();
1442 break; 1441 break;
1443 case IceType_i16: 1442 case IceType_i16:
1444 assert(llvm::cast<Variable>(Src0)->getRegNum() == 1443 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax);
1445 InstX86Base<Machine>::Traits::RegisterSet::Reg_ax); 1444 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_dx);
1446 assert(this->getDest()->getRegNum() ==
1447 InstX86Base<Machine>::Traits::RegisterSet::Reg_dx);
1448 Asm->cwd(); 1445 Asm->cwd();
1449 break; 1446 break;
1450 case IceType_i32: 1447 case IceType_i32:
1451 assert(llvm::cast<Variable>(Src0)->getRegNum() == 1448 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1452 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 1449 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1453 assert(this->getDest()->getRegNum() ==
1454 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1455 Asm->cdq(); 1450 Asm->cdq();
1456 break; 1451 break;
1457 case IceType_i64: 1452 case IceType_i64:
1458 assert(this->getDest()->getRegNum() == 1453 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1459 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1460 Asm->cqo(); 1454 Asm->cqo();
1461 break; 1455 break;
1462 } 1456 }
1463 } 1457 }
1464 1458
1465 template <class Machine> void InstX86Mul<Machine>::emit(const Cfg *Func) const { 1459 template <class Machine> void InstX86Mul<Machine>::emit(const Cfg *Func) const {
1466 if (!BuildDefs::dump()) 1460 if (!BuildDefs::dump())
1467 return; 1461 return;
1468 Ostream &Str = Func->getContext()->getStrEmit(); 1462 Ostream &Str = Func->getContext()->getStrEmit();
1469 assert(this->getSrcSize() == 2); 1463 assert(this->getSrcSize() == 2);
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after
2271 assert(this->getSrcSize() == 1); 2265 assert(this->getSrcSize() == 1);
2272 Operand *Src = this->getSrc(0); 2266 Operand *Src = this->getSrc(0);
2273 Type SrcTy = Src->getType(); 2267 Type SrcTy = Src->getType();
2274 Type DestTy = this->getDest()->getType(); 2268 Type DestTy = this->getDest()->getType();
2275 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 && 2269 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 &&
2276 isIntegerConstant(Src)) { 2270 isIntegerConstant(Src)) {
2277 Str << "\tmovabs\t"; 2271 Str << "\tmovabs\t";
2278 } else { 2272 } else {
2279 Str << "\tmov" 2273 Str << "\tmov"
2280 << (!isScalarFloatingType(DestTy) 2274 << (!isScalarFloatingType(DestTy)
2281 ? this->getWidthString(SrcTy) 2275 ? this->getWidthString(DestTy)
2282 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy] 2276 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy]
2283 .SdSsString) << "\t"; 2277 .SdSsString) << "\t";
2284 } 2278 }
2285 // For an integer truncation operation, src is wider than dest. Ideally, we 2279 // For an integer truncation operation, src is wider than dest. In this case,
2286 // use a mov instruction whose data width matches the narrower dest. This is 2280 // we use a mov instruction whose data width matches the narrower dest.
2287 // a problem if e.g. src is a register like esi or si where there is no 8-bit
2288 // version of the register. To be safe, we instead widen the dest to match
2289 // src. This works even for stack-allocated dest variables because
2290 // typeWidthOnStack() pads to a 4-byte boundary even if only a lower portion
2291 // is used.
2292 // TODO: This assert disallows usages such as copying a floating 2281 // TODO: This assert disallows usages such as copying a floating
2293 // point value between a vector and a scalar (which movss is used for). Clean 2282 // point value between a vector and a scalar (which movss is used for). Clean
2294 // this up. 2283 // this up.
2295 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) == 2284 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) ==
2296 Func->getTarget()->typeWidthInBytesOnStack(SrcTy)); 2285 Func->getTarget()->typeWidthInBytesOnStack(SrcTy));
2297 Src->emit(Func); 2286 const Operand *NewSrc = Src;
2287 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
2288 int32_t NewRegNum = Variable::NoRegister;
2289 if (SrcVar->hasReg())
2290 NewRegNum = InstX86Base<Machine>::Traits::getGprForType(
2291 DestTy, SrcVar->getRegNum());
2292 if (SrcTy != DestTy)
2293 NewSrc = SrcVar->asType(DestTy, NewRegNum);
2294 }
2295 NewSrc->emit(Func);
2298 Str << ", "; 2296 Str << ", ";
2299 int32_t NewRegNum = Variable::NoRegister; 2297 this->getDest()->emit(Func);
2300 if (this->getDest()->hasReg())
2301 NewRegNum = InstX86Base<Machine>::Traits::getGprForType(
2302 SrcTy, this->getDest()->getRegNum());
2303 const Variable *NewDest = SrcTy == DestTy
2304 ? this->getDest()
2305 : this->getDest()->asType(SrcTy, NewRegNum);
2306 NewDest->emit(Func);
2307 } 2298 }
2308 2299
2309 template <class Machine> 2300 template <class Machine>
2310 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const { 2301 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const {
2311 assert(this->getSrcSize() == 1); 2302 assert(this->getSrcSize() == 1);
2312 const Variable *Dest = this->getDest(); 2303 const Variable *Dest = this->getDest();
2313 const Operand *Src = this->getSrc(0); 2304 const Operand *Src = this->getSrc(0);
2314 Type DestTy = Dest->getType(); 2305 Type DestTy = Dest->getType();
2315 Type SrcTy = Src->getType(); 2306 Type SrcTy = Src->getType();
2316 // Mov can be used for GPRs or XMM registers. Also, the type does not 2307 // Mov can be used for GPRs or XMM registers. Also, the type does not
2317 // necessarily match (Mov can be used for bitcasts). However, when the type 2308 // necessarily match (Mov can be used for bitcasts). However, when the type
2318 // does not match, one of the operands must be a register. Thus, the strategy 2309 // does not match, one of the operands must be a register. Thus, the strategy
2319 // is to find out if Src or Dest are a register, then use that register's 2310 // is to find out if Src or Dest are a register, then use that register's
2320 // type to decide on which emitter set to use. The emitter set will include 2311 // type to decide on which emitter set to use. The emitter set will include
2321 // reg-reg movs, but that case should be unused when the types don't match. 2312 // reg-reg movs, but that case should be unused when the types don't match.
2322 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 2313 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
2323 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss, 2314 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss,
2324 &InstX86Base<Machine>::Traits::Assembler::movss}; 2315 &InstX86Base<Machine>::Traits::Assembler::movss};
2325 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp 2316 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2326 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov, 2317 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov,
2327 &InstX86Base<Machine>::Traits::Assembler::mov, 2318 &InstX86Base<Machine>::Traits::Assembler::mov,
2328 &InstX86Base<Machine>::Traits::Assembler::mov}; 2319 &InstX86Base<Machine>::Traits::Assembler::mov};
2329 static const typename InstX86Base< 2320 static const typename InstX86Base<
2330 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = { 2321 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2331 &InstX86Base<Machine>::Traits::Assembler::mov, 2322 &InstX86Base<Machine>::Traits::Assembler::mov,
2332 &InstX86Base<Machine>::Traits::Assembler::mov}; 2323 &InstX86Base<Machine>::Traits::Assembler::mov};
2333 // For an integer truncation operation, src is wider than dest. Ideally, we 2324 // For an integer truncation operation, src is wider than dest. In this case,
2334 // use a mov instruction whose data width matches the narrower dest. This is 2325 // we use a mov instruction whose data width matches the narrower dest.
2335 // a problem if e.g. src is a register like esi or si where there is no 8-bit
2336 // version of the register. To be safe, we instead widen the dest to match
2337 // src. This works even for stack-allocated dest variables because
2338 // typeWidthOnStack() pads to a 4-byte boundary even if only a lower portion
2339 // is used.
2340 // TODO: This assert disallows usages such as copying a floating 2326 // TODO: This assert disallows usages such as copying a floating
2341 // point value between a vector and a scalar (which movss is used for). Clean 2327 // point value between a vector and a scalar (which movss is used for). Clean
2342 // this up. 2328 // this up.
2343 assert( 2329 assert(
2344 Func->getTarget()->typeWidthInBytesOnStack(this->getDest()->getType()) == 2330 Func->getTarget()->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2345 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); 2331 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
2346 if (Dest->hasReg()) { 2332 if (Dest->hasReg()) {
2347 if (isScalarFloatingType(DestTy)) { 2333 if (isScalarFloatingType(DestTy)) {
2348 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter); 2334 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter);
2349 return; 2335 return;
2350 } else { 2336 } else {
2351 assert(isScalarIntegerType(DestTy)); 2337 assert(isScalarIntegerType(DestTy));
2352 // Widen DestTy for truncation (see above note). We should only do this 2338 // Widen DestTy for truncation (see above note). We should only do this
2353 // when both Src and Dest are integer types. 2339 // when both Src and Dest are integer types.
2354 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 && 2340 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 &&
2355 isIntegerConstant(Src)) { 2341 isIntegerConstant(Src)) {
2356 uint64_t Value = -1; 2342 uint64_t Value = -1;
2357 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) { 2343 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
2358 Value = C64->getValue(); 2344 Value = C64->getValue();
2359 } else { 2345 } else {
2360 Value = llvm::cast<ConstantInteger32>(Src)->getValue(); 2346 Value = llvm::cast<ConstantInteger32>(Src)->getValue();
2361 } 2347 }
2362 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>() 2348 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>()
2363 ->movabs( 2349 ->movabs(
2364 InstX86Base<Machine>::Traits::getEncodedGPR(Dest->getRegNum()), 2350 InstX86Base<Machine>::Traits::getEncodedGPR(Dest->getRegNum()),
2365 Value); 2351 Value);
2366 return; 2352 return;
2367 } 2353 }
2368 if (isScalarIntegerType(SrcTy)) { 2354 if (isScalarIntegerType(SrcTy)) {
2369 DestTy = SrcTy; 2355 SrcTy = DestTy;
2370 } 2356 }
2371 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter); 2357 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter);
2372 return; 2358 return;
2373 } 2359 }
2374 } else { 2360 } else {
2375 // Dest must be Stack and Src *could* be a register. Use Src's type to 2361 // Dest must be Stack and Src *could* be a register. Use Src's type to
2376 // decide on the emitters. 2362 // decide on the emitters.
2377 typename InstX86Base<Machine>::Traits::Address StackAddr( 2363 typename InstX86Base<Machine>::Traits::Address StackAddr(
2378 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>( 2364 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2379 Func->getTarget()) 2365 Func->getTarget())
(...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after
3284 return; 3270 return;
3285 Ostream &Str = Func->getContext()->getStrDump(); 3271 Ostream &Str = Func->getContext()->getStrDump();
3286 Str << "IACA_END"; 3272 Str << "IACA_END";
3287 } 3273 }
3288 3274
3289 } // end of namespace X86Internal 3275 } // end of namespace X86Internal
3290 3276
3291 } // end of namespace Ice 3277 } // end of namespace Ice
3292 3278
3293 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H 3279 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H
OLDNEW
« no previous file with comments | « src/IceInstX8664.def ('k') | src/IceOperand.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698