Add InstCombine/InstructionSimplify support for Freeze Instruction

Summary:
- Add llvm::SimplifyFreezeInst
- Add InstCombiner::visitFreeze
- Add llvm tests

Reviewers: majnemer, sanjoy, reames, lebedev.ri, spatel

Reviewed By: reames, lebedev.ri

Subscribers: reames, lebedev.ri, filcab, regehr, trentxintong, llvm-commits

Differential Revision: https://reviews.llvm.org/D29013
This commit is contained in:
aqjune 2019-11-07 01:12:17 +09:00 committed by Juneyoung Lee
parent 70193b21d1
commit 4187cb138b
8 changed files with 88 additions and 0 deletions

View File

@ -259,6 +259,10 @@ Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
/// Given a callsite, fold the result or return null.
Value *SimplifyCall(CallBase *Call, const SimplifyQuery &Q);
/// Given an operand for a Freeze, see if we can fold the result.
/// If not, this returns null.
Value *SimplifyFreezeInst(Value *Op, const SimplifyQuery &Q);
/// See if we can compute a simplified version of this instruction. If not,
/// return null.
Value *SimplifyInstruction(Instruction *I, const SimplifyQuery &Q,

View File

@ -561,6 +561,10 @@ class Value;
/// the parent of I.
bool programUndefinedIfFullPoison(const Instruction *PoisonI);
/// Return true if this function can prove that V is never undef value
/// or poison value.
bool isGuaranteedNotToBeUndefOrPoison(const Value *V);
/// Specific patterns of select instructions we can match.
enum SelectPatternFlavor {
SPF_UNKNOWN = 0,

View File

@ -5241,6 +5241,19 @@ Value *llvm::SimplifyCall(CallBase *Call, const SimplifyQuery &Q) {
return ConstantFoldCall(Call, F, ConstantArgs, Q.TLI);
}
/// 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 SimplifyQuery &Q) {
return ::SimplifyFreezeInst(Op0);
}
/// See if we can compute a simplified version of this instruction.
/// If not, this returns null.
@ -5383,6 +5396,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ,
Result = SimplifyCall(cast<CallInst>(I), Q);
break;
}
case Instruction::Freeze:
Result = SimplifyFreezeInst(I->getOperand(0), Q);
break;
#define HANDLE_CAST_INST(num, opc, clas) case Instruction::opc:
#include "llvm/IR/Instruction.def"
#undef HANDLE_CAST_INST

View File

@ -4221,6 +4221,20 @@ bool llvm::isOverflowIntrinsicNoWrap(const WithOverflowInst *WO,
return llvm::any_of(GuardingBranches, AllUsesGuardedByBranch);
}
bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V) {
// If the value is a freeze instruction, then it can never
// be undef or poison.
if (isa<FreezeInst>(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<ConstantInt>(V) || isa<GlobalVariable>(V))
return true;
return false;
}
OverflowResult llvm::computeOverflowForSignedAdd(const AddOperator *Add,
const DataLayout &DL,

View File

@ -446,6 +446,7 @@ public:
Instruction *visitLandingPadInst(LandingPadInst &LI);
Instruction *visitVAStartInst(VAStartInst &I);
Instruction *visitVACopyInst(VACopyInst &I);
Instruction *visitFreeze(FreezeInst &I);
/// Specify what to return for unhandled instructions.
Instruction *visitInstruction(Instruction &I) { return nullptr; }

View File

@ -3131,6 +3131,15 @@ Instruction *InstCombiner::visitLandingPadInst(LandingPadInst &LI) {
return nullptr;
}
Instruction *InstCombiner::visitFreeze(FreezeInst &I) {
Value *Op0 = I.getOperand(0);
if (Value *V = SimplifyFreezeInst(Op0, SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, 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

View File

@ -0,0 +1,20 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
define i32 @fold(i32 %x) {
; CHECK-LABEL: @fold(
; CHECK-NEXT: [[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-LABEL: @make_const(
; CHECK-NEXT: ret i32 10
;
%x = freeze i32 10
ret i32 %x
}

View File

@ -0,0 +1,20 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instsimplify -S | FileCheck %s
define i32 @fold(i32 %x) {
; CHECK-LABEL: @fold(
; CHECK-NEXT: [[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-LABEL: @make_const(
; CHECK-NEXT: ret i32 10
;
%x = freeze i32 10
ret i32 %x
}