Chromium Code Reviews

Unified Diff: src/IceTargetLoweringARM32.cpp

Issue 1156713003: Subzero ARM: lower alloca instruction. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: trailing space Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceTargetLoweringARM32.cpp
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 26f01f9492c2cbdcbdd2273cb0745d8f335692a7..2305a1b0c50107f439f6a7e3e616269bf6d44742 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -123,6 +123,9 @@ ICEINSTICMP_TABLE
// The maximum number of arguments to pass in GPR registers.
const uint32_t ARM32_MAX_GPR_ARG = 4;
+// Stack alignment
+const uint32_t ARM32_STACK_ALIGNMENT_BYTES = 16;
+
} // end of anonymous namespace
TargetARM32::TargetARM32(Cfg *Func)
@@ -607,8 +610,42 @@ void TargetARM32::lowerAlloca(const InstAlloca *Inst) {
// stack alignment is preserved after the alloca. The stack alignment
// restriction can be relaxed in some cases.
NeedsStackAlignment = true;
- (void)Inst;
- UnimplementedError(Func->getContext()->getFlags());
+
+ // TODO(stichnot): minimize the number of adjustments of SP, etc.
+ Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
+ Variable *Dest = Inst->getDest();
+ uint32_t AlignmentParam = Inst->getAlignInBytes();
+ // For default align=0, set it to the real value 1, to avoid any
+ // bit-manipulation problems below.
+ AlignmentParam = std::max(AlignmentParam, 1u);
+
+ // LLVM enforces power of 2 alignment.
+ assert(llvm::isPowerOf2_32(AlignmentParam));
+ assert(llvm::isPowerOf2_32(ARM32_STACK_ALIGNMENT_BYTES));
+
+ uint32_t Alignment = std::max(AlignmentParam, ARM32_STACK_ALIGNMENT_BYTES);
+ if (Alignment > ARM32_STACK_ALIGNMENT_BYTES) {
+ alignRegisterPow2(SP, Alignment);
+ }
+ Operand *TotalSize = Inst->getSizeInBytes();
+ if (const auto *ConstantTotalSize =
+ llvm::dyn_cast<ConstantInteger32>(TotalSize)) {
+ uint32_t Value = ConstantTotalSize->getValue();
+ Value = Utils::applyAlignment(Value, Alignment);
+ Operand *SubAmount = legalize(Ctx->getConstantInt32(Value));
+ _sub(SP, SP, SubAmount);
+ } else {
+ // Non-constant sizes need to be adjusted to the next highest
+ // multiple of the required alignment at runtime.
+ TotalSize = legalize(TotalSize);
+ Variable *T = makeReg(IceType_i32);
+ _mov(T, TotalSize);
+ Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1));
+ _add(T, T, AddAmount);
+ alignRegisterPow2(T, Alignment);
+ _sub(SP, SP, T);
+ }
+ _mov(Dest, SP);
}
void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
@@ -1528,6 +1565,23 @@ Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) {
return Reg;
}
+void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align) {
+ assert(llvm::isPowerOf2_32(Align));
+ uint32_t RotateAmt = 0;
+ uint32_t Immed_8;
+ Operand *Mask;
+ // Use AND or BIC to mask off the bits, depending on which immediate fits
+ // (if it fits at all). Assume Align is usually small, in which case BIC
+ // works better.
+ if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) {
+ Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex);
+ _bic(Reg, Reg, Mask);
+ } else {
+ Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex);
+ _and(Reg, Reg, Mask);
+ }
+}
+
void TargetARM32::postLower() {
if (Ctx->getFlags().getOptLevel() == Opt_m1)
return;
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »

Powered by Google App Engine