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

Side by Side Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2504253002: [Subzero][MIPS] Implements atomic intrinsics for MIPS32 (Closed)
Patch Set: Included lit tests and formated source code Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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(Intrinsics::AtomicRMWOperation Operation,
4257 Variable *Dest, Variable *Src0,
4258 Variable *Src1) {
4259 switch (Operation) {
4260 default:
4261 llvm::report_fatal_error("Unknown AtomicRMW operation");
4262 case Intrinsics::AtomicExchange:
4263 llvm::report_fatal_error("Can't handle Atomic xchg operation");
4264 case Intrinsics::AtomicAdd:
4265 _addu(Dest, Src0, Src1);
4266 break;
4267 case Intrinsics::AtomicAnd:
4268 _and(Dest, Src0, Src1);
4269 break;
4270 case Intrinsics::AtomicSub:
4271 _subu(Dest, Src0, Src1);
4272 break;
4273 case Intrinsics::AtomicOr:
4274 _or(Dest, Src0, Src1);
4275 break;
4276 case Intrinsics::AtomicXor:
4277 _xor(Dest, Src0, Src1);
4278 break;
4279 }
4280 }
4281
4238 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { 4282 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
4239 Variable *Dest = Instr->getDest(); 4283 Variable *Dest = Instr->getDest();
4240 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType(); 4284 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType();
4241 switch (Instr->getIntrinsicInfo().ID) { 4285
4286 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID;
4287 switch (ID) {
4288 case Intrinsics::AtomicLoad: {
4289 assert(isScalarIntegerType(DestTy));
4290 // We require the memory address to be naturally aligned. Given that is the
4291 // case, then normal loads are atomic.
4292 if (!Intrinsics::isMemoryOrderValid(
4293 ID, getConstantMemoryOrder(Instr->getArg(1)))) {
4294 Func->setError("Unexpected memory ordering for AtomicLoad");
4295 return;
4296 }
4297 if (DestTy == IceType_i64) {
4298 auto *Base = legalizeToReg(Instr->getArg(0));
4299 auto *AddrLo = OperandMIPS32Mem::create(
4300 Func, IceType_i32, Base,
4301 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)));
4302 auto *AddrHi = OperandMIPS32Mem::create(
4303 Func, IceType_i32, Base,
4304 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4)));
4305 auto *T_Lo = makeReg(IceType_i32);
4306 auto *T_Hi = makeReg(IceType_i32);
4307 auto *Dest64 = llvm::cast<Variable64On32>(Dest);
4308 lowerLoad(InstLoad::create(Func, T_Lo, AddrLo, IceType_i32));
4309 lowerLoad(InstLoad::create(Func, T_Hi, AddrHi, IceType_i32));
4310 _sync();
4311 _mov(Dest64->getLo(), T_Lo);
4312 _mov(Dest64->getHi(), T_Hi);
4313 // Adding a fake-use of T to ensure the atomic load is not removed if Dest
4314 // is unused.
4315 Context.insert<InstFakeUse>(T_Lo);
4316 Context.insert<InstFakeUse>(T_Hi);
4317 } else {
4318 auto *T = makeReg(DestTy);
4319 lowerLoad(InstLoad::create(Func, T,
4320 formMemoryOperand(Instr->getArg(0), DestTy)));
4321 _sync();
4322 _mov(Dest, T);
4323 // Adding a fake-use of T to ensure the atomic load is not removed if Dest
4324 // is unused.
4325 Context.insert<InstFakeUse>(T);
4326 }
4327 return;
4328 }
4329 case Intrinsics::AtomicStore: {
4330 // We require the memory address to be naturally aligned. Given that is the
4331 // case, then normal stores are atomic.
4332 if (!Intrinsics::isMemoryOrderValid(
4333 ID, getConstantMemoryOrder(Instr->getArg(2)))) {
4334 Func->setError("Unexpected memory ordering for AtomicStore");
4335 return;
4336 }
4337 auto *Val = Instr->getArg(0);
4338 auto Ty = Val->getType();
4339 if (Ty == IceType_i64) {
4340 Variable *ValHi, *ValLo;
4341 _sync();
4342 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Val)) {
4343 const uint64_t Value = C64->getValue();
4344 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF;
4345 uint64_t Lower32Bits = Value & 0xFFFFFFFF;
4346 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits));
4347 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits));
4348 } else {
4349 auto *Val64 = llvm::cast<Variable64On32>(Val);
4350 ValLo = legalizeToReg(loOperand(Val64));
4351 ValHi = legalizeToReg(hiOperand(Val64));
4352 }
4353
4354 auto *Base = legalizeToReg(Instr->getArg(1));
4355 auto *AddrLo = OperandMIPS32Mem::create(
4356 Func, IceType_i32, Base,
4357 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)));
4358 auto *AddrHi = OperandMIPS32Mem::create(
4359 Func, IceType_i32, Base,
4360 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4)));
4361 lowerStore(InstStore::create(Func, ValLo, AddrLo, IceType_i32));
4362 lowerStore(InstStore::create(Func, ValHi, AddrHi, IceType_i32));
4363 _sync();
4364 } else {
4365 _sync();
4366 auto *Val = legalizeToReg(Instr->getArg(0));
4367 lowerStore(InstStore::create(
4368 Func, Val, formMemoryOperand(Instr->getArg(1), DestTy)));
4369 _sync();
4370 }
4371 return;
4372 }
4242 case Intrinsics::AtomicCmpxchg: { 4373 case Intrinsics::AtomicCmpxchg: {
4243 UnimplementedLoweringError(this, Instr); 4374 assert(isScalarIntegerType(DestTy));
4375 // We require the memory address to be naturally aligned. Given that is the
4376 // case, then normal loads are atomic.
4377 if (!Intrinsics::isMemoryOrderValid(
4378 ID, getConstantMemoryOrder(Instr->getArg(3)),
4379 getConstantMemoryOrder(Instr->getArg(4)))) {
4380 Func->setError("Unexpected memory ordering for AtomicCmpxchg");
4381 return;
4382 }
4383
4384 InstMIPS32Label *Exit = InstMIPS32Label::create(Func, this);
4385 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this);
4386 constexpr CfgNode *NoTarget = nullptr;
4387 auto *New = Instr->getArg(2);
4388 auto *Expected = Instr->getArg(1);
4389 auto *ActualAddress = Instr->getArg(0);
4390
4391 if (DestTy == IceType_i64) {
4392 InstMIPS32Label *Retry1 = InstMIPS32Label::create(Func, this);
4393 auto *T1 = I32Reg();
4394 auto *T2 = I32Reg();
4395 _sync();
4396 Variable *ValHi, *ValLo, *ExpectedLo, *ExpectedHi;
4397 if (llvm::isa<ConstantUndef>(Expected)) {
4398 ExpectedLo = legalizeToReg(Ctx->getConstantZero(IceType_i32));
4399 ExpectedHi = legalizeToReg(Ctx->getConstantZero(IceType_i32));
4400 } else {
4401 auto *Expected64 = llvm::cast<Variable64On32>(Expected);
4402 ExpectedLo = legalizeToReg(loOperand(Expected64));
4403 ExpectedHi = legalizeToReg(hiOperand(Expected64));
4404 }
4405 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(New)) {
4406 const uint64_t Value = C64->getValue();
4407 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF;
4408 uint64_t Lower32Bits = Value & 0xFFFFFFFF;
4409 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits));
4410 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits));
4411 } else {
4412 auto *Val = llvm::cast<Variable64On32>(New);
4413 ValLo = legalizeToReg(loOperand(Val));
4414 ValHi = legalizeToReg(hiOperand(Val));
4415 }
4416 auto *Dest64 = llvm::cast<Variable64On32>(Dest);
4417 auto *BaseR = legalizeToReg(ActualAddress);
4418 auto *AddrLo = OperandMIPS32Mem::create(
4419 Func, IceType_i32, BaseR,
4420 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)));
4421 auto *AddrHi = OperandMIPS32Mem::create(
4422 Func, IceType_i32, BaseR,
4423 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4)));
4424 Context.insert(Retry);
4425 _ll(T1, AddrLo);
4426 _br(NoTarget, NoTarget, T1, ExpectedLo, Exit, CondMIPS32::Cond::NE);
4427 _sc(ValLo, AddrLo);
4428 _br(NoTarget, NoTarget, ValLo, getZero(), Retry, CondMIPS32::Cond::EQ);
4429 _mov(Dest64->getLo(), T1);
4430 Context.insert(Retry1);
4431 _ll(T2, AddrHi);
4432 _br(NoTarget, NoTarget, T2, ExpectedHi, Exit, CondMIPS32::Cond::NE);
4433 _sc(ValHi, AddrHi);
4434 _br(NoTarget, NoTarget, ValHi, getZero(), Retry1, CondMIPS32::Cond::EQ);
4435 _mov(Dest64->getHi(), T2);
4436 Context.insert<InstFakeUse>(getZero());
4437 Context.insert(Exit);
4438 _sync();
4439 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) {
4440 auto *NewR = legalizeToReg(New);
4441 auto *ExpectedR = legalizeToReg(Expected);
4442 auto *ActualAddressR = legalizeToReg(ActualAddress);
4443 const uint32_t ShiftAmount =
4444 (INT32_BITS - CHAR_BITS * typeWidthInBytes(DestTy));
4445 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1;
4446 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT);
4447 auto *T1 = I32Reg();
4448 auto *T2 = I32Reg();
4449 auto *T3 = I32Reg();
4450 auto *T4 = I32Reg();
4451 auto *T5 = I32Reg();
4452 auto *T6 = I32Reg();
4453 auto *T7 = I32Reg();
4454 auto *T8 = I32Reg();
4455 auto *T9 = I32Reg();
4456 _sync();
4457 _addiu(RegAt, getZero(), -4);
4458 _and(T1, ActualAddressR, RegAt);
4459 _andi(RegAt, ActualAddressR, 3);
4460 _sll(T2, RegAt, 3);
4461 _ori(RegAt, getZero(), Mask);
4462 _sllv(T3, RegAt, T2);
4463 _nor(T4, getZero(), T3);
4464 _andi(RegAt, ExpectedR, Mask);
4465 _sllv(T5, RegAt, T2);
4466 _andi(RegAt, NewR, Mask);
4467 _sllv(T6, RegAt, T2);
4468 Context.insert(Retry);
4469 _ll(T7, formMemoryOperand(T1, DestTy));
4470 _and(T8, T7, T3);
4471 _br(NoTarget, NoTarget, T8, T5, Exit, CondMIPS32::Cond::NE);
4472 _and(RegAt, T7, T4);
4473 _or(T9, RegAt, T6);
4474 _sc(T9, formMemoryOperand(T1, DestTy));
4475 _br(NoTarget, NoTarget, getZero(), T9, Retry, CondMIPS32::Cond::EQ);
4476 Context.insert<InstFakeUse>(getZero());
4477 Context.insert(Exit);
4478 _srlv(RegAt, T8, T2);
4479 _sll(RegAt, RegAt, ShiftAmount);
4480 _sra(RegAt, RegAt, ShiftAmount);
4481 _mov(Dest, RegAt);
4482 _sync();
4483 Context.insert<InstFakeUse>(ExpectedR);
4484 Context.insert<InstFakeUse>(NewR);
4485 } else {
4486 auto *T1 = I32Reg();
4487 auto *NewR = legalizeToReg(New);
4488 auto *ExpectedR = legalizeToReg(Expected);
4489 auto *ActualAddressR = legalizeToReg(ActualAddress);
4490 _sync();
4491 Context.insert(Retry);
4492 _ll(T1, formMemoryOperand(ActualAddressR, DestTy));
4493 _br(NoTarget, NoTarget, T1, ExpectedR, Exit, CondMIPS32::Cond::NE);
4494 _sc(NewR, formMemoryOperand(ActualAddressR, DestTy));
4495 _br(NoTarget, NoTarget, NewR, getZero(), Retry, CondMIPS32::Cond::EQ);
4496 Context.insert<InstFakeUse>(getZero());
4497 Context.insert(Exit);
4498 _mov(Dest, T1);
4499 _sync();
4500 Context.insert<InstFakeUse>(ExpectedR);
4501 Context.insert<InstFakeUse>(NewR);
4502 }
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 AtomicRMW");
4512 return;
4513 }
4514
4515 constexpr CfgNode *NoTarget = nullptr;
4516 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this);
4517 auto Operation = static_cast<Intrinsics::AtomicRMWOperation>(
4518 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue());
4519 auto *New = Instr->getArg(2);
4520 auto *ActualAddress = Instr->getArg(1);
4521
4522 if (DestTy == IceType_i64) {
4523 InstMIPS32Label *Retry1 = InstMIPS32Label::create(Func, this);
4524 _sync();
4525 Variable *ValHi, *ValLo;
4526 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(New)) {
4527 const uint64_t Value = C64->getValue();
4528 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF;
4529 uint64_t Lower32Bits = Value & 0xFFFFFFFF;
4530 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits));
4531 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits));
4532 } else {
4533 auto *Val = llvm::cast<Variable64On32>(New);
4534 ValLo = legalizeToReg(loOperand(Val));
4535 ValHi = legalizeToReg(hiOperand(Val));
4536 }
4537 auto *Dest64 = llvm::cast<Variable64On32>(Dest);
4538 auto *BaseR = legalizeToReg(ActualAddress);
4539 auto *AddrLo = OperandMIPS32Mem::create(
4540 Func, IceType_i32, BaseR,
4541 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)));
4542 auto *AddrHi = OperandMIPS32Mem::create(
4543 Func, IceType_i32, BaseR,
4544 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4)));
4545 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT);
4546 auto *T1 = I32Reg();
4547 auto *T2 = I32Reg();
4548 auto *T3 = I32Reg();
4549 Context.insert(Retry);
4550 _ll(T1, AddrLo);
4551 if (Operation == Intrinsics::AtomicExchange) {
4552 _mov(RegAt, ValLo);
4553 } else if (Operation == Intrinsics::AtomicAdd) {
4554 createArithInst(Operation, RegAt, T1, ValLo);
4555 _sltu(T2, RegAt, T1);
4556 } else if (Operation == Intrinsics::AtomicSub) {
4557 createArithInst(Operation, RegAt, T1, ValLo);
4558 _sltu(T2, T1, ValLo);
4559 } else {
4560 createArithInst(Operation, RegAt, T1, ValLo);
4561 }
4562 _sc(RegAt, AddrLo);
4563 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ);
4564 Context.insert<InstFakeUse>(getZero());
4565 _mov(Dest64->getLo(), T1);
4566 Context.insert(Retry1);
4567 _ll(T3, AddrHi);
4568 if (Operation == Intrinsics::AtomicAdd ||
4569 Operation == Intrinsics::AtomicSub) {
4570 _addu(RegAt, T2, ValHi);
4571 createArithInst(Operation, RegAt, T3, RegAt);
4572 } else if (Operation == Intrinsics::AtomicExchange) {
4573 _mov(RegAt, ValHi);
4574 } else {
4575 createArithInst(Operation, RegAt, T3, ValHi);
4576 }
4577 _sc(RegAt, AddrHi);
4578 _br(NoTarget, NoTarget, RegAt, getZero(), Retry1, CondMIPS32::Cond::EQ);
4579 Context.insert<InstFakeUse>(getZero());
4580 _mov(Dest64->getHi(), T3);
4581 Context.insert<InstFakeUse>(ValLo);
4582 Context.insert<InstFakeUse>(ValHi);
4583 _sync();
4584 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) {
4585 const uint32_t ShiftAmount =
4586 INT32_BITS - (CHAR_BITS * typeWidthInBytes(DestTy));
4587 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1;
4588 auto *NewR = legalizeToReg(New);
4589 auto *ActualAddressR = legalizeToReg(ActualAddress);
4590 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT);
4591 auto *T1 = I32Reg();
4592 auto *T2 = I32Reg();
4593 auto *T3 = I32Reg();
4594 auto *T4 = I32Reg();
4595 auto *T5 = I32Reg();
4596 auto *T6 = I32Reg();
4597 auto *T7 = I32Reg();
4598 _sync();
4599 _addiu(RegAt, getZero(), -4);
4600 _and(T1, ActualAddressR, RegAt);
4601 _andi(RegAt, ActualAddressR, 3);
4602 _sll(T2, RegAt, 3);
4603 _ori(RegAt, getZero(), Mask);
4604 _sllv(T3, RegAt, T2);
4605 _nor(T4, getZero(), T3);
4606 _sllv(T5, NewR, T2);
4607 Context.insert(Retry);
4608 _ll(T6, formMemoryOperand(T1, DestTy));
4609 if (Operation != Intrinsics::AtomicExchange) {
4610 createArithInst(Operation, RegAt, T6, T5);
4611 _and(RegAt, RegAt, T3);
4612 }
4613 _and(T7, T6, T4);
4614 if (Operation == Intrinsics::AtomicExchange) {
4615 _or(RegAt, T7, T5);
4616 } else {
4617 _or(RegAt, T7, RegAt);
4618 }
4619 _sc(RegAt, formMemoryOperand(T1, DestTy));
4620 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ);
4621 Context.insert<InstFakeUse>(getZero());
4622 _and(RegAt, T6, T3);
4623 _srlv(RegAt, RegAt, T2);
4624 _sll(RegAt, RegAt, ShiftAmount);
4625 _sra(RegAt, RegAt, ShiftAmount);
4626 _mov(Dest, RegAt);
4627 _sync();
4628 Context.insert<InstFakeUse>(NewR);
4629 Context.insert<InstFakeUse>(Dest);
4630 } else {
4631 auto *T1 = I32Reg();
4632 auto *T2 = I32Reg();
4633 auto *NewR = legalizeToReg(New);
4634 auto *ActualAddressR = legalizeToReg(ActualAddress);
4635 _sync();
4636 Context.insert(Retry);
4637 _ll(T1, formMemoryOperand(ActualAddressR, DestTy));
4638 if (Operation == Intrinsics::AtomicExchange) {
4639 _mov(T2, NewR);
4640 } else {
4641 createArithInst(Operation, T2, T1, NewR);
4642 }
4643 _sc(T2, formMemoryOperand(ActualAddressR, DestTy));
4644 _br(NoTarget, NoTarget, T2, getZero(), Retry, CondMIPS32::Cond::EQ);
4645 Context.insert<InstFakeUse>(getZero());
4646 _mov(Dest, T1);
4647 _sync();
4648 Context.insert<InstFakeUse>(NewR);
4649 Context.insert<InstFakeUse>(Dest);
4650 }
4244 return; 4651 return;
4245 } 4652 }
4246 case Intrinsics::AtomicFence: 4653 case Intrinsics::AtomicFence:
4247 UnimplementedLoweringError(this, Instr);
4248 return;
4249 case Intrinsics::AtomicFenceAll: 4654 case Intrinsics::AtomicFenceAll:
4250 // NOTE: FenceAll should prevent and load/store from being moved across the 4655 assert(Dest == nullptr);
4251 // fence (both atomic and non-atomic). The InstMIPS32Mfence instruction is 4656 _sync();
4252 // currently marked coarsely as "HasSideEffects".
4253 UnimplementedLoweringError(this, Instr);
4254 return; 4657 return;
4255 case Intrinsics::AtomicIsLockFree: { 4658 case Intrinsics::AtomicIsLockFree: {
4256 UnimplementedLoweringError(this, Instr); 4659 Operand *ByteSize = Instr->getArg(0);
4257 return; 4660 auto *CI = llvm::dyn_cast<ConstantInteger32>(ByteSize);
4258 } 4661 auto *T = I32Reg();
4259 case Intrinsics::AtomicLoad: { 4662 if (CI == nullptr) {
4260 UnimplementedLoweringError(this, Instr); 4663 // The PNaCl ABI requires the byte size to be a compile-time constant.
4261 return; 4664 Func->setError("AtomicIsLockFree byte size should be compile-time const");
4262 } 4665 return;
4263 case Intrinsics::AtomicRMW: 4666 }
4264 UnimplementedLoweringError(this, Instr); 4667 static constexpr int32_t NotLockFree = 0;
4265 return; 4668 static constexpr int32_t LockFree = 1;
4266 case Intrinsics::AtomicStore: { 4669 int32_t Result = NotLockFree;
4267 UnimplementedLoweringError(this, Instr); 4670 switch (CI->getValue()) {
4671 case 1:
4672 case 2:
4673 case 4:
4674 case 8:
4675 Result = LockFree;
4676 break;
4677 }
4678 _addiu(T, getZero(), Result);
4679 _mov(Dest, T);
4268 return; 4680 return;
4269 } 4681 }
4270 case Intrinsics::Bswap: { 4682 case Intrinsics::Bswap: {
4271 auto *Src = Instr->getArg(0); 4683 auto *Src = Instr->getArg(0);
4272 const Type SrcTy = Src->getType(); 4684 const Type SrcTy = Src->getType();
4273 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || 4685 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 ||
4274 SrcTy == IceType_i64); 4686 SrcTy == IceType_i64);
4275 switch (SrcTy) { 4687 switch (SrcTy) {
4276 case IceType_i16: { 4688 case IceType_i16: {
4277 auto *T1 = I32Reg(); 4689 auto *T1 = I32Reg();
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
4928 break; 5340 break;
4929 case IceType_f32: 5341 case IceType_f32:
4930 _movn_s(SrcFR, SrcTR, ConditionR); 5342 _movn_s(SrcFR, SrcTR, ConditionR);
4931 _mov(Dest, SrcFR); 5343 _mov(Dest, SrcFR);
4932 break; 5344 break;
4933 case IceType_f64: 5345 case IceType_f64:
4934 _movn_d(SrcFR, SrcTR, ConditionR); 5346 _movn_d(SrcFR, SrcTR, ConditionR);
4935 _mov(Dest, SrcFR); 5347 _mov(Dest, SrcFR);
4936 break; 5348 break;
4937 default: 5349 default:
4938 UnimplementedLoweringError(this, Instr); 5350 llvm::report_fatal_error("Select: Invalid type.");
4939 } 5351 }
4940 } 5352 }
4941 5353
4942 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { 5354 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) {
4943 UnimplementedLoweringError(this, Instr); 5355 UnimplementedLoweringError(this, Instr);
4944 } 5356 }
4945 5357
4946 void TargetMIPS32::lowerStore(const InstStore *Instr) { 5358 void TargetMIPS32::lowerStore(const InstStore *Instr) {
4947 Operand *Value = Instr->getData(); 5359 Operand *Value = Instr->getData();
4948 Operand *Addr = Instr->getAddr(); 5360 Operand *Addr = Instr->getAddr();
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
5290 Variable *TReg = makeReg(Ty, RegNum); 5702 Variable *TReg = makeReg(Ty, RegNum);
5291 _lui(TReg, C, RO_Hi); 5703 _lui(TReg, C, RO_Hi);
5292 _addiu(Reg, TReg, C, RO_Lo); 5704 _addiu(Reg, TReg, C, RO_Lo);
5293 return Reg; 5705 return Reg;
5294 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { 5706 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) {
5295 const uint32_t Value = C32->getValue(); 5707 const uint32_t Value = C32->getValue();
5296 // Use addiu if the immediate is a 16bit value. Otherwise load it 5708 // Use addiu if the immediate is a 16bit value. Otherwise load it
5297 // using a lui-ori instructions. 5709 // using a lui-ori instructions.
5298 Variable *Reg = makeReg(Ty, RegNum); 5710 Variable *Reg = makeReg(Ty, RegNum);
5299 if (isInt<16>(int32_t(Value))) { 5711 if (isInt<16>(int32_t(Value))) {
5300 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); 5712 Variable *Zero = makeReg(Ty, RegMIPS32::Reg_ZERO);
5301 Context.insert<InstFakeDef>(Zero); 5713 Context.insert<InstFakeDef>(Zero);
5302 _addiu(Reg, Zero, Value); 5714 _addiu(Reg, Zero, Value);
5303 } else { 5715 } else {
5304 uint32_t UpperBits = (Value >> 16) & 0xFFFF; 5716 uint32_t UpperBits = (Value >> 16) & 0xFFFF;
5305 uint32_t LowerBits = Value & 0xFFFF; 5717 uint32_t LowerBits = Value & 0xFFFF;
5306 Variable *TReg = makeReg(Ty, RegNum); 5718 Variable *TReg = makeReg(Ty, RegNum);
5307 if (LowerBits) { 5719 if (LowerBits) {
5308 _lui(TReg, Ctx->getConstantInt32(UpperBits)); 5720 _lui(TReg, Ctx->getConstantInt32(UpperBits));
5309 _ori(Reg, TReg, LowerBits); 5721 _ori(Reg, TReg, LowerBits);
5310 } else { 5722 } else {
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
5538 5950
5539 InstMIPS32Call *TargetMIPS32::Sandboxer::jal(Variable *ReturnReg, 5951 InstMIPS32Call *TargetMIPS32::Sandboxer::jal(Variable *ReturnReg,
5540 Operand *CallTarget) { 5952 Operand *CallTarget) {
5541 if (Target->NeedSandboxing) 5953 if (Target->NeedSandboxing)
5542 createAutoBundle(); 5954 createAutoBundle();
5543 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget); 5955 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget);
5544 } 5956 }
5545 5957
5546 } // end of namespace MIPS32 5958 } // end of namespace MIPS32
5547 } // end of namespace Ice 5959 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698