Subzero ARM: lowerLoad and lowerStore.
Thought leaving "mov" simple and not handle memory operands,
but then we'd have to duplicate some of the lowerAssign code
for lowerLoad =/
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076
R=kschimpf@google.com, stichnot@chromium.org
Review URL: https://codereview.chromium.org/1152703006
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index e160a3c..37f5e19 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -1628,9 +1628,18 @@
return;
}
-void TargetARM32::lowerLoad(const InstLoad *Inst) {
- (void)Inst;
- UnimplementedError(Func->getContext()->getFlags());
+void TargetARM32::lowerLoad(const InstLoad *Load) {
+ // A Load instruction can be treated the same as an Assign
+ // instruction, after the source operand is transformed into an
+ // OperandARM32Mem operand.
+ Type Ty = Load->getDest()->getType();
+ Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty);
+ Variable *DestLoad = Load->getDest();
+
+ // TODO(jvoung): handled folding opportunities. Sign and zero extension
+ // can be folded into a load.
+ InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0);
+ lowerAssign(Assign);
}
void TargetARM32::doAddressOptLoad() {
@@ -1687,8 +1696,22 @@
}
void TargetARM32::lowerStore(const InstStore *Inst) {
- (void)Inst;
- UnimplementedError(Func->getContext()->getFlags());
+ Operand *Value = Inst->getData();
+ Operand *Addr = Inst->getAddr();
+ OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType());
+ Type Ty = NewAddr->getType();
+
+ if (Ty == IceType_i64) {
+ Variable *ValueHi = legalizeToVar(hiOperand(Value));
+ Variable *ValueLo = legalizeToVar(loOperand(Value));
+ _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr)));
+ _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr)));
+ } else if (isVectorType(Ty)) {
+ UnimplementedError(Func->getContext()->getFlags());
+ } else {
+ Variable *ValueR = legalizeToVar(Value);
+ _str(ValueR, NewAddr);
+ }
}
void TargetARM32::doAddressOptStore() {
@@ -1891,6 +1914,23 @@
return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
}
+OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) {
+ OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand);
+ // It may be the case that address mode optimization already creates
+ // an OperandARM32Mem, so in that case it wouldn't need another level
+ // of transformation.
+ if (Mem) {
+ return llvm::cast<OperandARM32Mem>(legalize(Mem));
+ }
+ // If we didn't do address mode optimization, then we only
+ // have a base/offset to work with. ARM always requires a base
+ // register, so just use that to hold the operand.
+ Variable *Base = legalizeToVar(Operand);
+ return OperandARM32Mem::create(
+ Func, Ty, Base,
+ llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)));
+}
+
Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) {
// There aren't any 64-bit integer registers for ARM32.
assert(Type != IceType_i64);