forked from OSchip/llvm-project
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:
parent
70193b21d1
commit
4187cb138b
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue