Index: include/llvm/CodeGen/FunctionLoweringInfo.h =================================================================== --- include/llvm/CodeGen/FunctionLoweringInfo.h +++ include/llvm/CodeGen/FunctionLoweringInfo.h @@ -184,6 +184,8 @@ /// selection. SmallPtrSet VisitedBBs; + SmallPtrSet InvalidatedPHIs; + /// PHINodesToUpdate - A list of phi instructions whose operand list will /// be updated after processing the current basic block. /// TODO: This isn't per-function state, it's per-basic-block state. But @@ -263,6 +265,11 @@ /// register based on the LiveOutInfo of its operands. void ComputePHILiveOutRegInfo(const PHINode*); + /// TryToRecomputePHILiveOutRegInfo - Try to recompute LiveOutInfo for a PHI + /// which was invalidated before. + const LiveOutInfo *TryToRecomputePHILiveOutRegInfo(Value *V, + unsigned BitWidth); + /// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be /// called when a block is visited before all of its predecessors. void InvalidatePHILiveOutRegInfo(const PHINode *PN) { Index: lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp =================================================================== --- lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -409,6 +409,26 @@ return LOI; } +const FunctionLoweringInfo::LiveOutInfo * +FunctionLoweringInfo::TryToRecomputePHILiveOutRegInfo(Value *V, + unsigned BitWidth) { + PHINode *Phi = dyn_cast(V); + if (!Phi || !InvalidatedPHIs.count(Phi)) + return nullptr; + + const BasicBlock *LLVMBB = Phi->getParent(); + for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB); + PI != PE; ++PI) { + if (!VisitedBBs.count(*PI) || MBBMap[*PI] == MBB) + return nullptr; + } + // If all predecessors are visited, retry to compute LiveOutRegInfo. + unsigned SrcReg = ValueMap[Phi]; + InvalidatedPHIs.erase(Phi); + ComputePHILiveOutRegInfo(Phi); + return GetLiveOutRegInfo(SrcReg, BitWidth); +} + /// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination /// register based on the LiveOutInfo of its operands. void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) { @@ -457,8 +477,10 @@ } const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth); if (!SrcLOI) { - DestLOI.IsValid = false; - return; + if (!(SrcLOI = TryToRecomputePHILiveOutRegInfo(V, BitWidth))) { + DestLOI.IsValid = false; + return; + } } DestLOI = *SrcLOI; } @@ -494,8 +516,10 @@ } const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth); if (!SrcLOI) { - DestLOI.IsValid = false; - return; + if (!(SrcLOI = TryToRecomputePHILiveOutRegInfo(V, BitWidth))) { + DestLOI.IsValid = false; + return; + } } DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, SrcLOI->NumSignBits); DestLOI.KnownZero &= SrcLOI->KnownZero; Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1413,6 +1413,7 @@ I = RPOT.begin(), E = RPOT.end(); I != E; ++I) { const BasicBlock *LLVMBB = *I; + FuncInfo->MBB = FuncInfo->MBBMap[LLVMBB]; if (OptLevel != CodeGenOpt::None) { bool AllPredsVisited = true; for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB); @@ -1429,10 +1430,11 @@ FuncInfo->ComputePHILiveOutRegInfo(PN); } else { for (BasicBlock::const_iterator I = LLVMBB->begin(); - const PHINode *PN = dyn_cast(I); ++I) + const PHINode *PN = dyn_cast(I); ++I) { FuncInfo->InvalidatePHILiveOutRegInfo(PN); + FuncInfo->InvalidatedPHIs.insert(PN); + } } - FuncInfo->VisitedBBs.insert(LLVMBB); } @@ -1441,7 +1443,6 @@ BasicBlock::const_iterator const End = LLVMBB->end(); BasicBlock::const_iterator BI = End; - FuncInfo->MBB = FuncInfo->MBBMap[LLVMBB]; if (!FuncInfo->MBB) continue; // Some blocks like catchpads have no code or MBB. FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI(); Index: test/CodeGen/AArch64/selectdag-assertzext.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/selectdag-assertzext.ll @@ -0,0 +1,46 @@ +; RUN: llc < %s -mtriple=aarch64--linux-gnu | FileCheck %s + +; This test is to check an AND instruction for zext is not generated in %while.end +; by adding AssertZext to CopyFromReg for %idx while building DAG. + +; CHECK-LABEL: @checkLiveoutInfo +; CHECK: ldrb w[[LD:[0-9]+]], [x1] +; CHECK-LABEL: %while.end +; CHECK-NOT: and w{{[0-9]+}}, w[[LD]], #0xff + +@CA = common global i8* null, align 8 + +define i32 @checkLiveoutInfo(i64 %c,i8* %s) { +entry: + %l1 = load i8, i8* %s, align 1 + %cmp12 = icmp eq i8 %l1, 0 + br i1 %cmp12, label %while.end, label %land.rhs.preheader + +land.rhs.preheader: ; preds = %entry + %scevgep = getelementptr i8, i8* %s, i64 -1 + br label %land.rhs + +land.rhs: ; preds = %land.rhs.preheader, %while.body + %lsr.iv = phi i8* [ %scevgep, %land.rhs.preheader ], [ %scevgep16, %while.body ] + %invalidatedPhi = phi i8 [ %l2, %while.body ], [ %l1, %land.rhs.preheader ] + %cmp4 = icmp eq i64 %c, 0 + br i1 %cmp4, label %while.body, label %while.end + +while.body: ; preds = %land.rhs + %l2 = load i8, i8* %lsr.iv, align 1 + %cmp = icmp eq i8 %l2, 0 + %scevgep16 = getelementptr i8, i8* %lsr.iv, i64 -1 + br i1 %cmp, label %while.end, label %land.rhs + +while.end: ; preds = %land.rhs, %while.body, %entry + %idx= phi i8 [ 0, %entry ], [ %invalidatedPhi, %land.rhs ], [ 0, %while.body ] + %l3 = load i8*, i8** @CA, align 8 + %zext1 = zext i8 %idx to i64 + %arrayidx = getelementptr inbounds i8, i8* %l3, i64 %zext1 + %l4 = load i8, i8* %arrayidx, align 1 + %zext2 = zext i8 %l4 to i32 + ret i32 %zext2 +} + + +