diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -1247,11 +1247,11 @@ } // Return true if the instruction type of Val is supported by -// constantFoldUser(). Currently CastInst and BinaryOperator only. Call this -// before calling constantFoldUser() to find out if it's even worth attempting -// to call it. +// constantFoldUser(). Currently CastInst, BinaryOperator and FreezeInst only. +// Call this before calling constantFoldUser() to find out if it's even worth +// attempting to call it. static bool isOperationFoldable(User *Usr) { - return isa(Usr) || isa(Usr); + return isa(Usr) || isa(Usr) || isa(Usr); } // Check if Usr can be simplified to an integer constant when the value of one @@ -1282,6 +1282,9 @@ SimplifyBinOp(BO->getOpcode(), LHS, RHS, DL))) { return ValueLatticeElement::getRange(ConstantRange(C->getValue())); } + } else if (auto *FI = dyn_cast(Usr)) { + assert(FI->getOperand(0) == Op && "Operand 0 isn't Op"); + return ValueLatticeElement::getRange(ConstantRange(OpConstVal)); } return ValueLatticeElement::getOverdefined(); } @@ -1306,7 +1309,11 @@ // If V is the condition of the branch itself, then we know exactly what // it is. - if (Condition == Val) + // Since it is used as a branch conditional, Condition cannot be undef + // or poison. Exploit this to strip freeze from Val. + if (Condition == Val || + (isa(Val) && + Condition == cast(Val)->getOperand(0))) return ValueLatticeElement::get(ConstantInt::get( Type::getInt1Ty(Val->getContext()), isTrueDest)); diff --git a/llvm/test/Transforms/JumpThreading/freeze-lvi-edgevaluelocal.ll b/llvm/test/Transforms/JumpThreading/freeze-lvi-edgevaluelocal.ll --- a/llvm/test/Transforms/JumpThreading/freeze-lvi-edgevaluelocal.ll +++ b/llvm/test/Transforms/JumpThreading/freeze-lvi-edgevaluelocal.ll @@ -9,10 +9,7 @@ define i32 @simple(i1 %cond) { ; CHECK-LABEL: @simple( ; CHECK-NEXT: ENTRY: -; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]] -; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[EXIT:%.*]] -; CHECK: A: -; CHECK-NEXT: br i1 [[COND_FR]], label [[B:%.*]], label [[EXIT]] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[B:%.*]], label [[EXIT:%.*]] ; CHECK: B: ; CHECK-NEXT: call void @f() ; CHECK-NEXT: ret i32 1 @@ -36,8 +33,8 @@ ; CHECK-NEXT: ENTRY: ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i32 [[COND:%.*]] ; CHECK-NEXT: switch i32 [[COND]], label [[DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[A:%.*]] -; CHECK-NEXT: i32 1, label [[B:%.*]] +; CHECK-NEXT: i32 0, label [[A_TAKEN:%.*]] +; CHECK-NEXT: i32 1, label [[B_TAKEN:%.*]] ; CHECK-NEXT: ] ; CHECK: DEFAULT: ; CHECK-NEXT: switch i32 [[COND_FR]], label [[PRESERVED1:%.*]] [ @@ -49,26 +46,12 @@ ; CHECK: PRESERVED2: ; CHECK-NEXT: call void @f2() ; CHECK-NEXT: ret void -; CHECK: A: -; CHECK-NEXT: switch i32 [[COND_FR]], label [[A_NOTTAKEN:%.*]] [ -; CHECK-NEXT: i32 0, label [[A_TAKEN:%.*]] -; CHECK-NEXT: ] ; CHECK: A_TAKEN: ; CHECK-NEXT: call void @f() ; CHECK-NEXT: ret void -; CHECK: A_NOTTAKEN: -; CHECK-NEXT: call void @f2() -; CHECK-NEXT: ret void -; CHECK: B: -; CHECK-NEXT: switch i32 [[COND_FR]], label [[B_TAKEN:%.*]] [ -; CHECK-NEXT: i32 0, label [[B_NOTTAKEN:%.*]] -; CHECK-NEXT: ] ; CHECK: B_TAKEN: ; CHECK-NEXT: call void @f() ; CHECK-NEXT: ret void -; CHECK: B_NOTTAKEN: -; CHECK-NEXT: call void @f2() -; CHECK-NEXT: ret void ; ENTRY: %cond.fr = freeze i32 %cond