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

Unified Diff: src/IceTargetLoweringARM32.cpp

Issue 1457683004: Subzero. ARM32. Removing memory legalization warts. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments Created 5 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 side-by-side diff with in-line comments
Download patch
Index: src/IceTargetLoweringARM32.cpp
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 9657c1dd0c28a25ddf0b42a30fbc90b617e970e5..24cced83ce6b60edfbacb8bbd907d03a4b88621b 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -475,9 +475,6 @@ void TargetARM32::emitVariable(const Variable *Var) const {
Offset += getStackAdjustment();
}
const Type VarTy = Var->getType();
- if (!isLegalMemOffset(VarTy, Offset)) {
- llvm::report_fatal_error("Illegal stack offset");
- }
Str << "[" << getRegName(BaseRegNum, VarTy);
if (Offset != 0) {
Str << ", " << getConstantPrefix() << Offset;
@@ -625,7 +622,7 @@ void TargetARM32::lowerArguments() {
// to copy Arg into its assigned register if applicable.
void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr,
size_t BasicFrameOffset,
- size_t &InArgsSizeBytes) {
+ size_t *InArgsSizeBytes) {
if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) {
Variable *Lo = Arg64On32->getLo();
Variable *Hi = Arg64On32->getHi();
@@ -634,26 +631,23 @@ void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr,
return;
}
Type Ty = Arg->getType();
- InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty);
- Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes);
- InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
- // If the argument variable has been assigned a register, we need to load the
- // value from the stack slot.
- if (Arg->hasReg()) {
- assert(Ty != IceType_i64);
- // This should be simple, just load the parameter off the stack using a nice
- // sp + imm addressing mode. Because ARM, we can't do that (e.g., VLDR, for
- // fp types, cannot have an index register), so we legalize the memory
- // operand instead.
- auto *Mem = OperandARM32Mem::create(
- Func, Ty, FramePtr, llvm::cast<ConstantInteger32>(
- Ctx->getConstantInt32(Arg->getStackOffset())));
- _mov(Arg, legalizeToReg(Mem, Arg->getRegNum()));
- // This argument-copying instruction uses an explicit OperandARM32Mem
- // operand instead of a Variable, so its fill-from-stack operation has to
- // be tracked separately for statistics.
- Ctx->statsUpdateFills();
+ assert(Ty != IceType_i64);
+
+ *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty);
+ const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes;
+ *InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
+
+ if (!Arg->hasReg()) {
+ Arg->setStackOffset(ArgStackOffset);
+ return;
}
+
+ // If the argument variable has been assigned a register, we need to copy the
+ // value from the stack slot.
+ Variable *Parameter = Func->makeVariable(Ty);
+ Parameter->setMustNotHaveReg();
+ Parameter->setStackOffset(ArgStackOffset);
+ _mov(Arg, Parameter);
}
Type TargetARM32::stackSlotType() { return IceType_i32; }
@@ -754,8 +748,6 @@ void TargetARM32::addProlog(CfgNode *Node) {
continue;
}
if (CalleeSaves[i] && RegsUsed[i]) {
- // TODO(jvoung): do separate vpush for each floating point register
- // segment and += 4, or 8 depending on type.
++NumCallee;
Variable *PhysicalRegister = getPhysicalRegister(i);
PreservedRegsSizeBytes +=
@@ -837,7 +829,7 @@ void TargetARM32::addProlog(CfgNode *Node) {
InRegs = CC.I32InReg(&DummyReg);
}
if (!InRegs)
- finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes);
+ finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, &InArgsSizeBytes);
}
// Fill in stack offsets for locals.
@@ -981,11 +973,18 @@ Variable *TargetARM32::newBaseRegister(int32_t OriginalOffset,
return ScratchReg;
}
-StackVariable *TargetARM32::legalizeStackSlot(Type Ty, int32_t Offset,
- int32_t StackAdjust,
- Variable *OrigBaseReg,
- Variable **NewBaseReg,
- int32_t *NewBaseOffset) {
+OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset,
+ int32_t StackAdjust,
+ Variable *OrigBaseReg,
+ Variable **NewBaseReg,
+ int32_t *NewBaseOffset) {
+ if (isLegalMemOffset(Ty, Offset + StackAdjust)) {
+ return OperandARM32Mem::create(
+ Func, Ty, OrigBaseReg, llvm::cast<ConstantInteger32>(
+ Ctx->getConstantInt32(Offset + StackAdjust)),
+ OperandARM32Mem::Offset);
+ }
+
if (*NewBaseReg == nullptr) {
*NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg);
*NewBaseOffset = Offset + StackAdjust;
@@ -998,18 +997,15 @@ StackVariable *TargetARM32::legalizeStackSlot(Type Ty, int32_t Offset,
OffsetDiff = 0;
}
- StackVariable *NewDest = Func->makeVariable<StackVariable>(Ty);
- NewDest->setMustNotHaveReg();
- NewDest->setBaseRegNum((*NewBaseReg)->getRegNum());
- NewDest->setStackOffset(OffsetDiff);
- return NewDest;
+ return OperandARM32Mem::create(
+ Func, Ty, *NewBaseReg,
+ llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)),
+ OperandARM32Mem::Offset);
}
-void TargetARM32::legalizeMovStackAddrImm(InstARM32Mov *MovInstr,
- int32_t StackAdjust,
- Variable *OrigBaseReg,
- Variable **NewBaseReg,
- int32_t *NewBaseOffset) {
+void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, int32_t StackAdjust,
+ Variable *OrigBaseReg, Variable **NewBaseReg,
+ int32_t *NewBaseOffset) {
Variable *Dest = MovInstr->getDest();
assert(Dest != nullptr);
Type DestTy = Dest->getType();
@@ -1017,6 +1013,7 @@ void TargetARM32::legalizeMovStackAddrImm(InstARM32Mov *MovInstr,
Operand *Src = MovInstr->getSrc(0);
Type SrcTy = Src->getType();
+ (void)SrcTy;
assert(SrcTy != IceType_i64);
if (MovInstr->isMultiDest() || MovInstr->isMultiSource())
@@ -1024,40 +1021,29 @@ void TargetARM32::legalizeMovStackAddrImm(InstARM32Mov *MovInstr,
bool Legalized = false;
if (!Dest->hasReg()) {
- assert(llvm::cast<Variable>(Src)->hasReg());
+ auto *const SrcR = llvm::cast<Variable>(Src);
Jim Stichnoth 2015/11/22 03:40:47 "auto *const" seems odd -- did you mean "const aut
John 2015/11/23 18:52:56 No, I meant auto *const. Removing as git grep 'aut
+ assert(SrcR->hasReg());
const int32_t Offset = Dest->getStackOffset();
- if (!isLegalMemOffset(DestTy, Offset + StackAdjust)) {
- Legalized = true;
- Dest = legalizeStackSlot(DestTy, Offset, StackAdjust, OrigBaseReg,
- NewBaseReg, NewBaseOffset);
- }
+ // This is a _mov(Mem(), Variable), i.e., a store.
+ _str(SrcR, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg,
+ NewBaseReg, NewBaseOffset),
+ MovInstr->getPredicate());
+ // _str() does not have a Dest, so we add a fake-def(Dest).
+ Context.insert(InstFakeDef::create(Func, Dest));
+ Legalized = true;
} else if (auto *Var = llvm::dyn_cast<Variable>(Src)) {
if (!Var->hasReg()) {
const int32_t Offset = Var->getStackOffset();
- if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) {
- Legalized = true;
- Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg,
- NewBaseReg, NewBaseOffset);
- }
- }
- } else if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) {
- if (ConstantInteger32 *OffsetOp = Mem->getOffset()) {
- const int32_t Offset = OffsetOp->getValue();
- if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) {
- assert(Mem->getBase()->hasReg());
- assert(Mem->getBase()->getRegNum() == (int32_t)getFrameOrStackReg());
- Legalized = true;
- Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg,
- NewBaseReg, NewBaseOffset);
- }
+ _ldr(Dest, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg,
+ NewBaseReg, NewBaseOffset),
+ MovInstr->getPredicate());
+ Legalized = true;
}
}
if (Legalized) {
if (MovInstr->isDestRedefined()) {
- _mov_redefined(Dest, Src, MovInstr->getPredicate());
- } else {
- _mov(Dest, Src, MovInstr->getPredicate());
+ _set_dest_redefined();
}
MovInstr->setDeleted();
}
@@ -1075,11 +1061,6 @@ void TargetARM32::legalizeStackSlots() {
// clobber the flags register.
Func->dump("Before legalizeStackSlots");
assert(hasComputedFrame());
- // Early exit, if SpillAreaSizeBytes is really small.
- // TODO(jpp): this is not safe -- loads and stores of q registers can't have
- // offsets.
- if (isLegalMemOffset(IceType_v4i32, SpillAreaSizeBytes))
- return;
Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg());
int32_t StackAdjust = 0;
// Do a fairly naive greedy clustering for now. Pick the first stack slot
@@ -1122,11 +1103,9 @@ void TargetARM32::legalizeStackSlots() {
}
}
- // The Lowering ensures that ldr and str always have legal Mem operands.
- // The only other instruction that may access memory is mov.
if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) {
- legalizeMovStackAddrImm(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg,
- &NewBaseOffset);
+ legalizeMov(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg,
+ &NewBaseOffset);
}
}
}
@@ -4600,7 +4579,11 @@ Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) {
Type Ty = Src->getType();
Variable *Reg = makeReg(Ty, RegNum);
- _mov(Reg, Src);
+ if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) {
+ _ldr(Reg, Mem);
+ } else {
+ _mov(Reg, Src);
+ }
return Reg;
}
@@ -4641,7 +4624,6 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
Variable *RegIndex = nullptr;
assert(Base);
RegBase = legalizeToReg(Base);
- bool InvalidImm = false;
assert(Ty < MemTraitsSize);
if (Index) {
assert(Offset == nullptr);
@@ -4653,12 +4635,7 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
static constexpr bool ZeroExt = false;
assert(MemTraits[Ty].CanHaveImm);
if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) {
- assert(RegBase->hasReg());
- assert(RegBase->getRegNum() == (int32_t)getFrameOrStackReg());
- // We are a bit more lenient with invalid immediate when accessing the
- // stack here, and then rely on legalizeStackSlots() to fix things as
- // appropriate.
- InvalidImm = true;
+ llvm::report_fatal_error("Invalid memory offset.");
}
}
@@ -4679,15 +4656,7 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
From = Mem;
} else {
Variable *Reg = makeReg(Ty, RegNum);
- if (InvalidImm) {
- // If Mem has an invalid immediate, we legalize it to a Reg using mov
- // instead of ldr because legalizeStackSlots() will later kick in and
- // fix the immediate for us.
- _mov(Reg, Mem);
- } else {
- _ldr(Reg, Mem);
- }
-
+ _ldr(Reg, Mem);
From = Reg;
}
return From;

Powered by Google App Engine
This is Rietveld 408576698