Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // | 1 // |
| 2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
| 3 // | 3 // |
| 4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
| 5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
| 6 // | 6 // |
| 7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
| 8 /// | 8 /// |
| 9 /// \file | 9 /// \file |
| 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 continue; | 233 continue; |
| 234 } | 234 } |
| 235 | 235 |
| 236 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); | 236 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); |
| 237 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 237 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 238 } | 238 } |
| 239 | 239 |
| 240 return applyStackAlignment(OutArgsSizeBytes); | 240 return applyStackAlignment(OutArgsSizeBytes); |
| 241 } | 241 } |
| 242 | 242 |
| 243 namespace { | |
| 244 inline uint64_t getConstantMemoryOrder(Operand *Opnd) { | |
| 245 if (auto *Integer = llvm::dyn_cast<ConstantInteger32>(Opnd)) | |
| 246 return Integer->getValue(); | |
| 247 return Intrinsics::MemoryOrderInvalid; | |
| 248 } | |
| 249 } | |
| 250 | |
| 243 void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { | 251 void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
| 244 constexpr bool NoTailCall = false; | 252 constexpr bool NoTailCall = false; |
| 245 constexpr bool IsTargetHelperCall = true; | 253 constexpr bool IsTargetHelperCall = true; |
| 246 Variable *Dest = Instr->getDest(); | 254 Variable *Dest = Instr->getDest(); |
| 247 const Type DestTy = Dest ? Dest->getType() : IceType_void; | 255 const Type DestTy = Dest ? Dest->getType() : IceType_void; |
| 248 | 256 |
| 249 switch (Instr->getKind()) { | 257 switch (Instr->getKind()) { |
| 250 default: | 258 default: |
| 251 return; | 259 return; |
| 252 case Inst::Select: { | 260 case Inst::Select: { |
| (...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1046 if (ArgNo == 0) { | 1054 if (ArgNo == 0) { |
| 1047 UseFPRegs = true; | 1055 UseFPRegs = true; |
| 1048 return argInVFP(Ty, Reg); | 1056 return argInVFP(Ty, Reg); |
| 1049 } | 1057 } |
| 1050 if (UseFPRegs && ArgNo == 1) { | 1058 if (UseFPRegs && ArgNo == 1) { |
| 1051 UseFPRegs = false; | 1059 UseFPRegs = false; |
| 1052 return argInVFP(Ty, Reg); | 1060 return argInVFP(Ty, Reg); |
| 1053 } | 1061 } |
| 1054 return argInGPR(Ty, Reg); | 1062 return argInGPR(Ty, Reg); |
| 1055 } | 1063 } |
| 1056 UnimplementedError(getFlags()); | 1064 llvm::report_fatal_error("argInReg: Invalid type."); |
| 1057 return false; | 1065 return false; |
| 1058 } | 1066 } |
| 1059 | 1067 |
| 1060 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { | 1068 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { |
| 1061 CfgVector<RegNumT> *Source; | 1069 CfgVector<RegNumT> *Source; |
| 1062 | 1070 |
| 1063 switch (Ty) { | 1071 switch (Ty) { |
| 1064 default: { | 1072 default: { |
| 1065 UnimplementedError(getFlags()); | 1073 llvm::report_fatal_error("argInGPR: Invalid type."); |
| 1066 return false; | 1074 return false; |
| 1067 } break; | 1075 } break; |
| 1068 case IceType_v4i1: | 1076 case IceType_v4i1: |
| 1069 case IceType_v8i1: | 1077 case IceType_v8i1: |
| 1070 case IceType_v16i1: | 1078 case IceType_v16i1: |
| 1071 case IceType_v16i8: | 1079 case IceType_v16i8: |
| 1072 case IceType_v8i16: | 1080 case IceType_v8i16: |
| 1073 case IceType_v4i32: | 1081 case IceType_v4i32: |
| 1074 case IceType_v4f32: | 1082 case IceType_v4f32: |
| 1075 case IceType_i32: | 1083 case IceType_i32: |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1140 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | 1148 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { |
| 1141 discardNextGPRAndItsAliases(Regs); | 1149 discardNextGPRAndItsAliases(Regs); |
| 1142 } | 1150 } |
| 1143 } | 1151 } |
| 1144 | 1152 |
| 1145 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { | 1153 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { |
| 1146 CfgVector<RegNumT> *Source; | 1154 CfgVector<RegNumT> *Source; |
| 1147 | 1155 |
| 1148 switch (Ty) { | 1156 switch (Ty) { |
| 1149 default: { | 1157 default: { |
| 1150 UnimplementedError(getFlags()); | 1158 llvm::report_fatal_error("argInVFP: Invalid type."); |
| 1151 return false; | 1159 return false; |
| 1152 } break; | 1160 } break; |
| 1153 case IceType_f32: { | 1161 case IceType_f32: { |
| 1154 Source = &FP32Args; | 1162 Source = &FP32Args; |
| 1155 } break; | 1163 } break; |
| 1156 case IceType_f64: { | 1164 case IceType_f64: { |
| 1157 Source = &FP64Args; | 1165 Source = &FP64Args; |
| 1158 } break; | 1166 } break; |
| 1159 } | 1167 } |
| 1160 | 1168 |
| (...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2532 _mov(T1_Hi, T_Hi); | 2540 _mov(T1_Hi, T_Hi); |
| 2533 _mov(T1_Lo, T_Lo); | 2541 _mov(T1_Lo, T_Lo); |
| 2534 _andi(T5, Src1LoR, INT32_BITS); | 2542 _andi(T5, Src1LoR, INT32_BITS); |
| 2535 _movn(T1_Lo, T_Hi, T5); | 2543 _movn(T1_Lo, T_Hi, T5); |
| 2536 _sra(T6, Src0HiR, INT32_BITS - 1); | 2544 _sra(T6, Src0HiR, INT32_BITS - 1); |
| 2537 _movn(T1_Hi, T6, T5); | 2545 _movn(T1_Hi, T6, T5); |
| 2538 _mov(DestHi, T1_Hi); | 2546 _mov(DestHi, T1_Hi); |
| 2539 _mov(DestLo, T1_Lo); | 2547 _mov(DestLo, T1_Lo); |
| 2540 return; | 2548 return; |
| 2541 } | 2549 } |
| 2542 default: | 2550 case InstArithmetic::Fadd: |
| 2543 UnimplementedLoweringError(this, Instr); | 2551 case InstArithmetic::Fsub: |
| 2552 case InstArithmetic::Fmul: | |
| 2553 case InstArithmetic::Fdiv: | |
| 2554 case InstArithmetic::Frem: | |
| 2555 llvm::report_fatal_error("FP instruction with i64 type"); | |
| 2556 return; | |
| 2557 case InstArithmetic::Udiv: | |
| 2558 case InstArithmetic::Sdiv: | |
| 2559 case InstArithmetic::Urem: | |
| 2560 case InstArithmetic::Srem: | |
| 2561 llvm::report_fatal_error("64-bit div and rem should have been prelowered"); | |
| 2544 return; | 2562 return; |
| 2545 } | 2563 } |
| 2546 } | 2564 } |
| 2547 | 2565 |
| 2548 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { | 2566 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { |
| 2549 Variable *Dest = Instr->getDest(); | 2567 Variable *Dest = Instr->getDest(); |
| 2550 | 2568 |
| 2551 if (Dest->isRematerializable()) { | 2569 if (Dest->isRematerializable()) { |
| 2552 Context.insert<InstFakeDef>(Dest); | 2570 Context.insert<InstFakeDef>(Dest); |
| 2553 return; | 2571 return; |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2777 if (DestTy == IceType_f64) { | 2795 if (DestTy == IceType_f64) { |
| 2778 _div_d(T, Src0R, Src1R); | 2796 _div_d(T, Src0R, Src1R); |
| 2779 _mov(Dest, T); | 2797 _mov(Dest, T); |
| 2780 return; | 2798 return; |
| 2781 } | 2799 } |
| 2782 break; | 2800 break; |
| 2783 case InstArithmetic::Frem: | 2801 case InstArithmetic::Frem: |
| 2784 llvm::report_fatal_error("frem should have been prelowered."); | 2802 llvm::report_fatal_error("frem should have been prelowered."); |
| 2785 break; | 2803 break; |
| 2786 } | 2804 } |
| 2787 UnimplementedLoweringError(this, Instr); | 2805 llvm::report_fatal_error("Unknown arithmetic operator"); |
| 2788 } | 2806 } |
| 2789 | 2807 |
| 2790 void TargetMIPS32::lowerAssign(const InstAssign *Instr) { | 2808 void TargetMIPS32::lowerAssign(const InstAssign *Instr) { |
| 2791 Variable *Dest = Instr->getDest(); | 2809 Variable *Dest = Instr->getDest(); |
| 2792 | 2810 |
| 2793 if (Dest->isRematerializable()) { | 2811 if (Dest->isRematerializable()) { |
| 2794 Context.insert<InstFakeDef>(Dest); | 2812 Context.insert<InstFakeDef>(Dest); |
| 2795 return; | 2813 return; |
| 2796 } | 2814 } |
| 2797 | 2815 |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3489 return; | 3507 return; |
| 3490 } | 3508 } |
| 3491 if (Src0Ty == IceType_f64 && isScalarIntegerType(DestTy)) { | 3509 if (Src0Ty == IceType_f64 && isScalarIntegerType(DestTy)) { |
| 3492 Variable *Src0R = legalizeToReg(Src0); | 3510 Variable *Src0R = legalizeToReg(Src0); |
| 3493 Variable *FTmp = makeReg(IceType_f64); | 3511 Variable *FTmp = makeReg(IceType_f64); |
| 3494 _trunc_w_d(FTmp, Src0R); | 3512 _trunc_w_d(FTmp, Src0R); |
| 3495 _mov(Dest, FTmp); | 3513 _mov(Dest, FTmp); |
| 3496 return; | 3514 return; |
| 3497 } | 3515 } |
| 3498 } | 3516 } |
| 3499 UnimplementedLoweringError(this, Instr); | 3517 llvm::report_fatal_error("Destination is i64 in fp-to-i32"); |
| 3500 break; | 3518 break; |
| 3501 } | 3519 } |
| 3502 case InstCast::Sitofp: | 3520 case InstCast::Sitofp: |
| 3503 case InstCast::Uitofp: { | 3521 case InstCast::Uitofp: { |
| 3504 if (llvm::isa<Variable64On32>(Dest)) { | 3522 if (llvm::isa<Variable64On32>(Dest)) { |
| 3505 llvm::report_fatal_error("i64-to-fp should have been prelowered."); | 3523 llvm::report_fatal_error("i64-to-fp should have been prelowered."); |
| 3506 return; | 3524 return; |
| 3507 } | 3525 } |
| 3508 if (Src0Ty != IceType_i64) { | 3526 if (Src0Ty != IceType_i64) { |
| 3509 Variable *Src0R = legalizeToReg(Src0); | 3527 Variable *Src0R = legalizeToReg(Src0); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 3522 } | 3540 } |
| 3523 if (isScalarIntegerType(Src0Ty) && DestTy == IceType_f64) { | 3541 if (isScalarIntegerType(Src0Ty) && DestTy == IceType_f64) { |
| 3524 Variable *FTmp1 = makeReg(IceType_f64); | 3542 Variable *FTmp1 = makeReg(IceType_f64); |
| 3525 Variable *FTmp2 = makeReg(IceType_f64); | 3543 Variable *FTmp2 = makeReg(IceType_f64); |
| 3526 _mtc1(FTmp1, T0R); | 3544 _mtc1(FTmp1, T0R); |
| 3527 _cvt_d_w(FTmp2, FTmp1); | 3545 _cvt_d_w(FTmp2, FTmp1); |
| 3528 _mov(Dest, FTmp2); | 3546 _mov(Dest, FTmp2); |
| 3529 return; | 3547 return; |
| 3530 } | 3548 } |
| 3531 } | 3549 } |
| 3532 UnimplementedLoweringError(this, Instr); | 3550 llvm::report_fatal_error("Source is i64 in i32-to-fp"); |
| 3533 break; | 3551 break; |
| 3534 } | 3552 } |
| 3535 case InstCast::Bitcast: { | 3553 case InstCast::Bitcast: { |
| 3536 Operand *Src0 = Instr->getSrc(0); | 3554 Operand *Src0 = Instr->getSrc(0); |
| 3537 if (DestTy == Src0->getType()) { | 3555 if (DestTy == Src0->getType()) { |
| 3538 auto *Assign = InstAssign::create(Func, Dest, Src0); | 3556 auto *Assign = InstAssign::create(Func, Dest, Src0); |
| 3539 lowerAssign(Assign); | 3557 lowerAssign(Assign); |
| 3540 return; | 3558 return; |
| 3541 } | 3559 } |
| 3542 if (isVectorType(DestTy) || isVectorType(Src0->getType())) { | 3560 if (isVectorType(DestTy) || isVectorType(Src0->getType())) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3591 _mov(Dest, RegHi, RegLo); | 3609 _mov(Dest, RegHi, RegLo); |
| 3592 } else { | 3610 } else { |
| 3593 auto *Var64On32 = llvm::cast<Variable64On32>(Src0); | 3611 auto *Var64On32 = llvm::cast<Variable64On32>(Src0); |
| 3594 auto *RegLo = legalizeToReg(loOperand(Var64On32)); | 3612 auto *RegLo = legalizeToReg(loOperand(Var64On32)); |
| 3595 auto *RegHi = legalizeToReg(hiOperand(Var64On32)); | 3613 auto *RegHi = legalizeToReg(hiOperand(Var64On32)); |
| 3596 _mov(Dest, RegHi, RegLo); | 3614 _mov(Dest, RegHi, RegLo); |
| 3597 } | 3615 } |
| 3598 break; | 3616 break; |
| 3599 } | 3617 } |
| 3600 default: | 3618 default: |
| 3601 UnimplementedLoweringError(this, Instr); | 3619 llvm::report_fatal_error("Unexpected bitcast."); |
| 3602 } | 3620 } |
| 3603 break; | 3621 break; |
| 3604 } | 3622 } |
| 3605 } | 3623 } |
| 3606 } | 3624 } |
| 3607 | 3625 |
| 3608 void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { | 3626 void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { |
| 3609 Variable *Dest = Instr->getDest(); | 3627 Variable *Dest = Instr->getDest(); |
| 3610 const Type DestTy = Dest->getType(); | 3628 const Type DestTy = Dest->getType(); |
| 3611 Operand *Src1 = Instr->getSrc(1); | 3629 Operand *Src1 = Instr->getSrc(1); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3683 InstFcmp::FCond Cond = Instr->getCondition(); | 3701 InstFcmp::FCond Cond = Instr->getCondition(); |
| 3684 auto *DestR = makeReg(IceType_i32); | 3702 auto *DestR = makeReg(IceType_i32); |
| 3685 auto *Src0R = legalizeToReg(Src0); | 3703 auto *Src0R = legalizeToReg(Src0); |
| 3686 auto *Src1R = legalizeToReg(Src1); | 3704 auto *Src1R = legalizeToReg(Src1); |
| 3687 const Type Src0Ty = Src0->getType(); | 3705 const Type Src0Ty = Src0->getType(); |
| 3688 | 3706 |
| 3689 Operand *FCC0 = OperandMIPS32FCC::create(getFunc(), OperandMIPS32FCC::FCC0); | 3707 Operand *FCC0 = OperandMIPS32FCC::create(getFunc(), OperandMIPS32FCC::FCC0); |
| 3690 | 3708 |
| 3691 switch (Cond) { | 3709 switch (Cond) { |
| 3692 default: { | 3710 default: { |
| 3693 UnimplementedLoweringError(this, Instr); | 3711 llvm::report_fatal_error("Unhandled fp comparison."); |
| 3694 return; | 3712 return; |
| 3695 } | 3713 } |
| 3696 case InstFcmp::False: { | 3714 case InstFcmp::False: { |
| 3697 Context.insert<InstFakeUse>(Src0R); | 3715 Context.insert<InstFakeUse>(Src0R); |
| 3698 Context.insert<InstFakeUse>(Src1R); | 3716 Context.insert<InstFakeUse>(Src1R); |
| 3699 _addiu(DestR, Zero, 0); | 3717 _addiu(DestR, Zero, 0); |
| 3700 _mov(Dest, DestR); | 3718 _mov(Dest, DestR); |
| 3701 break; | 3719 break; |
| 3702 } | 3720 } |
| 3703 case InstFcmp::Oeq: { | 3721 case InstFcmp::Oeq: { |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4228 } | 4246 } |
| 4229 } | 4247 } |
| 4230 // Write back temporary vector to the destination | 4248 // Write back temporary vector to the destination |
| 4231 auto *Assign = InstAssign::create(Func, Dest, TDest); | 4249 auto *Assign = InstAssign::create(Func, Dest, TDest); |
| 4232 lowerAssign(Assign); | 4250 lowerAssign(Assign); |
| 4233 return; | 4251 return; |
| 4234 } | 4252 } |
| 4235 llvm::report_fatal_error("InsertElement requires a constant index"); | 4253 llvm::report_fatal_error("InsertElement requires a constant index"); |
| 4236 } | 4254 } |
| 4237 | 4255 |
| 4256 void TargetMIPS32::createArithInst(uint32_t Operation, Variable *Dest, | |
|
Jim Stichnoth
2016/11/17 05:35:39
Can you declare Operation as Intrinsics::Intrinsic
sagar.thakur
2016/11/17 10:57:29
Done.
| |
| 4257 Variable *Src0, Variable *Src1) { | |
| 4258 switch (Operation) { | |
| 4259 default: | |
| 4260 llvm::report_fatal_error("Unknown AtomicRMW operation"); | |
| 4261 case Intrinsics::AtomicExchange: | |
| 4262 llvm::report_fatal_error("Can't handle Atomic xchg operation"); | |
| 4263 case Intrinsics::AtomicAdd: | |
| 4264 _addu(Dest, Src0, Src1); | |
| 4265 break; | |
| 4266 case Intrinsics::AtomicAnd: | |
| 4267 _and(Dest, Src0, Src1); | |
| 4268 break; | |
| 4269 case Intrinsics::AtomicSub: | |
| 4270 _subu(Dest, Src0, Src1); | |
| 4271 break; | |
| 4272 case Intrinsics::AtomicOr: | |
| 4273 _or(Dest, Src0, Src1); | |
| 4274 break; | |
| 4275 case Intrinsics::AtomicXor: | |
| 4276 _xor(Dest, Src0, Src1); | |
| 4277 break; | |
| 4278 } | |
| 4279 } | |
| 4280 | |
| 4238 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { | 4281 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
| 4239 Variable *Dest = Instr->getDest(); | 4282 Variable *Dest = Instr->getDest(); |
| 4240 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType(); | 4283 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType(); |
| 4284 | |
| 4285 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID; | |
| 4241 switch (Instr->getIntrinsicInfo().ID) { | 4286 switch (Instr->getIntrinsicInfo().ID) { |
|
Jim Stichnoth
2016/11/17 05:35:39
switch (ID) {
sagar.thakur
2016/11/17 10:57:28
Done.
| |
| 4287 case Intrinsics::AtomicLoad: { | |
| 4288 assert(isScalarIntegerType(DestTy)); | |
| 4289 // We require the memory address to be naturally aligned. Given that is the | |
| 4290 // case, then normal loads are atomic. | |
| 4291 if (!Intrinsics::isMemoryOrderValid( | |
| 4292 ID, getConstantMemoryOrder(Instr->getArg(1)))) { | |
| 4293 Func->setError("Unexpected memory ordering for AtomicLoad"); | |
| 4294 return; | |
| 4295 } | |
| 4296 if (DestTy == IceType_i64) { | |
| 4297 auto *Base = legalizeToReg(Instr->getArg(0)); | |
| 4298 auto *AddrLo = OperandMIPS32Mem::create( | |
| 4299 Func, IceType_i32, Base, | |
| 4300 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | |
| 4301 auto *AddrHi = OperandMIPS32Mem::create( | |
| 4302 Func, IceType_i32, Base, | |
| 4303 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
| 4304 Variable *T_Lo = makeReg(IceType_i32); | |
| 4305 Variable *T_Hi = makeReg(IceType_i32); | |
| 4306 auto *Dest64 = llvm::cast<Variable64On32>(Dest); | |
| 4307 lowerLoad(InstLoad::create(Func, T_Lo, AddrLo, IceType_i32)); | |
| 4308 lowerLoad(InstLoad::create(Func, T_Hi, AddrHi, IceType_i32)); | |
| 4309 _sync(); | |
| 4310 _mov(Dest64->getLo(), T_Lo); | |
| 4311 _mov(Dest64->getHi(), T_Hi); | |
| 4312 // Adding a fake-use of T to ensure the atomic load is not removed | |
|
Jim Stichnoth
2016/11/17 05:35:39
Reflow this and other comments to 80-col
sagar.thakur
2016/11/17 10:57:28
Done.
| |
| 4313 // if Dest is unused. | |
| 4314 Context.insert<InstFakeUse>(T_Lo); | |
| 4315 Context.insert<InstFakeUse>(T_Hi); | |
| 4316 } else { | |
| 4317 Variable *T = makeReg(DestTy); | |
| 4318 lowerLoad(InstLoad::create(Func, T, | |
| 4319 formMemoryOperand(Instr->getArg(0), DestTy))); | |
| 4320 _sync(); | |
| 4321 _mov(Dest, T); | |
| 4322 // Adding a fake-use of T to ensure the atomic load is not removed | |
| 4323 // if Dest is unused. | |
| 4324 Context.insert<InstFakeUse>(T); | |
| 4325 } | |
| 4326 return; | |
| 4327 } | |
| 4328 case Intrinsics::AtomicStore: { | |
| 4329 // We require the memory address to be naturally aligned. Given that is the | |
| 4330 // case, then normal stores are atomic. | |
| 4331 if (!Intrinsics::isMemoryOrderValid( | |
| 4332 ID, getConstantMemoryOrder(Instr->getArg(2)))) { | |
| 4333 Func->setError("Unexpected memory ordering for AtomicLoad"); | |
|
Jim Stichnoth
2016/11/17 05:35:39
AtomicStore
sagar.thakur
2016/11/17 10:57:28
Done.
| |
| 4334 return; | |
| 4335 } | |
| 4336 auto *Val = Instr->getArg(0); | |
| 4337 auto Ty = Val->getType(); | |
| 4338 if (Ty == IceType_i64) { | |
| 4339 Variable *ValHi, *ValLo; | |
| 4340 _sync(); | |
| 4341 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Val)) { | |
| 4342 const uint64_t Value = C64->getValue(); | |
| 4343 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; | |
| 4344 uint64_t Lower32Bits = Value & 0XFFFFFFFF; | |
|
Jim Stichnoth
2016/11/17 05:35:39
lowercase 'x' for consistency
(here and below)
sagar.thakur
2016/11/17 10:57:28
Done.
| |
| 4345 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); | |
| 4346 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); | |
| 4347 } else { | |
| 4348 auto *Val64 = llvm::cast<Variable64On32>(Val); | |
| 4349 ValLo = legalizeToReg(loOperand(Val64)); | |
| 4350 ValHi = legalizeToReg(hiOperand(Val64)); | |
| 4351 } | |
| 4352 | |
| 4353 auto *Base = legalizeToReg(Instr->getArg(1)); | |
| 4354 auto *AddrLo = OperandMIPS32Mem::create( | |
| 4355 Func, IceType_i32, Base, | |
| 4356 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | |
| 4357 auto *AddrHi = OperandMIPS32Mem::create( | |
| 4358 Func, IceType_i32, Base, | |
| 4359 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
| 4360 lowerStore(InstStore::create(Func, ValLo, AddrLo, IceType_i32)); | |
| 4361 lowerStore(InstStore::create(Func, ValHi, AddrHi, IceType_i32)); | |
| 4362 _sync(); | |
| 4363 } else { | |
| 4364 _sync(); | |
| 4365 Variable *Val = legalizeToReg(Instr->getArg(0)); | |
| 4366 lowerStore(InstStore::create( | |
| 4367 Func, Val, formMemoryOperand(Instr->getArg(1), DestTy))); | |
| 4368 _sync(); | |
| 4369 } | |
| 4370 return; | |
| 4371 } | |
| 4242 case Intrinsics::AtomicCmpxchg: { | 4372 case Intrinsics::AtomicCmpxchg: { |
| 4243 UnimplementedLoweringError(this, Instr); | 4373 assert(isScalarIntegerType(DestTy)); |
| 4374 // We require the memory address to be naturally aligned. Given that is the | |
| 4375 // case, then normal loads are atomic. | |
| 4376 if (!Intrinsics::isMemoryOrderValid( | |
| 4377 ID, getConstantMemoryOrder(Instr->getArg(3)), | |
| 4378 getConstantMemoryOrder(Instr->getArg(4)))) { | |
| 4379 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); | |
| 4380 return; | |
| 4381 } | |
| 4382 | |
| 4383 InstMIPS32Label *Label1 = InstMIPS32Label::create(Func, this); | |
| 4384 constexpr CfgNode *NoTarget = nullptr; | |
| 4385 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | |
| 4386 Variable *T1 = I32Reg(); | |
| 4387 Variable *T2 = I32Reg(); | |
| 4388 Variable *T3 = I32Reg(); | |
| 4389 Variable *T4 = I32Reg(); | |
| 4390 Variable *T5 = I32Reg(); | |
| 4391 Variable *T6 = I32Reg(); | |
| 4392 Variable *T7 = I32Reg(); | |
| 4393 Variable *T8 = I32Reg(); | |
| 4394 Variable *T9 = I32Reg(); | |
| 4395 | |
| 4396 if (DestTy == IceType_i64) { | |
| 4397 InstMIPS32Label *Retry1 = InstMIPS32Label::create(Func, this); | |
| 4398 InstMIPS32Label *Retry2 = InstMIPS32Label::create(Func, this); | |
| 4399 _sync(); | |
| 4400 Variable *ValHi, *ValLo, *ExpectedLo, *ExpectedHi; | |
| 4401 Operand *Expected = Instr->getArg(1); | |
| 4402 if (llvm::isa<ConstantUndef>(Expected)) { | |
| 4403 ExpectedLo = legalizeToReg(Ctx->getConstantZero(IceType_i32)); | |
| 4404 ExpectedHi = legalizeToReg(Ctx->getConstantZero(IceType_i32)); | |
| 4405 } else { | |
| 4406 auto *Expected64 = llvm::cast<Variable64On32>(Expected); | |
| 4407 ExpectedLo = legalizeToReg(loOperand(Expected64)); | |
| 4408 ExpectedHi = legalizeToReg(hiOperand(Expected64)); | |
| 4409 } | |
| 4410 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Instr->getArg(2))) { | |
| 4411 const uint64_t Value = C64->getValue(); | |
| 4412 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; | |
| 4413 uint64_t Lower32Bits = Value & 0XFFFFFFFF; | |
| 4414 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); | |
| 4415 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); | |
| 4416 } else { | |
| 4417 auto *Val = llvm::cast<Variable64On32>(Instr->getArg(2)); | |
| 4418 ValLo = legalizeToReg(loOperand(Val)); | |
| 4419 ValHi = legalizeToReg(hiOperand(Val)); | |
| 4420 } | |
| 4421 auto *Dest64 = llvm::cast<Variable64On32>(Dest); | |
| 4422 auto *Base = legalizeToReg(Instr->getArg(0)); | |
| 4423 auto *AddrLo = OperandMIPS32Mem::create( | |
| 4424 Func, IceType_i32, Base, | |
| 4425 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | |
| 4426 auto *AddrHi = OperandMIPS32Mem::create( | |
| 4427 Func, IceType_i32, Base, | |
| 4428 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
| 4429 | |
| 4430 Context.insert(Retry1); | |
| 4431 _ll(T1, AddrLo); | |
| 4432 _br(NoTarget, NoTarget, T1, ExpectedLo, Label1, CondMIPS32::Cond::NE); | |
| 4433 _sc(ValLo, AddrLo); | |
| 4434 _br(NoTarget, NoTarget, ValLo, getZero(), Retry1, CondMIPS32::Cond::EQ); | |
| 4435 _mov(Dest64->getLo(), T1); | |
| 4436 Context.insert(Retry2); | |
| 4437 _ll(T2, AddrHi); | |
| 4438 _br(NoTarget, NoTarget, T2, ExpectedHi, Label1, CondMIPS32::Cond::NE); | |
| 4439 _sc(ValHi, AddrHi); | |
| 4440 _br(NoTarget, NoTarget, ValHi, getZero(), Retry2, CondMIPS32::Cond::EQ); | |
| 4441 _mov(Dest64->getHi(), T2); | |
| 4442 _br(NoTarget, Label1); | |
| 4443 Context.insert<InstFakeUse>(getZero()); | |
| 4444 | |
| 4445 Context.insert(Label1); | |
| 4446 _sync(); | |
| 4447 return; | |
| 4448 } | |
| 4449 | |
| 4450 auto *New = legalizeToReg(Instr->getArg(2)); | |
| 4451 auto *Expected = legalizeToReg(Instr->getArg(1)); | |
| 4452 auto *ActualAddress = legalizeToReg(Instr->getArg(0)); | |
| 4453 InstMIPS32Label *Label2 = InstMIPS32Label::create(Func, this); | |
| 4454 | |
| 4455 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; | |
| 4456 | |
| 4457 if (DestTy == IceType_i8 || DestTy == IceType_i16) { | |
| 4458 const uint32_t ShiftAmount = | |
| 4459 (INT32_BITS - CHAR_BITS * typeWidthInBytes(DestTy)); | |
| 4460 _sync(); | |
| 4461 _addiu(RegAt, getZero(), -4); | |
| 4462 _and(T1, ActualAddress, RegAt); | |
| 4463 _andi(RegAt, ActualAddress, 3); | |
| 4464 _sll(T2, RegAt, 3); | |
| 4465 _ori(RegAt, getZero(), Mask); | |
| 4466 _sllv(T3, RegAt, T2); | |
| 4467 _nor(T4, getZero(), T3); | |
| 4468 _andi(RegAt, Expected, Mask); | |
| 4469 _sllv(T5, RegAt, T2); | |
| 4470 _andi(RegAt, New, Mask); | |
| 4471 _sllv(T6, RegAt, T2); | |
| 4472 | |
| 4473 Context.insert(Label1); | |
| 4474 _ll(T7, formMemoryOperand(T1, DestTy)); | |
| 4475 _and(T8, T7, T3); | |
| 4476 _br(NoTarget, NoTarget, T8, T5, Label2, CondMIPS32::Cond::NE); | |
| 4477 _and(RegAt, T7, T4); | |
| 4478 _or(T9, RegAt, T6); | |
| 4479 _sc(T9, formMemoryOperand(T1, DestTy)); | |
| 4480 _br(NoTarget, NoTarget, getZero(), T9, Label1, CondMIPS32::Cond::EQ); | |
| 4481 Context.insert<InstFakeUse>(getZero()); | |
| 4482 Context.insert(Label2); | |
| 4483 _srlv(RegAt, T8, T2); | |
| 4484 _sll(RegAt, RegAt, ShiftAmount); | |
| 4485 _sra(RegAt, RegAt, ShiftAmount); | |
| 4486 _mov(Dest, RegAt); | |
| 4487 _sync(); | |
| 4488 } else { | |
| 4489 _sync(); | |
| 4490 Context.insert(Label1); | |
| 4491 _ll(T1, formMemoryOperand(ActualAddress, DestTy)); | |
| 4492 _br(NoTarget, NoTarget, T1, Expected, Label2, CondMIPS32::Cond::NE); | |
| 4493 _sc(New, formMemoryOperand(ActualAddress, DestTy)); | |
| 4494 _br(NoTarget, NoTarget, New, getZero(), Label1, CondMIPS32::Cond::EQ); | |
| 4495 Context.insert<InstFakeUse>(getZero()); | |
| 4496 Context.insert(Label2); | |
| 4497 _sync(); | |
| 4498 _mov(Dest, T1); | |
| 4499 } | |
| 4500 | |
| 4501 Context.insert<InstFakeUse>(Expected); | |
| 4502 Context.insert<InstFakeUse>(New); | |
| 4503 return; | |
| 4504 } | |
| 4505 case Intrinsics::AtomicRMW: { | |
| 4506 assert(isScalarIntegerType(DestTy)); | |
| 4507 // We require the memory address to be naturally aligned. Given that is the | |
| 4508 // case, then normal loads are atomic. | |
| 4509 if (!Intrinsics::isMemoryOrderValid( | |
| 4510 ID, getConstantMemoryOrder(Instr->getArg(3)))) { | |
| 4511 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); | |
|
Jim Stichnoth
2016/11/17 05:35:39
AtomicRMW
sagar.thakur
2016/11/17 10:57:29
Done.
| |
| 4512 return; | |
| 4513 } | |
| 4514 | |
| 4515 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | |
| 4516 Variable *T1 = I32Reg(); | |
| 4517 Variable *T2 = I32Reg(); | |
| 4518 Variable *T3 = I32Reg(); | |
| 4519 Variable *T4 = I32Reg(); | |
| 4520 Variable *T5 = I32Reg(); | |
| 4521 Variable *T6 = I32Reg(); | |
| 4522 Variable *T7 = I32Reg(); | |
| 4523 constexpr CfgNode *NoTarget = nullptr; | |
| 4524 InstMIPS32Label *Label1 = InstMIPS32Label::create(Func, this); | |
| 4525 uint32_t Operation = static_cast<uint32_t>( | |
|
Jim Stichnoth
2016/11/17 05:35:39
Can it be like this:
auto Operation = static_ca
sagar.thakur
2016/11/17 10:57:29
Done.
| |
| 4526 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()); | |
| 4527 | |
| 4528 if (DestTy == IceType_i64) { | |
| 4529 InstMIPS32Label *Label2 = InstMIPS32Label::create(Func, this); | |
| 4530 _sync(); | |
| 4531 Variable *ValHi, *ValLo; | |
| 4532 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Instr->getArg(2))) { | |
| 4533 const uint64_t Value = C64->getValue(); | |
| 4534 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; | |
| 4535 uint64_t Lower32Bits = Value & 0xFFFFFFFF; | |
| 4536 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); | |
| 4537 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); | |
| 4538 } else { | |
| 4539 auto *Val = llvm::cast<Variable64On32>(Instr->getArg(2)); | |
| 4540 ValLo = legalizeToReg(loOperand(Val)); | |
| 4541 ValHi = legalizeToReg(hiOperand(Val)); | |
| 4542 } | |
| 4543 auto *Dest64 = llvm::cast<Variable64On32>(Dest); | |
| 4544 auto *Base = legalizeToReg(Instr->getArg(1)); | |
| 4545 auto *AddrLo = OperandMIPS32Mem::create( | |
| 4546 Func, IceType_i32, Base, | |
| 4547 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | |
| 4548 auto *AddrHi = OperandMIPS32Mem::create( | |
| 4549 Func, IceType_i32, Base, | |
| 4550 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
| 4551 | |
| 4552 Context.insert(Label1); | |
| 4553 _ll(T1, AddrLo); | |
| 4554 if (Operation == Intrinsics::AtomicExchange) { | |
| 4555 _mov(RegAt, ValLo); | |
| 4556 } else if (Operation == Intrinsics::AtomicAdd) { | |
| 4557 createArithInst(Operation, RegAt, T1, ValLo); | |
| 4558 _sltu(T2, RegAt, T1); | |
| 4559 } else if (Operation == Intrinsics::AtomicSub) { | |
| 4560 createArithInst(Operation, RegAt, T1, ValLo); | |
| 4561 _sltu(T2, T1, ValLo); | |
| 4562 } else { | |
| 4563 createArithInst(Operation, RegAt, T1, ValLo); | |
| 4564 } | |
| 4565 _sc(RegAt, AddrLo); | |
| 4566 _br(NoTarget, NoTarget, RegAt, getZero(), Label1, CondMIPS32::Cond::EQ); | |
| 4567 Context.insert<InstFakeUse>(getZero()); | |
| 4568 _mov(Dest64->getLo(), T1); | |
| 4569 | |
| 4570 Context.insert(Label2); | |
| 4571 _ll(T3, AddrHi); | |
| 4572 if (Operation == Intrinsics::AtomicAdd || | |
| 4573 Operation == Intrinsics::AtomicSub) { | |
| 4574 _addu(RegAt, T2, ValHi); | |
| 4575 createArithInst(Operation, RegAt, T3, RegAt); | |
| 4576 } else if (Operation == Intrinsics::AtomicExchange) { | |
| 4577 _mov(RegAt, ValHi); | |
| 4578 } else { | |
| 4579 createArithInst(Operation, RegAt, T3, ValHi); | |
| 4580 } | |
| 4581 _sc(RegAt, AddrHi); | |
| 4582 _br(NoTarget, NoTarget, RegAt, getZero(), Label2, CondMIPS32::Cond::EQ); | |
| 4583 Context.insert<InstFakeUse>(getZero()); | |
| 4584 _mov(Dest64->getHi(), T3); | |
| 4585 Context.insert<InstFakeUse>(ValLo); | |
| 4586 Context.insert<InstFakeUse>(ValHi); | |
| 4587 _sync(); | |
| 4588 return; | |
| 4589 } | |
| 4590 | |
| 4591 auto *New = legalizeToReg(Instr->getArg(2)); | |
| 4592 auto *ActualAddress = legalizeToReg(Instr->getArg(1)); | |
| 4593 | |
| 4594 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; | |
| 4595 | |
| 4596 if (DestTy == IceType_i8 || DestTy == IceType_i16) { | |
| 4597 const uint32_t ShiftAmount = | |
| 4598 INT32_BITS - (CHAR_BITS * typeWidthInBytes(DestTy)); | |
| 4599 _sync(); | |
| 4600 _addiu(RegAt, getZero(), -4); | |
| 4601 _and(T1, ActualAddress, RegAt); | |
| 4602 _andi(RegAt, ActualAddress, 3); | |
| 4603 _sll(T2, RegAt, 3); | |
| 4604 _ori(RegAt, getZero(), Mask); | |
| 4605 _sllv(T3, RegAt, T2); | |
| 4606 _nor(T4, getZero(), T3); | |
| 4607 _sllv(T5, New, T2); | |
| 4608 Context.insert(Label1); | |
| 4609 _ll(T6, formMemoryOperand(T1, DestTy)); | |
| 4610 if (Operation == Intrinsics::AtomicExchange) { | |
| 4611 _mov(RegAt, T6); | |
| 4612 } else { | |
| 4613 createArithInst(Operation, RegAt, T6, T5); | |
| 4614 _and(RegAt, RegAt, T3); | |
| 4615 } | |
| 4616 _and(T7, T6, T4); | |
| 4617 _or(RegAt, T7, RegAt); | |
| 4618 _sc(RegAt, formMemoryOperand(T1, DestTy)); | |
| 4619 _br(NoTarget, NoTarget, RegAt, getZero(), Label1, CondMIPS32::Cond::EQ); | |
| 4620 Context.insert<InstFakeUse>(getZero()); | |
| 4621 _and(RegAt, T6, T3); | |
| 4622 _srlv(RegAt, RegAt, T2); | |
| 4623 _sll(RegAt, RegAt, ShiftAmount); | |
| 4624 _sra(RegAt, RegAt, ShiftAmount); | |
| 4625 _mov(Dest, RegAt); | |
| 4626 _sync(); | |
| 4627 } else { | |
| 4628 _sync(); | |
| 4629 Context.insert(Label1); | |
| 4630 _ll(T1, formMemoryOperand(ActualAddress, DestTy)); | |
| 4631 if (Operation == Intrinsics::AtomicExchange) { | |
| 4632 _mov(T2, New); | |
| 4633 } else { | |
| 4634 createArithInst(Operation, T2, T1, New); | |
| 4635 } | |
| 4636 _sc(T2, formMemoryOperand(ActualAddress, DestTy)); | |
| 4637 _br(NoTarget, NoTarget, T2, getZero(), Label1, CondMIPS32::Cond::EQ); | |
| 4638 Context.insert<InstFakeUse>(getZero()); | |
| 4639 _mov(Dest, T1); | |
| 4640 _sync(); | |
| 4641 } | |
| 4642 | |
| 4643 Context.insert<InstFakeUse>(Dest); | |
| 4644 Context.insert<InstFakeUse>(New); | |
| 4244 return; | 4645 return; |
| 4245 } | 4646 } |
| 4246 case Intrinsics::AtomicFence: | 4647 case Intrinsics::AtomicFence: |
| 4247 UnimplementedLoweringError(this, Instr); | |
| 4248 return; | |
| 4249 case Intrinsics::AtomicFenceAll: | 4648 case Intrinsics::AtomicFenceAll: |
| 4250 // NOTE: FenceAll should prevent and load/store from being moved across the | 4649 assert(Dest == nullptr); |
| 4251 // fence (both atomic and non-atomic). The InstMIPS32Mfence instruction is | 4650 _sync(); |
| 4252 // currently marked coarsely as "HasSideEffects". | |
| 4253 UnimplementedLoweringError(this, Instr); | |
| 4254 return; | 4651 return; |
| 4255 case Intrinsics::AtomicIsLockFree: { | 4652 case Intrinsics::AtomicIsLockFree: { |
| 4256 UnimplementedLoweringError(this, Instr); | 4653 Operand *ByteSize = Instr->getArg(0); |
| 4257 return; | 4654 auto *CI = llvm::dyn_cast<ConstantInteger32>(ByteSize); |
| 4258 } | 4655 auto *T = I32Reg(); |
| 4259 case Intrinsics::AtomicLoad: { | 4656 if (CI == nullptr) { |
| 4260 UnimplementedLoweringError(this, Instr); | 4657 // The PNaCl ABI requires the byte size to be a compile-time constant. |
| 4261 return; | 4658 Func->setError("AtomicIsLockFree byte size should be compile-time const"); |
| 4262 } | 4659 return; |
| 4263 case Intrinsics::AtomicRMW: | 4660 } |
| 4264 UnimplementedLoweringError(this, Instr); | 4661 static constexpr int32_t NotLockFree = 0; |
| 4265 return; | 4662 static constexpr int32_t LockFree = 1; |
| 4266 case Intrinsics::AtomicStore: { | 4663 int32_t Result = NotLockFree; |
| 4267 UnimplementedLoweringError(this, Instr); | 4664 switch (CI->getValue()) { |
| 4665 case 1: | |
| 4666 case 2: | |
| 4667 case 4: | |
| 4668 case 8: | |
| 4669 Result = LockFree; | |
| 4670 break; | |
| 4671 } | |
| 4672 _addiu(T, getZero(), Result); | |
| 4673 _mov(Dest, T); | |
| 4268 return; | 4674 return; |
| 4269 } | 4675 } |
| 4270 case Intrinsics::Bswap: { | 4676 case Intrinsics::Bswap: { |
| 4271 auto *Src = Instr->getArg(0); | 4677 auto *Src = Instr->getArg(0); |
| 4272 const Type SrcTy = Src->getType(); | 4678 const Type SrcTy = Src->getType(); |
| 4273 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || | 4679 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || |
| 4274 SrcTy == IceType_i64); | 4680 SrcTy == IceType_i64); |
| 4275 switch (SrcTy) { | 4681 switch (SrcTy) { |
| 4276 case IceType_i16: { | 4682 case IceType_i16: { |
| 4277 auto *T1 = I32Reg(); | 4683 auto *T1 = I32Reg(); |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4928 break; | 5334 break; |
| 4929 case IceType_f32: | 5335 case IceType_f32: |
| 4930 _movn_s(SrcFR, SrcTR, ConditionR); | 5336 _movn_s(SrcFR, SrcTR, ConditionR); |
| 4931 _mov(Dest, SrcFR); | 5337 _mov(Dest, SrcFR); |
| 4932 break; | 5338 break; |
| 4933 case IceType_f64: | 5339 case IceType_f64: |
| 4934 _movn_d(SrcFR, SrcTR, ConditionR); | 5340 _movn_d(SrcFR, SrcTR, ConditionR); |
| 4935 _mov(Dest, SrcFR); | 5341 _mov(Dest, SrcFR); |
| 4936 break; | 5342 break; |
| 4937 default: | 5343 default: |
| 4938 UnimplementedLoweringError(this, Instr); | 5344 llvm::report_fatal_error("Select: Invalid type."); |
| 4939 } | 5345 } |
| 4940 } | 5346 } |
| 4941 | 5347 |
| 4942 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { | 5348 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { |
| 4943 UnimplementedLoweringError(this, Instr); | 5349 UnimplementedLoweringError(this, Instr); |
| 4944 } | 5350 } |
| 4945 | 5351 |
| 4946 void TargetMIPS32::lowerStore(const InstStore *Instr) { | 5352 void TargetMIPS32::lowerStore(const InstStore *Instr) { |
| 4947 Operand *Value = Instr->getData(); | 5353 Operand *Value = Instr->getData(); |
| 4948 Operand *Addr = Instr->getAddr(); | 5354 Operand *Addr = Instr->getAddr(); |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5290 Variable *TReg = makeReg(Ty, RegNum); | 5696 Variable *TReg = makeReg(Ty, RegNum); |
| 5291 _lui(TReg, C, RO_Hi); | 5697 _lui(TReg, C, RO_Hi); |
| 5292 _addiu(Reg, TReg, C, RO_Lo); | 5698 _addiu(Reg, TReg, C, RO_Lo); |
| 5293 return Reg; | 5699 return Reg; |
| 5294 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | 5700 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
| 5295 const uint32_t Value = C32->getValue(); | 5701 const uint32_t Value = C32->getValue(); |
| 5296 // Use addiu if the immediate is a 16bit value. Otherwise load it | 5702 // Use addiu if the immediate is a 16bit value. Otherwise load it |
| 5297 // using a lui-ori instructions. | 5703 // using a lui-ori instructions. |
| 5298 Variable *Reg = makeReg(Ty, RegNum); | 5704 Variable *Reg = makeReg(Ty, RegNum); |
| 5299 if (isInt<16>(int32_t(Value))) { | 5705 if (isInt<16>(int32_t(Value))) { |
| 5300 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); | 5706 Variable *Zero = makeReg(Ty, RegMIPS32::Reg_ZERO); |
| 5301 Context.insert<InstFakeDef>(Zero); | 5707 Context.insert<InstFakeDef>(Zero); |
| 5302 _addiu(Reg, Zero, Value); | 5708 _addiu(Reg, Zero, Value); |
| 5303 } else { | 5709 } else { |
| 5304 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | 5710 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
| 5305 uint32_t LowerBits = Value & 0xFFFF; | 5711 uint32_t LowerBits = Value & 0xFFFF; |
| 5306 Variable *TReg = makeReg(Ty, RegNum); | 5712 Variable *TReg = makeReg(Ty, RegNum); |
| 5307 if (LowerBits) { | 5713 if (LowerBits) { |
| 5308 _lui(TReg, Ctx->getConstantInt32(UpperBits)); | 5714 _lui(TReg, Ctx->getConstantInt32(UpperBits)); |
| 5309 _ori(Reg, TReg, LowerBits); | 5715 _ori(Reg, TReg, LowerBits); |
| 5310 } else { | 5716 } else { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5538 | 5944 |
| 5539 InstMIPS32Call *TargetMIPS32::Sandboxer::jal(Variable *ReturnReg, | 5945 InstMIPS32Call *TargetMIPS32::Sandboxer::jal(Variable *ReturnReg, |
| 5540 Operand *CallTarget) { | 5946 Operand *CallTarget) { |
| 5541 if (Target->NeedSandboxing) | 5947 if (Target->NeedSandboxing) |
| 5542 createAutoBundle(); | 5948 createAutoBundle(); |
| 5543 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget); | 5949 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget); |
| 5544 } | 5950 } |
| 5545 | 5951 |
| 5546 } // end of namespace MIPS32 | 5952 } // end of namespace MIPS32 |
| 5547 } // end of namespace Ice | 5953 } // end of namespace Ice |
| OLD | NEW |