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) : Flag(F) { | |
| 258 OldValue = F; | |
| 259 F = NewValue; | |
| 260 } | |
| 261 ~BoolFlagSaver() { Flag = OldValue; } | |
| 262 | |
| 263 private: | |
| 264 bool &Flag; | |
| 265 bool OldValue; | |
| 266 }; | |
| 267 | |
| 249 } // end of anonymous namespace | 268 } // end of anonymous namespace |
| 250 | 269 |
| 251 BoolFoldingEntry::BoolFoldingEntry(Inst *I) | 270 BoolFoldingEntry::BoolFoldingEntry(Inst *I) |
| 252 : Instr(I), IsComplex(BoolFolding::hasComplexLowering(I)), IsLiveOut(true), | 271 : Instr(I), IsComplex(BoolFolding::hasComplexLowering(I)), IsLiveOut(true), |
| 253 NumUses(0) {} | 272 NumUses(0) {} |
| 254 | 273 |
| 255 BoolFolding::BoolFoldingProducerKind | 274 BoolFolding::BoolFoldingProducerKind |
| 256 BoolFolding::getProducerKind(const Inst *Instr) { | 275 BoolFolding::getProducerKind(const Inst *Instr) { |
| 257 if (llvm::isa<InstIcmp>(Instr)) { | 276 if (llvm::isa<InstIcmp>(Instr)) { |
| 258 if (Instr->getSrc(0)->getType() != IceType_i64) | 277 if (Instr->getSrc(0)->getType() != IceType_i64) |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 void TargetX8632::initNodeForLowering(CfgNode *Node) { | 411 void TargetX8632::initNodeForLowering(CfgNode *Node) { |
| 393 FoldingInfo.init(Node); | 412 FoldingInfo.init(Node); |
| 394 FoldingInfo.dump(Func); | 413 FoldingInfo.dump(Func); |
| 395 } | 414 } |
| 396 | 415 |
| 397 TargetX8632::TargetX8632(Cfg *Func) | 416 TargetX8632::TargetX8632(Cfg *Func) |
| 398 : TargetLowering(Func), | 417 : TargetLowering(Func), |
| 399 InstructionSet(static_cast<X86InstructionSet>( | 418 InstructionSet(static_cast<X86InstructionSet>( |
| 400 Func->getContext()->getFlags().getTargetInstructionSet() - | 419 Func->getContext()->getFlags().getTargetInstructionSet() - |
| 401 TargetInstructionSet::X86InstructionSet_Begin)), | 420 TargetInstructionSet::X86InstructionSet_Begin)), |
| 402 IsEbpBasedFrame(false), NeedsStackAlignment(false), | 421 IsEbpBasedFrame(false), NeedsStackAlignment(false), SpillAreaSizeBytes(0), |
| 403 SpillAreaSizeBytes(0) { | 422 RandomizationPoolingPaused(false) { |
| 404 static_assert((X86InstructionSet::End - X86InstructionSet::Begin) == | 423 static_assert((X86InstructionSet::End - X86InstructionSet::Begin) == |
| 405 (TargetInstructionSet::X86InstructionSet_End - | 424 (TargetInstructionSet::X86InstructionSet_End - |
| 406 TargetInstructionSet::X86InstructionSet_Begin), | 425 TargetInstructionSet::X86InstructionSet_Begin), |
| 407 "X86InstructionSet range different from TargetInstructionSet"); | 426 "X86InstructionSet range different from TargetInstructionSet"); |
| 408 // TODO: Don't initialize IntegerRegisters and friends every time. | 427 // TODO: Don't initialize IntegerRegisters and friends every time. |
| 409 // Instead, initialize in some sort of static initializer for the | 428 // Instead, initialize in some sort of static initializer for the |
| 410 // class. | 429 // class. |
| 411 llvm::SmallBitVector IntegerRegisters(RegX8632::Reg_NUM); | 430 llvm::SmallBitVector IntegerRegisters(RegX8632::Reg_NUM); |
| 412 llvm::SmallBitVector IntegerRegistersI8(RegX8632::Reg_NUM); | 431 llvm::SmallBitVector IntegerRegistersI8(RegX8632::Reg_NUM); |
| 413 llvm::SmallBitVector FloatRegisters(RegX8632::Reg_NUM); | 432 llvm::SmallBitVector FloatRegisters(RegX8632::Reg_NUM); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 431 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 450 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
| 432 TypeToRegisterSet[IceType_f32] = FloatRegisters; | 451 TypeToRegisterSet[IceType_f32] = FloatRegisters; |
| 433 TypeToRegisterSet[IceType_f64] = FloatRegisters; | 452 TypeToRegisterSet[IceType_f64] = FloatRegisters; |
| 434 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 453 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
| 435 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 454 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
| 436 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 455 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
| 437 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 456 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
| 438 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 457 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
| 439 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 458 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
| 440 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 459 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
| 460 | |
| 461 // qining: initialize the assistant pause flag | |
| 462 // for constant blinding and pooling. | |
| 463 // When this is set to true, all constant blinding | |
| 464 // and pooling will be disabled. This should be set to | |
| 465 // true for doLoadOpt() and advancedPhiLowering(). | |
| 466 // Note, when a physical regs are available for the Dest | |
| 467 // of Phi lowering assignment, we should set this flag to | |
|
qining
2015/06/17 04:28:55
This will be removed soon.
| |
| 468 // false to enable blinding/pooling for that instruction. | |
| 441 } | 469 } |
| 442 | 470 |
| 443 void TargetX8632::translateO2() { | 471 void TargetX8632::translateO2() { |
| 444 TimerMarker T(TimerStack::TT_O2, Func); | 472 TimerMarker T(TimerStack::TT_O2, Func); |
| 445 | 473 |
| 446 if (!Ctx->getFlags().getPhiEdgeSplit()) { | 474 if (!Ctx->getFlags().getPhiEdgeSplit()) { |
| 447 // Lower Phi instructions. | 475 // Lower Phi instructions. |
| 448 Func->placePhiLoads(); | 476 Func->placePhiLoads(); |
| 449 if (Func->hasError()) | 477 if (Func->hasError()) |
| 450 return; | 478 return; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 475 return; | 503 return; |
| 476 | 504 |
| 477 // TODO: It should be sufficient to use the fastest liveness | 505 // TODO: It should be sufficient to use the fastest liveness |
| 478 // calculation, i.e. livenessLightweight(). However, for some | 506 // calculation, i.e. livenessLightweight(). However, for some |
| 479 // reason that slows down the rest of the translation. Investigate. | 507 // reason that slows down the rest of the translation. Investigate. |
| 480 Func->liveness(Liveness_Basic); | 508 Func->liveness(Liveness_Basic); |
| 481 if (Func->hasError()) | 509 if (Func->hasError()) |
| 482 return; | 510 return; |
| 483 Func->dump("After x86 address mode opt"); | 511 Func->dump("After x86 address mode opt"); |
| 484 | 512 |
| 485 doLoadOpt(); | 513 // qining: disable constant blinding or pooling for load optimization |
| 514 { | |
| 515 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 516 doLoadOpt(); | |
| 517 } | |
| 486 Func->genCode(); | 518 Func->genCode(); |
| 487 if (Func->hasError()) | 519 if (Func->hasError()) |
| 488 return; | 520 return; |
| 489 Func->dump("After x86 codegen"); | 521 Func->dump("After x86 codegen"); |
| 490 | 522 |
| 491 // Register allocation. This requires instruction renumbering and | 523 // Register allocation. This requires instruction renumbering and |
| 492 // full liveness analysis. | 524 // full liveness analysis. |
| 493 Func->renumberInstructions(); | 525 Func->renumberInstructions(); |
| 494 if (Func->hasError()) | 526 if (Func->hasError()) |
| 495 return; | 527 return; |
| 496 Func->liveness(Liveness_Intervals); | 528 Func->liveness(Liveness_Intervals); |
| 497 if (Func->hasError()) | 529 if (Func->hasError()) |
| 498 return; | 530 return; |
| 499 // Validate the live range computations. The expensive validation | 531 // Validate the live range computations. The expensive validation |
| 500 // call is deliberately only made when assertions are enabled. | 532 // call is deliberately only made when assertions are enabled. |
| 501 assert(Func->validateLiveness()); | 533 assert(Func->validateLiveness()); |
| 502 // The post-codegen dump is done here, after liveness analysis and | 534 // The post-codegen dump is done here, after liveness analysis and |
| 503 // associated cleanup, to make the dump cleaner and more useful. | 535 // associated cleanup, to make the dump cleaner and more useful. |
| 504 Func->dump("After initial x8632 codegen"); | 536 Func->dump("After initial x8632 codegen"); |
| 505 Func->getVMetadata()->init(VMK_All); | 537 Func->getVMetadata()->init(VMK_All); |
| 506 regAlloc(RAK_Global); | 538 regAlloc(RAK_Global); |
| 507 if (Func->hasError()) | 539 if (Func->hasError()) |
| 508 return; | 540 return; |
| 509 Func->dump("After linear scan regalloc"); | 541 Func->dump("After linear scan regalloc"); |
| 510 | 542 |
| 511 if (Ctx->getFlags().getPhiEdgeSplit()) { | 543 if (Ctx->getFlags().getPhiEdgeSplit()) { |
| 512 Func->advancedPhiLowering(); | 544 // qining: In general we need to pause constant blinding or pooling |
| 545 // during advanced phi lowering, unless the lowering assignment has a | |
| 546 // physical register for the Dest Variable | |
| 547 { | |
| 548 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 549 Func->advancedPhiLowering(); | |
| 550 } | |
| 513 Func->dump("After advanced Phi lowering"); | 551 Func->dump("After advanced Phi lowering"); |
| 514 } | 552 } |
| 515 | 553 |
| 516 // Stack frame mapping. | 554 // Stack frame mapping. |
| 517 Func->genFrame(); | 555 Func->genFrame(); |
| 518 if (Func->hasError()) | 556 if (Func->hasError()) |
| 519 return; | 557 return; |
| 520 Func->dump("After stack frame mapping"); | 558 Func->dump("After stack frame mapping"); |
| 521 | 559 |
| 522 Func->contractEmptyNodes(); | 560 Func->contractEmptyNodes(); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 755 return RegNames[RegNum]; | 793 return RegNames[RegNum]; |
| 756 } | 794 } |
| 757 } | 795 } |
| 758 | 796 |
| 759 void TargetX8632::emitVariable(const Variable *Var) const { | 797 void TargetX8632::emitVariable(const Variable *Var) const { |
| 760 Ostream &Str = Ctx->getStrEmit(); | 798 Ostream &Str = Ctx->getStrEmit(); |
| 761 if (Var->hasReg()) { | 799 if (Var->hasReg()) { |
| 762 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); | 800 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); |
| 763 return; | 801 return; |
| 764 } | 802 } |
| 765 if (Var->getWeight().isInf()) | 803 if (Var->getWeight().isInf()) { |
| 766 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 804 llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| 805 } | |
| 767 int32_t Offset = Var->getStackOffset(); | 806 int32_t Offset = Var->getStackOffset(); |
| 768 if (!hasFramePointer()) | 807 if (!hasFramePointer()) |
| 769 Offset += getStackAdjustment(); | 808 Offset += getStackAdjustment(); |
| 770 if (Offset) | 809 if (Offset) |
| 771 Str << Offset; | 810 Str << Offset; |
| 772 const Type FrameSPTy = IceType_i32; | 811 const Type FrameSPTy = IceType_i32; |
| 773 Str << "(%" << getRegName(getFrameOrStackReg(), FrameSPTy) << ")"; | 812 Str << "(%" << getRegName(getFrameOrStackReg(), FrameSPTy) << ")"; |
| 774 } | 813 } |
| 775 | 814 |
| 776 X8632::Address TargetX8632::stackVarToAsmOperand(const Variable *Var) const { | 815 X8632::Address TargetX8632::stackVarToAsmOperand(const Variable *Var) const { |
| 777 if (Var->hasReg()) | 816 if (Var->hasReg()) |
| 778 llvm_unreachable("Stack Variable has a register assigned"); | 817 llvm_unreachable("Stack Variable has a register assigned"); |
| 779 if (Var->getWeight().isInf()) | 818 if (Var->getWeight().isInf()) { |
| 780 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 819 llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| 820 } | |
| 781 int32_t Offset = Var->getStackOffset(); | 821 int32_t Offset = Var->getStackOffset(); |
| 782 if (!hasFramePointer()) | 822 if (!hasFramePointer()) |
| 783 Offset += getStackAdjustment(); | 823 Offset += getStackAdjustment(); |
| 784 return X8632::Address(RegX8632::getEncodedGPR(getFrameOrStackReg()), Offset); | 824 return X8632::Address(RegX8632::getEncodedGPR(getFrameOrStackReg()), Offset); |
| 785 } | 825 } |
| 786 | 826 |
| 787 void TargetX8632::lowerArguments() { | 827 void TargetX8632::lowerArguments() { |
| 788 VarList &Args = Func->getArgs(); | 828 VarList &Args = Func->getArgs(); |
| 789 // The first four arguments of vector type, regardless of their | 829 // The first four arguments of vector type, regardless of their |
| 790 // position relative to the other arguments in the argument list, are | 830 // position relative to the other arguments in the argument list, are |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1161 Operand *TargetX8632::loOperand(Operand *Operand) { | 1201 Operand *TargetX8632::loOperand(Operand *Operand) { |
| 1162 assert(Operand->getType() == IceType_i64 || | 1202 assert(Operand->getType() == IceType_i64 || |
| 1163 Operand->getType() == IceType_f64); | 1203 Operand->getType() == IceType_f64); |
| 1164 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) | 1204 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) |
| 1165 return Operand; | 1205 return Operand; |
| 1166 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 1206 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 1167 split64(Var); | 1207 split64(Var); |
| 1168 return Var->getLo(); | 1208 return Var->getLo(); |
| 1169 } | 1209 } |
| 1170 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1210 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 1171 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | 1211 ConstantInteger32 *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
| 1212 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); | |
| 1213 // check if we need to blind/pool the constant | |
| 1214 return randomizeOrPoolImmediate(ConstInt); | |
| 1172 } | 1215 } |
| 1173 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 1216 if (OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(Operand)) { |
| 1174 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), | 1217 OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
| 1175 Mem->getOffset(), Mem->getIndex(), | 1218 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
| 1176 Mem->getShift(), Mem->getSegmentRegister()); | 1219 Mem->getShift(), Mem->getSegmentRegister()); |
| 1220 // Test if we should randomize or pool the offset, if so randomize it or | |
| 1221 // pool it then create mem operand with the blinded/pooled constant. | |
| 1222 // Otherwise, return the mem operand as ordinary mem operand. | |
| 1223 return randomizeOrPoolImmediate(MemOperand); | |
| 1177 } | 1224 } |
| 1178 llvm_unreachable("Unsupported operand type"); | 1225 llvm_unreachable("Unsupported operand type"); |
| 1179 return nullptr; | 1226 return nullptr; |
| 1180 } | 1227 } |
| 1181 | 1228 |
| 1182 Operand *TargetX8632::hiOperand(Operand *Operand) { | 1229 Operand *TargetX8632::hiOperand(Operand *Operand) { |
| 1183 assert(Operand->getType() == IceType_i64 || | 1230 assert(Operand->getType() == IceType_i64 || |
| 1184 Operand->getType() == IceType_f64); | 1231 Operand->getType() == IceType_f64); |
| 1185 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) | 1232 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) |
| 1186 return Operand; | 1233 return Operand; |
| 1187 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 1234 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 1188 split64(Var); | 1235 split64(Var); |
| 1189 return Var->getHi(); | 1236 return Var->getHi(); |
| 1190 } | 1237 } |
| 1191 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1238 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 1192 return Ctx->getConstantInt32( | 1239 ConstantInteger32 *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
| 1193 static_cast<uint32_t>(Const->getValue() >> 32)); | 1240 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue() >> 32))); |
| 1241 // check if we need to blind/pool the constant | |
| 1242 return randomizeOrPoolImmediate(ConstInt); | |
| 1194 } | 1243 } |
| 1195 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 1244 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
| 1196 Constant *Offset = Mem->getOffset(); | 1245 Constant *Offset = Mem->getOffset(); |
| 1197 if (Offset == nullptr) { | 1246 if (Offset == nullptr) { |
| 1198 Offset = Ctx->getConstantInt32(4); | 1247 Offset = Ctx->getConstantInt32(4); |
| 1199 } else if (ConstantInteger32 *IntOffset = | 1248 } else if (ConstantInteger32 *IntOffset = |
| 1200 llvm::dyn_cast<ConstantInteger32>(Offset)) { | 1249 llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| 1201 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); | 1250 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); |
| 1202 } else if (ConstantRelocatable *SymOffset = | 1251 } else if (ConstantRelocatable *SymOffset = |
| 1203 llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 1252 llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
| 1204 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); | 1253 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); |
| 1205 Offset = | 1254 Offset = |
| 1206 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), | 1255 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), |
| 1207 SymOffset->getSuppressMangling()); | 1256 SymOffset->getSuppressMangling()); |
| 1208 } | 1257 } |
| 1209 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset, | 1258 OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
| 1210 Mem->getIndex(), Mem->getShift(), | 1259 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
| 1211 Mem->getSegmentRegister()); | 1260 Mem->getShift(), Mem->getSegmentRegister()); |
| 1261 // Test if the Offset is an eligible i32 constants for randomization and | |
| 1262 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem | |
| 1263 // operand. | |
| 1264 return randomizeOrPoolImmediate(MemOperand); | |
| 1212 } | 1265 } |
| 1213 llvm_unreachable("Unsupported operand type"); | 1266 llvm_unreachable("Unsupported operand type"); |
| 1214 return nullptr; | 1267 return nullptr; |
| 1215 } | 1268 } |
| 1216 | 1269 |
| 1217 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, | 1270 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, |
| 1218 RegSetMask Exclude) const { | 1271 RegSetMask Exclude) const { |
| 1219 llvm::SmallBitVector Registers(RegX8632::Reg_NUM); | 1272 llvm::SmallBitVector Registers(RegX8632::Reg_NUM); |
| 1220 | 1273 |
| 1221 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | 1274 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1280 // multiple of the required alignment at runtime. | 1333 // multiple of the required alignment at runtime. |
| 1281 Variable *T = makeReg(IceType_i32); | 1334 Variable *T = makeReg(IceType_i32); |
| 1282 _mov(T, TotalSize); | 1335 _mov(T, TotalSize); |
| 1283 _add(T, Ctx->getConstantInt32(Alignment - 1)); | 1336 _add(T, Ctx->getConstantInt32(Alignment - 1)); |
| 1284 _and(T, Ctx->getConstantInt32(-Alignment)); | 1337 _and(T, Ctx->getConstantInt32(-Alignment)); |
| 1285 _sub(esp, T); | 1338 _sub(esp, T); |
| 1286 } | 1339 } |
| 1287 _mov(Dest, esp); | 1340 _mov(Dest, esp); |
| 1288 } | 1341 } |
| 1289 | 1342 |
| 1343 // Strength-reduce scalar integer multiplication by a constant (for | |
| 1344 // i32 or narrower) for certain constants. The lea instruction can be | |
| 1345 // used to multiply by 3, 5, or 9, and the lsh instruction can be used | |
| 1346 // to multiply by powers of 2. These can be combined such that | |
| 1347 // e.g. multiplying by 100 can be done as 2 lea-based multiplies by 5, | |
| 1348 // combined with left-shifting by 2. | |
| 1349 bool TargetX8632::optimizeScalarMul(Variable *Dest, Operand *Src0, | |
| 1350 int32_t Src1) { | |
| 1351 // Disable this optimization for Om1 and O0, just to keep things | |
| 1352 // simple there. | |
| 1353 if (Ctx->getFlags().getOptLevel() < Opt_1) | |
| 1354 return false; | |
| 1355 Type Ty = Dest->getType(); | |
| 1356 Variable *T = nullptr; | |
| 1357 if (Src1 == -1) { | |
| 1358 _mov(T, Src0); | |
| 1359 _neg(T); | |
| 1360 _mov(Dest, T); | |
| 1361 return true; | |
| 1362 } | |
| 1363 if (Src1 == 0) { | |
| 1364 _mov(Dest, Ctx->getConstantZero(Ty)); | |
| 1365 return true; | |
| 1366 } | |
| 1367 if (Src1 == 1) { | |
| 1368 _mov(T, Src0); | |
| 1369 _mov(Dest, T); | |
| 1370 return true; | |
| 1371 } | |
| 1372 // Don't bother with the edge case where Src1 == MININT. | |
| 1373 if (Src1 == -Src1) | |
| 1374 return false; | |
| 1375 const bool Src1IsNegative = Src1 < 0; | |
| 1376 if (Src1IsNegative) | |
| 1377 Src1 = -Src1; | |
| 1378 uint32_t Count9 = 0; | |
| 1379 uint32_t Count5 = 0; | |
| 1380 uint32_t Count3 = 0; | |
| 1381 uint32_t Count2 = 0; | |
| 1382 uint32_t CountOps = 0; | |
| 1383 while (Src1 > 1) { | |
| 1384 if (Src1 % 9 == 0) { | |
| 1385 ++CountOps; | |
| 1386 ++Count9; | |
| 1387 Src1 /= 9; | |
| 1388 } else if (Src1 % 5 == 0) { | |
| 1389 ++CountOps; | |
| 1390 ++Count5; | |
| 1391 Src1 /= 5; | |
| 1392 } else if (Src1 % 3 == 0) { | |
| 1393 ++CountOps; | |
| 1394 ++Count3; | |
| 1395 Src1 /= 3; | |
| 1396 } else if (Src1 % 2 == 0) { | |
| 1397 if (Count2 == 0) | |
| 1398 ++CountOps; | |
| 1399 ++Count2; | |
| 1400 Src1 /= 2; | |
| 1401 } else { | |
| 1402 return false; | |
| 1403 } | |
| 1404 } | |
| 1405 // Lea optimization only works for i16 and i32 types, not i8. | |
| 1406 if (Ty != IceType_i16 && Ty != IceType_i32 && (Count3 || Count5 || Count9)) | |
| 1407 return false; | |
| 1408 // Limit the number of lea/shl operations for a single multiply, to | |
| 1409 // a somewhat arbitrary choice of 3. | |
| 1410 const uint32_t MaxOpsForOptimizedMul = 3; | |
| 1411 if (CountOps > MaxOpsForOptimizedMul) | |
| 1412 return false; | |
| 1413 _mov(T, Src0); | |
| 1414 Constant *Zero = Ctx->getConstantZero(IceType_i32); | |
| 1415 for (uint32_t i = 0; i < Count9; ++i) { | |
| 1416 const uint16_t Shift = 3; // log2(9-1) | |
| 1417 _lea(T, OperandX8632Mem::create(Func, IceType_void, T, Zero, T, Shift)); | |
| 1418 _set_dest_nonkillable(); | |
| 1419 } | |
| 1420 for (uint32_t i = 0; i < Count5; ++i) { | |
| 1421 const uint16_t Shift = 2; // log2(5-1) | |
| 1422 _lea(T, OperandX8632Mem::create(Func, IceType_void, T, Zero, T, Shift)); | |
| 1423 _set_dest_nonkillable(); | |
| 1424 } | |
| 1425 for (uint32_t i = 0; i < Count3; ++i) { | |
| 1426 const uint16_t Shift = 1; // log2(3-1) | |
| 1427 _lea(T, OperandX8632Mem::create(Func, IceType_void, T, Zero, T, Shift)); | |
| 1428 _set_dest_nonkillable(); | |
| 1429 } | |
| 1430 if (Count2) { | |
| 1431 _shl(T, Ctx->getConstantInt(Ty, Count2)); | |
| 1432 } | |
| 1433 if (Src1IsNegative) | |
| 1434 _neg(T); | |
| 1435 _mov(Dest, T); | |
| 1436 return true; | |
| 1437 } | |
|
qining
2015/06/17 04:28:55
I believe this new block comes from rebasing.
| |
| 1438 | |
| 1290 void TargetX8632::lowerArithmetic(const InstArithmetic *Inst) { | 1439 void TargetX8632::lowerArithmetic(const InstArithmetic *Inst) { |
| 1291 Variable *Dest = Inst->getDest(); | 1440 Variable *Dest = Inst->getDest(); |
| 1292 Operand *Src0 = legalize(Inst->getSrc(0)); | 1441 Operand *Src0 = legalize(Inst->getSrc(0)); |
| 1293 Operand *Src1 = legalize(Inst->getSrc(1)); | 1442 Operand *Src1 = legalize(Inst->getSrc(1)); |
| 1294 if (Inst->isCommutative()) { | 1443 if (Inst->isCommutative()) { |
| 1295 if (!llvm::isa<Variable>(Src0) && llvm::isa<Variable>(Src1)) | 1444 if (!llvm::isa<Variable>(Src0) && llvm::isa<Variable>(Src1)) |
| 1296 std::swap(Src0, Src1); | 1445 std::swap(Src0, Src1); |
| 1446 if (llvm::isa<Constant>(Src0) && !llvm::isa<Constant>(Src1)) | |
| 1447 std::swap(Src0, Src1); | |
| 1297 } | 1448 } |
| 1298 if (Dest->getType() == IceType_i64) { | 1449 if (Dest->getType() == IceType_i64) { |
| 1450 switch (Inst->getOp()) { | |
| 1451 case InstArithmetic::Udiv: { | |
| 1452 const SizeT MaxSrcs = 2; | |
| 1453 InstCall *Call = makeHelperCall(H_udiv_i64, Dest, MaxSrcs); | |
| 1454 Call->addArg(Inst->getSrc(0)); | |
| 1455 Call->addArg(Inst->getSrc(1)); | |
| 1456 lowerCall(Call); | |
| 1457 return; | |
| 1458 } | |
| 1459 case InstArithmetic::Sdiv: { | |
| 1460 const SizeT MaxSrcs = 2; | |
| 1461 InstCall *Call = makeHelperCall(H_sdiv_i64, Dest, MaxSrcs); | |
| 1462 Call->addArg(Inst->getSrc(0)); | |
| 1463 Call->addArg(Inst->getSrc(1)); | |
| 1464 lowerCall(Call); | |
| 1465 return; | |
| 1466 } | |
| 1467 case InstArithmetic::Urem: { | |
| 1468 const SizeT MaxSrcs = 2; | |
| 1469 InstCall *Call = makeHelperCall(H_urem_i64, Dest, MaxSrcs); | |
| 1470 Call->addArg(Inst->getSrc(0)); | |
| 1471 Call->addArg(Inst->getSrc(1)); | |
| 1472 lowerCall(Call); | |
| 1473 return; | |
| 1474 } | |
| 1475 case InstArithmetic::Srem: { | |
| 1476 const SizeT MaxSrcs = 2; | |
| 1477 InstCall *Call = makeHelperCall(H_srem_i64, Dest, MaxSrcs); | |
| 1478 Call->addArg(Inst->getSrc(0)); | |
| 1479 Call->addArg(Inst->getSrc(1)); | |
| 1480 lowerCall(Call); | |
| 1481 return; | |
| 1482 } | |
| 1483 default: | |
| 1484 break; | |
| 1485 } | |
| 1486 | |
|
qining
2015/06/17 04:28:55
For the operations using helper calls, we should n
| |
| 1299 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1487 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1300 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1488 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1301 Operand *Src0Lo = loOperand(Src0); | 1489 Operand *Src0Lo = loOperand(Src0); |
| 1302 Operand *Src0Hi = hiOperand(Src0); | 1490 Operand *Src0Hi = hiOperand(Src0); |
| 1303 Operand *Src1Lo = loOperand(Src1); | 1491 Operand *Src1Lo = loOperand(Src1); |
| 1304 Operand *Src1Hi = hiOperand(Src1); | 1492 Operand *Src1Hi = hiOperand(Src1); |
| 1305 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 1493 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 1306 switch (Inst->getOp()) { | 1494 switch (Inst->getOp()) { |
| 1307 case InstArithmetic::_num: | 1495 case InstArithmetic::_num: |
| 1308 llvm_unreachable("Unknown arithmetic operator"); | 1496 llvm_unreachable("Unknown arithmetic operator"); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1478 // T_2 and T_3 are being assigned again because of the | 1666 // T_2 and T_3 are being assigned again because of the |
| 1479 // intra-block control flow, so T_2 needs the _mov_nonkillable | 1667 // intra-block control flow, so T_2 needs the _mov_nonkillable |
| 1480 // variant to avoid liveness problems. T_3 doesn't need special | 1668 // variant to avoid liveness problems. T_3 doesn't need special |
| 1481 // treatment because it is reassigned via _sar instead of _mov. | 1669 // treatment because it is reassigned via _sar instead of _mov. |
| 1482 _mov_nonkillable(T_2, T_3); | 1670 _mov_nonkillable(T_2, T_3); |
| 1483 _sar(T_3, SignExtend); | 1671 _sar(T_3, SignExtend); |
| 1484 Context.insert(Label); | 1672 Context.insert(Label); |
| 1485 _mov(DestLo, T_2); | 1673 _mov(DestLo, T_2); |
| 1486 _mov(DestHi, T_3); | 1674 _mov(DestHi, T_3); |
| 1487 } break; | 1675 } break; |
| 1488 case InstArithmetic::Udiv: { | |
| 1489 const SizeT MaxSrcs = 2; | |
| 1490 InstCall *Call = makeHelperCall(H_udiv_i64, Dest, MaxSrcs); | |
| 1491 Call->addArg(Inst->getSrc(0)); | |
| 1492 Call->addArg(Inst->getSrc(1)); | |
| 1493 lowerCall(Call); | |
| 1494 } break; | |
| 1495 case InstArithmetic::Sdiv: { | |
| 1496 const SizeT MaxSrcs = 2; | |
| 1497 InstCall *Call = makeHelperCall(H_sdiv_i64, Dest, MaxSrcs); | |
| 1498 Call->addArg(Inst->getSrc(0)); | |
| 1499 Call->addArg(Inst->getSrc(1)); | |
| 1500 lowerCall(Call); | |
| 1501 } break; | |
| 1502 case InstArithmetic::Urem: { | |
| 1503 const SizeT MaxSrcs = 2; | |
| 1504 InstCall *Call = makeHelperCall(H_urem_i64, Dest, MaxSrcs); | |
| 1505 Call->addArg(Inst->getSrc(0)); | |
| 1506 Call->addArg(Inst->getSrc(1)); | |
| 1507 lowerCall(Call); | |
| 1508 } break; | |
| 1509 case InstArithmetic::Srem: { | |
| 1510 const SizeT MaxSrcs = 2; | |
| 1511 InstCall *Call = makeHelperCall(H_srem_i64, Dest, MaxSrcs); | |
| 1512 Call->addArg(Inst->getSrc(0)); | |
| 1513 Call->addArg(Inst->getSrc(1)); | |
| 1514 lowerCall(Call); | |
| 1515 } break; | |
| 1516 case InstArithmetic::Fadd: | 1676 case InstArithmetic::Fadd: |
| 1517 case InstArithmetic::Fsub: | 1677 case InstArithmetic::Fsub: |
| 1518 case InstArithmetic::Fmul: | 1678 case InstArithmetic::Fmul: |
| 1519 case InstArithmetic::Fdiv: | 1679 case InstArithmetic::Fdiv: |
| 1520 case InstArithmetic::Frem: | 1680 case InstArithmetic::Frem: |
| 1521 llvm_unreachable("FP instruction with i64 type"); | 1681 llvm_unreachable("FP instruction with i64 type"); |
| 1522 break; | 1682 break; |
| 1683 default: | |
| 1684 llvm_unreachable("Unknown instruction with i64 type"); | |
| 1685 break; | |
| 1523 } | 1686 } |
| 1524 } else if (isVectorType(Dest->getType())) { | 1687 return; |
| 1688 } | |
| 1689 if (isVectorType(Dest->getType())) { | |
| 1525 // TODO: Trap on integer divide and integer modulo by zero. | 1690 // TODO: Trap on integer divide and integer modulo by zero. |
| 1526 // See: https://code.google.com/p/nativeclient/issues/detail?id=3899 | 1691 // See: https://code.google.com/p/nativeclient/issues/detail?id=3899 |
| 1527 if (llvm::isa<OperandX8632Mem>(Src1)) | 1692 if (llvm::isa<OperandX8632Mem>(Src1)) |
| 1528 Src1 = legalizeToVar(Src1); | 1693 Src1 = legalizeToVar(Src1); |
| 1529 switch (Inst->getOp()) { | 1694 switch (Inst->getOp()) { |
| 1530 case InstArithmetic::_num: | 1695 case InstArithmetic::_num: |
| 1531 llvm_unreachable("Unknown arithmetic operator"); | 1696 llvm_unreachable("Unknown arithmetic operator"); |
| 1532 break; | 1697 break; |
| 1533 case InstArithmetic::Add: { | 1698 case InstArithmetic::Add: { |
| 1534 Variable *T = makeReg(Dest->getType()); | 1699 Variable *T = makeReg(Dest->getType()); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1643 case InstArithmetic::Fdiv: { | 1808 case InstArithmetic::Fdiv: { |
| 1644 Variable *T = makeReg(Dest->getType()); | 1809 Variable *T = makeReg(Dest->getType()); |
| 1645 _movp(T, Src0); | 1810 _movp(T, Src0); |
| 1646 _divps(T, Src1); | 1811 _divps(T, Src1); |
| 1647 _movp(Dest, T); | 1812 _movp(Dest, T); |
| 1648 } break; | 1813 } break; |
| 1649 case InstArithmetic::Frem: | 1814 case InstArithmetic::Frem: |
| 1650 scalarizeArithmetic(Inst->getOp(), Dest, Src0, Src1); | 1815 scalarizeArithmetic(Inst->getOp(), Dest, Src0, Src1); |
| 1651 break; | 1816 break; |
| 1652 } | 1817 } |
| 1653 } else { // Dest->getType() is non-i64 scalar | 1818 return; |
| 1654 Variable *T_edx = nullptr; | 1819 } |
| 1655 Variable *T = nullptr; | 1820 Variable *T_edx = nullptr; |
| 1656 switch (Inst->getOp()) { | 1821 Variable *T = nullptr; |
| 1657 case InstArithmetic::_num: | 1822 switch (Inst->getOp()) { |
| 1658 llvm_unreachable("Unknown arithmetic operator"); | 1823 case InstArithmetic::_num: |
| 1659 break; | 1824 llvm_unreachable("Unknown arithmetic operator"); |
| 1660 case InstArithmetic::Add: | 1825 break; |
| 1826 case InstArithmetic::Add: | |
| 1827 _mov(T, Src0); | |
| 1828 _add(T, Src1); | |
| 1829 _mov(Dest, T); | |
| 1830 break; | |
| 1831 case InstArithmetic::And: | |
| 1832 _mov(T, Src0); | |
| 1833 _and(T, Src1); | |
| 1834 _mov(Dest, T); | |
| 1835 break; | |
| 1836 case InstArithmetic::Or: | |
| 1837 _mov(T, Src0); | |
| 1838 _or(T, Src1); | |
| 1839 _mov(Dest, T); | |
| 1840 break; | |
| 1841 case InstArithmetic::Xor: | |
| 1842 _mov(T, Src0); | |
| 1843 _xor(T, Src1); | |
| 1844 _mov(Dest, T); | |
| 1845 break; | |
| 1846 case InstArithmetic::Sub: | |
| 1847 _mov(T, Src0); | |
| 1848 _sub(T, Src1); | |
| 1849 _mov(Dest, T); | |
| 1850 break; | |
| 1851 case InstArithmetic::Mul: | |
| 1852 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { | |
| 1853 if (optimizeScalarMul(Dest, Src0, C->getValue())) | |
| 1854 return; | |
| 1855 } | |
| 1856 // The 8-bit version of imul only allows the form "imul r/m8" | |
| 1857 // where T must be in eax. | |
| 1858 if (isByteSizedArithType(Dest->getType())) { | |
| 1859 _mov(T, Src0, RegX8632::Reg_eax); | |
| 1860 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | |
| 1861 } else { | |
| 1661 _mov(T, Src0); | 1862 _mov(T, Src0); |
| 1662 _add(T, Src1); | 1863 } |
| 1663 _mov(Dest, T); | 1864 _imul(T, Src1); |
| 1664 break; | 1865 _mov(Dest, T); |
| 1665 case InstArithmetic::And: | 1866 break; |
| 1666 _mov(T, Src0); | 1867 case InstArithmetic::Shl: |
| 1667 _and(T, Src1); | 1868 _mov(T, Src0); |
| 1668 _mov(Dest, T); | 1869 if (!llvm::isa<Constant>(Src1)) |
| 1669 break; | 1870 Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); |
| 1670 case InstArithmetic::Or: | 1871 _shl(T, Src1); |
| 1671 _mov(T, Src0); | 1872 _mov(Dest, T); |
| 1672 _or(T, Src1); | 1873 break; |
| 1673 _mov(Dest, T); | 1874 case InstArithmetic::Lshr: |
| 1674 break; | 1875 _mov(T, Src0); |
| 1675 case InstArithmetic::Xor: | 1876 if (!llvm::isa<Constant>(Src1)) |
| 1676 _mov(T, Src0); | 1877 Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); |
| 1677 _xor(T, Src1); | 1878 _shr(T, Src1); |
| 1678 _mov(Dest, T); | 1879 _mov(Dest, T); |
| 1679 break; | 1880 break; |
| 1680 case InstArithmetic::Sub: | 1881 case InstArithmetic::Ashr: |
| 1681 _mov(T, Src0); | 1882 _mov(T, Src0); |
| 1682 _sub(T, Src1); | 1883 if (!llvm::isa<Constant>(Src1)) |
| 1683 _mov(Dest, T); | 1884 Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); |
| 1684 break; | 1885 _sar(T, Src1); |
| 1685 case InstArithmetic::Mul: | 1886 _mov(Dest, T); |
| 1686 // TODO: Optimize for llvm::isa<Constant>(Src1) | 1887 break; |
| 1687 // TODO: Strength-reduce multiplications by a constant, | 1888 case InstArithmetic::Udiv: |
| 1688 // particularly -1 and powers of 2. Advanced: use lea to | 1889 // div and idiv are the few arithmetic operators that do not allow |
| 1689 // multiply by 3, 5, 9. | 1890 // immediates as the operand. |
| 1690 // | 1891 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); |
| 1691 // The 8-bit version of imul only allows the form "imul r/m8" | 1892 if (isByteSizedArithType(Dest->getType())) { |
| 1692 // where T must be in eax. | 1893 Variable *T_ah = nullptr; |
| 1693 if (isByteSizedArithType(Dest->getType())) { | 1894 Constant *Zero = Ctx->getConstantZero(IceType_i8); |
| 1694 _mov(T, Src0, RegX8632::Reg_eax); | 1895 _mov(T, Src0, RegX8632::Reg_eax); |
| 1695 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 1896 _mov(T_ah, Zero, RegX8632::Reg_ah); |
| 1696 } else { | 1897 _div(T, Src1, T_ah); |
| 1697 _mov(T, Src0); | 1898 _mov(Dest, T); |
| 1899 } else { | |
| 1900 Constant *Zero = Ctx->getConstantZero(IceType_i32); | |
| 1901 _mov(T, Src0, RegX8632::Reg_eax); | |
| 1902 _mov(T_edx, Zero, RegX8632::Reg_edx); | |
| 1903 _div(T, Src1, T_edx); | |
| 1904 _mov(Dest, T); | |
| 1905 } | |
| 1906 break; | |
| 1907 case InstArithmetic::Sdiv: | |
| 1908 // TODO(stichnot): Enable this after doing better performance | |
| 1909 // and cross testing. | |
| 1910 if (false && Ctx->getFlags().getOptLevel() >= Opt_1) { | |
| 1911 // Optimize division by constant power of 2, but not for Om1 | |
| 1912 // or O0, just to keep things simple there. | |
| 1913 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { | |
| 1914 int32_t Divisor = C->getValue(); | |
| 1915 uint32_t UDivisor = static_cast<uint32_t>(Divisor); | |
| 1916 if (Divisor > 0 && llvm::isPowerOf2_32(UDivisor)) { | |
| 1917 uint32_t LogDiv = llvm::Log2_32(UDivisor); | |
| 1918 Type Ty = Dest->getType(); | |
| 1919 // LLVM does the following for dest=src/(1<<log): | |
| 1920 // t=src | |
| 1921 // sar t,typewidth-1 // -1 if src is negative, 0 if not | |
| 1922 // shr t,typewidth-log | |
| 1923 // add t,src | |
| 1924 // sar t,log | |
| 1925 // dest=t | |
| 1926 uint32_t TypeWidth = X86_CHAR_BIT * typeWidthInBytes(Ty); | |
| 1927 _mov(T, Src0); | |
| 1928 // If for some reason we are dividing by 1, just treat it | |
| 1929 // like an assignment. | |
| 1930 if (LogDiv > 0) { | |
| 1931 // The initial sar is unnecessary when dividing by 2. | |
| 1932 if (LogDiv > 1) | |
| 1933 _sar(T, Ctx->getConstantInt(Ty, TypeWidth - 1)); | |
| 1934 _shr(T, Ctx->getConstantInt(Ty, TypeWidth - LogDiv)); | |
| 1935 _add(T, Src0); | |
| 1936 _sar(T, Ctx->getConstantInt(Ty, LogDiv)); | |
| 1937 } | |
| 1938 _mov(Dest, T); | |
| 1939 return; | |
| 1940 } | |
| 1698 } | 1941 } |
| 1699 _imul(T, Src1); | 1942 } |
| 1700 _mov(Dest, T); | 1943 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); |
| 1701 break; | 1944 if (isByteSizedArithType(Dest->getType())) { |
| 1702 case InstArithmetic::Shl: | 1945 _mov(T, Src0, RegX8632::Reg_eax); |
| 1703 _mov(T, Src0); | 1946 _cbwdq(T, T); |
| 1704 if (!llvm::isa<Constant>(Src1)) | 1947 _idiv(T, Src1, T); |
| 1705 Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); | 1948 _mov(Dest, T); |
| 1706 _shl(T, Src1); | 1949 } else { |
| 1707 _mov(Dest, T); | 1950 T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); |
| 1708 break; | 1951 _mov(T, Src0, RegX8632::Reg_eax); |
| 1709 case InstArithmetic::Lshr: | 1952 _cbwdq(T_edx, T); |
| 1710 _mov(T, Src0); | 1953 _idiv(T, Src1, T_edx); |
| 1711 if (!llvm::isa<Constant>(Src1)) | 1954 _mov(Dest, T); |
| 1712 Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); | 1955 } |
| 1713 _shr(T, Src1); | 1956 break; |
| 1714 _mov(Dest, T); | 1957 case InstArithmetic::Urem: |
| 1715 break; | 1958 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); |
| 1716 case InstArithmetic::Ashr: | 1959 if (isByteSizedArithType(Dest->getType())) { |
| 1717 _mov(T, Src0); | 1960 Variable *T_ah = nullptr; |
| 1718 if (!llvm::isa<Constant>(Src1)) | 1961 Constant *Zero = Ctx->getConstantZero(IceType_i8); |
| 1719 Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); | 1962 _mov(T, Src0, RegX8632::Reg_eax); |
| 1720 _sar(T, Src1); | 1963 _mov(T_ah, Zero, RegX8632::Reg_ah); |
| 1721 _mov(Dest, T); | 1964 _div(T_ah, Src1, T); |
| 1722 break; | 1965 _mov(Dest, T_ah); |
| 1723 case InstArithmetic::Udiv: | 1966 } else { |
| 1724 // div and idiv are the few arithmetic operators that do not allow | 1967 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 1725 // immediates as the operand. | 1968 _mov(T_edx, Zero, RegX8632::Reg_edx); |
| 1726 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 1969 _mov(T, Src0, RegX8632::Reg_eax); |
| 1727 if (isByteSizedArithType(Dest->getType())) { | 1970 _div(T_edx, Src1, T); |
| 1728 Variable *T_ah = nullptr; | 1971 _mov(Dest, T_edx); |
| 1729 Constant *Zero = Ctx->getConstantZero(IceType_i8); | 1972 } |
| 1730 _mov(T, Src0, RegX8632::Reg_eax); | 1973 break; |
| 1731 _mov(T_ah, Zero, RegX8632::Reg_ah); | 1974 case InstArithmetic::Srem: |
| 1732 _div(T, Src1, T_ah); | 1975 // TODO(stichnot): Enable this after doing better performance |
| 1733 _mov(Dest, T); | 1976 // and cross testing. |
| 1734 } else { | 1977 if (false && Ctx->getFlags().getOptLevel() >= Opt_1) { |
| 1735 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 1978 // Optimize mod by constant power of 2, but not for Om1 or O0, |
| 1736 _mov(T, Src0, RegX8632::Reg_eax); | 1979 // just to keep things simple there. |
| 1737 _mov(T_edx, Zero, RegX8632::Reg_edx); | 1980 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { |
| 1738 _div(T, Src1, T_edx); | 1981 int32_t Divisor = C->getValue(); |
| 1739 _mov(Dest, T); | 1982 uint32_t UDivisor = static_cast<uint32_t>(Divisor); |
| 1983 if (Divisor > 0 && llvm::isPowerOf2_32(UDivisor)) { | |
| 1984 uint32_t LogDiv = llvm::Log2_32(UDivisor); | |
| 1985 Type Ty = Dest->getType(); | |
| 1986 // LLVM does the following for dest=src%(1<<log): | |
| 1987 // t=src | |
| 1988 // sar t,typewidth-1 // -1 if src is negative, 0 if not | |
| 1989 // shr t,typewidth-log | |
| 1990 // add t,src | |
| 1991 // and t, -(1<<log) | |
| 1992 // sub t,src | |
| 1993 // neg t | |
| 1994 // dest=t | |
| 1995 uint32_t TypeWidth = X86_CHAR_BIT * typeWidthInBytes(Ty); | |
| 1996 // If for some reason we are dividing by 1, just assign 0. | |
| 1997 if (LogDiv == 0) { | |
| 1998 _mov(Dest, Ctx->getConstantZero(Ty)); | |
| 1999 return; | |
| 2000 } | |
| 2001 _mov(T, Src0); | |
| 2002 // The initial sar is unnecessary when dividing by 2. | |
| 2003 if (LogDiv > 1) | |
| 2004 _sar(T, Ctx->getConstantInt(Ty, TypeWidth - 1)); | |
| 2005 _shr(T, Ctx->getConstantInt(Ty, TypeWidth - LogDiv)); | |
| 2006 _add(T, Src0); | |
| 2007 _and(T, Ctx->getConstantInt(Ty, -(1 << LogDiv))); | |
| 2008 _sub(T, Src0); | |
| 2009 _neg(T); | |
| 2010 _mov(Dest, T); | |
| 2011 return; | |
| 2012 } | |
| 1740 } | 2013 } |
| 1741 break; | 2014 } |
| 1742 case InstArithmetic::Sdiv: | 2015 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); |
| 1743 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 2016 if (isByteSizedArithType(Dest->getType())) { |
| 1744 if (isByteSizedArithType(Dest->getType())) { | 2017 Variable *T_ah = makeReg(IceType_i8, RegX8632::Reg_ah); |
| 1745 _mov(T, Src0, RegX8632::Reg_eax); | 2018 _mov(T, Src0, RegX8632::Reg_eax); |
| 1746 _cbwdq(T, T); | 2019 _cbwdq(T, T); |
| 1747 _idiv(T, Src1, T); | 2020 Context.insert(InstFakeDef::create(Func, T_ah)); |
| 1748 _mov(Dest, T); | 2021 _idiv(T_ah, Src1, T); |
| 1749 } else { | 2022 _mov(Dest, T_ah); |
| 1750 T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); | 2023 } else { |
| 1751 _mov(T, Src0, RegX8632::Reg_eax); | 2024 T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); |
| 1752 _cbwdq(T_edx, T); | 2025 _mov(T, Src0, RegX8632::Reg_eax); |
| 1753 _idiv(T, Src1, T_edx); | 2026 _cbwdq(T_edx, T); |
| 1754 _mov(Dest, T); | 2027 _idiv(T_edx, Src1, T); |
| 1755 } | 2028 _mov(Dest, T_edx); |
| 1756 break; | 2029 } |
| 1757 case InstArithmetic::Urem: | 2030 break; |
| 1758 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 2031 case InstArithmetic::Fadd: |
| 1759 if (isByteSizedArithType(Dest->getType())) { | 2032 _mov(T, Src0); |
| 1760 Variable *T_ah = nullptr; | 2033 _addss(T, Src1); |
| 1761 Constant *Zero = Ctx->getConstantZero(IceType_i8); | 2034 _mov(Dest, T); |
| 1762 _mov(T, Src0, RegX8632::Reg_eax); | 2035 break; |
| 1763 _mov(T_ah, Zero, RegX8632::Reg_ah); | 2036 case InstArithmetic::Fsub: |
| 1764 _div(T_ah, Src1, T); | 2037 _mov(T, Src0); |
| 1765 _mov(Dest, T_ah); | 2038 _subss(T, Src1); |
| 1766 } else { | 2039 _mov(Dest, T); |
| 1767 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 2040 break; |
| 1768 _mov(T_edx, Zero, RegX8632::Reg_edx); | 2041 case InstArithmetic::Fmul: |
| 1769 _mov(T, Src0, RegX8632::Reg_eax); | 2042 _mov(T, Src0); |
| 1770 _div(T_edx, Src1, T); | 2043 _mulss(T, Src1); |
| 1771 _mov(Dest, T_edx); | 2044 _mov(Dest, T); |
| 1772 } | 2045 break; |
| 1773 break; | 2046 case InstArithmetic::Fdiv: |
| 1774 case InstArithmetic::Srem: | 2047 _mov(T, Src0); |
| 1775 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 2048 _divss(T, Src1); |
| 1776 if (isByteSizedArithType(Dest->getType())) { | 2049 _mov(Dest, T); |
| 1777 Variable *T_ah = makeReg(IceType_i8, RegX8632::Reg_ah); | 2050 break; |
| 1778 _mov(T, Src0, RegX8632::Reg_eax); | 2051 case InstArithmetic::Frem: { |
| 1779 _cbwdq(T, T); | 2052 const SizeT MaxSrcs = 2; |
| 1780 Context.insert(InstFakeDef::create(Func, T_ah)); | 2053 Type Ty = Dest->getType(); |
| 1781 _idiv(T_ah, Src1, T); | 2054 InstCall *Call = makeHelperCall( |
| 1782 _mov(Dest, T_ah); | 2055 isFloat32Asserting32Or64(Ty) ? H_frem_f32 : H_frem_f64, Dest, MaxSrcs); |
| 1783 } else { | 2056 Call->addArg(Src0); |
| 1784 T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); | 2057 Call->addArg(Src1); |
| 1785 _mov(T, Src0, RegX8632::Reg_eax); | 2058 return lowerCall(Call); |
| 1786 _cbwdq(T_edx, T); | 2059 } |
| 1787 _idiv(T_edx, Src1, T); | |
| 1788 _mov(Dest, T_edx); | |
| 1789 } | |
| 1790 break; | |
| 1791 case InstArithmetic::Fadd: | |
| 1792 _mov(T, Src0); | |
| 1793 _addss(T, Src1); | |
| 1794 _mov(Dest, T); | |
| 1795 break; | |
| 1796 case InstArithmetic::Fsub: | |
| 1797 _mov(T, Src0); | |
| 1798 _subss(T, Src1); | |
| 1799 _mov(Dest, T); | |
| 1800 break; | |
| 1801 case InstArithmetic::Fmul: | |
| 1802 _mov(T, Src0); | |
| 1803 _mulss(T, Src1); | |
| 1804 _mov(Dest, T); | |
| 1805 break; | |
| 1806 case InstArithmetic::Fdiv: | |
| 1807 _mov(T, Src0); | |
| 1808 _divss(T, Src1); | |
| 1809 _mov(Dest, T); | |
| 1810 break; | |
| 1811 case InstArithmetic::Frem: { | |
| 1812 const SizeT MaxSrcs = 2; | |
| 1813 Type Ty = Dest->getType(); | |
| 1814 InstCall *Call = | |
| 1815 makeHelperCall(isFloat32Asserting32Or64(Ty) ? H_frem_f32 : H_frem_f64, | |
| 1816 Dest, MaxSrcs); | |
| 1817 Call->addArg(Src0); | |
| 1818 Call->addArg(Src1); | |
| 1819 return lowerCall(Call); | |
| 1820 } break; | |
| 1821 } | |
| 1822 } | 2060 } |
| 1823 } | 2061 } |
| 1824 | 2062 |
| 1825 void TargetX8632::lowerAssign(const InstAssign *Inst) { | 2063 void TargetX8632::lowerAssign(const InstAssign *Inst) { |
| 1826 Variable *Dest = Inst->getDest(); | 2064 Variable *Dest = Inst->getDest(); |
| 1827 Operand *Src0 = Inst->getSrc(0); | 2065 Operand *Src0 = Inst->getSrc(0); |
| 1828 assert(Dest->getType() == Src0->getType()); | 2066 assert(Dest->getType() == Src0->getType()); |
| 1829 if (Dest->getType() == IceType_i64) { | 2067 if (Dest->getType() == IceType_i64) { |
| 1830 Src0 = legalize(Src0); | 2068 Src0 = legalize(Src0); |
| 1831 Operand *Src0Lo = loOperand(Src0); | 2069 Operand *Src0Lo = loOperand(Src0); |
| 1832 Operand *Src0Hi = hiOperand(Src0); | 2070 Operand *Src0Hi = hiOperand(Src0); |
| 1833 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2071 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1834 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2072 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1835 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 2073 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 1836 _mov(T_Lo, Src0Lo); | 2074 _mov(T_Lo, Src0Lo); |
| 1837 _mov(DestLo, T_Lo); | 2075 _mov(DestLo, T_Lo); |
| 1838 _mov(T_Hi, Src0Hi); | 2076 _mov(T_Hi, Src0Hi); |
| 1839 _mov(DestHi, T_Hi); | 2077 _mov(DestHi, T_Hi); |
| 1840 } else { | 2078 } else { |
| 1841 Operand *RI; | 2079 Operand *RI; |
| 1842 if (Dest->hasReg()) | 2080 if (Dest->hasReg()) { |
| 1843 // If Dest already has a physical register, then legalize the | 2081 // If Dest already has a physical register, then legalize the |
| 1844 // Src operand into a Variable with the same register | 2082 // Src operand into a Variable with the same register |
| 1845 // assignment. This is mostly a workaround for advanced phi | 2083 // assignment. This is mostly a workaround for advanced phi |
| 1846 // lowering's ad-hoc register allocation which assumes no | 2084 // lowering's ad-hoc register allocation which assumes no |
| 1847 // register allocation is needed when at least one of the | 2085 // register allocation is needed when at least one of the |
| 1848 // operands is non-memory. | 2086 // operands is non-memory. |
| 1849 RI = legalize(Src0, Legal_Reg, Dest->getRegNum()); | 2087 |
| 1850 else | 2088 // qining: if we have a physical register for the dest variable, |
| 2089 // we can enable our constant blinding or pooling again. Note | |
| 2090 // this is only for advancedPhiLowering(), the flag flip should | |
| 2091 // leave no other side effect. | |
| 2092 { | |
| 2093 BoolFlagSaver B(RandomizationPoolingPaused, false); | |
| 2094 RI = legalize(Src0, Legal_Reg, Dest->getRegNum()); | |
| 2095 } | |
| 2096 } else { | |
| 1851 // If Dest could be a stack operand, then RI must be a physical | 2097 // If Dest could be a stack operand, then RI must be a physical |
| 1852 // register or a scalar integer immediate. | 2098 // register or a scalar integer immediate. |
| 1853 RI = legalize(Src0, Legal_Reg | Legal_Imm); | 2099 RI = legalize(Src0, Legal_Reg | Legal_Imm); |
| 2100 } | |
| 1854 if (isVectorType(Dest->getType())) | 2101 if (isVectorType(Dest->getType())) |
| 1855 _movp(Dest, RI); | 2102 _movp(Dest, RI); |
| 1856 else | 2103 else |
| 1857 _mov(Dest, RI); | 2104 _mov(Dest, RI); |
| 1858 } | 2105 } |
| 1859 } | 2106 } |
| 1860 | 2107 |
| 1861 void TargetX8632::lowerBr(const InstBr *Inst) { | 2108 void TargetX8632::lowerBr(const InstBr *Inst) { |
| 1862 if (Inst->isUnconditional()) { | 2109 if (Inst->isUnconditional()) { |
| 1863 _br(Inst->getTargetUnconditional()); | 2110 _br(Inst->getTargetUnconditional()); |
| (...skipping 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3112 Context.insert( | 3359 Context.insert( |
| 3113 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | 3360 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); |
| 3114 return; | 3361 return; |
| 3115 } | 3362 } |
| 3116 case Intrinsics::AtomicRMW: | 3363 case Intrinsics::AtomicRMW: |
| 3117 if (!Intrinsics::isMemoryOrderValid( | 3364 if (!Intrinsics::isMemoryOrderValid( |
| 3118 ID, getConstantMemoryOrder(Instr->getArg(3)))) { | 3365 ID, getConstantMemoryOrder(Instr->getArg(3)))) { |
| 3119 Func->setError("Unexpected memory ordering for AtomicRMW"); | 3366 Func->setError("Unexpected memory ordering for AtomicRMW"); |
| 3120 return; | 3367 return; |
| 3121 } | 3368 } |
| 3122 lowerAtomicRMW(Instr->getDest(), | 3369 lowerAtomicRMW( |
| 3123 static_cast<uint32_t>(llvm::cast<ConstantInteger32>( | 3370 Instr->getDest(), |
| 3124 Instr->getArg(0))->getValue()), | 3371 static_cast<uint32_t>( |
| 3125 Instr->getArg(1), Instr->getArg(2)); | 3372 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()), |
| 3373 Instr->getArg(1), Instr->getArg(2)); | |
| 3126 return; | 3374 return; |
| 3127 case Intrinsics::AtomicStore: { | 3375 case Intrinsics::AtomicStore: { |
| 3128 if (!Intrinsics::isMemoryOrderValid( | 3376 if (!Intrinsics::isMemoryOrderValid( |
| 3129 ID, getConstantMemoryOrder(Instr->getArg(2)))) { | 3377 ID, getConstantMemoryOrder(Instr->getArg(2)))) { |
| 3130 Func->setError("Unexpected memory ordering for AtomicStore"); | 3378 Func->setError("Unexpected memory ordering for AtomicStore"); |
| 3131 return; | 3379 return; |
| 3132 } | 3380 } |
| 3133 // We require the memory address to be naturally aligned. | 3381 // We require the memory address to be naturally aligned. |
| 3134 // Given that is the case, then normal stores are atomic. | 3382 // Given that is the case, then normal stores are atomic. |
| 3135 // Add a fence after the store to make it visible. | 3383 // Add a fence after the store to make it visible. |
| (...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4318 } | 4566 } |
| 4319 } | 4567 } |
| 4320 | 4568 |
| 4321 void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { _ud2(); } | 4569 void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { _ud2(); } |
| 4322 | 4570 |
| 4323 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to | 4571 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to |
| 4324 // preserve integrity of liveness analysis. Undef values are also | 4572 // preserve integrity of liveness analysis. Undef values are also |
| 4325 // turned into zeroes, since loOperand() and hiOperand() don't expect | 4573 // turned into zeroes, since loOperand() and hiOperand() don't expect |
| 4326 // Undef input. | 4574 // Undef input. |
| 4327 void TargetX8632::prelowerPhis() { | 4575 void TargetX8632::prelowerPhis() { |
| 4576 // Pause constant blinding or pooling, blinding or pooling will be done later | |
| 4577 // during phi lowering assignments | |
| 4578 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 4579 | |
| 4328 CfgNode *Node = Context.getNode(); | 4580 CfgNode *Node = Context.getNode(); |
| 4329 for (Inst &I : Node->getPhis()) { | 4581 for (Inst &I : Node->getPhis()) { |
| 4330 auto Phi = llvm::dyn_cast<InstPhi>(&I); | 4582 auto Phi = llvm::dyn_cast<InstPhi>(&I); |
| 4331 if (Phi->isDeleted()) | 4583 if (Phi->isDeleted()) |
| 4332 continue; | 4584 continue; |
| 4333 Variable *Dest = Phi->getDest(); | 4585 Variable *Dest = Phi->getDest(); |
| 4334 if (Dest->getType() == IceType_i64) { | 4586 if (Dest->getType() == IceType_i64) { |
| 4335 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 4587 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 4336 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 4588 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 4337 InstPhi *PhiLo = InstPhi::create(Func, Phi->getSrcSize(), DestLo); | 4589 InstPhi *PhiLo = InstPhi::create(Func, Phi->getSrcSize(), DestLo); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4417 // assignment, add Dest to the set of available registers, and | 4669 // assignment, add Dest to the set of available registers, and |
| 4418 // remove Src from the set of available registers. Iteration is | 4670 // remove Src from the set of available registers. Iteration is |
| 4419 // done backwards to enable incremental updates of the available | 4671 // done backwards to enable incremental updates of the available |
| 4420 // register set, and the lowered instruction numbers may be out of | 4672 // register set, and the lowered instruction numbers may be out of |
| 4421 // order, but that can be worked around by renumbering the block | 4673 // order, but that can be worked around by renumbering the block |
| 4422 // afterwards if necessary. | 4674 // afterwards if necessary. |
| 4423 for (const Inst &I : reverse_range(Assignments)) { | 4675 for (const Inst &I : reverse_range(Assignments)) { |
| 4424 Context.rewind(); | 4676 Context.rewind(); |
| 4425 auto Assign = llvm::dyn_cast<InstAssign>(&I); | 4677 auto Assign = llvm::dyn_cast<InstAssign>(&I); |
| 4426 Variable *Dest = Assign->getDest(); | 4678 Variable *Dest = Assign->getDest(); |
| 4679 | |
| 4680 // qining: Here is an ugly hack for phi.ll test. | |
| 4681 // In function test_split_undef_int_vec, the advanced phi | |
| 4682 // lowering process will find an assignment of undefined | |
| 4683 // vector. This vector, as the Src here, will crash if it | |
| 4684 // go through legalize(). legalize() will create new variable | |
| 4685 // with makeVectorOfZeros(), but this new variable will be | |
| 4686 // assigned a stack slot. This will fail the assertion in | |
| 4687 // IceInstX8632.cpp:789, as XmmEmitterRegOp() complain: | |
| 4688 // Var->hasReg() fails. Note this failure is irrelevant to | |
| 4689 // randomization or pooling of constants. | |
| 4690 // So, we do not call legalize() to add pool label for the | |
| 4691 // src operands of phi assignment instructions. | |
| 4692 // Instead, we manually add pool label for constant float and | |
| 4693 // constant double values here. | |
| 4694 // Note going through legalize() does not affect the testing | |
| 4695 // results of SPEC2K and xtests. | |
| 4696 // Operand *Src = legalize(Assign->getSrc(0)); | |
| 4427 Operand *Src = Assign->getSrc(0); | 4697 Operand *Src = Assign->getSrc(0); |
| 4698 if (llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) { | |
| 4699 Variable *Base = nullptr; | |
| 4700 std::string Buffer; | |
| 4701 llvm::raw_string_ostream StrBuf(Buffer); | |
| 4702 llvm::cast<Constant>(Src)->emitPoolLabel(StrBuf); | |
| 4703 llvm::cast<Constant>(Src)->shouldBePooled = true; | |
| 4704 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | |
| 4705 Src = OperandX8632Mem::create(Func, Src->getType(), Base, Offset); | |
| 4706 } | |
| 4707 | |
| 4428 Variable *SrcVar = llvm::dyn_cast<Variable>(Src); | 4708 Variable *SrcVar = llvm::dyn_cast<Variable>(Src); |
| 4429 // Use normal assignment lowering, except lower mem=mem specially | 4709 // Use normal assignment lowering, except lower mem=mem specially |
| 4430 // so we can register-allocate at the same time. | 4710 // so we can register-allocate at the same time. |
| 4431 if (!isMemoryOperand(Dest) || !isMemoryOperand(Src)) { | 4711 if (!isMemoryOperand(Dest) || !isMemoryOperand(Src)) { |
| 4432 lowerAssign(Assign); | 4712 lowerAssign(Assign); |
| 4433 } else { | 4713 } else { |
| 4434 assert(Dest->getType() == Src->getType()); | 4714 assert(Dest->getType() == Src->getType()); |
| 4435 const llvm::SmallBitVector &RegsForType = | 4715 const llvm::SmallBitVector &RegsForType = |
| 4436 getRegisterSetForType(Dest->getType()); | 4716 getRegisterSetForType(Dest->getType()); |
| 4437 llvm::SmallBitVector AvailRegsForType = RegsForType & Available; | 4717 llvm::SmallBitVector AvailRegsForType = RegsForType & Available; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4607 Variable *Index = Mem->getIndex(); | 4887 Variable *Index = Mem->getIndex(); |
| 4608 Variable *RegBase = nullptr; | 4888 Variable *RegBase = nullptr; |
| 4609 Variable *RegIndex = nullptr; | 4889 Variable *RegIndex = nullptr; |
| 4610 if (Base) { | 4890 if (Base) { |
| 4611 RegBase = legalizeToVar(Base); | 4891 RegBase = legalizeToVar(Base); |
| 4612 } | 4892 } |
| 4613 if (Index) { | 4893 if (Index) { |
| 4614 RegIndex = legalizeToVar(Index); | 4894 RegIndex = legalizeToVar(Index); |
| 4615 } | 4895 } |
| 4616 if (Base != RegBase || Index != RegIndex) { | 4896 if (Base != RegBase || Index != RegIndex) { |
| 4617 From = | 4897 Mem = |
| 4618 OperandX8632Mem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex, | 4898 OperandX8632Mem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex, |
| 4619 Mem->getShift(), Mem->getSegmentRegister()); | 4899 Mem->getShift(), Mem->getSegmentRegister()); |
| 4620 } | 4900 } |
| 4621 | 4901 |
| 4902 // qining: For all Memory Operands, we do randomization/pooling here | |
| 4903 From = randomizeOrPoolImmediate(Mem); | |
| 4904 | |
| 4622 if (!(Allowed & Legal_Mem)) { | 4905 if (!(Allowed & Legal_Mem)) { |
| 4623 From = copyToReg(From, RegNum); | 4906 From = copyToReg(From, RegNum); |
| 4624 } | 4907 } |
| 4625 return From; | 4908 return From; |
| 4626 } | 4909 } |
| 4627 if (llvm::isa<Constant>(From)) { | 4910 if (llvm::isa<Constant>(From)) { |
| 4628 if (llvm::isa<ConstantUndef>(From)) { | 4911 if (llvm::isa<ConstantUndef>(From)) { |
| 4629 // Lower undefs to zero. Another option is to lower undefs to an | 4912 // Lower undefs to zero. Another option is to lower undefs to an |
| 4630 // uninitialized register; however, using an uninitialized register | 4913 // uninitialized register; however, using an uninitialized register |
| 4631 // results in less predictable code. | 4914 // results in less predictable code. |
| 4632 // | 4915 // |
| 4633 // If in the future the implementation is changed to lower undef | 4916 // If in the future the implementation is changed to lower undef |
| 4634 // values to uninitialized registers, a FakeDef will be needed: | 4917 // values to uninitialized registers, a FakeDef will be needed: |
| 4635 // Context.insert(InstFakeDef::create(Func, Reg)); | 4918 // Context.insert(InstFakeDef::create(Func, Reg)); |
| 4636 // This is in order to ensure that the live range of Reg is not | 4919 // This is in order to ensure that the live range of Reg is not |
| 4637 // overestimated. If the constant being lowered is a 64 bit value, | 4920 // overestimated. If the constant being lowered is a 64 bit value, |
| 4638 // then the result should be split and the lo and hi components will | 4921 // then the result should be split and the lo and hi components will |
| 4639 // need to go in uninitialized registers. | 4922 // need to go in uninitialized registers. |
| 4640 if (isVectorType(Ty)) | 4923 if (isVectorType(Ty)) |
| 4641 return makeVectorOfZeros(Ty, RegNum); | 4924 return makeVectorOfZeros(Ty, RegNum); |
| 4642 From = Ctx->getConstantZero(Ty); | 4925 From = Ctx->getConstantZero(Ty); |
| 4643 } | 4926 } |
| 4644 // There should be no constants of vector type (other than undef). | 4927 // There should be no constants of vector type (other than undef). |
| 4645 assert(!isVectorType(Ty)); | 4928 assert(!isVectorType(Ty)); |
| 4929 | |
| 4930 // If the operand is an 32 bit constant integer, we should check | |
| 4931 // whether we need to randomize it or pool it. | |
| 4932 if (ConstantInteger32 *C = llvm::dyn_cast<ConstantInteger32>(From)) { | |
| 4933 Operand *NewFrom = randomizeOrPoolImmediate(C, RegNum); | |
| 4934 if (NewFrom != From) { | |
| 4935 return NewFrom; | |
| 4936 } | |
| 4937 } | |
| 4938 | |
| 4646 // Convert a scalar floating point constant into an explicit | 4939 // Convert a scalar floating point constant into an explicit |
| 4647 // memory operand. | 4940 // memory operand. |
| 4648 if (isScalarFloatingType(Ty)) { | 4941 if (isScalarFloatingType(Ty)) { |
| 4649 Variable *Base = nullptr; | 4942 Variable *Base = nullptr; |
| 4650 std::string Buffer; | 4943 std::string Buffer; |
| 4651 llvm::raw_string_ostream StrBuf(Buffer); | 4944 llvm::raw_string_ostream StrBuf(Buffer); |
| 4652 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf); | 4945 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf); |
| 4946 llvm::cast<Constant>(From)->shouldBePooled = true; | |
| 4653 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | 4947 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
| 4654 From = OperandX8632Mem::create(Func, Ty, Base, Offset); | 4948 From = OperandX8632Mem::create(Func, Ty, Base, Offset); |
| 4655 } | 4949 } |
| 4656 bool NeedsReg = false; | 4950 bool NeedsReg = false; |
| 4657 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) | 4951 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) |
| 4658 // Immediate specifically not allowed | 4952 // Immediate specifically not allowed |
| 4659 NeedsReg = true; | 4953 NeedsReg = true; |
| 4660 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) | 4954 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) |
| 4661 // On x86, FP constants are lowered to mem operands. | 4955 // On x86, FP constants are lowered to mem operands. |
| 4662 NeedsReg = true; | 4956 NeedsReg = true; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4699 bool IsSrc1ImmOrReg = false; | 4993 bool IsSrc1ImmOrReg = false; |
| 4700 if (llvm::isa<Constant>(Src1)) { | 4994 if (llvm::isa<Constant>(Src1)) { |
| 4701 IsSrc1ImmOrReg = true; | 4995 IsSrc1ImmOrReg = true; |
| 4702 } else if (Variable *Var = llvm::dyn_cast<Variable>(Src1)) { | 4996 } else if (Variable *Var = llvm::dyn_cast<Variable>(Src1)) { |
| 4703 if (Var->hasReg()) | 4997 if (Var->hasReg()) |
| 4704 IsSrc1ImmOrReg = true; | 4998 IsSrc1ImmOrReg = true; |
| 4705 } | 4999 } |
| 4706 return legalize(Src0, IsSrc1ImmOrReg ? (Legal_Reg | Legal_Mem) : Legal_Reg); | 5000 return legalize(Src0, IsSrc1ImmOrReg ? (Legal_Reg | Legal_Mem) : Legal_Reg); |
| 4707 } | 5001 } |
| 4708 | 5002 |
| 4709 OperandX8632Mem *TargetX8632::formMemoryOperand(Operand *Operand, Type Ty, | 5003 OperandX8632Mem *TargetX8632::formMemoryOperand(Operand *Opnd, Type Ty, |
| 4710 bool DoLegalize) { | 5004 bool DoLegalize) { |
| 4711 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand); | 5005 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Opnd); |
| 4712 // It may be the case that address mode optimization already creates | 5006 // It may be the case that address mode optimization already creates |
| 4713 // an OperandX8632Mem, so in that case it wouldn't need another level | 5007 // an OperandX8632Mem, so in that case it wouldn't need another level |
| 4714 // of transformation. | 5008 // of transformation. |
| 4715 if (!Mem) { | 5009 if (!Mem) { |
| 4716 Variable *Base = llvm::dyn_cast<Variable>(Operand); | 5010 Variable *Base = llvm::dyn_cast<Variable>(Opnd); |
| 4717 Constant *Offset = llvm::dyn_cast<Constant>(Operand); | 5011 Constant *Offset = llvm::dyn_cast<Constant>(Opnd); |
| 4718 assert(Base || Offset); | 5012 assert(Base || Offset); |
| 4719 if (Offset) { | 5013 if (Offset) { |
| 4720 // Make sure Offset is not undef. | 5014 // qining: during memory operand building, we do not |
| 4721 Offset = llvm::cast<Constant>(legalize(Offset)); | 5015 // blind or pool the constant offset, we will work on |
| 5016 // the whole memory operand later as one entity later, | |
| 5017 // this save one instruction. By turning blinding and | |
| 5018 // pooling off, we guarantee legalize(Offset) will return | |
| 5019 // a constant* | |
| 5020 { | |
| 5021 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 5022 | |
| 5023 Offset = llvm::cast<Constant>(legalize(Offset)); | |
| 5024 } | |
| 5025 | |
| 4722 assert(llvm::isa<ConstantInteger32>(Offset) || | 5026 assert(llvm::isa<ConstantInteger32>(Offset) || |
| 4723 llvm::isa<ConstantRelocatable>(Offset)); | 5027 llvm::isa<ConstantRelocatable>(Offset)); |
| 4724 } | 5028 } |
| 4725 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); | 5029 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); |
| 4726 } | 5030 } |
| 4727 return llvm::cast<OperandX8632Mem>(DoLegalize ? legalize(Mem) : Mem); | 5031 // qining: do legalization, which contains randomization/pooling |
| 5032 // or do randomization/pooling. | |
| 5033 return llvm::cast<OperandX8632Mem>( | |
| 5034 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); | |
| 4728 } | 5035 } |
| 4729 | 5036 |
| 4730 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { | 5037 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { |
| 4731 // There aren't any 64-bit integer registers for x86-32. | 5038 // There aren't any 64-bit integer registers for x86-32. |
| 4732 assert(Type != IceType_i64); | 5039 assert(Type != IceType_i64); |
| 4733 Variable *Reg = Func->makeVariable(Type); | 5040 Variable *Reg = Func->makeVariable(Type); |
| 4734 if (RegNum == Variable::NoRegister) | 5041 if (RegNum == Variable::NoRegister) |
| 4735 Reg->setWeightInfinite(); | 5042 Reg->setWeightInfinite(); |
| 4736 else | 5043 else |
| 4737 Reg->setRegNum(RegNum); | 5044 Reg->setRegNum(RegNum); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4958 typedef ConstantDouble IceType; | 5265 typedef ConstantDouble IceType; |
| 4959 static const Type Ty = IceType_f64; | 5266 static const Type Ty = IceType_f64; |
| 4960 static const char *TypeName; | 5267 static const char *TypeName; |
| 4961 static const char *AsmTag; | 5268 static const char *AsmTag; |
| 4962 static const char *PrintfString; | 5269 static const char *PrintfString; |
| 4963 }; | 5270 }; |
| 4964 const char *PoolTypeConverter<double>::TypeName = "double"; | 5271 const char *PoolTypeConverter<double>::TypeName = "double"; |
| 4965 const char *PoolTypeConverter<double>::AsmTag = ".quad"; | 5272 const char *PoolTypeConverter<double>::AsmTag = ".quad"; |
| 4966 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; | 5273 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; |
| 4967 | 5274 |
| 5275 // Add converter for int type constant pooling | |
| 5276 template <> struct PoolTypeConverter<int> { | |
| 5277 typedef uint32_t PrimitiveIntType; | |
| 5278 typedef ConstantInteger32 IceType; | |
| 5279 static const Type Ty = IceType_i32; | |
| 5280 static const char *TypeName; | |
| 5281 static const char *AsmTag; | |
| 5282 static const char *PrintfString; | |
| 5283 }; | |
| 5284 const char *PoolTypeConverter<int>::TypeName = "i32"; | |
| 5285 const char *PoolTypeConverter<int>::AsmTag = ".long"; | |
| 5286 const char *PoolTypeConverter<int>::PrintfString = "0x%x"; | |
| 5287 | |
| 5288 // Add converter for int type constant pooling | |
| 5289 template <> struct PoolTypeConverter<short> { | |
| 5290 typedef uint32_t PrimitiveIntType; | |
| 5291 typedef ConstantInteger32 IceType; | |
| 5292 static const Type Ty = IceType_i16; | |
| 5293 static const char *TypeName; | |
| 5294 static const char *AsmTag; | |
| 5295 static const char *PrintfString; | |
| 5296 }; | |
| 5297 const char *PoolTypeConverter<short>::TypeName = "i16"; | |
| 5298 const char *PoolTypeConverter<short>::AsmTag = ".short"; | |
| 5299 const char *PoolTypeConverter<short>::PrintfString = "0x%x"; | |
| 5300 | |
| 5301 // Add converter for int type constant pooling | |
| 5302 template <> struct PoolTypeConverter<char> { | |
| 5303 typedef uint32_t PrimitiveIntType; | |
| 5304 typedef ConstantInteger32 IceType; | |
| 5305 static const Type Ty = IceType_i8; | |
| 5306 static const char *TypeName; | |
| 5307 static const char *AsmTag; | |
| 5308 static const char *PrintfString; | |
| 5309 }; | |
| 5310 const char *PoolTypeConverter<char>::TypeName = "i8"; | |
| 5311 const char *PoolTypeConverter<char>::AsmTag = ".byte"; | |
| 5312 const char *PoolTypeConverter<char>::PrintfString = "0x%x"; | |
| 5313 | |
| 4968 template <typename T> | 5314 template <typename T> |
| 4969 void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { | 5315 void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { |
| 4970 if (!ALLOW_DUMP) | 5316 if (!ALLOW_DUMP) |
| 4971 return; | 5317 return; |
| 4972 Ostream &Str = Ctx->getStrEmit(); | 5318 Ostream &Str = Ctx->getStrEmit(); |
| 4973 Type Ty = T::Ty; | 5319 Type Ty = T::Ty; |
| 4974 SizeT Align = typeAlignInBytes(Ty); | 5320 SizeT Align = typeAlignInBytes(Ty); |
| 4975 ConstantList Pool = Ctx->getConstantPool(Ty); | 5321 ConstantList Pool = Ctx->getConstantPool(Ty); |
| 4976 | 5322 |
| 4977 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align | 5323 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align |
| 4978 << "\n"; | 5324 << "\n"; |
| 4979 Str << "\t.align\t" << Align << "\n"; | 5325 Str << "\t.align\t" << Align << "\n"; |
| 4980 for (Constant *C : Pool) { | 5326 for (Constant *C : Pool) { |
| 5327 if (!C->shouldBePooled) | |
| 5328 continue; | |
| 4981 typename T::IceType *Const = llvm::cast<typename T::IceType>(C); | 5329 typename T::IceType *Const = llvm::cast<typename T::IceType>(C); |
| 4982 typename T::IceType::PrimType Value = Const->getValue(); | 5330 typename T::IceType::PrimType Value = Const->getValue(); |
| 4983 // Use memcpy() to copy bits from Value into RawValue in a way | 5331 // Use memcpy() to copy bits from Value into RawValue in a way |
| 4984 // that avoids breaking strict-aliasing rules. | 5332 // that avoids breaking strict-aliasing rules. |
| 4985 typename T::PrimitiveIntType RawValue; | 5333 typename T::PrimitiveIntType RawValue; |
| 4986 memcpy(&RawValue, &Value, sizeof(Value)); | 5334 memcpy(&RawValue, &Value, sizeof(Value)); |
| 4987 char buf[30]; | 5335 char buf[30]; |
| 4988 int CharsPrinted = | 5336 int CharsPrinted = |
| 4989 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); | 5337 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); |
| 4990 assert(CharsPrinted >= 0 && | 5338 assert(CharsPrinted >= 0 && |
| 4991 (size_t)CharsPrinted < llvm::array_lengthof(buf)); | 5339 (size_t)CharsPrinted < llvm::array_lengthof(buf)); |
| 4992 (void)CharsPrinted; // avoid warnings if asserts are disabled | 5340 (void)CharsPrinted; // avoid warnings if asserts are disabled |
| 4993 Const->emitPoolLabel(Str); | 5341 Const->emitPoolLabel(Str); |
| 4994 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " | 5342 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " |
| 4995 << Value << "\n"; | 5343 << Value << "\n"; |
| 4996 } | 5344 } |
| 4997 } | 5345 } |
| 4998 | 5346 |
| 4999 void TargetDataX8632::lowerConstants() const { | 5347 void TargetDataX8632::lowerConstants() const { |
| 5000 if (Ctx->getFlags().getDisableTranslation()) | 5348 if (Ctx->getFlags().getDisableTranslation()) |
| 5001 return; | 5349 return; |
| 5002 // No need to emit constants from the int pool since (for x86) they | 5350 // No need to emit constants from the int pool since (for x86) they |
| 5003 // are embedded as immediates in the instructions, just emit float/double. | 5351 // are embedded as immediates in the instructions, just emit float/double. |
| 5004 switch (Ctx->getFlags().getOutFileType()) { | 5352 switch (Ctx->getFlags().getOutFileType()) { |
| 5005 case FT_Elf: { | 5353 case FT_Elf: { |
| 5006 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 5354 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 5355 | |
| 5356 // If immediates pooling turned on, pool the integer constants | |
| 5357 // if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { | |
| 5358 // Writer->writeConstantPool<ConstantInteger32>(IceType_i8); | |
| 5359 // Writer->writeConstantPool<ConstantInteger32>(IceType_i16); | |
| 5360 // Writer->writeConstantPool<ConstantInteger32>(IceType_i32); | |
| 5361 //} | |
| 5362 | |
| 5363 Writer->writeConstantPool<ConstantInteger32>(IceType_i8); | |
| 5364 Writer->writeConstantPool<ConstantInteger32>(IceType_i16); | |
| 5365 Writer->writeConstantPool<ConstantInteger32>(IceType_i32); | |
| 5366 | |
|
qining
2015/06/17 04:28:55
I will remove the commented if statement. That is
| |
| 5007 Writer->writeConstantPool<ConstantFloat>(IceType_f32); | 5367 Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
| 5008 Writer->writeConstantPool<ConstantDouble>(IceType_f64); | 5368 Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
| 5009 } break; | 5369 } break; |
| 5010 case FT_Asm: | 5370 case FT_Asm: |
| 5011 case FT_Iasm: { | 5371 case FT_Iasm: { |
| 5012 OstreamLocker L(Ctx); | 5372 OstreamLocker L(Ctx); |
| 5373 | |
| 5374 // If immediates pooling turned on, pool the integer constants | |
| 5375 // if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { | |
| 5376 // emitConstantPool<PoolTypeConverter<char>>(Ctx); | |
| 5377 // emitConstantPool<PoolTypeConverter<short>>(Ctx); | |
| 5378 // emitConstantPool<PoolTypeConverter<int>>(Ctx); | |
| 5379 //} | |
| 5380 | |
| 5381 emitConstantPool<PoolTypeConverter<char>>(Ctx); | |
| 5382 emitConstantPool<PoolTypeConverter<short>>(Ctx); | |
| 5383 emitConstantPool<PoolTypeConverter<int>>(Ctx); | |
| 5384 | |
| 5013 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 5385 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 5014 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 5386 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 5015 } break; | 5387 } break; |
| 5016 } | 5388 } |
| 5017 } | 5389 } |
| 5018 | 5390 |
| 5019 TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) | 5391 TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) |
| 5020 : TargetHeaderLowering(Ctx) {} | 5392 : TargetHeaderLowering(Ctx) {} |
| 5021 | 5393 |
| 5394 // Blind/pool an Immediate | |
| 5395 Operand *TargetX8632::randomizeOrPoolImmediate(Constant *Immediate, | |
| 5396 int32_t RegNum) { | |
| 5397 assert(llvm::isa<ConstantInteger32>(Immediate) || | |
| 5398 llvm::isa<ConstantRelocatable>(Immediate)); | |
| 5399 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | |
| 5400 RandomizationPoolingPaused == true) { | |
| 5401 // immediates randomization/pool turned off | |
| 5402 return Immediate; | |
| 5403 } | |
| 5404 if (Constant *C = llvm::dyn_cast_or_null<Constant>(Immediate)) { | |
| 5405 if (C->shouldBeRandomizedOrPooled(Ctx)) { | |
| 5406 Ctx->statsUpdateRPImms(); | |
| 5407 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == | |
| 5408 RPI_Randomize) { | |
| 5409 // blind the constant | |
| 5410 // FROM: | |
| 5411 // imm | |
| 5412 // TO: | |
| 5413 // insert: mov imm+cookie, Reg | |
| 5414 // insert: lea -cookie[Reg], Reg | |
| 5415 // => Reg | |
| 5416 // If we have already assigned a phy register, we must come from | |
| 5417 // andvancedPhiLowering()=>lowerAssign(). In this case we should reuse | |
| 5418 // the assigned register as this assignment is that start of its use-def | |
| 5419 // chain. So we add RegNum argument here. | |
| 5420 Variable *Reg = makeReg(IceType_i32, RegNum); | |
| 5421 ConstantInteger32 *Integer = llvm::cast<ConstantInteger32>(Immediate); | |
| 5422 uint32_t Value = Integer->getValue(); | |
| 5423 uint32_t Cookie = Ctx->getRandomizationCookie(); | |
| 5424 _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); | |
| 5425 Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); | |
| 5426 _lea(Reg, | |
| 5427 OperandX8632Mem::create(Func, IceType_i32, Reg, Offset, NULL, 0)); | |
| 5428 // make sure liveness analysis won't kill this variable, otherwise a | |
| 5429 // liveness | |
| 5430 // assertion will be triggered. | |
| 5431 _set_dest_nonkillable(); | |
| 5432 if (Immediate->getType() != IceType_i32) { | |
| 5433 Variable *TruncReg = makeReg(Immediate->getType(), RegNum); | |
| 5434 _mov(TruncReg, Reg); | |
| 5435 return TruncReg; | |
| 5436 } | |
| 5437 return Reg; | |
| 5438 } | |
| 5439 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { | |
| 5440 // pool the constant | |
| 5441 // FROM: | |
| 5442 // imm | |
| 5443 // TO: | |
| 5444 // insert: mov $label, Reg | |
| 5445 // => Reg | |
| 5446 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == | |
| 5447 RPI_Pool); | |
| 5448 Immediate->shouldBePooled = true; | |
| 5449 // if we have already assigned a phy register, we must come from | |
| 5450 // andvancedPhiLowering()=>lowerAssign(). In this case we should reuse | |
| 5451 // the assigned register as this assignment is that start of its use-def | |
| 5452 // chain. So we add RegNum argument here. | |
| 5453 Variable *Reg = makeReg(Immediate->getType(), RegNum); | |
| 5454 IceString Label; | |
| 5455 llvm::raw_string_ostream Label_stream(Label); | |
| 5456 Immediate->emitPoolLabel(Label_stream); | |
| 5457 const RelocOffsetT Offset = 0; | |
| 5458 const bool SuppressMangling = true; | |
| 5459 Constant *Symbol = | |
| 5460 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); | |
| 5461 OperandX8632Mem *MemOperand = | |
| 5462 OperandX8632Mem::create(Func, Immediate->getType(), NULL, Symbol); | |
| 5463 _mov(Reg, MemOperand); | |
| 5464 return Reg; | |
| 5465 } | |
| 5466 assert("Unsupported -randomize-pool-immediates option" && false); | |
| 5467 } | |
| 5468 } | |
| 5469 // the constant Immediate is not eligible for blinding/pooling | |
| 5470 return Immediate; | |
| 5471 } | |
| 5472 | |
| 5473 OperandX8632Mem * | |
| 5474 TargetX8632::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, | |
| 5475 int32_t RegNum) { | |
| 5476 assert(MemOperand); | |
| 5477 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | |
| 5478 RandomizationPoolingPaused == true) { | |
| 5479 // immediates randomization/pooling is turned off | |
| 5480 return MemOperand; | |
| 5481 } | |
| 5482 | |
| 5483 if (Constant *C = llvm::dyn_cast_or_null<Constant>(MemOperand->getOffset())) { | |
| 5484 if (C->shouldBeRandomizedOrPooled(Ctx)) { | |
| 5485 // The offset of this mem operand should be blinded or pooled | |
| 5486 Ctx->statsUpdateRPImms(); | |
| 5487 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == | |
| 5488 RPI_Randomize) { | |
| 5489 // blind the constant offset | |
| 5490 // FROM: | |
| 5491 // offset[base, index, shift] | |
| 5492 // TO: | |
| 5493 // insert: lea offset+cookie[base], RegTemp | |
| 5494 // => -cookie[RegTemp, index, shift] | |
| 5495 uint32_t Value = | |
| 5496 llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset()) | |
| 5497 ->getValue(); | |
| 5498 uint64_t Cookie = Ctx->getRandomizationCookie(); | |
| 5499 Constant *Mask1 = Ctx->getConstantInt( | |
| 5500 MemOperand->getOffset()->getType(), Cookie + Value); | |
| 5501 Constant *Mask2 = | |
| 5502 Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie); | |
| 5503 // qining: We need to make sure the MemOperand->getBase() has a physical | |
| 5504 // register, if it is a variable! | |
| 5505 if (MemOperand->getBase() != NULL) | |
| 5506 MemOperand->getBase()->setWeightInfinite(); | |
| 5507 OperandX8632Mem *TempMemOperand = OperandX8632Mem::create( | |
| 5508 Func, MemOperand->getType(), MemOperand->getBase(), Mask1); | |
| 5509 // If we have already assigned a physical register, we must come from | |
| 5510 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse | |
| 5511 // the assigned register as this assignment is that start of its use-def | |
| 5512 // chain. So we add RegNum argument here. | |
| 5513 Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum); | |
| 5514 _lea(RegTemp, TempMemOperand); | |
| 5515 // As source operand doesn't use the dstreg, we don't need to add | |
| 5516 // _set_dest_nonkillable(). | |
| 5517 // qining: but if we use the same Dest Reg, that is, with RegNum | |
| 5518 // assigned, we should add this _set_dest_nonkillable() | |
| 5519 if (RegNum != Variable::NoRegister) | |
| 5520 _set_dest_nonkillable(); | |
| 5521 | |
| 5522 OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( | |
| 5523 Func, MemOperand->getType(), RegTemp, Mask2, MemOperand->getIndex(), | |
| 5524 MemOperand->getShift(), MemOperand->getSegmentRegister()); | |
| 5525 | |
| 5526 return NewMemOperand; | |
| 5527 } | |
| 5528 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { | |
| 5529 // pool the constant offset | |
| 5530 // FROM: | |
| 5531 // offset[base, index, shift] | |
| 5532 // TO: | |
| 5533 // insert: mov $label, RegTemp | |
| 5534 // insert: lea [base, RegTemp], RegTemp | |
| 5535 // =>[RegTemp, index, shift] | |
| 5536 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == | |
| 5537 RPI_Pool); | |
| 5538 // qining: Mem operand should never exist as source operands in phi | |
| 5539 // lowering | |
| 5540 // assignments, so there is no need to reuse any registers here. | |
| 5541 // However, for phi lowering, we should not ask for new physical | |
| 5542 // registers in general. | |
| 5543 // However, if we do meet MemOperand during phi lowering, we should not | |
| 5544 // blind or pool the immediates for now | |
| 5545 if (RegNum != Variable::NoRegister) | |
| 5546 return MemOperand; | |
| 5547 Variable *RegTemp = makeReg(IceType_i32); | |
| 5548 IceString Label; | |
| 5549 llvm::raw_string_ostream Label_stream(Label); | |
| 5550 MemOperand->getOffset()->emitPoolLabel(Label_stream); | |
| 5551 MemOperand->getOffset()->shouldBePooled = true; | |
| 5552 const RelocOffsetT SymOffset = 0; | |
| 5553 bool SuppressMangling = true; | |
| 5554 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), | |
| 5555 SuppressMangling); | |
| 5556 OperandX8632Mem *SymbolOperand = OperandX8632Mem::create( | |
| 5557 Func, MemOperand->getOffset()->getType(), NULL, Symbol); | |
| 5558 _mov(RegTemp, SymbolOperand); | |
| 5559 // qining: We need to make sure the MemOperand->getBase() has a physical | |
| 5560 // register! If we do not have base register here, we won't need an | |
| 5561 // extra lea instruction anymore. | |
| 5562 if (MemOperand->getBase()) { | |
| 5563 MemOperand->getBase()->setWeightInfinite(); | |
| 5564 OperandX8632Mem *CalculateOperand = OperandX8632Mem::create( | |
| 5565 Func, MemOperand->getType(), MemOperand->getBase(), NULL, RegTemp, | |
| 5566 0, MemOperand->getSegmentRegister()); | |
| 5567 _lea(RegTemp, CalculateOperand); | |
| 5568 _set_dest_nonkillable(); | |
| 5569 } | |
| 5570 OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( | |
| 5571 Func, MemOperand->getType(), RegTemp, NULL, MemOperand->getIndex(), | |
| 5572 MemOperand->getShift(), MemOperand->getSegmentRegister()); | |
| 5573 return NewMemOperand; | |
| 5574 } | |
| 5575 assert("Unsupported -randomize-pool-immediates option" && false); | |
| 5576 } | |
| 5577 } | |
| 5578 // the offset is not eligible for blinding or pooling, return the original | |
| 5579 // mem operand | |
| 5580 return MemOperand; | |
| 5581 } | |
| 5582 | |
| 5022 } // end of namespace Ice | 5583 } // end of namespace Ice |
| OLD | NEW |