Chromium Code Reviews| Index: src/IceCfg.cpp |
| diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp |
| index 9bc1ba58333d6ef000a824c67ac59fd2ad4192de..438d5917dbb43d22cacab8fb69cace80bb1753df 100644 |
| --- a/src/IceCfg.cpp |
| +++ b/src/IceCfg.cpp |
| @@ -630,6 +630,83 @@ void Cfg::processAllocas(bool SortAndCombine) { |
| AllocaBaseVariableType BasePointerType = |
| (HasDynamicAllocation ? BVT_UserPointer : BVT_StackPointer); |
| sortAndCombineAllocas(FixedAllocas, MaxAlignment, Insts, BasePointerType); |
| + |
| + if (!FixedAllocas.empty() || !AlignedAllocas.empty()) |
| + // No use calling findRematerializable() unless there is some |
| + // rematerializable alloca instruction to seed it. |
| + findRematerializable(); |
| +} |
| + |
| +/// Scan the function to find additional rematerializable variables. This is |
| +/// possible when the source operand of an InstAssignment is a rematerializable |
| +/// variable, or the same for a pointer-type InstCast::Bitcast, or when an |
| +/// InstArithmetic is an add of a rematerializable variable and an immediate. |
| +/// Note that InstAssignment instructions and pointer-type InstCast::Bitcast |
| +/// instructions generally only come about from the IceConverter's treatment of |
| +/// inttoptr, ptrtoint, and bitcast instructions. TODO(stichnot): Consider |
| +/// other possibilities, however unlikely, such as InstArithmetic::Sub, or |
| +/// commutativity. |
| +void Cfg::findRematerializable() { |
| + // Scan the instructions in order, and repeat until no new opportunities are |
| + // found. It may take more than one iteration because a variable's defining |
| + // block may happen to come after a block where it is used, depending on the |
| + // CfgNode linearization order. |
| + bool FoundNewAssignment; |
| + do { |
| + FoundNewAssignment = false; |
| + for (CfgNode *Node : getNodes()) { |
| + // No need to process Phi instructions. |
| + for (Inst &Instr : Node->getInsts()) { |
| + if (Instr.isDeleted()) |
| + continue; |
| + Variable *Dest = Instr.getDest(); |
| + if (Dest == nullptr) |
| + continue; |
| + if (Dest->isRematerializable()) |
| + continue; |
| + if (auto *Arith = llvm::dyn_cast<InstArithmetic>(&Instr)) { |
| + // Just look at Add for now. |
| + if (Arith->getOp() == InstArithmetic::Add) { |
| + // Assume "v+10" for now, don't bother considering "10+v". |
| + if (auto *Src0Var = llvm::dyn_cast<Variable>(Arith->getSrc(0))) { |
| + if (Src0Var->isRematerializable()) { |
|
John
2015/11/12 20:43:14
soooo many nest levels. My brain hurts... :(
Jim Stichnoth
2015/11/12 21:02:44
I hear you... Unfortunately, the "best" order for
John
2015/11/12 21:11:39
I would create small helper functions, e.g.,
if (
Jim Stichnoth
2015/11/13 01:18:47
OK thanks. I split it into helper calls. PTAL.
|
| + if (auto *Src1Imm = |
| + llvm::dyn_cast<ConstantInteger32>(Arith->getSrc(1))) { |
| + Dest->setRematerializable(Src0Var->getRegNum(), |
| + Src0Var->getStackOffset() + |
| + Src1Imm->getValue()); |
| + FoundNewAssignment = true; |
| + } |
| + } |
| + } |
| + } |
| + continue; |
| + } // end of InstArithmetic |
| + if (auto *Assign = llvm::dyn_cast<InstAssign>(&Instr)) { |
| + if (auto *Src0Var = llvm::dyn_cast<Variable>(Assign->getSrc(0))) { |
| + if (Src0Var->isRematerializable()) { |
| + Dest->setRematerializable(Src0Var->getRegNum(), |
| + Src0Var->getStackOffset()); |
| + FoundNewAssignment = true; |
| + } |
| + } |
| + continue; |
| + } // end of InstAssign |
| + if (auto *Cast = llvm::dyn_cast<InstCast>(&Instr)) { |
| + if (Cast->getCastKind() == InstCast::Bitcast) { |
| + if (auto *Src0Var = llvm::dyn_cast<Variable>(Cast->getSrc(0))) { |
| + if (Src0Var->isRematerializable() && |
| + Src0Var->getType() == Dest->getType()) { |
| + Dest->setRematerializable(Src0Var->getRegNum(), |
| + Src0Var->getStackOffset()); |
| + FoundNewAssignment = true; |
| + } |
| + } |
| + } |
| + } // end of InstCast |
| + } |
| + } |
| + } while (FoundNewAssignment); |
| } |
| void Cfg::doAddressOpt() { |
| @@ -907,7 +984,7 @@ void Cfg::emit() { |
| deleteJumpTableInsts(); |
| if (Ctx->getFlags().getDecorateAsm()) { |
| for (Variable *Var : getVariables()) { |
| - if (Var->getStackOffset()) { |
| + if (Var->getStackOffset() && !Var->isRematerializable()) { |
| Str << "\t" << Var->getSymbolicStackOffset(this) << " = " |
| << Var->getStackOffset() << "\n"; |
| } |