Chromium Code Reviews| 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 #undef X | 239 #undef X |
| 240 // Repeat the static asserts with respect to the high-level table | 240 // Repeat the static asserts with respect to the high-level table |
| 241 // entries in case the high-level table has extra entries. | 241 // entries in case the high-level table has extra entries. |
| 242 #define X(tag, size, align, elts, elty, str) \ | 242 #define X(tag, size, align, elts, elty, str) \ |
| 243 static_assert(_table1_##tag == _table2_##tag, \ | 243 static_assert(_table1_##tag == _table2_##tag, \ |
| 244 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); | 244 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
| 245 ICETYPE_TABLE | 245 ICETYPE_TABLE |
| 246 #undef X | 246 #undef X |
| 247 } // end of namespace dummy3 | 247 } // end of namespace dummy3 |
| 248 | 248 |
| 249 // A helper class to ease the settings of RandomizationPoolingPause | |
| 250 // to disable constant blinding or pooling for some translation phases. | |
| 251 class BoolFlagSaver { | |
| 252 BoolFlagSaver() = delete; | |
| 253 BoolFlagSaver(const BoolFlagSaver &) = delete; | |
| 254 BoolFlagSaver &operator=(const BoolFlagSaver &) = delete; | |
| 255 | |
| 256 public: | |
| 257 BoolFlagSaver(bool &F, bool NewValue) : OldValue(F), Flag(F) { F = NewValue; } | |
| 258 ~BoolFlagSaver() { Flag = OldValue; } | |
| 259 | |
| 260 private: | |
| 261 const bool OldValue; | |
| 262 bool &Flag; | |
| 263 }; | |
| 264 | |
| 249 } // end of anonymous namespace | 265 } // end of anonymous namespace |
| 250 | 266 |
| 251 BoolFoldingEntry::BoolFoldingEntry(Inst *I) | 267 BoolFoldingEntry::BoolFoldingEntry(Inst *I) |
| 252 : Instr(I), IsComplex(BoolFolding::hasComplexLowering(I)), IsLiveOut(true), | 268 : Instr(I), IsComplex(BoolFolding::hasComplexLowering(I)), IsLiveOut(true), |
| 253 NumUses(0) {} | 269 NumUses(0) {} |
| 254 | 270 |
| 255 BoolFolding::BoolFoldingProducerKind | 271 BoolFolding::BoolFoldingProducerKind |
| 256 BoolFolding::getProducerKind(const Inst *Instr) { | 272 BoolFolding::getProducerKind(const Inst *Instr) { |
| 257 if (llvm::isa<InstIcmp>(Instr)) { | 273 if (llvm::isa<InstIcmp>(Instr)) { |
| 258 if (Instr->getSrc(0)->getType() != IceType_i64) | 274 if (Instr->getSrc(0)->getType() != IceType_i64) |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 } | 405 } |
| 390 } | 406 } |
| 391 | 407 |
| 392 void TargetX8632::initNodeForLowering(CfgNode *Node) { | 408 void TargetX8632::initNodeForLowering(CfgNode *Node) { |
| 393 FoldingInfo.init(Node); | 409 FoldingInfo.init(Node); |
| 394 FoldingInfo.dump(Func); | 410 FoldingInfo.dump(Func); |
| 395 } | 411 } |
| 396 | 412 |
| 397 TargetX8632::TargetX8632(Cfg *Func) | 413 TargetX8632::TargetX8632(Cfg *Func) |
| 398 : TargetLowering(Func), InstructionSet(X86InstructionSet::Begin), | 414 : TargetLowering(Func), InstructionSet(X86InstructionSet::Begin), |
| 399 IsEbpBasedFrame(false), NeedsStackAlignment(false), | 415 IsEbpBasedFrame(false), NeedsStackAlignment(false), SpillAreaSizeBytes(0), |
| 400 SpillAreaSizeBytes(0) { | 416 RandomizationPoolingPaused(false) { |
| 401 static_assert((X86InstructionSet::End - X86InstructionSet::Begin) == | 417 static_assert((X86InstructionSet::End - X86InstructionSet::Begin) == |
| 402 (TargetInstructionSet::X86InstructionSet_End - | 418 (TargetInstructionSet::X86InstructionSet_End - |
| 403 TargetInstructionSet::X86InstructionSet_Begin), | 419 TargetInstructionSet::X86InstructionSet_Begin), |
| 404 "X86InstructionSet range different from TargetInstructionSet"); | 420 "X86InstructionSet range different from TargetInstructionSet"); |
| 405 if (Func->getContext()->getFlags().getTargetInstructionSet() != | 421 if (Func->getContext()->getFlags().getTargetInstructionSet() != |
| 406 TargetInstructionSet::BaseInstructionSet) { | 422 TargetInstructionSet::BaseInstructionSet) { |
| 407 InstructionSet = static_cast<X86InstructionSet>( | 423 InstructionSet = static_cast<X86InstructionSet>( |
| 408 (Func->getContext()->getFlags().getTargetInstructionSet() - | 424 (Func->getContext()->getFlags().getTargetInstructionSet() - |
| 409 TargetInstructionSet::X86InstructionSet_Begin) + | 425 TargetInstructionSet::X86InstructionSet_Begin) + |
| 410 X86InstructionSet::Begin); | 426 X86InstructionSet::Begin); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 return; | 501 return; |
| 486 | 502 |
| 487 // TODO: It should be sufficient to use the fastest liveness | 503 // TODO: It should be sufficient to use the fastest liveness |
| 488 // calculation, i.e. livenessLightweight(). However, for some | 504 // calculation, i.e. livenessLightweight(). However, for some |
| 489 // reason that slows down the rest of the translation. Investigate. | 505 // reason that slows down the rest of the translation. Investigate. |
| 490 Func->liveness(Liveness_Basic); | 506 Func->liveness(Liveness_Basic); |
| 491 if (Func->hasError()) | 507 if (Func->hasError()) |
| 492 return; | 508 return; |
| 493 Func->dump("After x86 address mode opt"); | 509 Func->dump("After x86 address mode opt"); |
| 494 | 510 |
| 495 doLoadOpt(); | 511 // Disable constant blinding or pooling for load optimization. |
| 512 { | |
| 513 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 514 doLoadOpt(); | |
| 515 } | |
| 496 Func->genCode(); | 516 Func->genCode(); |
| 497 if (Func->hasError()) | 517 if (Func->hasError()) |
| 498 return; | 518 return; |
| 499 Func->dump("After x86 codegen"); | 519 Func->dump("After x86 codegen"); |
| 500 | 520 |
| 501 // Register allocation. This requires instruction renumbering and | 521 // Register allocation. This requires instruction renumbering and |
| 502 // full liveness analysis. | 522 // full liveness analysis. |
| 503 Func->renumberInstructions(); | 523 Func->renumberInstructions(); |
| 504 if (Func->hasError()) | 524 if (Func->hasError()) |
| 505 return; | 525 return; |
| 506 Func->liveness(Liveness_Intervals); | 526 Func->liveness(Liveness_Intervals); |
| 507 if (Func->hasError()) | 527 if (Func->hasError()) |
| 508 return; | 528 return; |
| 509 // Validate the live range computations. The expensive validation | 529 // Validate the live range computations. The expensive validation |
| 510 // call is deliberately only made when assertions are enabled. | 530 // call is deliberately only made when assertions are enabled. |
| 511 assert(Func->validateLiveness()); | 531 assert(Func->validateLiveness()); |
| 512 // The post-codegen dump is done here, after liveness analysis and | 532 // The post-codegen dump is done here, after liveness analysis and |
| 513 // associated cleanup, to make the dump cleaner and more useful. | 533 // associated cleanup, to make the dump cleaner and more useful. |
| 514 Func->dump("After initial x8632 codegen"); | 534 Func->dump("After initial x8632 codegen"); |
| 515 Func->getVMetadata()->init(VMK_All); | 535 Func->getVMetadata()->init(VMK_All); |
| 516 regAlloc(RAK_Global); | 536 regAlloc(RAK_Global); |
| 517 if (Func->hasError()) | 537 if (Func->hasError()) |
| 518 return; | 538 return; |
| 519 Func->dump("After linear scan regalloc"); | 539 Func->dump("After linear scan regalloc"); |
| 520 | 540 |
| 521 if (Ctx->getFlags().getPhiEdgeSplit()) { | 541 if (Ctx->getFlags().getPhiEdgeSplit()) { |
| 522 Func->advancedPhiLowering(); | 542 // We need to pause constant blinding or pooling during advanced |
| 543 // phi lowering, unless the lowering assignment has a physical | |
| 544 // register for the dest Variable. | |
| 545 { | |
| 546 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 547 Func->advancedPhiLowering(); | |
| 548 } | |
| 523 Func->dump("After advanced Phi lowering"); | 549 Func->dump("After advanced Phi lowering"); |
| 524 } | 550 } |
| 525 | 551 |
| 526 // Stack frame mapping. | 552 // Stack frame mapping. |
| 527 Func->genFrame(); | 553 Func->genFrame(); |
| 528 if (Func->hasError()) | 554 if (Func->hasError()) |
| 529 return; | 555 return; |
| 530 Func->dump("After stack frame mapping"); | 556 Func->dump("After stack frame mapping"); |
| 531 | 557 |
| 532 Func->contractEmptyNodes(); | 558 Func->contractEmptyNodes(); |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 904 return RegNames[RegNum]; | 930 return RegNames[RegNum]; |
| 905 } | 931 } |
| 906 } | 932 } |
| 907 | 933 |
| 908 void TargetX8632::emitVariable(const Variable *Var) const { | 934 void TargetX8632::emitVariable(const Variable *Var) const { |
| 909 Ostream &Str = Ctx->getStrEmit(); | 935 Ostream &Str = Ctx->getStrEmit(); |
| 910 if (Var->hasReg()) { | 936 if (Var->hasReg()) { |
| 911 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); | 937 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); |
| 912 return; | 938 return; |
| 913 } | 939 } |
| 914 if (Var->getWeight().isInf()) | 940 if (Var->getWeight().isInf()) { |
| 915 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 941 llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| 942 } | |
| 916 int32_t Offset = Var->getStackOffset(); | 943 int32_t Offset = Var->getStackOffset(); |
| 917 if (!hasFramePointer()) | 944 if (!hasFramePointer()) |
| 918 Offset += getStackAdjustment(); | 945 Offset += getStackAdjustment(); |
| 919 if (Offset) | 946 if (Offset) |
| 920 Str << Offset; | 947 Str << Offset; |
| 921 const Type FrameSPTy = IceType_i32; | 948 const Type FrameSPTy = IceType_i32; |
| 922 Str << "(%" << getRegName(getFrameOrStackReg(), FrameSPTy) << ")"; | 949 Str << "(%" << getRegName(getFrameOrStackReg(), FrameSPTy) << ")"; |
| 923 } | 950 } |
| 924 | 951 |
| 925 X8632::Address TargetX8632::stackVarToAsmOperand(const Variable *Var) const { | 952 X8632::Address TargetX8632::stackVarToAsmOperand(const Variable *Var) const { |
| 926 if (Var->hasReg()) | 953 if (Var->hasReg()) |
| 927 llvm_unreachable("Stack Variable has a register assigned"); | 954 llvm_unreachable("Stack Variable has a register assigned"); |
| 928 if (Var->getWeight().isInf()) | 955 if (Var->getWeight().isInf()) { |
| 929 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 956 llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| 957 } | |
| 930 int32_t Offset = Var->getStackOffset(); | 958 int32_t Offset = Var->getStackOffset(); |
| 931 if (!hasFramePointer()) | 959 if (!hasFramePointer()) |
| 932 Offset += getStackAdjustment(); | 960 Offset += getStackAdjustment(); |
| 933 return X8632::Address(RegX8632::getEncodedGPR(getFrameOrStackReg()), Offset); | 961 return X8632::Address(RegX8632::getEncodedGPR(getFrameOrStackReg()), Offset); |
| 934 } | 962 } |
| 935 | 963 |
| 936 void TargetX8632::lowerArguments() { | 964 void TargetX8632::lowerArguments() { |
| 937 VarList &Args = Func->getArgs(); | 965 VarList &Args = Func->getArgs(); |
| 938 // The first four arguments of vector type, regardless of their | 966 // The first four arguments of vector type, regardless of their |
| 939 // position relative to the other arguments in the argument list, are | 967 // position relative to the other arguments in the argument list, are |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1310 Operand *TargetX8632::loOperand(Operand *Operand) { | 1338 Operand *TargetX8632::loOperand(Operand *Operand) { |
| 1311 assert(Operand->getType() == IceType_i64 || | 1339 assert(Operand->getType() == IceType_i64 || |
| 1312 Operand->getType() == IceType_f64); | 1340 Operand->getType() == IceType_f64); |
| 1313 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) | 1341 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) |
| 1314 return Operand; | 1342 return Operand; |
| 1315 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 1343 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 1316 split64(Var); | 1344 split64(Var); |
| 1317 return Var->getLo(); | 1345 return Var->getLo(); |
| 1318 } | 1346 } |
| 1319 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1347 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 1320 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | 1348 ConstantInteger32 *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
| 1349 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); | |
| 1350 return legalize(ConstInt); | |
| 1321 } | 1351 } |
| 1322 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 1352 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
| 1323 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), | 1353 OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
| 1324 Mem->getOffset(), Mem->getIndex(), | 1354 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
| 1325 Mem->getShift(), Mem->getSegmentRegister()); | 1355 Mem->getShift(), Mem->getSegmentRegister()); |
| 1356 // Test if we should randomize or pool the offset, if so randomize it or | |
| 1357 // pool it then create mem operand with the blinded/pooled constant. | |
| 1358 // Otherwise, return the mem operand as ordinary mem operand. | |
| 1359 return legalize(MemOperand); | |
| 1326 } | 1360 } |
| 1327 llvm_unreachable("Unsupported operand type"); | 1361 llvm_unreachable("Unsupported operand type"); |
| 1328 return nullptr; | 1362 return nullptr; |
| 1329 } | 1363 } |
| 1330 | 1364 |
| 1331 Operand *TargetX8632::hiOperand(Operand *Operand) { | 1365 Operand *TargetX8632::hiOperand(Operand *Operand) { |
| 1332 assert(Operand->getType() == IceType_i64 || | 1366 assert(Operand->getType() == IceType_i64 || |
| 1333 Operand->getType() == IceType_f64); | 1367 Operand->getType() == IceType_f64); |
| 1334 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) | 1368 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) |
| 1335 return Operand; | 1369 return Operand; |
| 1336 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 1370 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 1337 split64(Var); | 1371 split64(Var); |
| 1338 return Var->getHi(); | 1372 return Var->getHi(); |
| 1339 } | 1373 } |
| 1340 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1374 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 1341 return Ctx->getConstantInt32( | 1375 ConstantInteger32 *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
| 1342 static_cast<uint32_t>(Const->getValue() >> 32)); | 1376 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue() >> 32))); |
| 1377 // check if we need to blind/pool the constant | |
| 1378 return legalize(ConstInt); | |
| 1343 } | 1379 } |
| 1344 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 1380 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
| 1345 Constant *Offset = Mem->getOffset(); | 1381 Constant *Offset = Mem->getOffset(); |
| 1346 if (Offset == nullptr) { | 1382 if (Offset == nullptr) { |
| 1347 Offset = Ctx->getConstantInt32(4); | 1383 Offset = Ctx->getConstantInt32(4); |
| 1348 } else if (ConstantInteger32 *IntOffset = | 1384 } else if (ConstantInteger32 *IntOffset = |
| 1349 llvm::dyn_cast<ConstantInteger32>(Offset)) { | 1385 llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| 1350 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); | 1386 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); |
| 1351 } else if (ConstantRelocatable *SymOffset = | 1387 } else if (ConstantRelocatable *SymOffset = |
| 1352 llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 1388 llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
| 1353 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); | 1389 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); |
| 1354 Offset = | 1390 Offset = |
| 1355 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), | 1391 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), |
| 1356 SymOffset->getSuppressMangling()); | 1392 SymOffset->getSuppressMangling()); |
| 1357 } | 1393 } |
| 1358 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset, | 1394 OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
| 1359 Mem->getIndex(), Mem->getShift(), | 1395 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
| 1360 Mem->getSegmentRegister()); | 1396 Mem->getShift(), Mem->getSegmentRegister()); |
| 1397 // Test if the Offset is an eligible i32 constants for randomization and | |
| 1398 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem | |
| 1399 // operand. | |
| 1400 return legalize(MemOperand); | |
| 1361 } | 1401 } |
| 1362 llvm_unreachable("Unsupported operand type"); | 1402 llvm_unreachable("Unsupported operand type"); |
| 1363 return nullptr; | 1403 return nullptr; |
| 1364 } | 1404 } |
| 1365 | 1405 |
| 1366 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, | 1406 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, |
| 1367 RegSetMask Exclude) const { | 1407 RegSetMask Exclude) const { |
| 1368 llvm::SmallBitVector Registers(RegX8632::Reg_NUM); | 1408 llvm::SmallBitVector Registers(RegX8632::Reg_NUM); |
| 1369 | 1409 |
| 1370 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | 1410 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1536 Variable *Dest = Inst->getDest(); | 1576 Variable *Dest = Inst->getDest(); |
| 1537 Operand *Src0 = legalize(Inst->getSrc(0)); | 1577 Operand *Src0 = legalize(Inst->getSrc(0)); |
| 1538 Operand *Src1 = legalize(Inst->getSrc(1)); | 1578 Operand *Src1 = legalize(Inst->getSrc(1)); |
| 1539 if (Inst->isCommutative()) { | 1579 if (Inst->isCommutative()) { |
| 1540 if (!llvm::isa<Variable>(Src0) && llvm::isa<Variable>(Src1)) | 1580 if (!llvm::isa<Variable>(Src0) && llvm::isa<Variable>(Src1)) |
| 1541 std::swap(Src0, Src1); | 1581 std::swap(Src0, Src1); |
| 1542 if (llvm::isa<Constant>(Src0) && !llvm::isa<Constant>(Src1)) | 1582 if (llvm::isa<Constant>(Src0) && !llvm::isa<Constant>(Src1)) |
| 1543 std::swap(Src0, Src1); | 1583 std::swap(Src0, Src1); |
| 1544 } | 1584 } |
| 1545 if (Dest->getType() == IceType_i64) { | 1585 if (Dest->getType() == IceType_i64) { |
| 1586 // These helper-call-involved instructions are lowered in this | |
| 1587 // separate switch. This is because loOperand() and hiOperand() | |
| 1588 // may insert redundant instructions for constant blinding and | |
| 1589 // pooling. Such redundant instructions will fail liveness analysis | |
| 1590 // under -Om1 setting. And, actually these arguments do not need | |
| 1591 // to be processed with loOperand() and hiOperand() to be used. | |
| 1592 switch (Inst->getOp()) { | |
| 1593 case InstArithmetic::Udiv: { | |
| 1594 const SizeT MaxSrcs = 2; | |
| 1595 InstCall *Call = makeHelperCall(H_udiv_i64, Dest, MaxSrcs); | |
| 1596 Call->addArg(Inst->getSrc(0)); | |
| 1597 Call->addArg(Inst->getSrc(1)); | |
| 1598 lowerCall(Call); | |
| 1599 return; | |
| 1600 } | |
| 1601 case InstArithmetic::Sdiv: { | |
| 1602 const SizeT MaxSrcs = 2; | |
| 1603 InstCall *Call = makeHelperCall(H_sdiv_i64, Dest, MaxSrcs); | |
| 1604 Call->addArg(Inst->getSrc(0)); | |
| 1605 Call->addArg(Inst->getSrc(1)); | |
| 1606 lowerCall(Call); | |
| 1607 return; | |
| 1608 } | |
| 1609 case InstArithmetic::Urem: { | |
| 1610 const SizeT MaxSrcs = 2; | |
| 1611 InstCall *Call = makeHelperCall(H_urem_i64, Dest, MaxSrcs); | |
| 1612 Call->addArg(Inst->getSrc(0)); | |
| 1613 Call->addArg(Inst->getSrc(1)); | |
| 1614 lowerCall(Call); | |
| 1615 return; | |
| 1616 } | |
| 1617 case InstArithmetic::Srem: { | |
| 1618 const SizeT MaxSrcs = 2; | |
| 1619 InstCall *Call = makeHelperCall(H_srem_i64, Dest, MaxSrcs); | |
| 1620 Call->addArg(Inst->getSrc(0)); | |
| 1621 Call->addArg(Inst->getSrc(1)); | |
| 1622 lowerCall(Call); | |
| 1623 return; | |
| 1624 } | |
| 1625 default: | |
| 1626 break; | |
| 1627 } | |
| 1628 | |
| 1546 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1629 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1547 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1630 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1548 Operand *Src0Lo = loOperand(Src0); | 1631 Operand *Src0Lo = loOperand(Src0); |
| 1549 Operand *Src0Hi = hiOperand(Src0); | 1632 Operand *Src0Hi = hiOperand(Src0); |
| 1550 Operand *Src1Lo = loOperand(Src1); | 1633 Operand *Src1Lo = loOperand(Src1); |
| 1551 Operand *Src1Hi = hiOperand(Src1); | 1634 Operand *Src1Hi = hiOperand(Src1); |
| 1552 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 1635 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 1553 switch (Inst->getOp()) { | 1636 switch (Inst->getOp()) { |
| 1554 case InstArithmetic::_num: | 1637 case InstArithmetic::_num: |
| 1555 llvm_unreachable("Unknown arithmetic operator"); | 1638 llvm_unreachable("Unknown arithmetic operator"); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1725 // T_2 and T_3 are being assigned again because of the | 1808 // T_2 and T_3 are being assigned again because of the |
| 1726 // intra-block control flow, so T_2 needs the _mov_nonkillable | 1809 // intra-block control flow, so T_2 needs the _mov_nonkillable |
| 1727 // variant to avoid liveness problems. T_3 doesn't need special | 1810 // variant to avoid liveness problems. T_3 doesn't need special |
| 1728 // treatment because it is reassigned via _sar instead of _mov. | 1811 // treatment because it is reassigned via _sar instead of _mov. |
| 1729 _mov_nonkillable(T_2, T_3); | 1812 _mov_nonkillable(T_2, T_3); |
| 1730 _sar(T_3, SignExtend); | 1813 _sar(T_3, SignExtend); |
| 1731 Context.insert(Label); | 1814 Context.insert(Label); |
| 1732 _mov(DestLo, T_2); | 1815 _mov(DestLo, T_2); |
| 1733 _mov(DestHi, T_3); | 1816 _mov(DestHi, T_3); |
| 1734 } break; | 1817 } break; |
| 1735 case InstArithmetic::Udiv: { | |
| 1736 const SizeT MaxSrcs = 2; | |
| 1737 InstCall *Call = makeHelperCall(H_udiv_i64, Dest, MaxSrcs); | |
| 1738 Call->addArg(Inst->getSrc(0)); | |
| 1739 Call->addArg(Inst->getSrc(1)); | |
| 1740 lowerCall(Call); | |
| 1741 } break; | |
| 1742 case InstArithmetic::Sdiv: { | |
| 1743 const SizeT MaxSrcs = 2; | |
| 1744 InstCall *Call = makeHelperCall(H_sdiv_i64, Dest, MaxSrcs); | |
| 1745 Call->addArg(Inst->getSrc(0)); | |
| 1746 Call->addArg(Inst->getSrc(1)); | |
| 1747 lowerCall(Call); | |
| 1748 } break; | |
| 1749 case InstArithmetic::Urem: { | |
| 1750 const SizeT MaxSrcs = 2; | |
| 1751 InstCall *Call = makeHelperCall(H_urem_i64, Dest, MaxSrcs); | |
| 1752 Call->addArg(Inst->getSrc(0)); | |
| 1753 Call->addArg(Inst->getSrc(1)); | |
| 1754 lowerCall(Call); | |
| 1755 } break; | |
| 1756 case InstArithmetic::Srem: { | |
| 1757 const SizeT MaxSrcs = 2; | |
| 1758 InstCall *Call = makeHelperCall(H_srem_i64, Dest, MaxSrcs); | |
| 1759 Call->addArg(Inst->getSrc(0)); | |
| 1760 Call->addArg(Inst->getSrc(1)); | |
| 1761 lowerCall(Call); | |
| 1762 } break; | |
| 1763 case InstArithmetic::Fadd: | 1818 case InstArithmetic::Fadd: |
| 1764 case InstArithmetic::Fsub: | 1819 case InstArithmetic::Fsub: |
| 1765 case InstArithmetic::Fmul: | 1820 case InstArithmetic::Fmul: |
| 1766 case InstArithmetic::Fdiv: | 1821 case InstArithmetic::Fdiv: |
| 1767 case InstArithmetic::Frem: | 1822 case InstArithmetic::Frem: |
| 1768 llvm_unreachable("FP instruction with i64 type"); | 1823 llvm_unreachable("FP instruction with i64 type"); |
| 1769 break; | 1824 break; |
| 1825 case InstArithmetic::Udiv: | |
| 1826 case InstArithmetic::Sdiv: | |
| 1827 case InstArithmetic::Urem: | |
| 1828 case InstArithmetic::Srem: | |
| 1829 llvm_unreachable("Call-helper-involved instruction for i64 type \ | |
| 1830 should has already been handled before"); | |
|
Jim Stichnoth
2015/06/20 17:42:16
should have
| |
| 1831 break; | |
| 1770 } | 1832 } |
| 1771 return; | 1833 return; |
| 1772 } | 1834 } |
| 1773 if (isVectorType(Dest->getType())) { | 1835 if (isVectorType(Dest->getType())) { |
| 1774 // TODO: Trap on integer divide and integer modulo by zero. | 1836 // TODO: Trap on integer divide and integer modulo by zero. |
| 1775 // See: https://code.google.com/p/nativeclient/issues/detail?id=3899 | 1837 // See: https://code.google.com/p/nativeclient/issues/detail?id=3899 |
| 1776 if (llvm::isa<OperandX8632Mem>(Src1)) | 1838 if (llvm::isa<OperandX8632Mem>(Src1)) |
| 1777 Src1 = legalizeToVar(Src1); | 1839 Src1 = legalizeToVar(Src1); |
| 1778 switch (Inst->getOp()) { | 1840 switch (Inst->getOp()) { |
| 1779 case InstArithmetic::_num: | 1841 case InstArithmetic::_num: |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2154 Operand *Src0Hi = hiOperand(Src0); | 2216 Operand *Src0Hi = hiOperand(Src0); |
| 2155 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2217 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2156 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2218 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2157 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 2219 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 2158 _mov(T_Lo, Src0Lo); | 2220 _mov(T_Lo, Src0Lo); |
| 2159 _mov(DestLo, T_Lo); | 2221 _mov(DestLo, T_Lo); |
| 2160 _mov(T_Hi, Src0Hi); | 2222 _mov(T_Hi, Src0Hi); |
| 2161 _mov(DestHi, T_Hi); | 2223 _mov(DestHi, T_Hi); |
| 2162 } else { | 2224 } else { |
| 2163 Operand *RI; | 2225 Operand *RI; |
| 2164 if (Dest->hasReg()) | 2226 if (Dest->hasReg()) { |
| 2165 // If Dest already has a physical register, then legalize the | 2227 // If Dest already has a physical register, then legalize the |
| 2166 // Src operand into a Variable with the same register | 2228 // Src operand into a Variable with the same register |
| 2167 // assignment. This is mostly a workaround for advanced phi | 2229 // assignment. This is mostly a workaround for advanced phi |
| 2168 // lowering's ad-hoc register allocation which assumes no | 2230 // lowering's ad-hoc register allocation which assumes no |
| 2169 // register allocation is needed when at least one of the | 2231 // register allocation is needed when at least one of the |
| 2170 // operands is non-memory. | 2232 // operands is non-memory. |
| 2171 RI = legalize(Src0, Legal_Reg, Dest->getRegNum()); | 2233 |
| 2172 else | 2234 // If we have a physical register for the dest variable, we can |
| 2235 // enable our constant blinding or pooling again. Note this is | |
| 2236 // only for advancedPhiLowering(), the flag flip should leave | |
| 2237 // no other side effect. | |
| 2238 { | |
| 2239 BoolFlagSaver B(RandomizationPoolingPaused, false); | |
| 2240 RI = legalize(Src0, Legal_Reg, Dest->getRegNum()); | |
| 2241 } | |
| 2242 } else { | |
| 2173 // If Dest could be a stack operand, then RI must be a physical | 2243 // If Dest could be a stack operand, then RI must be a physical |
| 2174 // register or a scalar integer immediate. | 2244 // register or a scalar integer immediate. |
| 2175 RI = legalize(Src0, Legal_Reg | Legal_Imm); | 2245 RI = legalize(Src0, Legal_Reg | Legal_Imm); |
| 2246 } | |
| 2176 if (isVectorType(Dest->getType())) | 2247 if (isVectorType(Dest->getType())) |
| 2177 _movp(Dest, RI); | 2248 _movp(Dest, RI); |
| 2178 else | 2249 else |
| 2179 _mov(Dest, RI); | 2250 _mov(Dest, RI); |
| 2180 } | 2251 } |
| 2181 } | 2252 } |
| 2182 | 2253 |
| 2183 void TargetX8632::lowerBr(const InstBr *Inst) { | 2254 void TargetX8632::lowerBr(const InstBr *Inst) { |
| 2184 if (Inst->isUnconditional()) { | 2255 if (Inst->isUnconditional()) { |
| 2185 _br(Inst->getTargetUnconditional()); | 2256 _br(Inst->getTargetUnconditional()); |
| (...skipping 2540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4726 } else { | 4797 } else { |
| 4727 TargetLowering::lowerOther(Instr); | 4798 TargetLowering::lowerOther(Instr); |
| 4728 } | 4799 } |
| 4729 } | 4800 } |
| 4730 | 4801 |
| 4731 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to | 4802 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to |
| 4732 // preserve integrity of liveness analysis. Undef values are also | 4803 // preserve integrity of liveness analysis. Undef values are also |
| 4733 // turned into zeroes, since loOperand() and hiOperand() don't expect | 4804 // turned into zeroes, since loOperand() and hiOperand() don't expect |
| 4734 // Undef input. | 4805 // Undef input. |
| 4735 void TargetX8632::prelowerPhis() { | 4806 void TargetX8632::prelowerPhis() { |
| 4807 // Pause constant blinding or pooling, blinding or pooling will be done later | |
| 4808 // during phi lowering assignments | |
| 4809 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 4810 | |
| 4736 CfgNode *Node = Context.getNode(); | 4811 CfgNode *Node = Context.getNode(); |
| 4737 for (Inst &I : Node->getPhis()) { | 4812 for (Inst &I : Node->getPhis()) { |
| 4738 auto Phi = llvm::dyn_cast<InstPhi>(&I); | 4813 auto Phi = llvm::dyn_cast<InstPhi>(&I); |
| 4739 if (Phi->isDeleted()) | 4814 if (Phi->isDeleted()) |
| 4740 continue; | 4815 continue; |
| 4741 Variable *Dest = Phi->getDest(); | 4816 Variable *Dest = Phi->getDest(); |
| 4742 if (Dest->getType() == IceType_i64) { | 4817 if (Dest->getType() == IceType_i64) { |
| 4743 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 4818 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 4744 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 4819 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 4745 InstPhi *PhiLo = InstPhi::create(Func, Phi->getSrcSize(), DestLo); | 4820 InstPhi *PhiLo = InstPhi::create(Func, Phi->getSrcSize(), DestLo); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4825 // assignment, add Dest to the set of available registers, and | 4900 // assignment, add Dest to the set of available registers, and |
| 4826 // remove Src from the set of available registers. Iteration is | 4901 // remove Src from the set of available registers. Iteration is |
| 4827 // done backwards to enable incremental updates of the available | 4902 // done backwards to enable incremental updates of the available |
| 4828 // register set, and the lowered instruction numbers may be out of | 4903 // register set, and the lowered instruction numbers may be out of |
| 4829 // order, but that can be worked around by renumbering the block | 4904 // order, but that can be worked around by renumbering the block |
| 4830 // afterwards if necessary. | 4905 // afterwards if necessary. |
| 4831 for (const Inst &I : reverse_range(Assignments)) { | 4906 for (const Inst &I : reverse_range(Assignments)) { |
| 4832 Context.rewind(); | 4907 Context.rewind(); |
| 4833 auto Assign = llvm::dyn_cast<InstAssign>(&I); | 4908 auto Assign = llvm::dyn_cast<InstAssign>(&I); |
| 4834 Variable *Dest = Assign->getDest(); | 4909 Variable *Dest = Assign->getDest(); |
| 4910 | |
| 4911 // If the source operand is ConstantUndef, do not legalize it. | |
| 4912 // In function test_split_undef_int_vec, the advanced phi | |
| 4913 // lowering process will find an assignment of undefined | |
| 4914 // vector. This vector, as the Src here, will crash if it | |
| 4915 // go through legalize(). legalize() will create new variable | |
| 4916 // with makeVectorOfZeros(), but this new variable will be | |
| 4917 // assigned a stack slot. This will fail the assertion in | |
| 4918 // IceInstX8632.cpp:789, as XmmEmitterRegOp() complain: | |
| 4919 // Var->hasReg() fails. Note this failure is irrelevant to | |
| 4920 // randomization or pooling of constants. | |
| 4921 // So, we do not call legalize() to add pool label for the | |
| 4922 // src operands of phi assignment instructions. | |
| 4923 // Instead, we manually add pool label for constant float and | |
| 4924 // constant double values here. | |
| 4925 // Note going through legalize() does not affect the testing | |
| 4926 // results of SPEC2K and xtests. | |
| 4835 Operand *Src = Assign->getSrc(0); | 4927 Operand *Src = Assign->getSrc(0); |
| 4928 if (!llvm::isa<ConstantUndef>(Assign->getSrc(0))) { | |
| 4929 Src = legalize(Src); | |
| 4930 } | |
| 4931 | |
| 4836 Variable *SrcVar = llvm::dyn_cast<Variable>(Src); | 4932 Variable *SrcVar = llvm::dyn_cast<Variable>(Src); |
| 4837 // Use normal assignment lowering, except lower mem=mem specially | 4933 // Use normal assignment lowering, except lower mem=mem specially |
| 4838 // so we can register-allocate at the same time. | 4934 // so we can register-allocate at the same time. |
| 4839 if (!isMemoryOperand(Dest) || !isMemoryOperand(Src)) { | 4935 if (!isMemoryOperand(Dest) || !isMemoryOperand(Src)) { |
| 4840 lowerAssign(Assign); | 4936 lowerAssign(Assign); |
| 4841 } else { | 4937 } else { |
| 4842 assert(Dest->getType() == Src->getType()); | 4938 assert(Dest->getType() == Src->getType()); |
| 4843 const llvm::SmallBitVector &RegsForType = | 4939 const llvm::SmallBitVector &RegsForType = |
| 4844 getRegisterSetForType(Dest->getType()); | 4940 getRegisterSetForType(Dest->getType()); |
| 4845 llvm::SmallBitVector AvailRegsForType = RegsForType & Available; | 4941 llvm::SmallBitVector AvailRegsForType = RegsForType & Available; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5001 // Assert that a physical register is allowed. To date, all calls | 5097 // Assert that a physical register is allowed. To date, all calls |
| 5002 // to legalize() allow a physical register. If a physical register | 5098 // to legalize() allow a physical register. If a physical register |
| 5003 // needs to be explicitly disallowed, then new code will need to be | 5099 // needs to be explicitly disallowed, then new code will need to be |
| 5004 // written to force a spill. | 5100 // written to force a spill. |
| 5005 assert(Allowed & Legal_Reg); | 5101 assert(Allowed & Legal_Reg); |
| 5006 // If we're asking for a specific physical register, make sure we're | 5102 // If we're asking for a specific physical register, make sure we're |
| 5007 // not allowing any other operand kinds. (This could be future | 5103 // not allowing any other operand kinds. (This could be future |
| 5008 // work, e.g. allow the shl shift amount to be either an immediate | 5104 // work, e.g. allow the shl shift amount to be either an immediate |
| 5009 // or in ecx.) | 5105 // or in ecx.) |
| 5010 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); | 5106 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); |
| 5107 | |
| 5011 if (auto Mem = llvm::dyn_cast<OperandX8632Mem>(From)) { | 5108 if (auto Mem = llvm::dyn_cast<OperandX8632Mem>(From)) { |
| 5012 // Before doing anything with a Mem operand, we need to ensure | 5109 // Before doing anything with a Mem operand, we need to ensure |
| 5013 // that the Base and Index components are in physical registers. | 5110 // that the Base and Index components are in physical registers. |
| 5014 Variable *Base = Mem->getBase(); | 5111 Variable *Base = Mem->getBase(); |
| 5015 Variable *Index = Mem->getIndex(); | 5112 Variable *Index = Mem->getIndex(); |
| 5016 Variable *RegBase = nullptr; | 5113 Variable *RegBase = nullptr; |
| 5017 Variable *RegIndex = nullptr; | 5114 Variable *RegIndex = nullptr; |
| 5018 if (Base) { | 5115 if (Base) { |
| 5019 RegBase = legalizeToVar(Base); | 5116 RegBase = legalizeToVar(Base); |
| 5020 } | 5117 } |
| 5021 if (Index) { | 5118 if (Index) { |
| 5022 RegIndex = legalizeToVar(Index); | 5119 RegIndex = legalizeToVar(Index); |
| 5023 } | 5120 } |
| 5024 if (Base != RegBase || Index != RegIndex) { | 5121 if (Base != RegBase || Index != RegIndex) { |
| 5025 From = | 5122 Mem = |
| 5026 OperandX8632Mem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex, | 5123 OperandX8632Mem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex, |
| 5027 Mem->getShift(), Mem->getSegmentRegister()); | 5124 Mem->getShift(), Mem->getSegmentRegister()); |
| 5028 } | 5125 } |
| 5029 | 5126 |
| 5127 // For all Memory Operands, we do randomization/pooling here | |
| 5128 From = randomizeOrPoolImmediate(Mem); | |
| 5129 | |
| 5030 if (!(Allowed & Legal_Mem)) { | 5130 if (!(Allowed & Legal_Mem)) { |
| 5031 From = copyToReg(From, RegNum); | 5131 From = copyToReg(From, RegNum); |
| 5032 } | 5132 } |
| 5033 return From; | 5133 return From; |
| 5034 } | 5134 } |
| 5035 if (llvm::isa<Constant>(From)) { | 5135 if (auto *Const = llvm::dyn_cast<Constant>(From)) { |
| 5036 if (llvm::isa<ConstantUndef>(From)) { | 5136 if (llvm::isa<ConstantUndef>(Const)) { |
| 5037 // Lower undefs to zero. Another option is to lower undefs to an | 5137 // Lower undefs to zero. Another option is to lower undefs to an |
| 5038 // uninitialized register; however, using an uninitialized register | 5138 // uninitialized register; however, using an uninitialized register |
| 5039 // results in less predictable code. | 5139 // results in less predictable code. |
| 5040 // | 5140 // |
| 5041 // If in the future the implementation is changed to lower undef | 5141 // If in the future the implementation is changed to lower undef |
| 5042 // values to uninitialized registers, a FakeDef will be needed: | 5142 // values to uninitialized registers, a FakeDef will be needed: |
| 5043 // Context.insert(InstFakeDef::create(Func, Reg)); | 5143 // Context.insert(InstFakeDef::create(Func, Reg)); |
| 5044 // This is in order to ensure that the live range of Reg is not | 5144 // This is in order to ensure that the live range of Reg is not |
| 5045 // overestimated. If the constant being lowered is a 64 bit value, | 5145 // overestimated. If the constant being lowered is a 64 bit value, |
| 5046 // then the result should be split and the lo and hi components will | 5146 // then the result should be split and the lo and hi components will |
| 5047 // need to go in uninitialized registers. | 5147 // need to go in uninitialized registers. |
| 5048 if (isVectorType(Ty)) | 5148 if (isVectorType(Ty)) |
| 5049 return makeVectorOfZeros(Ty, RegNum); | 5149 return makeVectorOfZeros(Ty, RegNum); |
| 5050 From = Ctx->getConstantZero(Ty); | 5150 From = Ctx->getConstantZero(Ty); |
|
Jim Stichnoth
2015/06/20 17:42:16
I think you need to reset Const as well, e.g.:
C
| |
| 5051 } | 5151 } |
| 5052 // There should be no constants of vector type (other than undef). | 5152 // There should be no constants of vector type (other than undef). |
| 5053 assert(!isVectorType(Ty)); | 5153 assert(!isVectorType(Ty)); |
| 5154 | |
| 5155 // If the operand is an 32 bit constant integer, we should check | |
| 5156 // whether we need to randomize it or pool it. | |
| 5157 if (ConstantInteger32 *C = llvm::dyn_cast<ConstantInteger32>(Const)) { | |
| 5158 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); | |
| 5159 if (NewConst != Const) { | |
| 5160 return NewConst; | |
| 5161 } | |
| 5162 } | |
| 5163 | |
| 5054 // Convert a scalar floating point constant into an explicit | 5164 // Convert a scalar floating point constant into an explicit |
| 5055 // memory operand. | 5165 // memory operand. |
| 5056 if (isScalarFloatingType(Ty)) { | 5166 if (isScalarFloatingType(Ty)) { |
| 5057 Variable *Base = nullptr; | 5167 Variable *Base = nullptr; |
| 5058 std::string Buffer; | 5168 std::string Buffer; |
| 5059 llvm::raw_string_ostream StrBuf(Buffer); | 5169 llvm::raw_string_ostream StrBuf(Buffer); |
| 5060 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf); | 5170 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf); |
| 5171 llvm::cast<Constant>(From)->setShouldBePooled(true); | |
| 5061 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | 5172 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
| 5062 From = OperandX8632Mem::create(Func, Ty, Base, Offset); | 5173 From = OperandX8632Mem::create(Func, Ty, Base, Offset); |
| 5063 } | 5174 } |
| 5064 bool NeedsReg = false; | 5175 bool NeedsReg = false; |
| 5065 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) | 5176 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) |
| 5066 // Immediate specifically not allowed | 5177 // Immediate specifically not allowed |
| 5067 NeedsReg = true; | 5178 NeedsReg = true; |
| 5068 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) | 5179 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) |
| 5069 // On x86, FP constants are lowered to mem operands. | 5180 // On x86, FP constants are lowered to mem operands. |
| 5070 NeedsReg = true; | 5181 NeedsReg = true; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5107 bool IsSrc1ImmOrReg = false; | 5218 bool IsSrc1ImmOrReg = false; |
| 5108 if (llvm::isa<Constant>(Src1)) { | 5219 if (llvm::isa<Constant>(Src1)) { |
| 5109 IsSrc1ImmOrReg = true; | 5220 IsSrc1ImmOrReg = true; |
| 5110 } else if (Variable *Var = llvm::dyn_cast<Variable>(Src1)) { | 5221 } else if (Variable *Var = llvm::dyn_cast<Variable>(Src1)) { |
| 5111 if (Var->hasReg()) | 5222 if (Var->hasReg()) |
| 5112 IsSrc1ImmOrReg = true; | 5223 IsSrc1ImmOrReg = true; |
| 5113 } | 5224 } |
| 5114 return legalize(Src0, IsSrc1ImmOrReg ? (Legal_Reg | Legal_Mem) : Legal_Reg); | 5225 return legalize(Src0, IsSrc1ImmOrReg ? (Legal_Reg | Legal_Mem) : Legal_Reg); |
| 5115 } | 5226 } |
| 5116 | 5227 |
| 5117 OperandX8632Mem *TargetX8632::formMemoryOperand(Operand *Operand, Type Ty, | 5228 OperandX8632Mem *TargetX8632::formMemoryOperand(Operand *Opnd, Type Ty, |
| 5118 bool DoLegalize) { | 5229 bool DoLegalize) { |
| 5119 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand); | 5230 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Opnd); |
| 5120 // It may be the case that address mode optimization already creates | 5231 // It may be the case that address mode optimization already creates |
| 5121 // an OperandX8632Mem, so in that case it wouldn't need another level | 5232 // an OperandX8632Mem, so in that case it wouldn't need another level |
| 5122 // of transformation. | 5233 // of transformation. |
| 5123 if (!Mem) { | 5234 if (!Mem) { |
| 5124 Variable *Base = llvm::dyn_cast<Variable>(Operand); | 5235 Variable *Base = llvm::dyn_cast<Variable>(Opnd); |
| 5125 Constant *Offset = llvm::dyn_cast<Constant>(Operand); | 5236 Constant *Offset = llvm::dyn_cast<Constant>(Opnd); |
| 5126 assert(Base || Offset); | 5237 assert(Base || Offset); |
| 5127 if (Offset) { | 5238 if (Offset) { |
| 5128 // Make sure Offset is not undef. | 5239 // During memory operand building, we do not blind or pool |
| 5129 Offset = llvm::cast<Constant>(legalize(Offset)); | 5240 // the constant offset, we will work on the whole memory |
| 5241 // operand later as one entity later, this save one instruction. | |
| 5242 // By turning blinding and pooling off, we guarantee | |
| 5243 // legalize(Offset) will return a constant*. | |
| 5244 { | |
| 5245 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 5246 | |
| 5247 Offset = llvm::cast<Constant>(legalize(Offset)); | |
| 5248 } | |
| 5249 | |
| 5130 assert(llvm::isa<ConstantInteger32>(Offset) || | 5250 assert(llvm::isa<ConstantInteger32>(Offset) || |
| 5131 llvm::isa<ConstantRelocatable>(Offset)); | 5251 llvm::isa<ConstantRelocatable>(Offset)); |
| 5132 } | 5252 } |
| 5133 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); | 5253 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); |
| 5134 } | 5254 } |
| 5135 return llvm::cast<OperandX8632Mem>(DoLegalize ? legalize(Mem) : Mem); | 5255 // Do legalization, which contains randomization/pooling |
| 5256 // or do randomization/pooling. | |
| 5257 return llvm::cast<OperandX8632Mem>( | |
| 5258 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); | |
| 5136 } | 5259 } |
| 5137 | 5260 |
| 5138 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { | 5261 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { |
| 5139 // There aren't any 64-bit integer registers for x86-32. | 5262 // There aren't any 64-bit integer registers for x86-32. |
| 5140 assert(Type != IceType_i64); | 5263 assert(Type != IceType_i64); |
| 5141 Variable *Reg = Func->makeVariable(Type); | 5264 Variable *Reg = Func->makeVariable(Type); |
| 5142 if (RegNum == Variable::NoRegister) | 5265 if (RegNum == Variable::NoRegister) |
| 5143 Reg->setWeightInfinite(); | 5266 Reg->setWeightInfinite(); |
| 5144 else | 5267 else |
| 5145 Reg->setRegNum(RegNum); | 5268 Reg->setRegNum(RegNum); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5290 typedef ConstantDouble IceType; | 5413 typedef ConstantDouble IceType; |
| 5291 static const Type Ty = IceType_f64; | 5414 static const Type Ty = IceType_f64; |
| 5292 static const char *TypeName; | 5415 static const char *TypeName; |
| 5293 static const char *AsmTag; | 5416 static const char *AsmTag; |
| 5294 static const char *PrintfString; | 5417 static const char *PrintfString; |
| 5295 }; | 5418 }; |
| 5296 const char *PoolTypeConverter<double>::TypeName = "double"; | 5419 const char *PoolTypeConverter<double>::TypeName = "double"; |
| 5297 const char *PoolTypeConverter<double>::AsmTag = ".quad"; | 5420 const char *PoolTypeConverter<double>::AsmTag = ".quad"; |
| 5298 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; | 5421 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; |
| 5299 | 5422 |
| 5423 // Add converter for int type constant pooling | |
| 5424 template <> struct PoolTypeConverter<uint32_t> { | |
| 5425 typedef uint32_t PrimitiveIntType; | |
| 5426 typedef ConstantInteger32 IceType; | |
| 5427 static const Type Ty = IceType_i32; | |
| 5428 static const char *TypeName; | |
| 5429 static const char *AsmTag; | |
| 5430 static const char *PrintfString; | |
| 5431 }; | |
| 5432 const char *PoolTypeConverter<uint32_t>::TypeName = "i32"; | |
| 5433 const char *PoolTypeConverter<uint32_t>::AsmTag = ".long"; | |
| 5434 const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x"; | |
| 5435 | |
| 5436 // Add converter for int type constant pooling | |
| 5437 template <> struct PoolTypeConverter<uint16_t> { | |
| 5438 typedef uint32_t PrimitiveIntType; | |
| 5439 typedef ConstantInteger32 IceType; | |
| 5440 static const Type Ty = IceType_i16; | |
| 5441 static const char *TypeName; | |
| 5442 static const char *AsmTag; | |
| 5443 static const char *PrintfString; | |
| 5444 }; | |
| 5445 const char *PoolTypeConverter<uint16_t>::TypeName = "i16"; | |
| 5446 const char *PoolTypeConverter<uint16_t>::AsmTag = ".short"; | |
| 5447 const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x"; | |
| 5448 | |
| 5449 // Add converter for int type constant pooling | |
| 5450 template <> struct PoolTypeConverter<uint8_t> { | |
| 5451 typedef uint32_t PrimitiveIntType; | |
| 5452 typedef ConstantInteger32 IceType; | |
| 5453 static const Type Ty = IceType_i8; | |
| 5454 static const char *TypeName; | |
| 5455 static const char *AsmTag; | |
| 5456 static const char *PrintfString; | |
| 5457 }; | |
| 5458 const char *PoolTypeConverter<uint8_t>::TypeName = "i8"; | |
| 5459 const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte"; | |
| 5460 const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x"; | |
| 5461 | |
| 5300 template <typename T> | 5462 template <typename T> |
| 5301 void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { | 5463 void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { |
| 5302 if (!ALLOW_DUMP) | 5464 if (!ALLOW_DUMP) |
| 5303 return; | 5465 return; |
| 5304 Ostream &Str = Ctx->getStrEmit(); | 5466 Ostream &Str = Ctx->getStrEmit(); |
| 5305 Type Ty = T::Ty; | 5467 Type Ty = T::Ty; |
| 5306 SizeT Align = typeAlignInBytes(Ty); | 5468 SizeT Align = typeAlignInBytes(Ty); |
| 5307 ConstantList Pool = Ctx->getConstantPool(Ty); | 5469 ConstantList Pool = Ctx->getConstantPool(Ty); |
| 5308 | 5470 |
| 5309 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align | 5471 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align |
| 5310 << "\n"; | 5472 << "\n"; |
| 5311 Str << "\t.align\t" << Align << "\n"; | 5473 Str << "\t.align\t" << Align << "\n"; |
| 5312 for (Constant *C : Pool) { | 5474 for (Constant *C : Pool) { |
| 5475 if (!C->getShouldBePooled()) | |
| 5476 continue; | |
| 5313 typename T::IceType *Const = llvm::cast<typename T::IceType>(C); | 5477 typename T::IceType *Const = llvm::cast<typename T::IceType>(C); |
| 5314 typename T::IceType::PrimType Value = Const->getValue(); | 5478 typename T::IceType::PrimType Value = Const->getValue(); |
| 5315 // Use memcpy() to copy bits from Value into RawValue in a way | 5479 // Use memcpy() to copy bits from Value into RawValue in a way |
| 5316 // that avoids breaking strict-aliasing rules. | 5480 // that avoids breaking strict-aliasing rules. |
| 5317 typename T::PrimitiveIntType RawValue; | 5481 typename T::PrimitiveIntType RawValue; |
| 5318 memcpy(&RawValue, &Value, sizeof(Value)); | 5482 memcpy(&RawValue, &Value, sizeof(Value)); |
| 5319 char buf[30]; | 5483 char buf[30]; |
| 5320 int CharsPrinted = | 5484 int CharsPrinted = |
| 5321 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); | 5485 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); |
| 5322 assert(CharsPrinted >= 0 && | 5486 assert(CharsPrinted >= 0 && |
| 5323 (size_t)CharsPrinted < llvm::array_lengthof(buf)); | 5487 (size_t)CharsPrinted < llvm::array_lengthof(buf)); |
| 5324 (void)CharsPrinted; // avoid warnings if asserts are disabled | 5488 (void)CharsPrinted; // avoid warnings if asserts are disabled |
| 5325 Const->emitPoolLabel(Str); | 5489 Const->emitPoolLabel(Str); |
| 5326 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " | 5490 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " |
| 5327 << Value << "\n"; | 5491 << Value << "\n"; |
| 5328 } | 5492 } |
| 5329 } | 5493 } |
| 5330 | 5494 |
| 5331 void TargetDataX8632::lowerConstants() { | 5495 void TargetDataX8632::lowerConstants() { |
| 5332 if (Ctx->getFlags().getDisableTranslation()) | 5496 if (Ctx->getFlags().getDisableTranslation()) |
| 5333 return; | 5497 return; |
| 5334 // No need to emit constants from the int pool since (for x86) they | 5498 // No need to emit constants from the int pool since (for x86) they |
| 5335 // are embedded as immediates in the instructions, just emit float/double. | 5499 // are embedded as immediates in the instructions, just emit float/double. |
| 5336 switch (Ctx->getFlags().getOutFileType()) { | 5500 switch (Ctx->getFlags().getOutFileType()) { |
| 5337 case FT_Elf: { | 5501 case FT_Elf: { |
| 5338 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 5502 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 5503 | |
| 5504 Writer->writeConstantPool<ConstantInteger32>(IceType_i8); | |
| 5505 Writer->writeConstantPool<ConstantInteger32>(IceType_i16); | |
| 5506 Writer->writeConstantPool<ConstantInteger32>(IceType_i32); | |
| 5507 | |
| 5339 Writer->writeConstantPool<ConstantFloat>(IceType_f32); | 5508 Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
| 5340 Writer->writeConstantPool<ConstantDouble>(IceType_f64); | 5509 Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
| 5341 } break; | 5510 } break; |
| 5342 case FT_Asm: | 5511 case FT_Asm: |
| 5343 case FT_Iasm: { | 5512 case FT_Iasm: { |
| 5344 OstreamLocker L(Ctx); | 5513 OstreamLocker L(Ctx); |
| 5514 | |
| 5515 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); | |
| 5516 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); | |
| 5517 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); | |
| 5518 | |
| 5345 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 5519 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 5346 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 5520 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 5347 } break; | 5521 } break; |
| 5348 } | 5522 } |
| 5349 } | 5523 } |
| 5350 | 5524 |
| 5351 TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) | 5525 TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) |
| 5352 : TargetHeaderLowering(Ctx) {} | 5526 : TargetHeaderLowering(Ctx) {} |
| 5353 | 5527 |
| 5528 // Randomize or pool an Immediate. | |
| 5529 Operand *TargetX8632::randomizeOrPoolImmediate(Constant *Immediate, | |
| 5530 int32_t RegNum) { | |
| 5531 assert(llvm::isa<ConstantInteger32>(Immediate) || | |
| 5532 llvm::isa<ConstantRelocatable>(Immediate)); | |
| 5533 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | |
| 5534 RandomizationPoolingPaused == true) { | |
| 5535 // Immediates randomization/pooling off or paused | |
| 5536 return Immediate; | |
| 5537 } | |
| 5538 if (Immediate->shouldBeRandomizedOrPooled(Ctx)) { | |
| 5539 Ctx->statsUpdateRPImms(); | |
| 5540 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == | |
| 5541 RPI_Randomize) { | |
| 5542 // blind the constant | |
| 5543 // FROM: | |
| 5544 // imm | |
| 5545 // TO: | |
| 5546 // insert: mov imm+cookie, Reg | |
| 5547 // insert: lea -cookie[Reg], Reg | |
| 5548 // => Reg | |
| 5549 // If we have already assigned a phy register, we must come from | |
| 5550 // andvancedPhiLowering()=>lowerAssign(). In this case we should reuse | |
| 5551 // the assigned register as this assignment is that start of its use-def | |
| 5552 // chain. So we add RegNum argument here. | |
| 5553 // Note we use 'lea' instruction instead of 'xor' to avoid affecting | |
| 5554 // the flags. | |
| 5555 Variable *Reg = makeReg(IceType_i32, RegNum); | |
| 5556 ConstantInteger32 *Integer = llvm::cast<ConstantInteger32>(Immediate); | |
| 5557 uint32_t Value = Integer->getValue(); | |
| 5558 uint32_t Cookie = Ctx->getRandomizationCookie(); | |
| 5559 _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); | |
| 5560 Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); | |
| 5561 _lea(Reg, | |
| 5562 OperandX8632Mem::create(Func, IceType_i32, Reg, Offset, nullptr, 0)); | |
| 5563 // make sure liveness analysis won't kill this variable, otherwise a | |
| 5564 // liveness | |
| 5565 // assertion will be triggered. | |
| 5566 _set_dest_nonkillable(); | |
| 5567 if (Immediate->getType() != IceType_i32) { | |
| 5568 Variable *TruncReg = makeReg(Immediate->getType(), RegNum); | |
| 5569 _mov(TruncReg, Reg); | |
| 5570 return TruncReg; | |
| 5571 } | |
| 5572 return Reg; | |
| 5573 } | |
| 5574 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { | |
| 5575 // pool the constant | |
| 5576 // FROM: | |
| 5577 // imm | |
| 5578 // TO: | |
| 5579 // insert: mov $label, Reg | |
| 5580 // => Reg | |
| 5581 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool); | |
| 5582 Immediate->setShouldBePooled(true); | |
| 5583 // if we have already assigned a phy register, we must come from | |
| 5584 // andvancedPhiLowering()=>lowerAssign(). In this case we should reuse | |
| 5585 // the assigned register as this assignment is that start of its use-def | |
| 5586 // chain. So we add RegNum argument here. | |
| 5587 Variable *Reg = makeReg(Immediate->getType(), RegNum); | |
| 5588 IceString Label; | |
| 5589 llvm::raw_string_ostream Label_stream(Label); | |
| 5590 Immediate->emitPoolLabel(Label_stream); | |
| 5591 const RelocOffsetT Offset = 0; | |
| 5592 const bool SuppressMangling = true; | |
| 5593 Constant *Symbol = | |
| 5594 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); | |
| 5595 OperandX8632Mem *MemOperand = | |
| 5596 OperandX8632Mem::create(Func, Immediate->getType(), nullptr, Symbol); | |
| 5597 _mov(Reg, MemOperand); | |
| 5598 return Reg; | |
| 5599 } | |
| 5600 assert("Unsupported -randomize-pool-immediates option" && false); | |
| 5601 } | |
| 5602 // the constant Immediate is not eligible for blinding/pooling | |
| 5603 return Immediate; | |
| 5604 } | |
| 5605 | |
| 5606 OperandX8632Mem * | |
| 5607 TargetX8632::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, | |
| 5608 int32_t RegNum) { | |
| 5609 assert(MemOperand); | |
| 5610 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | |
| 5611 RandomizationPoolingPaused == true) { | |
| 5612 // immediates randomization/pooling is turned off | |
| 5613 return MemOperand; | |
| 5614 } | |
| 5615 | |
| 5616 // If this memory operand is already a randommized one, we do | |
| 5617 // not randomize it again. | |
| 5618 if (MemOperand->getRandomize()) | |
| 5619 return MemOperand; | |
| 5620 | |
| 5621 if (Constant *C = llvm::dyn_cast_or_null<Constant>(MemOperand->getOffset())) { | |
| 5622 if (C->shouldBeRandomizedOrPooled(Ctx)) { | |
| 5623 // The offset of this mem operand should be blinded or pooled | |
| 5624 Ctx->statsUpdateRPImms(); | |
| 5625 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == | |
| 5626 RPI_Randomize) { | |
| 5627 // blind the constant offset | |
| 5628 // FROM: | |
| 5629 // offset[base, index, shift] | |
| 5630 // TO: | |
| 5631 // insert: lea offset+cookie[base], RegTemp | |
| 5632 // => -cookie[RegTemp, index, shift] | |
| 5633 uint32_t Value = | |
| 5634 llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset()) | |
| 5635 ->getValue(); | |
| 5636 uint32_t Cookie = Ctx->getRandomizationCookie(); | |
| 5637 Constant *Mask1 = Ctx->getConstantInt( | |
| 5638 MemOperand->getOffset()->getType(), Cookie + Value); | |
| 5639 Constant *Mask2 = | |
| 5640 Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie); | |
| 5641 | |
| 5642 OperandX8632Mem *TempMemOperand = OperandX8632Mem::create( | |
| 5643 Func, MemOperand->getType(), MemOperand->getBase(), Mask1); | |
| 5644 // If we have already assigned a physical register, we must come from | |
| 5645 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse | |
| 5646 // the assigned register as this assignment is that start of its use-def | |
| 5647 // chain. So we add RegNum argument here. | |
| 5648 Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum); | |
| 5649 _lea(RegTemp, TempMemOperand); | |
| 5650 // As source operand doesn't use the dstreg, we don't need to add | |
| 5651 // _set_dest_nonkillable(). | |
| 5652 // But if we use the same Dest Reg, that is, with RegNum | |
| 5653 // assigned, we should add this _set_dest_nonkillable() | |
| 5654 if (RegNum != Variable::NoRegister) | |
| 5655 _set_dest_nonkillable(); | |
| 5656 | |
| 5657 OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( | |
| 5658 Func, MemOperand->getType(), RegTemp, Mask2, MemOperand->getIndex(), | |
| 5659 MemOperand->getShift(), MemOperand->getSegmentRegister()); | |
| 5660 | |
| 5661 // Label this memory operand as randomize, so we won't randomize it | |
| 5662 // again in case we call legalize() mutiple times on this memory | |
| 5663 // operand. | |
| 5664 NewMemOperand->setRandomized(true); | |
| 5665 return NewMemOperand; | |
| 5666 } | |
| 5667 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { | |
| 5668 // pool the constant offset | |
| 5669 // FROM: | |
| 5670 // offset[base, index, shift] | |
| 5671 // TO: | |
| 5672 // insert: mov $label, RegTemp | |
| 5673 // insert: lea [base, RegTemp], RegTemp | |
| 5674 // =>[RegTemp, index, shift] | |
| 5675 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == | |
| 5676 RPI_Pool); | |
| 5677 // Memory operand should never exist as source operands in phi | |
| 5678 // lowering assignments, so there is no need to reuse any registers | |
| 5679 // here. For phi lowering, we should not ask for new physical | |
| 5680 // registers in general. | |
| 5681 // However, if we do meet Memory Operand during phi lowering, we | |
| 5682 // should not blind or pool the immediates for now. | |
| 5683 if (RegNum != Variable::NoRegister) | |
| 5684 return MemOperand; | |
| 5685 Variable *RegTemp = makeReg(IceType_i32); | |
| 5686 IceString Label; | |
| 5687 llvm::raw_string_ostream Label_stream(Label); | |
| 5688 MemOperand->getOffset()->emitPoolLabel(Label_stream); | |
| 5689 MemOperand->getOffset()->setShouldBePooled(true); | |
| 5690 const RelocOffsetT SymOffset = 0; | |
| 5691 bool SuppressMangling = true; | |
| 5692 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), | |
| 5693 SuppressMangling); | |
| 5694 OperandX8632Mem *SymbolOperand = OperandX8632Mem::create( | |
| 5695 Func, MemOperand->getOffset()->getType(), nullptr, Symbol); | |
| 5696 _mov(RegTemp, SymbolOperand); | |
| 5697 // If we have a base variable here, we should add the lea instruction | |
| 5698 // to add the value of the base variable to RegTemp. If there is no | |
| 5699 // base variable, we won't need this lea instruction. | |
| 5700 if (MemOperand->getBase()) { | |
| 5701 OperandX8632Mem *CalculateOperand = OperandX8632Mem::create( | |
| 5702 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, | |
| 5703 RegTemp, 0, MemOperand->getSegmentRegister()); | |
| 5704 _lea(RegTemp, CalculateOperand); | |
| 5705 _set_dest_nonkillable(); | |
| 5706 } | |
| 5707 OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( | |
| 5708 Func, MemOperand->getType(), RegTemp, nullptr, | |
| 5709 MemOperand->getIndex(), MemOperand->getShift(), | |
| 5710 MemOperand->getSegmentRegister()); | |
| 5711 return NewMemOperand; | |
| 5712 } | |
| 5713 assert("Unsupported -randomize-pool-immediates option" && false); | |
| 5714 } | |
| 5715 } | |
| 5716 // the offset is not eligible for blinding or pooling, return the original | |
| 5717 // mem operand | |
| 5718 return MemOperand; | |
| 5719 } | |
| 5720 | |
| 5354 } // end of namespace Ice | 5721 } // end of namespace Ice |
| OLD | NEW |