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

Unified Diff: src/IceTargetLoweringMIPS32.cpp

Issue 1640913004: Subzero: Mips: Lower some i64 arithmetic instructions (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: changes suggested by stichnot Created 4 years, 11 months 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 side-by-side diff with in-line comments
Download patch
Index: src/IceTargetLoweringMIPS32.cpp
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index d8cd65c2973ac502ca2cd18f8c99e000754c1f23..e8fdb352c982b131fc33966eedcacaa6d5d77425 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));
+ Variable *Src1LoR = legalizeToReg(loOperand(Src1));
+ Variable *Src0HiR = legalizeToReg(hiOperand(Src0));
+ Variable *Src1HiR = legalizeToReg(hiOperand(Src1));
+
+ 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);
+ _addu(T_Lo, Src0LoR, Src1LoR);
+ _mov(DestLo, T_Lo);
+ _sltu(T_Carry, T_Lo, Src0LoR);
+ _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);
John 2016/02/01 04:29:32 You could have done Context.insert<InstFakeDef>(F
rkotlerimgtec 2016/02/01 21:11:09 Done.
+ 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);
John 2016/02/01 04:29:32 Do you really want to report an error here?
rkotlerimgtec 2016/02/01 21:11:08 Done.
}
void TargetMIPS32::lowerCast(const InstCast *Inst) {
@@ -980,8 +1152,8 @@ void TargetMIPS32::prelowerPhis() {
void TargetMIPS32::postLower() {
if (Ctx->getFlags().getOptLevel() == Opt_m1)
return;
- // Find two-address non-SSA instructions where Dest==Src0, and set the
- // IsDestRedefined flag to keep liveness analysis consistent.
+ // TODO(rkotler): Find two-address non-SSA instructions where Dest==Src0,
+ // and set the IsDestRedefined flag to keep liveness analysis consistent.
John 2016/02/01 04:29:32 You're better off explicitly setting the bit durin
Jim Stichnoth 2016/02/01 04:57:50 What this TODO really means, I think, is to call T
rkotlerimgtec 2016/02/01 21:11:08 Yes. The intention is just to do what ARM does her
UnimplementedError(Func->getContext()->getFlags());
}
@@ -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;

Powered by Google App Engine
This is Rietveld 408576698