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 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 // Nop insertion | 580 // Nop insertion |
581 if (Ctx->getFlags().shouldDoNopInsertion()) { | 581 if (Ctx->getFlags().shouldDoNopInsertion()) { |
582 Func->doNopInsertion(); | 582 Func->doNopInsertion(); |
583 } | 583 } |
584 } | 584 } |
585 | 585 |
586 namespace { | 586 namespace { |
587 | 587 |
588 bool canRMW(const InstArithmetic *Arith) { | 588 bool canRMW(const InstArithmetic *Arith) { |
589 Type Ty = Arith->getDest()->getType(); | 589 Type Ty = Arith->getDest()->getType(); |
| 590 // X86 vector instructions write to a register and have no RMW |
| 591 // option. |
| 592 if (isVectorType(Ty)) |
| 593 return false; |
590 bool isI64 = Ty == IceType_i64; | 594 bool isI64 = Ty == IceType_i64; |
591 bool isVector = isVectorType(Ty); | |
592 | 595 |
593 switch (Arith->getOp()) { | 596 switch (Arith->getOp()) { |
594 // Not handled for lack of simple lowering: | 597 // Not handled for lack of simple lowering: |
595 // shift on i64 and vectors | 598 // shift on i64 |
596 // mul, udiv, urem, sdiv, srem, frem | 599 // mul, udiv, urem, sdiv, srem, frem |
| 600 // Not handled for lack of RMW instructions: |
| 601 // fadd, fsub, fmul, fdiv (also vector types) |
597 default: | 602 default: |
598 return false; | 603 return false; |
599 case InstArithmetic::Add: | 604 case InstArithmetic::Add: |
600 return !isI64 && !isVector; // TODO(stichnot): implement i64 and vector | |
601 case InstArithmetic::Sub: | 605 case InstArithmetic::Sub: |
602 case InstArithmetic::And: | 606 case InstArithmetic::And: |
603 case InstArithmetic::Or: | 607 case InstArithmetic::Or: |
604 case InstArithmetic::Xor: | 608 case InstArithmetic::Xor: |
605 case InstArithmetic::Fadd: | |
606 case InstArithmetic::Fsub: | |
607 case InstArithmetic::Fmul: | |
608 case InstArithmetic::Fdiv: | |
609 return false; // TODO(stichnot): implement | |
610 return true; | 609 return true; |
611 case InstArithmetic::Shl: | 610 case InstArithmetic::Shl: |
612 case InstArithmetic::Lshr: | 611 case InstArithmetic::Lshr: |
613 case InstArithmetic::Ashr: | 612 case InstArithmetic::Ashr: |
614 return false; // TODO(stichnot): implement | 613 return false; // TODO(stichnot): implement |
615 return !isI64 && !isVector; | 614 return !isI64; |
616 } | 615 } |
617 } | 616 } |
618 | 617 |
619 bool isSameMemAddressOperand(const Operand *A, const Operand *B) { | 618 bool isSameMemAddressOperand(const Operand *A, const Operand *B) { |
620 if (A == B) | 619 if (A == B) |
621 return true; | 620 return true; |
622 if (auto *MemA = llvm::dyn_cast<OperandX8632Mem>(A)) { | 621 if (auto *MemA = llvm::dyn_cast<OperandX8632Mem>(A)) { |
623 if (auto *MemB = llvm::dyn_cast<OperandX8632Mem>(B)) { | 622 if (auto *MemB = llvm::dyn_cast<OperandX8632Mem>(B)) { |
624 return MemA->getBase() == MemB->getBase() && | 623 return MemA->getBase() == MemB->getBase() && |
625 MemA->getOffset() == MemB->getOffset() && | 624 MemA->getOffset() == MemB->getOffset() && |
(...skipping 2809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3435 Context.insert( | 3434 Context.insert( |
3436 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | 3435 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); |
3437 return; | 3436 return; |
3438 } | 3437 } |
3439 case Intrinsics::AtomicRMW: | 3438 case Intrinsics::AtomicRMW: |
3440 if (!Intrinsics::isMemoryOrderValid( | 3439 if (!Intrinsics::isMemoryOrderValid( |
3441 ID, getConstantMemoryOrder(Instr->getArg(3)))) { | 3440 ID, getConstantMemoryOrder(Instr->getArg(3)))) { |
3442 Func->setError("Unexpected memory ordering for AtomicRMW"); | 3441 Func->setError("Unexpected memory ordering for AtomicRMW"); |
3443 return; | 3442 return; |
3444 } | 3443 } |
3445 lowerAtomicRMW(Instr->getDest(), | 3444 lowerAtomicRMW( |
3446 static_cast<uint32_t>(llvm::cast<ConstantInteger32>( | 3445 Instr->getDest(), |
3447 Instr->getArg(0))->getValue()), | 3446 static_cast<uint32_t>( |
3448 Instr->getArg(1), Instr->getArg(2)); | 3447 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()), |
| 3448 Instr->getArg(1), Instr->getArg(2)); |
3449 return; | 3449 return; |
3450 case Intrinsics::AtomicStore: { | 3450 case Intrinsics::AtomicStore: { |
3451 if (!Intrinsics::isMemoryOrderValid( | 3451 if (!Intrinsics::isMemoryOrderValid( |
3452 ID, getConstantMemoryOrder(Instr->getArg(2)))) { | 3452 ID, getConstantMemoryOrder(Instr->getArg(2)))) { |
3453 Func->setError("Unexpected memory ordering for AtomicStore"); | 3453 Func->setError("Unexpected memory ordering for AtomicStore"); |
3454 return; | 3454 return; |
3455 } | 3455 } |
3456 // We require the memory address to be naturally aligned. | 3456 // We require the memory address to be naturally aligned. |
3457 // Given that is the case, then normal stores are atomic. | 3457 // Given that is the case, then normal stores are atomic. |
3458 // Add a fence after the store to make it visible. | 3458 // Add a fence after the store to make it visible. |
(...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4653 // still there, either because the value being stored is used beyond | 4653 // still there, either because the value being stored is used beyond |
4654 // the Store instruction, or because dead code elimination did not | 4654 // the Store instruction, or because dead code elimination did not |
4655 // happen. In either case, we cancel RMW lowering (and the caller | 4655 // happen. In either case, we cancel RMW lowering (and the caller |
4656 // deletes the RMW instruction). | 4656 // deletes the RMW instruction). |
4657 if (!RMW->isLastUse(RMW->getBeacon())) | 4657 if (!RMW->isLastUse(RMW->getBeacon())) |
4658 return; | 4658 return; |
4659 Operand *Src = RMW->getData(); | 4659 Operand *Src = RMW->getData(); |
4660 Type Ty = Src->getType(); | 4660 Type Ty = Src->getType(); |
4661 OperandX8632Mem *Addr = formMemoryOperand(RMW->getAddr(), Ty); | 4661 OperandX8632Mem *Addr = formMemoryOperand(RMW->getAddr(), Ty); |
4662 if (Ty == IceType_i64) { | 4662 if (Ty == IceType_i64) { |
4663 // TODO(stichnot): Implement. | 4663 Operand *SrcLo = legalize(loOperand(Src), Legal_Reg | Legal_Imm); |
4664 } else if (isVectorType(Ty)) { | 4664 Operand *SrcHi = legalize(hiOperand(Src), Legal_Reg | Legal_Imm); |
4665 // TODO(stichnot): Implement. | 4665 OperandX8632Mem *AddrLo = llvm::cast<OperandX8632Mem>(loOperand(Addr)); |
4666 } else { | 4666 OperandX8632Mem *AddrHi = llvm::cast<OperandX8632Mem>(hiOperand(Addr)); |
4667 // i8, i16, i32, f32, f64 | |
4668 switch (RMW->getOp()) { | 4667 switch (RMW->getOp()) { |
4669 default: | 4668 default: |
4670 // TODO(stichnot): Implement other arithmetic operators. | 4669 // TODO(stichnot): Implement other arithmetic operators. |
| 4670 break; |
| 4671 case InstArithmetic::Add: |
| 4672 _add_rmw(AddrLo, SrcLo); |
| 4673 _adc_rmw(AddrHi, SrcHi); |
| 4674 return; |
| 4675 case InstArithmetic::Sub: |
| 4676 _sub_rmw(AddrLo, SrcLo); |
| 4677 _sbb_rmw(AddrHi, SrcHi); |
| 4678 return; |
| 4679 case InstArithmetic::And: |
| 4680 _and_rmw(AddrLo, SrcLo); |
| 4681 _and_rmw(AddrHi, SrcHi); |
| 4682 return; |
| 4683 case InstArithmetic::Or: |
| 4684 _or_rmw(AddrLo, SrcLo); |
| 4685 _or_rmw(AddrHi, SrcHi); |
| 4686 return; |
| 4687 case InstArithmetic::Xor: |
| 4688 _xor_rmw(AddrLo, SrcLo); |
| 4689 _xor_rmw(AddrHi, SrcHi); |
| 4690 return; |
| 4691 } |
| 4692 } else { |
| 4693 // i8, i16, i32 |
| 4694 switch (RMW->getOp()) { |
| 4695 default: |
| 4696 // TODO(stichnot): Implement other arithmetic operators. |
4671 break; | 4697 break; |
4672 case InstArithmetic::Add: | 4698 case InstArithmetic::Add: |
4673 Src = legalize(Src, Legal_Reg | Legal_Imm); | 4699 Src = legalize(Src, Legal_Reg | Legal_Imm); |
4674 _add_rmw(Addr, Src); | 4700 _add_rmw(Addr, Src); |
4675 return; | 4701 return; |
| 4702 case InstArithmetic::Sub: |
| 4703 Src = legalize(Src, Legal_Reg | Legal_Imm); |
| 4704 _sub_rmw(Addr, Src); |
| 4705 return; |
| 4706 case InstArithmetic::And: |
| 4707 Src = legalize(Src, Legal_Reg | Legal_Imm); |
| 4708 _and_rmw(Addr, Src); |
| 4709 return; |
| 4710 case InstArithmetic::Or: |
| 4711 Src = legalize(Src, Legal_Reg | Legal_Imm); |
| 4712 _or_rmw(Addr, Src); |
| 4713 return; |
| 4714 case InstArithmetic::Xor: |
| 4715 Src = legalize(Src, Legal_Reg | Legal_Imm); |
| 4716 _xor_rmw(Addr, Src); |
| 4717 return; |
4676 } | 4718 } |
4677 } | 4719 } |
4678 llvm::report_fatal_error("Couldn't lower RMW instruction"); | 4720 llvm::report_fatal_error("Couldn't lower RMW instruction"); |
4679 } | 4721 } |
4680 | 4722 |
4681 void TargetX8632::lowerOther(const Inst *Instr) { | 4723 void TargetX8632::lowerOther(const Inst *Instr) { |
4682 if (const auto *RMW = llvm::dyn_cast<InstX8632FakeRMW>(Instr)) { | 4724 if (const auto *RMW = llvm::dyn_cast<InstX8632FakeRMW>(Instr)) { |
4683 lowerRMW(RMW); | 4725 lowerRMW(RMW); |
4684 } else { | 4726 } else { |
4685 TargetLowering::lowerOther(Instr); | 4727 TargetLowering::lowerOther(Instr); |
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5303 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 5345 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
5304 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 5346 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
5305 } break; | 5347 } break; |
5306 } | 5348 } |
5307 } | 5349 } |
5308 | 5350 |
5309 TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) | 5351 TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) |
5310 : TargetHeaderLowering(Ctx) {} | 5352 : TargetHeaderLowering(Ctx) {} |
5311 | 5353 |
5312 } // end of namespace Ice | 5354 } // end of namespace Ice |
OLD | NEW |