Chromium Code Reviews| Index: src/IceTargetLoweringMIPS32.cpp |
| diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp |
| index d8cd65c2973ac502ca2cd18f8c99e000754c1f23..e19e4dcef283ad1a2aa94141d794f7d45d6519cc 100644 |
| --- a/src/IceTargetLoweringMIPS32.cpp |
| +++ b/src/IceTargetLoweringMIPS32.cpp |
| @@ -571,13 +571,101 @@ void TargetMIPS32::lowerAlloca(const InstAlloca *Inst) { |
| UnimplementedLoweringError(this, Inst); |
| } |
| +void TargetMIPS32::lowerInt64Arithmetic(const InstArithmetic *Inst, |
| + Variable *Dest, Operand *Src0, |
| + Operand *Src1) { |
| + InstArithmetic::OpKind Op = Inst->getOp(); |
| + switch (Op) { |
| + case InstArithmetic::Add: |
| + case InstArithmetic::And: |
| + case InstArithmetic::Or: |
| + case InstArithmetic::Sub: |
| + case InstArithmetic::Xor: |
| + break; |
| + default: |
| + UnimplementedLoweringError(this, Inst); |
| + return; |
| + } |
| + auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| + auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| + Variable *Src0LoR = legalizeToReg(loOperand(Src0), Legal_Reg); |
|
Jim Stichnoth
2016/01/31 05:29:47
Remove the Legal_Reg optional argument.
That argu
rkotlerimgtec
2016/01/31 21:06:12
Done.
|
| + Variable *Src1LoR = legalizeToReg(loOperand(Src1), Legal_Reg); |
| + Variable *Src0HiR = legalizeToReg(hiOperand(Src0), Legal_Reg); |
| + Variable *Src1HiR = legalizeToReg(hiOperand(Src1), Legal_Reg); |
| + |
| + switch (Op) { |
| + case InstArithmetic::_num: |
| + llvm::report_fatal_error("Unknown arithmetic operator"); |
| + return; |
| + case InstArithmetic::Add: { |
| + Variable *T_Carry = makeReg(IceType_i32); |
| + Variable *T_Lo = makeReg(IceType_i32); |
| + Variable *T_Hi = makeReg(IceType_i32); |
| + Variable *T_Hi2 = makeReg(IceType_i32); |
|
Jim Stichnoth
2016/01/31 05:29:47
You can remove this T_Hi2 and reuse T_Hi instead.
rkotlerimgtec
2016/01/31 21:06:12
I would rather address this issue in another patch
|
| + _addu(T_Lo, Src0LoR, Src1LoR); |
| + _mov(DestLo, T_Lo); |
| + _sltu(T_Carry, DestLo, Src0LoR); |
|
Jim Stichnoth
2016/01/31 05:29:47
Use T_Lo instead of DestLo here, since DestLo isn'
rkotlerimgtec
2016/01/31 21:06:12
Done.
|
| + _addu(T_Hi, T_Carry, Src0HiR); |
| + _addu(T_Hi2, Src1HiR, T_Hi); |
| + _mov(DestHi, T_Hi2); |
| + return; |
| + } |
| + case InstArithmetic::And: { |
| + Variable *T_Lo = makeReg(IceType_i32); |
| + Variable *T_Hi = makeReg(IceType_i32); |
| + _and(T_Lo, Src0LoR, Src1LoR); |
| + _mov(DestLo, T_Lo); |
| + _and(T_Hi, Src0HiR, Src1HiR); |
| + _mov(DestHi, T_Hi); |
| + return; |
| + } |
| + case InstArithmetic::Sub: { |
| + Variable *T_Borrow = makeReg(IceType_i32); |
| + Variable *T_Lo = makeReg(IceType_i32); |
| + Variable *T_Hi = makeReg(IceType_i32); |
| + Variable *T_Hi2 = makeReg(IceType_i32); |
| + _subu(T_Lo, Src0LoR, Src1LoR); |
| + _mov(DestLo, T_Lo); |
| + _sltu(T_Borrow, Src0LoR, Src1LoR); |
| + _addu(T_Hi, T_Borrow, Src1HiR); |
| + _subu(T_Hi2, Src0HiR, T_Hi); |
| + _mov(DestHi, T_Hi2); |
| + return; |
| + } |
| + case InstArithmetic::Or: { |
| + Variable *T_Lo = makeReg(IceType_i32); |
| + Variable *T_Hi = makeReg(IceType_i32); |
| + _or(T_Lo, Src0LoR, Src1LoR); |
| + _mov(DestLo, T_Lo); |
| + _or(T_Hi, Src0HiR, Src1HiR); |
| + _mov(DestHi, T_Hi); |
| + return; |
| + } |
| + case InstArithmetic::Xor: { |
| + Variable *T_Lo = makeReg(IceType_i32); |
| + Variable *T_Hi = makeReg(IceType_i32); |
| + _xor(T_Lo, Src0LoR, Src1LoR); |
| + _mov(DestLo, T_Lo); |
| + _xor(T_Hi, Src0HiR, Src1HiR); |
| + _mov(DestHi, T_Hi); |
| + return; |
| + } |
| + default: |
| + UnimplementedLoweringError(this, Inst); |
| + return; |
| + } |
| +} |
| + |
| void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { |
| Variable *Dest = Inst->getDest(); |
| // We need to signal all the UnimplementedLoweringError errors before any |
| // legalization into new variables, otherwise Om1 register allocation may fail |
| // when it sees variables that are defined but not used. |
| - if (Dest->getType() == IceType_i64) { |
| - UnimplementedLoweringError(this, Inst); |
| + Type DestTy = Dest->getType(); |
| + Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| + Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| + if (DestTy == IceType_i64) { |
| + lowerInt64Arithmetic(Inst, Inst->getDest(), Src0, Src1); |
| return; |
| } |
| if (isVectorType(Dest->getType())) { |
| @@ -606,8 +694,6 @@ void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { |
| // At this point Dest->getType() is non-i64 scalar |
| Variable *T = makeReg(Dest->getType()); |
| - Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| - Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| Variable *Src0R = legalizeToReg(Src0); |
| Variable *Src1R = legalizeToReg(Src1); |
| @@ -664,6 +750,7 @@ void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { |
| case InstArithmetic::Frem: |
| break; |
| } |
| + UnimplementedLoweringError(this, Inst); |
| } |
| void TargetMIPS32::lowerAssign(const InstAssign *Inst) { |
| @@ -708,8 +795,93 @@ void TargetMIPS32::lowerBr(const InstBr *Inst) { |
| UnimplementedLoweringError(this, Inst); |
| } |
| -void TargetMIPS32::lowerCall(const InstCall *Inst) { |
| - UnimplementedLoweringError(this, Inst); |
| +void TargetMIPS32::lowerCall(const InstCall *Instr) { |
| + // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. |
| + if (Instr->getNumArgs()) { |
| + UnimplementedLoweringError(this, Instr); |
| + return; |
| + } |
| + // Generate the call instruction. Assign its result to a temporary with high |
| + // register allocation weight. |
| + Variable *Dest = Instr->getDest(); |
| + // ReturnReg doubles as ReturnRegLo as necessary. |
| + Variable *ReturnReg = nullptr; |
| + Variable *ReturnRegHi = nullptr; |
| + if (Dest) { |
| + switch (Dest->getType()) { |
| + case IceType_NUM: |
| + llvm_unreachable("Invalid Call dest type"); |
| + return; |
| + case IceType_void: |
| + break; |
| + case IceType_i1: |
| + case IceType_i8: |
| + case IceType_i16: |
| + case IceType_i32: |
| + ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0); |
| + break; |
| + case IceType_i64: |
| + ReturnReg = makeReg(IceType_i32, RegMIPS32::Reg_V0); |
| + ReturnRegHi = makeReg(IceType_i32, RegMIPS32::Reg_V1); |
| + break; |
| + case IceType_f32: |
| + case IceType_f64: |
| + UnimplementedLoweringError(this, Instr); |
| + return; |
| + case IceType_v4i1: |
| + case IceType_v8i1: |
| + case IceType_v16i1: |
| + case IceType_v16i8: |
| + case IceType_v8i16: |
| + case IceType_v4i32: |
| + case IceType_v4f32: |
| + UnimplementedLoweringError(this, Instr); |
| + return; |
| + } |
| + } |
| + Operand *CallTarget = Instr->getCallTarget(); |
| + // Allow ConstantRelocatable to be left alone as a direct call, |
| + // but force other constants like ConstantInteger32 to be in |
| + // a register and make it an indirect call. |
| + if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| + CallTarget = legalize(CallTarget, Legal_Reg); |
| + } |
| + Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); |
| + Context.insert(NewCall); |
| + if (ReturnRegHi) |
| + Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
| + // Insert a register-kill pseudo instruction. |
| + Context.insert(InstFakeKill::create(Func, NewCall)); |
| + // Generate a FakeUse to keep the call live if necessary. |
| + if (Instr->hasSideEffects() && ReturnReg) { |
| + Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
| + Context.insert(FakeUse); |
| + } |
| + if (Dest == nullptr) |
| + return; |
| + |
| + // Assign the result of the call to Dest. |
| + if (ReturnReg) { |
| + if (ReturnRegHi) { |
| + assert(Dest->getType() == IceType_i64); |
| + auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| + Variable *DestLo = Dest64On32->getLo(); |
| + Variable *DestHi = Dest64On32->getHi(); |
| + _mov(DestLo, ReturnReg); |
| + _mov(DestHi, ReturnRegHi); |
| + } else { |
| + assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || |
| + Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || |
| + isVectorType(Dest->getType())); |
| + if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { |
| + UnimplementedLoweringError(this, Instr); |
| + return; |
| + } else { |
| + _mov(Dest, ReturnReg); |
| + } |
| + } |
| + } |
| + UnimplementedLoweringError(this, Instr); |
| } |
| void TargetMIPS32::lowerCast(const InstCast *Inst) { |
| @@ -1087,7 +1259,9 @@ Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
| else |
| Reg = getPhysicalRegister(RegNum); |
| if (isInt<16>(int32_t(Value))) { |
| - _addiu(Reg, getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty), Value); |
| + Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); |
| + Context.insert<InstFakeDef>(Zero); |
| + _addiu(Reg, Zero, Value); |
| } else { |
| uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
| (void)UpperBits; |