Index: include/llvm/Analysis/InstructionSimplify.h =================================================================== --- include/llvm/Analysis/InstructionSimplify.h +++ include/llvm/Analysis/InstructionSimplify.h @@ -291,6 +291,14 @@ AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// SimplifyFreezeInst - Given an operand for a Freeze, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyFreezeInst(Value *Op, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); + /// See if we can compute a simplified version of this instruction. If not, /// return null. Value *SimplifyInstruction(Instruction *I, const DataLayout &DL, Index: include/llvm/Analysis/ValueTracking.h =================================================================== --- include/llvm/Analysis/ValueTracking.h +++ include/llvm/Analysis/ValueTracking.h @@ -414,6 +414,10 @@ /// the parent of I. bool isKnownNotFullPoison(const Instruction *PoisonI); + /// Return true if this function can prove that V is never undef value + /// or poison value. + bool isGuaranteedNotToBeUndefOrPoison(const Value *V); + /// \brief Specific patterns of select instructions we can match. enum SelectPatternFlavor { SPF_UNKNOWN = 0, Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -4393,6 +4393,23 @@ Query(DL, TLI, DT, AC, CxtI), RecursionLimit); } +/// Given operands for a Freeze, see if we can fold the result. +static Value *SimplifyFreezeInst(Value *Op0) { + // Use a utility function defined in ValueTracking. + if (llvm::isGuaranteedNotToBeUndefOrPoison(Op0)) + return Op0; + // We have room for improvement. + return nullptr; +} + +Value *llvm::SimplifyFreezeInst(Value *Op0, + const DataLayout &DL, + const TargetLibraryInfo *TLI, + const DominatorTree *DT, AssumptionCache *AC, + const Instruction *CxtI) { + return ::SimplifyFreezeInst(Op0); +} + /// See if we can compute a simplified version of this instruction. /// If not, this returns null. Value *llvm::SimplifyInstruction(Instruction *I, const DataLayout &DL, @@ -4532,6 +4549,9 @@ TLI, DT, AC, I); break; } + case Instruction::Freeze: + Result = SimplifyFreezeInst(I->getOperand(0), DL, TLI, DT, AC, I); + break; #define HANDLE_CAST_INST(num, opc, clas) case Instruction::opc: #include "llvm/IR/Instruction.def" #undef HANDLE_CAST_INST Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -3898,6 +3898,20 @@ return false; } +bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V) { + // If the value is a freeze instruction, then it can never + // be undef or poison. + if (isa(V)) + return true; + // TODO: Some instructions are guaranteed to return neither undef + // nor poison if their arguments are not poison/undef. + + // TODO: Deal with other Constant subclasses. + if (isa(V)) + return true; + + return false; +} static bool isKnownNonNaN(const Value *V, FastMathFlags FMF) { if (FMF.noNaNs()) Index: lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- lib/Transforms/InstCombine/InstCombineInternal.h +++ lib/Transforms/InstCombine/InstCombineInternal.h @@ -279,6 +279,7 @@ Instruction *visitSelectInst(SelectInst &SI); Instruction *visitCallInst(CallInst &CI); Instruction *visitInvokeInst(InvokeInst &II); + Instruction *visitFreeze(FreezeInst &FI); Instruction *SliceUpIllegalIntegerPHI(PHINode &PN); Instruction *visitPHINode(PHINode &PN); Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2767,6 +2767,15 @@ return nullptr; } +Instruction *InstCombiner::visitFreeze(FreezeInst &FI) { + Value *Op0 = FI.getOperand(0); + + if (Value *V = SimplifyFreezeInst(Op0, DL, &TLI, &DT, &AC)) + return replaceInstUsesWith(FI, V); + + return nullptr; +} + /// Try to move the specified instruction from its current block into the /// beginning of DestBlock, which can only happen if it's safe to move the /// instruction past all of the instructions between it and the end of its Index: test/Transforms/InstCombine/freeze.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/freeze.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -instcombine -S | FileCheck --match-full-lines %s + +define i32 @fold(i32 %x) { +; CHECK: %y = freeze i32 %x +; CHECK-NEXT: ret i32 %y + %y = freeze i32 %x + %z = freeze i32 %y + ret i32 %z +} + +define i32 @make_const() { +; CHECK: ret i32 10 + %x = freeze i32 10 + ret i32 %x +}