summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Analysis/InstructionSimplify.h4
-rw-r--r--llvm/include/llvm/Analysis/ValueTracking.h4
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp16
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp14
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineInternal.h1
-rw-r--r--llvm/lib/Transforms/InstCombine/InstructionCombining.cpp9
-rw-r--r--llvm/test/Transforms/InstCombine/freeze.ll20
-rw-r--r--llvm/test/Transforms/InstSimplify/freeze.ll20
8 files changed, 88 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h
index a5ffca13046..b661caee684 100644
--- a/llvm/include/llvm/Analysis/InstructionSimplify.h
+++ b/llvm/include/llvm/Analysis/InstructionSimplify.h
@@ -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,
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 33b064fcf9d..8d5533b7ece 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -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,
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 83b767a8fd1..3ef8f9b0050 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -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
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index cc5acf5d010..b26c6294dce 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -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,
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index aabedbda7e6..524f9313d8c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -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; }
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index b1828d0fe32..7656d669e8a 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -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
diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll
new file mode 100644
index 00000000000..bbd3f1201e0
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/freeze.ll
@@ -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
+}
diff --git a/llvm/test/Transforms/InstSimplify/freeze.ll b/llvm/test/Transforms/InstSimplify/freeze.ll
new file mode 100644
index 00000000000..ac287b949f0
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/freeze.ll
@@ -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
+}
OpenPOWER on IntegriCloud