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

Side by Side Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2504253002: [Subzero][MIPS] Implements atomic intrinsics for MIPS32 (Closed)
Patch Set: 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
« src/IceInstMIPS32.h ('K') | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(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
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
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
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
OLDNEW
« src/IceInstMIPS32.h ('K') | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698