llvm.org GIT mirror llvm / 8db6b00
[TRE] Improve code motion in TRE, use AA to tell whether a load can be moved before a call that writes to memory. Summary: use AA to tell whether a load can be moved before a call that writes to memory. Reviewers: dberlin, davide, sanjoy, hfinkel Reviewed By: hfinkel Subscribers: hfinkel, llvm-commits Differential Revision: https://reviews.llvm.org/D34115 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305698 91177308-0d34-0410-b5e6-96231b3b80d8 Xin Tong 2 years ago
2 changed file(s) with 57 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
320320 /// instruction from after the call to before the call, assuming that all
321321 /// instructions between the call and this instruction are movable.
322322 ///
323 static bool canMoveAboveCall(Instruction *I, CallInst *CI) {
323 static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA) {
324324 // FIXME: We can move load/store/call/free instructions above the call if the
325325 // call does not mod/ref the memory location being processed.
326326 if (I->mayHaveSideEffects()) // This also handles volatile loads.
331331 if (CI->mayHaveSideEffects()) {
332332 // Non-volatile loads may be moved above a call with side effects if it
333333 // does not write to memory and the load provably won't trap.
334 // FIXME: Writes to memory only matter if they may alias the pointer
334 // Writes to memory only matter if they may alias the pointer
335335 // being loaded from.
336336 const DataLayout &DL = L->getModule()->getDataLayout();
337 if (CI->mayWriteToMemory() ||
337 if ((AA->getModRefInfo(CI, MemoryLocation::get(L)) & MRI_Mod) ||
338338 !isSafeToLoadUnconditionally(L->getPointerOperand(),
339339 L->getAlignment(), DL, L))
340340 return false;
491491 return CI;
492492 }
493493
494 static bool
495 eliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, BasicBlock *&OldEntry,
496 bool &TailCallsAreMarkedTail,
497 SmallVectorImpl &ArgumentPHIs) {
494 static bool eliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret,
495 BasicBlock *&OldEntry,
496 bool &TailCallsAreMarkedTail,
497 SmallVectorImpl &ArgumentPHIs,
498 AliasAnalysis *AA) {
498499 // If we are introducing accumulator recursion to eliminate operations after
499500 // the call instruction that are both associative and commutative, the initial
500501 // value for the accumulator is placed in this variable. If this value is set
514515 // Check that this is the case now.
515516 BasicBlock::iterator BBI(CI);
516517 for (++BBI; &*BBI != Ret; ++BBI) {
517 if (canMoveAboveCall(&*BBI, CI)) continue;
518 if (canMoveAboveCall(&*BBI, CI, AA))
519 continue;
518520
519521 // If we can't move the instruction above the call, it might be because it
520522 // is an associative and commutative operation that could be transformed
673675 bool &TailCallsAreMarkedTail,
674676 SmallVectorImpl &ArgumentPHIs,
675677 bool CannotTailCallElimCallsMarkedTail,
676 const TargetTransformInfo *TTI) {
678 const TargetTransformInfo *TTI,
679 AliasAnalysis *AA) {
677680 bool Change = false;
678681
679682 // Make sure this block is a trivial return block.
709712 BB->eraseFromParent();
710713
711714 eliminateRecursiveTailCall(CI, RI, OldEntry, TailCallsAreMarkedTail,
712 ArgumentPHIs);
715 ArgumentPHIs, AA);
713716 ++NumRetDuped;
714717 Change = true;
715718 }
722725 bool &TailCallsAreMarkedTail,
723726 SmallVectorImpl &ArgumentPHIs,
724727 bool CannotTailCallElimCallsMarkedTail,
725 const TargetTransformInfo *TTI) {
728 const TargetTransformInfo *TTI,
729 AliasAnalysis *AA) {
726730 CallInst *CI = findTRECandidate(Ret, CannotTailCallElimCallsMarkedTail, TTI);
727731 if (!CI)
728732 return false;
729733
730734 return eliminateRecursiveTailCall(CI, Ret, OldEntry, TailCallsAreMarkedTail,
731 ArgumentPHIs);
732 }
733
734 static bool eliminateTailRecursion(Function &F, const TargetTransformInfo *TTI) {
735 ArgumentPHIs, AA);
736 }
737
738 static bool eliminateTailRecursion(Function &F, const TargetTransformInfo *TTI,
739 AliasAnalysis *AA) {
735740 if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
736741 return false;
737742
766771 if (ReturnInst *Ret = dyn_cast(BB->getTerminator())) {
767772 bool Change =
768773 processReturningBlock(Ret, OldEntry, TailCallsAreMarkedTail,
769 ArgumentPHIs, !CanTRETailMarkedCall, TTI);
774 ArgumentPHIs, !CanTRETailMarkedCall, TTI, AA);
770775 if (!Change && BB->getFirstNonPHIOrDbg() == Ret)
771 Change =
772 foldReturnAndProcessPred(BB, Ret, OldEntry, TailCallsAreMarkedTail,
773 ArgumentPHIs, !CanTRETailMarkedCall, TTI);
776 Change = foldReturnAndProcessPred(BB, Ret, OldEntry,
777 TailCallsAreMarkedTail, ArgumentPHIs,
778 !CanTRETailMarkedCall, TTI, AA);
774779 MadeChange |= Change;
775780 }
776781 }
800805
801806 void getAnalysisUsage(AnalysisUsage &AU) const override {
802807 AU.addRequired();
808 AU.addRequired();
803809 AU.addPreserved();
804810 }
805811
808814 return false;
809815
810816 return eliminateTailRecursion(
811 F, &getAnalysis().getTTI(F));
817 F, &getAnalysis().getTTI(F),
818 &getAnalysis().getAAResults());
812819 }
813820 };
814821 }
829836 FunctionAnalysisManager &AM) {
830837
831838 TargetTransformInfo &TTI = AM.getResult(F);
832
833 bool Changed = eliminateTailRecursion(F, &TTI);
839 AliasAnalysis &AA = AM.getResult(F);
840
841 bool Changed = eliminateTailRecursion(F, &TTI, &AA);
834842
835843 if (!Changed)
836844 return PreservedAnalyses::all();
44
55 ; Several cases where tail call elimination should move the load above the call,
66 ; then eliminate the tail recursion.
7
78
89
910 @global = external global i32 ; [#uses=1]
144145 %tmp10 = add i32 %tmp9, %tmp8 ; [#uses=1]
145146 ret i32 %tmp10
146147 }
148
149 ; This load can be moved above the call because the function call does not write to the memory the load
150 ; is accessing and the load is safe to speculate.
151 define fastcc i32 @raise_load_6(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind {
152 ; CHECK-LABEL: @raise_load_6(
153 ; CHECK-NOT: call
154 ; CHECK: load i32, i32*
155 ; CHECK-NOT: call
156 ; CHECK: }
157 entry:
158 %s = alloca i32
159 store i32 4, i32* %s
160 %tmp2 = icmp sge i32 %start_arg, %a_len_arg ; [#uses=1]
161 br i1 %tmp2, label %if, label %else
162
163 if: ; preds = %entry
164 store i32 1, i32* %a_arg
165 ret i32 0
166
167 else: ; preds = %entry
168 %tmp7 = add i32 %start_arg, 1 ; [#uses=1]
169 %tmp8 = call fastcc i32 @raise_load_6(i32* %a_arg, i32 %a_len_arg, i32 %tmp7) ; [#uses=1]
170 %tmp9 = load i32, i32* %s ; [#uses=1]
171 %tmp10 = add i32 %tmp9, %tmp8 ; [#uses=1]
172 ret i32 %tmp10
173 }