forked from OSchip/llvm-project
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and the new implementation goal is that of addressing shortcomings of the current GVN infrastructure, i.e. long compile time for large testcases, lack of phi predication, no load/store value numbering etc... The current code just implements the "core" GVN algorithm, although other pieces (load coercion, phi handling, predicate system) are already implemented in a branch out of tree. Once the core is stable, we'll start adding pieces on top of the base framework. The test currently living in test/Transform/NewGVN are a copy of the ones in GVN, with proper `XFAIL` (missing features in NewGVN). A flag will be added in a future commit to enable NewGVN, so that interested parties can exercise this code easily. Differential Revision: https://reviews.llvm.org/D26224 llvm-svn: 290346
This commit is contained in:
parent
8b4340a5dd
commit
7e274e02ae
|
@ -56,6 +56,9 @@ void LLVMAddMergedLoadStoreMotionPass(LLVMPassManagerRef PM);
|
||||||
/** See llvm::createGVNPass function. */
|
/** See llvm::createGVNPass function. */
|
||||||
void LLVMAddGVNPass(LLVMPassManagerRef PM);
|
void LLVMAddGVNPass(LLVMPassManagerRef PM);
|
||||||
|
|
||||||
|
/** See llvm::createGVNPass function. */
|
||||||
|
void LLVMAddNewGVNPass(LLVMPassManagerRef PM);
|
||||||
|
|
||||||
/** See llvm::createIndVarSimplifyPass function. */
|
/** See llvm::createIndVarSimplifyPass function. */
|
||||||
void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM);
|
void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM);
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,7 @@ void initializeModuleDebugInfoPrinterPass(PassRegistry&);
|
||||||
void initializeModuleSummaryIndexWrapperPassPass(PassRegistry &);
|
void initializeModuleSummaryIndexWrapperPassPass(PassRegistry &);
|
||||||
void initializeNameAnonGlobalLegacyPassPass(PassRegistry &);
|
void initializeNameAnonGlobalLegacyPassPass(PassRegistry &);
|
||||||
void initializeNaryReassociateLegacyPassPass(PassRegistry &);
|
void initializeNaryReassociateLegacyPassPass(PassRegistry &);
|
||||||
|
void initializeNewGVNPass(PassRegistry&);
|
||||||
void initializeNoAAPass(PassRegistry&);
|
void initializeNoAAPass(PassRegistry&);
|
||||||
void initializeObjCARCAAWrapperPassPass(PassRegistry&);
|
void initializeObjCARCAAWrapperPassPass(PassRegistry&);
|
||||||
void initializeObjCARCAPElimPass(PassRegistry&);
|
void initializeObjCARCAPElimPass(PassRegistry&);
|
||||||
|
|
|
@ -167,6 +167,7 @@ namespace {
|
||||||
(void) llvm::createGVNHoistPass();
|
(void) llvm::createGVNHoistPass();
|
||||||
(void) llvm::createMergedLoadStoreMotionPass();
|
(void) llvm::createMergedLoadStoreMotionPass();
|
||||||
(void) llvm::createGVNPass();
|
(void) llvm::createGVNPass();
|
||||||
|
(void) llvm::createNewGVNPass();
|
||||||
(void) llvm::createMemCpyOptPass();
|
(void) llvm::createMemCpyOptPass();
|
||||||
(void) llvm::createLoopDeletionPass();
|
(void) llvm::createLoopDeletionPass();
|
||||||
(void) llvm::createPostDomTree();
|
(void) llvm::createPostDomTree();
|
||||||
|
|
|
@ -346,6 +346,13 @@ FunctionPass *createGVNHoistPass();
|
||||||
//
|
//
|
||||||
FunctionPass *createMergedLoadStoreMotionPass();
|
FunctionPass *createMergedLoadStoreMotionPass();
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// GVN - This pass performs global value numbering and redundant load
|
||||||
|
// elimination cotemporaneously.
|
||||||
|
//
|
||||||
|
FunctionPass *createNewGVNPass();
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// MemCpyOpt - This pass performs optimizations related to eliminating memcpy
|
// MemCpyOpt - This pass performs optimizations related to eliminating memcpy
|
||||||
|
|
|
@ -0,0 +1,551 @@
|
||||||
|
//======- GVNExpression.h - GVN Expression classes -------*- C++ -*-==-------=//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// \file
|
||||||
|
///
|
||||||
|
/// The header file for the GVN pass that contains expression handling
|
||||||
|
/// classes
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H
|
||||||
|
#define LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/Hashing.h"
|
||||||
|
#include "llvm/IR/Constant.h"
|
||||||
|
#include "llvm/IR/Instructions.h"
|
||||||
|
#include "llvm/IR/Value.h"
|
||||||
|
#include "llvm/Support/Allocator.h"
|
||||||
|
#include "llvm/Support/ArrayRecycler.h"
|
||||||
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class MemoryAccess;
|
||||||
|
|
||||||
|
namespace GVNExpression {
|
||||||
|
|
||||||
|
enum ExpressionType {
|
||||||
|
ET_Base,
|
||||||
|
ET_Constant,
|
||||||
|
ET_Variable,
|
||||||
|
ET_BasicStart,
|
||||||
|
ET_Basic,
|
||||||
|
ET_Call,
|
||||||
|
ET_AggregateValue,
|
||||||
|
ET_Phi,
|
||||||
|
ET_Load,
|
||||||
|
ET_Store,
|
||||||
|
ET_BasicEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
class Expression {
|
||||||
|
private:
|
||||||
|
ExpressionType EType;
|
||||||
|
unsigned Opcode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Expression(const Expression &) = delete;
|
||||||
|
Expression(ExpressionType ET = ET_Base, unsigned O = ~2U)
|
||||||
|
: EType(ET), Opcode(O) {}
|
||||||
|
void operator=(const Expression &) = delete;
|
||||||
|
virtual ~Expression();
|
||||||
|
|
||||||
|
static unsigned getEmptyKey() { return ~0U; }
|
||||||
|
static unsigned getTombstoneKey() { return ~1U; }
|
||||||
|
|
||||||
|
bool operator==(const Expression &Other) const {
|
||||||
|
if (getOpcode() != Other.getOpcode())
|
||||||
|
return false;
|
||||||
|
if (getOpcode() == getEmptyKey() || getOpcode() == getTombstoneKey())
|
||||||
|
return true;
|
||||||
|
// Compare the expression type for anything but load and store.
|
||||||
|
// For load and store we set the opcode to zero.
|
||||||
|
// This is needed for load coercion.
|
||||||
|
if (getExpressionType() != ET_Load &&
|
||||||
|
getExpressionType() != ET_Store &&
|
||||||
|
getExpressionType() != Other.getExpressionType())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return equals(Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const { return true; }
|
||||||
|
|
||||||
|
unsigned getOpcode() const { return Opcode; }
|
||||||
|
void setOpcode(unsigned opcode) { Opcode = opcode; }
|
||||||
|
ExpressionType getExpressionType() const { return EType; }
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const {
|
||||||
|
return hash_combine(getExpressionType(), getOpcode());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "etype = " << getExpressionType() << ",";
|
||||||
|
OS << "opcode = " << getOpcode() << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(raw_ostream &OS) const {
|
||||||
|
OS << "{ ";
|
||||||
|
printInternal(OS, true);
|
||||||
|
OS << "}";
|
||||||
|
}
|
||||||
|
void dump() const { print(dbgs()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline raw_ostream &operator<<(raw_ostream &OS, const Expression &E) {
|
||||||
|
E.print(OS);
|
||||||
|
return OS;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BasicExpression : public Expression {
|
||||||
|
private:
|
||||||
|
typedef ArrayRecycler<Value *> RecyclerType;
|
||||||
|
typedef RecyclerType::Capacity RecyclerCapacity;
|
||||||
|
Value **Operands;
|
||||||
|
unsigned MaxOperands;
|
||||||
|
unsigned NumOperands;
|
||||||
|
Type *ValueType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
ExpressionType ET = EB->getExpressionType();
|
||||||
|
return ET > ET_BasicStart && ET < ET_BasicEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicExpression(unsigned NumOperands)
|
||||||
|
: BasicExpression(NumOperands, ET_Basic) {}
|
||||||
|
BasicExpression(unsigned NumOperands, ExpressionType ET)
|
||||||
|
: Expression(ET), Operands(nullptr), MaxOperands(NumOperands),
|
||||||
|
NumOperands(0), ValueType(nullptr) {}
|
||||||
|
virtual ~BasicExpression() override;
|
||||||
|
void operator=(const BasicExpression &) = delete;
|
||||||
|
BasicExpression(const BasicExpression &) = delete;
|
||||||
|
BasicExpression() = delete;
|
||||||
|
|
||||||
|
/// \brief Swap two operands. Used during GVN to put commutative operands in
|
||||||
|
/// order.
|
||||||
|
void swapOperands(unsigned First, unsigned Second) {
|
||||||
|
std::swap(Operands[First], Operands[Second]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *getOperand(unsigned N) const {
|
||||||
|
assert(Operands && "Operands not allocated");
|
||||||
|
assert(N < NumOperands && "Operand out of range");
|
||||||
|
return Operands[N];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOperand(unsigned N, Value *V) {
|
||||||
|
assert(Operands && "Operands not allocated before setting");
|
||||||
|
assert(N < NumOperands && "Operand out of range");
|
||||||
|
Operands[N] = V;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getNumOperands() const { return NumOperands; }
|
||||||
|
|
||||||
|
typedef Value **op_iterator;
|
||||||
|
typedef Value *const *const_ops_iterator;
|
||||||
|
op_iterator ops_begin() { return Operands; }
|
||||||
|
op_iterator ops_end() { return Operands + NumOperands; }
|
||||||
|
const_ops_iterator ops_begin() const { return Operands; }
|
||||||
|
const_ops_iterator ops_end() const { return Operands + NumOperands; }
|
||||||
|
iterator_range<op_iterator> operands() {
|
||||||
|
return iterator_range<op_iterator>(ops_begin(), ops_end());
|
||||||
|
}
|
||||||
|
iterator_range<const_ops_iterator> operands() const {
|
||||||
|
return iterator_range<const_ops_iterator>(ops_begin(), ops_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ops_push_back(Value *Arg) {
|
||||||
|
assert(NumOperands < MaxOperands && "Tried to add too many operands");
|
||||||
|
assert(Operands && "Operandss not allocated before pushing");
|
||||||
|
Operands[NumOperands++] = Arg;
|
||||||
|
}
|
||||||
|
bool ops_empty() const { return getNumOperands() == 0; }
|
||||||
|
|
||||||
|
void allocateOperands(RecyclerType &Recycler, BumpPtrAllocator &Allocator) {
|
||||||
|
assert(!Operands && "Operands already allocated");
|
||||||
|
Operands = Recycler.allocate(RecyclerCapacity::get(MaxOperands), Allocator);
|
||||||
|
}
|
||||||
|
void deallocateOperands(RecyclerType &Recycler) {
|
||||||
|
Recycler.deallocate(RecyclerCapacity::get(MaxOperands), Operands);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setType(Type *T) { ValueType = T; }
|
||||||
|
Type *getType() const { return ValueType; }
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const override {
|
||||||
|
if (getOpcode() != Other.getOpcode())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto &OE = cast<BasicExpression>(Other);
|
||||||
|
if (getType() != OE.getType())
|
||||||
|
return false;
|
||||||
|
if (NumOperands != OE.NumOperands)
|
||||||
|
return false;
|
||||||
|
if (!std::equal(ops_begin(), ops_end(), OE.ops_begin()))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(getExpressionType(), getOpcode(), ValueType,
|
||||||
|
hash_combine_range(ops_begin(), ops_end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypeBasic, ";
|
||||||
|
|
||||||
|
this->Expression::printInternal(OS, false);
|
||||||
|
OS << "operands = {";
|
||||||
|
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
|
||||||
|
OS << "[" << i << "] = ";
|
||||||
|
Operands[i]->printAsOperand(OS);
|
||||||
|
OS << " ";
|
||||||
|
}
|
||||||
|
OS << "} ";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CallExpression final : public BasicExpression {
|
||||||
|
private:
|
||||||
|
CallInst *Call;
|
||||||
|
MemoryAccess *DefiningAccess;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
return EB->getExpressionType() == ET_Call;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallExpression(unsigned NumOperands, CallInst *C, MemoryAccess *DA)
|
||||||
|
: BasicExpression(NumOperands, ET_Call), Call(C),
|
||||||
|
DefiningAccess(DA) {}
|
||||||
|
void operator=(const CallExpression &) = delete;
|
||||||
|
CallExpression(const CallExpression &) = delete;
|
||||||
|
CallExpression() = delete;
|
||||||
|
virtual ~CallExpression() override;
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const override {
|
||||||
|
if (!this->BasicExpression::equals(Other))
|
||||||
|
return false;
|
||||||
|
const auto &OE = cast<CallExpression>(Other);
|
||||||
|
return DefiningAccess == OE.DefiningAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(this->BasicExpression::getHashValue(), DefiningAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypeCall, ";
|
||||||
|
this->BasicExpression::printInternal(OS, false);
|
||||||
|
OS << " represents call at " << Call;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoadExpression final : public BasicExpression {
|
||||||
|
private:
|
||||||
|
LoadInst *Load;
|
||||||
|
MemoryAccess *DefiningAccess;
|
||||||
|
unsigned Alignment;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
return EB->getExpressionType() == ET_Load;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadExpression(unsigned NumOperands, LoadInst *L, MemoryAccess *DA)
|
||||||
|
: LoadExpression(ET_Load, NumOperands, L, DA) {}
|
||||||
|
LoadExpression(enum ExpressionType EType, unsigned NumOperands,
|
||||||
|
LoadInst *L, MemoryAccess *DA)
|
||||||
|
: BasicExpression(NumOperands, EType), Load(L), DefiningAccess(DA) {
|
||||||
|
Alignment = L ? L->getAlignment() : 0;
|
||||||
|
}
|
||||||
|
void operator=(const LoadExpression &) = delete;
|
||||||
|
LoadExpression(const LoadExpression &) = delete;
|
||||||
|
LoadExpression() = delete;
|
||||||
|
virtual ~LoadExpression() override;
|
||||||
|
|
||||||
|
LoadInst *getLoadInst() const { return Load; }
|
||||||
|
void setLoadInst(LoadInst *L) { Load = L; }
|
||||||
|
|
||||||
|
MemoryAccess *getDefiningAccess() const { return DefiningAccess; }
|
||||||
|
void setDefiningAccess(MemoryAccess *MA) { DefiningAccess = MA; }
|
||||||
|
unsigned getAlignment() const { return Alignment; }
|
||||||
|
void setAlignment(unsigned Align) { Alignment = Align; }
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const override;
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(getOpcode(), getType(), DefiningAccess,
|
||||||
|
hash_combine_range(ops_begin(), ops_end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypeLoad, ";
|
||||||
|
this->BasicExpression::printInternal(OS, false);
|
||||||
|
OS << " represents Load at " << Load;
|
||||||
|
OS << " with DefiningAccess " << DefiningAccess;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class StoreExpression final : public BasicExpression {
|
||||||
|
private:
|
||||||
|
StoreInst *Store;
|
||||||
|
MemoryAccess *DefiningAccess;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
return EB->getExpressionType() == ET_Store;
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreExpression(unsigned NumOperands, StoreInst *S, MemoryAccess *DA)
|
||||||
|
: BasicExpression(NumOperands, ET_Store), Store(S),
|
||||||
|
DefiningAccess(DA) {}
|
||||||
|
void operator=(const StoreExpression &) = delete;
|
||||||
|
StoreExpression(const StoreExpression &) = delete;
|
||||||
|
StoreExpression() = delete;
|
||||||
|
virtual ~StoreExpression() override;
|
||||||
|
|
||||||
|
StoreInst *getStoreInst() const { return Store; }
|
||||||
|
MemoryAccess *getDefiningAccess() const { return DefiningAccess; }
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const override;
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(getOpcode(), getType(), DefiningAccess,
|
||||||
|
hash_combine_range(ops_begin(), ops_end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypeStore, ";
|
||||||
|
this->BasicExpression::printInternal(OS, false);
|
||||||
|
OS << " represents Store at " << Store;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AggregateValueExpression final : public BasicExpression {
|
||||||
|
private:
|
||||||
|
unsigned MaxIntOperands;
|
||||||
|
unsigned NumIntOperands;
|
||||||
|
unsigned *IntOperands;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
return EB->getExpressionType() == ET_AggregateValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AggregateValueExpression(unsigned NumOperands,
|
||||||
|
unsigned NumIntOperands)
|
||||||
|
: BasicExpression(NumOperands, ET_AggregateValue),
|
||||||
|
MaxIntOperands(NumIntOperands), NumIntOperands(0),
|
||||||
|
IntOperands(nullptr) {}
|
||||||
|
|
||||||
|
void operator=(const AggregateValueExpression &) = delete;
|
||||||
|
AggregateValueExpression(const AggregateValueExpression &) = delete;
|
||||||
|
AggregateValueExpression() = delete;
|
||||||
|
virtual ~AggregateValueExpression() override;
|
||||||
|
|
||||||
|
typedef unsigned *int_arg_iterator;
|
||||||
|
typedef const unsigned *const_int_arg_iterator;
|
||||||
|
|
||||||
|
int_arg_iterator int_ops_begin() { return IntOperands; }
|
||||||
|
int_arg_iterator int_ops_end() { return IntOperands + NumIntOperands; }
|
||||||
|
const_int_arg_iterator int_ops_begin() const { return IntOperands; }
|
||||||
|
const_int_arg_iterator int_ops_end() const {
|
||||||
|
return IntOperands + NumIntOperands;
|
||||||
|
}
|
||||||
|
unsigned int_ops_size() const { return NumIntOperands; }
|
||||||
|
bool int_ops_empty() const { return NumIntOperands == 0; }
|
||||||
|
void int_ops_push_back(unsigned IntOperand) {
|
||||||
|
assert(NumIntOperands < MaxIntOperands &&
|
||||||
|
"Tried to add too many int operands");
|
||||||
|
assert(IntOperands && "Operands not allocated before pushing");
|
||||||
|
IntOperands[NumIntOperands++] = IntOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void allocateIntOperands(BumpPtrAllocator &Allocator) {
|
||||||
|
assert(!IntOperands && "Operands already allocated");
|
||||||
|
IntOperands = Allocator.Allocate<unsigned>(MaxIntOperands);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const override {
|
||||||
|
if (!this->BasicExpression::equals(Other))
|
||||||
|
return false;
|
||||||
|
const AggregateValueExpression &OE = cast<AggregateValueExpression>(Other);
|
||||||
|
if (NumIntOperands != OE.NumIntOperands)
|
||||||
|
return false;
|
||||||
|
if (!std::equal(int_ops_begin(), int_ops_end(), OE.int_ops_begin()))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(this->BasicExpression::getHashValue(),
|
||||||
|
hash_combine_range(int_ops_begin(), int_ops_end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypeAggregateValue, ";
|
||||||
|
this->BasicExpression::printInternal(OS, false);
|
||||||
|
OS << ", intoperands = {";
|
||||||
|
for (unsigned i = 0, e = int_ops_size(); i != e; ++i) {
|
||||||
|
OS << "[" << i << "] = " << IntOperands[i] << " ";
|
||||||
|
}
|
||||||
|
OS << "}";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PHIExpression final : public BasicExpression {
|
||||||
|
private:
|
||||||
|
BasicBlock *BB;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
return EB->getExpressionType() == ET_Phi;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHIExpression(unsigned NumOperands, BasicBlock *B)
|
||||||
|
: BasicExpression(NumOperands, ET_Phi), BB(B) {}
|
||||||
|
void operator=(const PHIExpression &) = delete;
|
||||||
|
PHIExpression(const PHIExpression &) = delete;
|
||||||
|
PHIExpression() = delete;
|
||||||
|
virtual ~PHIExpression() override;
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const override {
|
||||||
|
if (!this->BasicExpression::equals(Other))
|
||||||
|
return false;
|
||||||
|
const PHIExpression &OE = cast<PHIExpression>(Other);
|
||||||
|
if (BB != OE.BB)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(this->BasicExpression::getHashValue(), BB);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypePhi, ";
|
||||||
|
this->BasicExpression::printInternal(OS, false);
|
||||||
|
OS << "bb = " << BB;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class VariableExpression final : public Expression {
|
||||||
|
private:
|
||||||
|
Value *VariableValue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
return EB->getExpressionType() == ET_Variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableExpression(Value *V)
|
||||||
|
: Expression(ET_Variable), VariableValue(V) {}
|
||||||
|
void operator=(const VariableExpression &) = delete;
|
||||||
|
VariableExpression(const VariableExpression &) = delete;
|
||||||
|
VariableExpression() = delete;
|
||||||
|
|
||||||
|
Value *getVariableValue() const { return VariableValue; }
|
||||||
|
void setVariableValue(Value *V) { VariableValue = V; }
|
||||||
|
virtual bool equals(const Expression &Other) const override {
|
||||||
|
const VariableExpression &OC = cast<VariableExpression>(Other);
|
||||||
|
if (VariableValue != OC.VariableValue)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(getExpressionType(), VariableValue->getType(),
|
||||||
|
VariableValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypeVariable, ";
|
||||||
|
this->Expression::printInternal(OS, false);
|
||||||
|
OS << " variable = " << *VariableValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstantExpression final : public Expression {
|
||||||
|
private:
|
||||||
|
Constant *ConstantValue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool classof(const Expression *EB) {
|
||||||
|
return EB->getExpressionType() == ET_Constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantExpression()
|
||||||
|
: Expression(ET_Constant), ConstantValue(NULL) {}
|
||||||
|
ConstantExpression(Constant *constantValue)
|
||||||
|
: Expression(ET_Constant), ConstantValue(constantValue) {}
|
||||||
|
void operator=(const ConstantExpression &) = delete;
|
||||||
|
ConstantExpression(const ConstantExpression &) = delete;
|
||||||
|
|
||||||
|
Constant *getConstantValue() const { return ConstantValue; }
|
||||||
|
void setConstantValue(Constant *V) { ConstantValue = V; }
|
||||||
|
|
||||||
|
virtual bool equals(const Expression &Other) const override {
|
||||||
|
const ConstantExpression &OC = cast<ConstantExpression>(Other);
|
||||||
|
return ConstantValue == OC.ConstantValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual hash_code getHashValue() const override {
|
||||||
|
return hash_combine(getExpressionType(), ConstantValue->getType(),
|
||||||
|
ConstantValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging support
|
||||||
|
//
|
||||||
|
virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
|
||||||
|
if (PrintEType)
|
||||||
|
OS << "ExpressionTypeConstant, ";
|
||||||
|
this->Expression::printInternal(OS, false);
|
||||||
|
OS << " constant = " << *ConstantValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,28 @@
|
||||||
|
//===----- NewGVN.h - Global Value Numbering Pass ---------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// \file
|
||||||
|
/// This file provides the interface for LLVM's Global Value Numbering pass.
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_TRANSFORMS_SCALAR_NEWGVN_H
|
||||||
|
#define LLVM_TRANSFORMS_SCALAR_NEWGVN_H
|
||||||
|
|
||||||
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class NewGVNPass : public PassInfoMixin<NewGVNPass> {
|
||||||
|
public:
|
||||||
|
/// \brief Run the pass over the function.
|
||||||
|
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LLVM_TRANSFORMS_SCALAR_NEWGVN_H
|
||||||
|
|
|
@ -39,6 +39,7 @@ add_llvm_library(LLVMScalarOpts
|
||||||
MemCpyOptimizer.cpp
|
MemCpyOptimizer.cpp
|
||||||
MergedLoadStoreMotion.cpp
|
MergedLoadStoreMotion.cpp
|
||||||
NaryReassociate.cpp
|
NaryReassociate.cpp
|
||||||
|
NewGVN.cpp
|
||||||
PartiallyInlineLibCalls.cpp
|
PartiallyInlineLibCalls.cpp
|
||||||
PlaceSafepoints.cpp
|
PlaceSafepoints.cpp
|
||||||
Reassociate.cpp
|
Reassociate.cpp
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -43,6 +43,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
|
||||||
initializeDSELegacyPassPass(Registry);
|
initializeDSELegacyPassPass(Registry);
|
||||||
initializeGuardWideningLegacyPassPass(Registry);
|
initializeGuardWideningLegacyPassPass(Registry);
|
||||||
initializeGVNLegacyPassPass(Registry);
|
initializeGVNLegacyPassPass(Registry);
|
||||||
|
initializeNewGVNPass(Registry);
|
||||||
initializeEarlyCSELegacyPassPass(Registry);
|
initializeEarlyCSELegacyPassPass(Registry);
|
||||||
initializeEarlyCSEMemSSALegacyPassPass(Registry);
|
initializeEarlyCSEMemSSALegacyPassPass(Registry);
|
||||||
initializeGVNHoistLegacyPassPass(Registry);
|
initializeGVNHoistLegacyPassPass(Registry);
|
||||||
|
@ -126,6 +127,10 @@ void LLVMAddGVNPass(LLVMPassManagerRef PM) {
|
||||||
unwrap(PM)->add(createGVNPass());
|
unwrap(PM)->add(createGVNPass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLVMAddNewGVNPass(LLVMPassManagerRef PM) {
|
||||||
|
unwrap(PM)->add(createNewGVNPass());
|
||||||
|
}
|
||||||
|
|
||||||
void LLVMAddMergedLoadStoreMotionPass(LLVMPassManagerRef PM) {
|
void LLVMAddMergedLoadStoreMotionPass(LLVMPassManagerRef PM) {
|
||||||
unwrap(PM)->add(createMergedLoadStoreMotionPass());
|
unwrap(PM)->add(createMergedLoadStoreMotionPass());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
|
||||||
|
%struct.PerlInterpreter = type { i8 }
|
||||||
|
@PL_sv_count = external global i32 ; <i32*> [#uses=2]
|
||||||
|
|
||||||
|
define void @perl_destruct(%struct.PerlInterpreter* %sv_interp) {
|
||||||
|
entry:
|
||||||
|
br i1 false, label %cond_next25, label %cond_true16
|
||||||
|
|
||||||
|
cond_true16: ; preds = %entry
|
||||||
|
ret void
|
||||||
|
|
||||||
|
cond_next25: ; preds = %entry
|
||||||
|
br i1 false, label %cond_next33, label %cond_true32
|
||||||
|
|
||||||
|
cond_true32: ; preds = %cond_next25
|
||||||
|
ret void
|
||||||
|
|
||||||
|
cond_next33: ; preds = %cond_next25
|
||||||
|
br i1 false, label %cond_next61, label %cond_true.i46
|
||||||
|
|
||||||
|
cond_true.i46: ; preds = %cond_next33
|
||||||
|
ret void
|
||||||
|
|
||||||
|
cond_next61: ; preds = %cond_next33
|
||||||
|
br i1 false, label %cond_next69, label %cond_true66
|
||||||
|
|
||||||
|
cond_true66: ; preds = %cond_next61
|
||||||
|
ret void
|
||||||
|
|
||||||
|
cond_next69: ; preds = %cond_next61
|
||||||
|
br i1 false, label %Perl_safefree.exit52, label %cond_true.i50
|
||||||
|
|
||||||
|
cond_true.i50: ; preds = %cond_next69
|
||||||
|
ret void
|
||||||
|
|
||||||
|
Perl_safefree.exit52: ; preds = %cond_next69
|
||||||
|
br i1 false, label %cond_next80, label %cond_true77
|
||||||
|
|
||||||
|
cond_true77: ; preds = %Perl_safefree.exit52
|
||||||
|
ret void
|
||||||
|
|
||||||
|
cond_next80: ; preds = %Perl_safefree.exit52
|
||||||
|
br i1 false, label %Perl_safefree.exit56, label %cond_true.i54
|
||||||
|
|
||||||
|
cond_true.i54: ; preds = %cond_next80
|
||||||
|
ret void
|
||||||
|
|
||||||
|
Perl_safefree.exit56: ; preds = %cond_next80
|
||||||
|
br i1 false, label %Perl_safefree.exit60, label %cond_true.i58
|
||||||
|
|
||||||
|
cond_true.i58: ; preds = %Perl_safefree.exit56
|
||||||
|
ret void
|
||||||
|
|
||||||
|
Perl_safefree.exit60: ; preds = %Perl_safefree.exit56
|
||||||
|
br i1 false, label %Perl_safefree.exit64, label %cond_true.i62
|
||||||
|
|
||||||
|
cond_true.i62: ; preds = %Perl_safefree.exit60
|
||||||
|
ret void
|
||||||
|
|
||||||
|
Perl_safefree.exit64: ; preds = %Perl_safefree.exit60
|
||||||
|
br i1 false, label %Perl_safefree.exit68, label %cond_true.i66
|
||||||
|
|
||||||
|
cond_true.i66: ; preds = %Perl_safefree.exit64
|
||||||
|
ret void
|
||||||
|
|
||||||
|
Perl_safefree.exit68: ; preds = %Perl_safefree.exit64
|
||||||
|
br i1 false, label %cond_next150, label %cond_true23.i
|
||||||
|
|
||||||
|
cond_true23.i: ; preds = %Perl_safefree.exit68
|
||||||
|
ret void
|
||||||
|
|
||||||
|
cond_next150: ; preds = %Perl_safefree.exit68
|
||||||
|
%tmp16092 = load i32, i32* @PL_sv_count, align 4 ; <i32> [#uses=0]
|
||||||
|
br label %cond_next165
|
||||||
|
|
||||||
|
bb157: ; preds = %cond_next165
|
||||||
|
%tmp158 = load i32, i32* @PL_sv_count, align 4 ; <i32> [#uses=0]
|
||||||
|
br label %cond_next165
|
||||||
|
|
||||||
|
cond_next165: ; preds = %bb157, %cond_next150
|
||||||
|
br i1 false, label %bb171, label %bb157
|
||||||
|
|
||||||
|
bb171: ; preds = %cond_next165
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
%struct.INT2 = type { i32, i32 }
|
||||||
|
@blkshifts = external global %struct.INT2* ; <%struct.INT2**> [#uses=2]
|
||||||
|
|
||||||
|
define i32 @xcompact() {
|
||||||
|
entry:
|
||||||
|
store %struct.INT2* null, %struct.INT2** @blkshifts, align 4
|
||||||
|
br label %bb
|
||||||
|
|
||||||
|
bb: ; preds = %bb, %entry
|
||||||
|
%tmp10 = load %struct.INT2*, %struct.INT2** @blkshifts, align 4 ; <%struct.INT2*> [#uses=0]
|
||||||
|
; CHECK-NOT: %tmp10
|
||||||
|
br label %bb
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
|
||||||
|
%struct.s_segment_inf = type { float, i32, i16, i16, float, float, i32, float, float }
|
||||||
|
|
||||||
|
define void @print_arch(i8* %arch_file, i32 %route_type, i64 %det_routing_arch.0.0, i64 %det_routing_arch.0.1, i64 %det_routing_arch.0.2, i64 %det_routing_arch.0.3, i64 %det_routing_arch.0.4, %struct.s_segment_inf* %segment_inf, i64 %timing_inf.0.0, i64 %timing_inf.0.1, i64 %timing_inf.0.2, i64 %timing_inf.0.3, i64 %timing_inf.0.4, i32 %timing_inf.1) {
|
||||||
|
entry:
|
||||||
|
br i1 false, label %bb278, label %bb344
|
||||||
|
|
||||||
|
bb278: ; preds = %bb278, %entry
|
||||||
|
br i1 false, label %bb278, label %bb344
|
||||||
|
|
||||||
|
bb344: ; preds = %bb278, %entry
|
||||||
|
%tmp38758 = load i16, i16* null, align 2 ; <i16> [#uses=0]
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
|
||||||
|
%struct.TypHeader = type { i32, %struct.TypHeader**, [3 x i8], i8 }
|
||||||
|
|
||||||
|
define %struct.TypHeader* @LtRec(%struct.TypHeader* %hdL, %struct.TypHeader* %hdR) {
|
||||||
|
entry:
|
||||||
|
br i1 false, label %bb556.preheader, label %bb534.preheader
|
||||||
|
|
||||||
|
bb534.preheader: ; preds = %entry
|
||||||
|
ret %struct.TypHeader* null
|
||||||
|
|
||||||
|
bb556.preheader: ; preds = %entry
|
||||||
|
%tmp56119 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
%tmp56220 = load i32, i32* %tmp56119 ; <i32> [#uses=0]
|
||||||
|
br i1 false, label %bb.nph23, label %bb675.preheader
|
||||||
|
|
||||||
|
bb.nph23: ; preds = %bb556.preheader
|
||||||
|
ret %struct.TypHeader* null
|
||||||
|
|
||||||
|
bb656: ; preds = %bb675.outer, %bb656
|
||||||
|
%tmp678 = load i32, i32* %tmp677 ; <i32> [#uses=0]
|
||||||
|
br i1 false, label %bb684, label %bb656
|
||||||
|
|
||||||
|
bb684: ; preds = %bb675.outer, %bb656
|
||||||
|
br i1 false, label %bb924.preheader, label %bb675.outer
|
||||||
|
|
||||||
|
bb675.outer: ; preds = %bb675.preheader, %bb684
|
||||||
|
%tmp67812 = load i32, i32* %tmp67711 ; <i32> [#uses=0]
|
||||||
|
br i1 false, label %bb684, label %bb656
|
||||||
|
|
||||||
|
bb675.preheader: ; preds = %bb556.preheader
|
||||||
|
%tmp67711 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
%tmp677 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
br label %bb675.outer
|
||||||
|
|
||||||
|
bb924.preheader: ; preds = %bb684
|
||||||
|
ret %struct.TypHeader* null
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
|
||||||
|
%struct.ggBRDF = type { i32 (...)** }
|
||||||
|
%struct.ggBox3 = type { %struct.ggPoint3, %struct.ggPoint3 }
|
||||||
|
%struct.ggMaterialRecord = type { %struct.ggPoint2, %struct.ggBox3, %struct.ggBox3, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggBRDF*, i32, i32, i32, i32 }
|
||||||
|
%struct.ggONB3 = type { %struct.ggPoint3, %struct.ggPoint3, %struct.ggPoint3 }
|
||||||
|
%struct.ggPoint2 = type { [2 x double] }
|
||||||
|
%struct.ggPoint3 = type { [3 x double] }
|
||||||
|
%struct.ggSpectrum = type { [8 x float] }
|
||||||
|
%struct.mrViewingHitRecord = type { double, %struct.ggPoint3, %struct.ggONB3, %struct.ggPoint2, double, %struct.ggSpectrum, %struct.ggSpectrum, i32, i32, i32, i32 }
|
||||||
|
%struct.mrXEllipticalCylinder = type { %struct.ggBRDF, float, float, float, float, float, float }
|
||||||
|
|
||||||
|
define i32 @_ZNK21mrZEllipticalCylinder10viewingHitERK6ggRay3dddR18mrViewingHitRecordR16ggMaterialRecord(%struct.mrXEllipticalCylinder* %this, %struct.ggBox3* %ray, double %unnamed_arg, double %tmin, double %tmax, %struct.mrViewingHitRecord* %VHR, %struct.ggMaterialRecord* %unnamed_arg2) {
|
||||||
|
entry:
|
||||||
|
%tmp80.i = getelementptr %struct.mrViewingHitRecord, %struct.mrViewingHitRecord* %VHR, i32 0, i32 1, i32 0, i32 0 ; <double*> [#uses=1]
|
||||||
|
store double 0.000000e+00, double* %tmp80.i
|
||||||
|
br i1 false, label %return, label %cond_next.i
|
||||||
|
|
||||||
|
cond_next.i: ; preds = %entry
|
||||||
|
br i1 false, label %return, label %cond_true
|
||||||
|
|
||||||
|
cond_true: ; preds = %cond_next.i
|
||||||
|
%tmp3.i8 = getelementptr %struct.mrViewingHitRecord, %struct.mrViewingHitRecord* %VHR, i32 0, i32 1, i32 0, i32 0 ; <double*> [#uses=1]
|
||||||
|
%tmp46 = load double, double* %tmp3.i8 ; <double> [#uses=0]
|
||||||
|
ret i32 1
|
||||||
|
|
||||||
|
return: ; preds = %cond_next.i, %entry
|
||||||
|
ret i32 0
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
@last = external global [65 x i32*]
|
||||||
|
|
||||||
|
define i32 @NextRootMove(i32 %wtm, i32 %x, i32 %y, i32 %z) {
|
||||||
|
entry:
|
||||||
|
%A = alloca i32*
|
||||||
|
%tmp17618 = load i32*, i32** getelementptr ([65 x i32*], [65 x i32*]* @last, i32 0, i32 1), align 4
|
||||||
|
store i32* %tmp17618, i32** %A
|
||||||
|
; CHECK: entry:
|
||||||
|
; CHECK-NEXT: alloca i32
|
||||||
|
; CHECK-NEXT: %tmp17618 = load
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK-NOT: phi
|
||||||
|
br label %cond_true116
|
||||||
|
|
||||||
|
cond_true116:
|
||||||
|
%cmp = icmp eq i32 %x, %y
|
||||||
|
br i1 %cmp, label %cond_true128, label %cond_true145
|
||||||
|
|
||||||
|
cond_true128:
|
||||||
|
%tmp17625 = load i32*, i32** getelementptr ([65 x i32*], [65 x i32*]* @last, i32 0, i32 1), align 4
|
||||||
|
store i32* %tmp17625, i32** %A
|
||||||
|
%cmp1 = icmp eq i32 %x, %z
|
||||||
|
br i1 %cmp1 , label %bb98.backedge, label %return.loopexit
|
||||||
|
|
||||||
|
bb98.backedge:
|
||||||
|
br label %cond_true116
|
||||||
|
|
||||||
|
cond_true145:
|
||||||
|
%tmp17631 = load i32*, i32** getelementptr ([65 x i32*], [65 x i32*]* @last, i32 0, i32 1), align 4
|
||||||
|
store i32* %tmp17631, i32** %A
|
||||||
|
br i1 false, label %bb98.backedge, label %return.loopexit
|
||||||
|
|
||||||
|
return.loopexit:
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return:
|
||||||
|
ret i32 0
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
|
||||||
|
@bsLive = external global i32 ; <i32*> [#uses=2]
|
||||||
|
|
||||||
|
define i32 @bsR(i32 %n) {
|
||||||
|
entry:
|
||||||
|
br i1 false, label %cond_next, label %bb19
|
||||||
|
|
||||||
|
cond_next: ; preds = %entry
|
||||||
|
store i32 0, i32* @bsLive, align 4
|
||||||
|
br label %bb19
|
||||||
|
|
||||||
|
bb19: ; preds = %cond_next, %entry
|
||||||
|
%tmp29 = load i32, i32* @bsLive, align 4 ; <i32> [#uses=0]
|
||||||
|
ret i32 0
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
%struct..0anon = type { i32 }
|
||||||
|
%struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 }
|
||||||
|
%struct.__sFILEX = type opaque
|
||||||
|
%struct.__sbuf = type { i8*, i32 }
|
||||||
|
%struct.rtx_def = type { i16, i8, i8, [1 x %struct..0anon] }
|
||||||
|
@n_spills = external global i32 ; <i32*> [#uses=2]
|
||||||
|
|
||||||
|
define i32 @reload(%struct.rtx_def* %first, i32 %global, %struct.FILE* %dumpfile) {
|
||||||
|
cond_next2835.1: ; preds = %cond_next2861
|
||||||
|
%tmp2922 = load i32, i32* @n_spills, align 4 ; <i32> [#uses=0]
|
||||||
|
br label %bb2928
|
||||||
|
|
||||||
|
bb2928: ; preds = %cond_next2835.1, %cond_next2943
|
||||||
|
br i1 false, label %cond_next2943, label %cond_true2935
|
||||||
|
|
||||||
|
cond_true2935: ; preds = %bb2928
|
||||||
|
br label %cond_next2943
|
||||||
|
|
||||||
|
cond_next2943: ; preds = %cond_true2935, %bb2928
|
||||||
|
br i1 false, label %bb2982.preheader, label %bb2928
|
||||||
|
|
||||||
|
bb2982.preheader: ; preds = %cond_next2943
|
||||||
|
%tmp298316 = load i32, i32* @n_spills, align 4 ; <i32> [#uses=0]
|
||||||
|
ret i32 %tmp298316
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: define i32 @reload(%struct.rtx_def* %first, i32 %global, %struct.FILE* %dumpfile) {
|
||||||
|
; CHECK-NEXT: cond_next2835.1:
|
||||||
|
; CHECK-NEXT: br label %bb2928
|
||||||
|
; CHECK: bb2928:
|
||||||
|
; CHECK-NEXT: br i1 false, label %bb2928.cond_next2943_crit_edge, label %cond_true2935
|
||||||
|
; CHECK: bb2928.cond_next2943_crit_edge:
|
||||||
|
; CHECK-NEXT: br label %cond_next2943
|
||||||
|
; CHECK: cond_true2935:
|
||||||
|
; CHECK-NEXT: br label %cond_next2943
|
||||||
|
; CHECK: cond_next2943:
|
||||||
|
; CHECK-NEXT: br i1 false, label %bb2982.preheader, label %bb2928
|
||||||
|
; CHECK: bb2982.preheader:
|
||||||
|
; CHECK-NEXT: %tmp298316 = load i32, i32* @n_spills, align 4
|
||||||
|
; CHECK-NEXT: ret i32 %tmp298316
|
||||||
|
; CHECK-NEXT: }
|
|
@ -0,0 +1,274 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
|
||||||
|
%"struct.Block::$_16" = type { i32 }
|
||||||
|
%struct.Exp = type { %struct.Exp_*, i32, i32, i32, %struct.Exp*, %struct.Exp*, %"struct.Exp::$_10", %"struct.Block::$_16", %"struct.Exp::$_12" }
|
||||||
|
%"struct.Exp::$_10" = type { %struct.Exp* }
|
||||||
|
%"struct.Exp::$_12" = type { %struct.Exp** }
|
||||||
|
%struct.Exp_ = type { i32, i32, i32, i32, %struct.Id* }
|
||||||
|
%struct.Id = type { i8*, i32, i32, i32, %"struct.Id::$_13" }
|
||||||
|
%"struct.Id::$_13" = type { double }
|
||||||
|
|
||||||
|
define i8* @_ZN3Exp8toStringEj(%struct.Exp* %this, i32 %nextpc) {
|
||||||
|
entry:
|
||||||
|
switch i32 0, label %bb970 [
|
||||||
|
i32 1, label %bb
|
||||||
|
i32 2, label %bb39
|
||||||
|
i32 3, label %bb195
|
||||||
|
i32 4, label %bb270
|
||||||
|
i32 5, label %bb418
|
||||||
|
i32 6, label %bb633
|
||||||
|
i32 7, label %bb810
|
||||||
|
i32 8, label %bb882
|
||||||
|
i32 9, label %bb925
|
||||||
|
]
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb39: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true, label %cond_false132
|
||||||
|
|
||||||
|
cond_true: ; preds = %bb39
|
||||||
|
br i1 false, label %cond_true73, label %cond_false
|
||||||
|
|
||||||
|
cond_true73: ; preds = %cond_true
|
||||||
|
br i1 false, label %cond_true108, label %cond_next
|
||||||
|
|
||||||
|
cond_true108: ; preds = %cond_true73
|
||||||
|
br label %cond_next
|
||||||
|
|
||||||
|
cond_next: ; preds = %cond_true108, %cond_true73
|
||||||
|
br label %cond_next131
|
||||||
|
|
||||||
|
cond_false: ; preds = %cond_true
|
||||||
|
br label %cond_next131
|
||||||
|
|
||||||
|
cond_next131: ; preds = %cond_false, %cond_next
|
||||||
|
br label %cond_next141
|
||||||
|
|
||||||
|
cond_false132: ; preds = %bb39
|
||||||
|
br label %cond_next141
|
||||||
|
|
||||||
|
cond_next141: ; preds = %cond_false132, %cond_next131
|
||||||
|
br i1 false, label %cond_true169, label %cond_false175
|
||||||
|
|
||||||
|
cond_true169: ; preds = %cond_next141
|
||||||
|
br label %cond_next181
|
||||||
|
|
||||||
|
cond_false175: ; preds = %cond_next141
|
||||||
|
br label %cond_next181
|
||||||
|
|
||||||
|
cond_next181: ; preds = %cond_false175, %cond_true169
|
||||||
|
br i1 false, label %cond_true189, label %cond_next191
|
||||||
|
|
||||||
|
cond_true189: ; preds = %cond_next181
|
||||||
|
br label %cond_next191
|
||||||
|
|
||||||
|
cond_next191: ; preds = %cond_true189, %cond_next181
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb195: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true248, label %cond_false250
|
||||||
|
|
||||||
|
cond_true248: ; preds = %bb195
|
||||||
|
br label %cond_next252
|
||||||
|
|
||||||
|
cond_false250: ; preds = %bb195
|
||||||
|
br label %cond_next252
|
||||||
|
|
||||||
|
cond_next252: ; preds = %cond_false250, %cond_true248
|
||||||
|
br i1 false, label %cond_true265, label %cond_next267
|
||||||
|
|
||||||
|
cond_true265: ; preds = %cond_next252
|
||||||
|
br label %cond_next267
|
||||||
|
|
||||||
|
cond_next267: ; preds = %cond_true265, %cond_next252
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb270: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true338, label %cond_false340
|
||||||
|
|
||||||
|
cond_true338: ; preds = %bb270
|
||||||
|
br label %cond_next342
|
||||||
|
|
||||||
|
cond_false340: ; preds = %bb270
|
||||||
|
br label %cond_next342
|
||||||
|
|
||||||
|
cond_next342: ; preds = %cond_false340, %cond_true338
|
||||||
|
br i1 false, label %cond_true362, label %cond_false364
|
||||||
|
|
||||||
|
cond_true362: ; preds = %cond_next342
|
||||||
|
br label %cond_next366
|
||||||
|
|
||||||
|
cond_false364: ; preds = %cond_next342
|
||||||
|
br label %cond_next366
|
||||||
|
|
||||||
|
cond_next366: ; preds = %cond_false364, %cond_true362
|
||||||
|
br i1 false, label %cond_true393, label %cond_next395
|
||||||
|
|
||||||
|
cond_true393: ; preds = %cond_next366
|
||||||
|
br label %cond_next395
|
||||||
|
|
||||||
|
cond_next395: ; preds = %cond_true393, %cond_next366
|
||||||
|
br i1 false, label %cond_true406, label %cond_next408
|
||||||
|
|
||||||
|
cond_true406: ; preds = %cond_next395
|
||||||
|
br label %cond_next408
|
||||||
|
|
||||||
|
cond_next408: ; preds = %cond_true406, %cond_next395
|
||||||
|
br i1 false, label %cond_true413, label %cond_next415
|
||||||
|
|
||||||
|
cond_true413: ; preds = %cond_next408
|
||||||
|
br label %cond_next415
|
||||||
|
|
||||||
|
cond_next415: ; preds = %cond_true413, %cond_next408
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb418: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true512, label %cond_false514
|
||||||
|
|
||||||
|
cond_true512: ; preds = %bb418
|
||||||
|
br label %cond_next516
|
||||||
|
|
||||||
|
cond_false514: ; preds = %bb418
|
||||||
|
br label %cond_next516
|
||||||
|
|
||||||
|
cond_next516: ; preds = %cond_false514, %cond_true512
|
||||||
|
br i1 false, label %cond_true536, label %cond_false538
|
||||||
|
|
||||||
|
cond_true536: ; preds = %cond_next516
|
||||||
|
br label %cond_next540
|
||||||
|
|
||||||
|
cond_false538: ; preds = %cond_next516
|
||||||
|
br label %cond_next540
|
||||||
|
|
||||||
|
cond_next540: ; preds = %cond_false538, %cond_true536
|
||||||
|
br i1 false, label %cond_true560, label %cond_false562
|
||||||
|
|
||||||
|
cond_true560: ; preds = %cond_next540
|
||||||
|
br label %cond_next564
|
||||||
|
|
||||||
|
cond_false562: ; preds = %cond_next540
|
||||||
|
br label %cond_next564
|
||||||
|
|
||||||
|
cond_next564: ; preds = %cond_false562, %cond_true560
|
||||||
|
br i1 false, label %cond_true597, label %cond_next599
|
||||||
|
|
||||||
|
cond_true597: ; preds = %cond_next564
|
||||||
|
br label %cond_next599
|
||||||
|
|
||||||
|
cond_next599: ; preds = %cond_true597, %cond_next564
|
||||||
|
br i1 false, label %cond_true614, label %cond_next616
|
||||||
|
|
||||||
|
cond_true614: ; preds = %cond_next599
|
||||||
|
br label %cond_next616
|
||||||
|
|
||||||
|
cond_next616: ; preds = %cond_true614, %cond_next599
|
||||||
|
br i1 false, label %cond_true621, label %cond_next623
|
||||||
|
|
||||||
|
cond_true621: ; preds = %cond_next616
|
||||||
|
br label %cond_next623
|
||||||
|
|
||||||
|
cond_next623: ; preds = %cond_true621, %cond_next616
|
||||||
|
br i1 false, label %cond_true628, label %cond_next630
|
||||||
|
|
||||||
|
cond_true628: ; preds = %cond_next623
|
||||||
|
br label %cond_next630
|
||||||
|
|
||||||
|
cond_next630: ; preds = %cond_true628, %cond_next623
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb633: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true667, label %cond_next669
|
||||||
|
|
||||||
|
cond_true667: ; preds = %bb633
|
||||||
|
br label %cond_next669
|
||||||
|
|
||||||
|
cond_next669: ; preds = %cond_true667, %bb633
|
||||||
|
br i1 false, label %cond_true678, label %cond_next791
|
||||||
|
|
||||||
|
cond_true678: ; preds = %cond_next669
|
||||||
|
br label %bb735
|
||||||
|
|
||||||
|
bb679: ; preds = %bb735
|
||||||
|
br i1 false, label %cond_true729, label %cond_next731
|
||||||
|
|
||||||
|
cond_true729: ; preds = %bb679
|
||||||
|
br label %cond_next731
|
||||||
|
|
||||||
|
cond_next731: ; preds = %cond_true729, %bb679
|
||||||
|
br label %bb735
|
||||||
|
|
||||||
|
bb735: ; preds = %cond_next731, %cond_true678
|
||||||
|
br i1 false, label %bb679, label %bb743
|
||||||
|
|
||||||
|
bb743: ; preds = %bb735
|
||||||
|
br i1 false, label %cond_true788, label %cond_next790
|
||||||
|
|
||||||
|
cond_true788: ; preds = %bb743
|
||||||
|
br label %cond_next790
|
||||||
|
|
||||||
|
cond_next790: ; preds = %cond_true788, %bb743
|
||||||
|
br label %cond_next791
|
||||||
|
|
||||||
|
cond_next791: ; preds = %cond_next790, %cond_next669
|
||||||
|
br i1 false, label %cond_true805, label %cond_next807
|
||||||
|
|
||||||
|
cond_true805: ; preds = %cond_next791
|
||||||
|
br label %cond_next807
|
||||||
|
|
||||||
|
cond_next807: ; preds = %cond_true805, %cond_next791
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb810: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true870, label %cond_next872
|
||||||
|
|
||||||
|
cond_true870: ; preds = %bb810
|
||||||
|
br label %cond_next872
|
||||||
|
|
||||||
|
cond_next872: ; preds = %cond_true870, %bb810
|
||||||
|
br i1 false, label %cond_true877, label %cond_next879
|
||||||
|
|
||||||
|
cond_true877: ; preds = %cond_next872
|
||||||
|
br label %cond_next879
|
||||||
|
|
||||||
|
cond_next879: ; preds = %cond_true877, %cond_next872
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb882: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true920, label %cond_next922
|
||||||
|
|
||||||
|
cond_true920: ; preds = %bb882
|
||||||
|
br label %cond_next922
|
||||||
|
|
||||||
|
cond_next922: ; preds = %cond_true920, %bb882
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb925: ; preds = %entry
|
||||||
|
br i1 false, label %cond_true965, label %cond_next967
|
||||||
|
|
||||||
|
cond_true965: ; preds = %bb925
|
||||||
|
br label %cond_next967
|
||||||
|
|
||||||
|
cond_next967: ; preds = %cond_true965, %bb925
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
bb970: ; preds = %entry
|
||||||
|
unreachable
|
||||||
|
; No predecessors!
|
||||||
|
store i8* null, i8** null
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return: ; preds = %0, %cond_next967, %cond_next922, %cond_next879, %cond_next807, %cond_next630, %cond_next415, %cond_next267, %cond_next191, %bb
|
||||||
|
%retval980 = load i8*, i8** null ; <i8*> [#uses=1]
|
||||||
|
ret i8* %retval980
|
||||||
|
}
|
|
@ -0,0 +1,315 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
%struct.anon = type { i32 (i32, i32, i32)*, i32, i32, [3 x i32], i8*, i8*, i8* }
|
||||||
|
@debug = external constant i32 ; <i32*> [#uses=0]
|
||||||
|
@counters = external constant i32 ; <i32*> [#uses=1]
|
||||||
|
@trialx = external global [17 x i32] ; <[17 x i32]*> [#uses=1]
|
||||||
|
@dummy1 = external global [7 x i32] ; <[7 x i32]*> [#uses=0]
|
||||||
|
@dummy2 = external global [4 x i32] ; <[4 x i32]*> [#uses=0]
|
||||||
|
@unacceptable = external global i32 ; <i32*> [#uses=0]
|
||||||
|
@isa = external global [13 x %struct.anon] ; <[13 x %struct.anon]*> [#uses=3]
|
||||||
|
@.str = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str1 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0]
|
||||||
|
@.str2 = external constant [1 x i8] ; <[1 x i8]*> [#uses=0]
|
||||||
|
@.str3 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str4 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0]
|
||||||
|
@.str5 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str6 = external constant [2 x i8] ; <[2 x i8]*> [#uses=0]
|
||||||
|
@.str7 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str8 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str9 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str10 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str11 = external constant [2 x i8] ; <[2 x i8]*> [#uses=0]
|
||||||
|
@.str12 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str13 = external constant [2 x i8] ; <[2 x i8]*> [#uses=0]
|
||||||
|
@.str14 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0]
|
||||||
|
@.str15 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0]
|
||||||
|
@.str16 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str17 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str18 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0]
|
||||||
|
@.str19 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str20 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str21 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str22 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str23 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0]
|
||||||
|
@.str24 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str25 = external constant [6 x i8] ; <[6 x i8]*> [#uses=0]
|
||||||
|
@.str26 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0]
|
||||||
|
@.str27 = external constant [6 x i8] ; <[6 x i8]*> [#uses=0]
|
||||||
|
@r = external global [17 x i32] ; <[17 x i32]*> [#uses=0]
|
||||||
|
@.str28 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0]
|
||||||
|
@.str29 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0]
|
||||||
|
@pgm = external global [5 x { i32, [3 x i32] }] ; <[5 x { i32, [3 x i32] }]*> [#uses=4]
|
||||||
|
@.str30 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0]
|
||||||
|
@.str31 = external constant [13 x i8] ; <[13 x i8]*> [#uses=0]
|
||||||
|
@.str32 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0]
|
||||||
|
@.str33 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0]
|
||||||
|
@.str34 = external constant [20 x i8] ; <[20 x i8]*> [#uses=0]
|
||||||
|
@numi = external global i32 ; <i32*> [#uses=7]
|
||||||
|
@.str35 = external constant [10 x i8] ; <[10 x i8]*> [#uses=0]
|
||||||
|
@counter = external global [5 x i32] ; <[5 x i32]*> [#uses=2]
|
||||||
|
@itrialx.2510 = external global i32 ; <i32*> [#uses=0]
|
||||||
|
@.str36 = external constant [43 x i8] ; <[43 x i8]*> [#uses=0]
|
||||||
|
@.str37 = external constant [42 x i8] ; <[42 x i8]*> [#uses=0]
|
||||||
|
@corr_result = external global i32 ; <i32*> [#uses=0]
|
||||||
|
@.str38 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0]
|
||||||
|
@.str39 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0]
|
||||||
|
@.str40 = external constant [47 x i8] ; <[47 x i8]*> [#uses=0]
|
||||||
|
@correct_result = external global [17 x i32] ; <[17 x i32]*> [#uses=1]
|
||||||
|
@.str41 = external constant [46 x i8] ; <[46 x i8]*> [#uses=0]
|
||||||
|
@.str42 = external constant [32 x i8] ; <[32 x i8]*> [#uses=0]
|
||||||
|
@.str43 = external constant [44 x i8] ; <[44 x i8]*> [#uses=1]
|
||||||
|
@.str44 = external constant [21 x i8] ; <[21 x i8]*> [#uses=1]
|
||||||
|
@.str45 = external constant [12 x i8] ; <[12 x i8]*> [#uses=1]
|
||||||
|
@.str46 = external constant [5 x i8] ; <[5 x i8]*> [#uses=1]
|
||||||
|
@.str47 = external constant [12 x i8] ; <[12 x i8]*> [#uses=1]
|
||||||
|
|
||||||
|
declare i32 @neg(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @Not(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @pop(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @nlz(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @rev(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @add(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @sub(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @mul(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @divide(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @divu(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @And(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @Or(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @Xor(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @rotl(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @shl(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @shr(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @shrs(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @cmpeq(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @cmplt(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @cmpltu(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @seleq(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @sellt(i32, i32, i32)
|
||||||
|
|
||||||
|
declare i32 @selle(i32, i32, i32)
|
||||||
|
|
||||||
|
declare void @print_expr(i32)
|
||||||
|
|
||||||
|
declare i32 @printf(i8*, ...)
|
||||||
|
|
||||||
|
declare i32 @putchar(i32)
|
||||||
|
|
||||||
|
declare void @print_pgm()
|
||||||
|
|
||||||
|
declare void @simulate_one_instruction(i32)
|
||||||
|
|
||||||
|
declare i32 @check(i32)
|
||||||
|
|
||||||
|
declare i32 @puts(i8*)
|
||||||
|
|
||||||
|
declare void @fix_operands(i32)
|
||||||
|
|
||||||
|
declare void @abort()
|
||||||
|
|
||||||
|
declare i32 @increment()
|
||||||
|
|
||||||
|
declare i32 @search()
|
||||||
|
|
||||||
|
define i32 @main(i32 %argc, i8** %argv) {
|
||||||
|
entry:
|
||||||
|
%argc_addr = alloca i32 ; <i32*> [#uses=1]
|
||||||
|
%argv_addr = alloca i8** ; <i8***> [#uses=1]
|
||||||
|
%retval = alloca i32, align 4 ; <i32*> [#uses=2]
|
||||||
|
%tmp = alloca i32, align 4 ; <i32*> [#uses=2]
|
||||||
|
%i = alloca i32, align 4 ; <i32*> [#uses=21]
|
||||||
|
%num_sol = alloca i32, align 4 ; <i32*> [#uses=4]
|
||||||
|
%total = alloca i32, align 4 ; <i32*> [#uses=4]
|
||||||
|
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
|
||||||
|
store i32 %argc, i32* %argc_addr
|
||||||
|
store i8** %argv, i8*** %argv_addr
|
||||||
|
store i32 0, i32* %num_sol
|
||||||
|
store i32 1, i32* @numi
|
||||||
|
br label %bb91
|
||||||
|
|
||||||
|
bb: ; preds = %cond_next97
|
||||||
|
%tmp1 = load i32, i32* @numi ; <i32> [#uses=1]
|
||||||
|
%tmp2 = getelementptr [44 x i8], [44 x i8]* @.str43, i32 0, i32 0 ; <i8*> [#uses=1]
|
||||||
|
%tmp3 = call i32 (i8*, ...) @printf( i8* %tmp2, i32 %tmp1 ) ; <i32> [#uses=0]
|
||||||
|
store i32 0, i32* %i
|
||||||
|
br label %bb13
|
||||||
|
|
||||||
|
bb4: ; preds = %bb13
|
||||||
|
%tmp5 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp6 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp7 = getelementptr [17 x i32], [17 x i32]* @trialx, i32 0, i32 %tmp6 ; <i32*> [#uses=1]
|
||||||
|
%tmp8 = load i32, i32* %tmp7 ; <i32> [#uses=1]
|
||||||
|
%tmp9 = call i32 @userfun( i32 %tmp8 ) ; <i32> [#uses=1]
|
||||||
|
%tmp10 = getelementptr [17 x i32], [17 x i32]* @correct_result, i32 0, i32 %tmp5 ; <i32*> [#uses=1]
|
||||||
|
store i32 %tmp9, i32* %tmp10
|
||||||
|
%tmp11 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp12 = add i32 %tmp11, 1 ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp12, i32* %i
|
||||||
|
br label %bb13
|
||||||
|
|
||||||
|
bb13: ; preds = %bb4, %bb
|
||||||
|
%tmp14 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp15 = icmp sle i32 %tmp14, 16 ; <i1> [#uses=1]
|
||||||
|
%tmp1516 = zext i1 %tmp15 to i32 ; <i32> [#uses=1]
|
||||||
|
%toBool = icmp ne i32 %tmp1516, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool, label %bb4, label %bb17
|
||||||
|
|
||||||
|
bb17: ; preds = %bb13
|
||||||
|
store i32 0, i32* %i
|
||||||
|
br label %bb49
|
||||||
|
|
||||||
|
bb18: ; preds = %bb49
|
||||||
|
%tmp19 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp20 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp19 ; <{ i32, [3 x i32] }*> [#uses=1]
|
||||||
|
%tmp21 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp20, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
store i32 0, i32* %tmp21
|
||||||
|
%tmp22 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp23 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1]
|
||||||
|
%tmp24 = getelementptr %struct.anon, %struct.anon* %tmp23, i32 0, i32 3 ; <[3 x i32]*> [#uses=1]
|
||||||
|
%tmp25 = getelementptr [3 x i32], [3 x i32]* %tmp24, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
%tmp26 = load i32, i32* %tmp25 ; <i32> [#uses=1]
|
||||||
|
%tmp27 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp22 ; <{ i32, [3 x i32] }*> [#uses=1]
|
||||||
|
%tmp28 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp27, i32 0, i32 1 ; <[3 x i32]*> [#uses=1]
|
||||||
|
%tmp29 = getelementptr [3 x i32], [3 x i32]* %tmp28, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
store i32 %tmp26, i32* %tmp29
|
||||||
|
%tmp30 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp31 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1]
|
||||||
|
%tmp32 = getelementptr %struct.anon, %struct.anon* %tmp31, i32 0, i32 3 ; <[3 x i32]*> [#uses=1]
|
||||||
|
%tmp33 = getelementptr [3 x i32], [3 x i32]* %tmp32, i32 0, i32 1 ; <i32*> [#uses=1]
|
||||||
|
%tmp34 = load i32, i32* %tmp33 ; <i32> [#uses=1]
|
||||||
|
%tmp35 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp30 ; <{ i32, [3 x i32] }*> [#uses=1]
|
||||||
|
%tmp36 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp35, i32 0, i32 1 ; <[3 x i32]*> [#uses=1]
|
||||||
|
%tmp37 = getelementptr [3 x i32], [3 x i32]* %tmp36, i32 0, i32 1 ; <i32*> [#uses=1]
|
||||||
|
store i32 %tmp34, i32* %tmp37
|
||||||
|
%tmp38 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp39 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1]
|
||||||
|
%tmp40 = getelementptr %struct.anon, %struct.anon* %tmp39, i32 0, i32 3 ; <[3 x i32]*> [#uses=1]
|
||||||
|
%tmp41 = getelementptr [3 x i32], [3 x i32]* %tmp40, i32 0, i32 2 ; <i32*> [#uses=1]
|
||||||
|
%tmp42 = load i32, i32* %tmp41 ; <i32> [#uses=1]
|
||||||
|
%tmp43 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp38 ; <{ i32, [3 x i32] }*> [#uses=1]
|
||||||
|
%tmp44 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp43, i32 0, i32 1 ; <[3 x i32]*> [#uses=1]
|
||||||
|
%tmp45 = getelementptr [3 x i32], [3 x i32]* %tmp44, i32 0, i32 2 ; <i32*> [#uses=1]
|
||||||
|
store i32 %tmp42, i32* %tmp45
|
||||||
|
%tmp46 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
call void @fix_operands( i32 %tmp46 )
|
||||||
|
%tmp47 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
; CHECK: %tmp47 = phi i32 [ %tmp48, %bb18 ], [ 0, %bb17 ]
|
||||||
|
%tmp48 = add i32 %tmp47, 1 ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp48, i32* %i
|
||||||
|
br label %bb49
|
||||||
|
|
||||||
|
bb49: ; preds = %bb18, %bb17
|
||||||
|
%tmp50 = load i32, i32* @numi ; <i32> [#uses=1]
|
||||||
|
%tmp51 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp52 = icmp slt i32 %tmp51, %tmp50 ; <i1> [#uses=1]
|
||||||
|
%tmp5253 = zext i1 %tmp52 to i32 ; <i32> [#uses=1]
|
||||||
|
%toBool54 = icmp ne i32 %tmp5253, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool54, label %bb18, label %bb55
|
||||||
|
|
||||||
|
bb55: ; preds = %bb49
|
||||||
|
%tmp56 = call i32 @search( ) ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp56, i32* %num_sol
|
||||||
|
%tmp57 = getelementptr [21 x i8], [21 x i8]* @.str44, i32 0, i32 0 ; <i8*> [#uses=1]
|
||||||
|
%tmp58 = load i32, i32* %num_sol ; <i32> [#uses=1]
|
||||||
|
%tmp59 = call i32 (i8*, ...) @printf( i8* %tmp57, i32 %tmp58 ) ; <i32> [#uses=0]
|
||||||
|
%tmp60 = load i32, i32* @counters ; <i32> [#uses=1]
|
||||||
|
%tmp61 = icmp ne i32 %tmp60, 0 ; <i1> [#uses=1]
|
||||||
|
%tmp6162 = zext i1 %tmp61 to i32 ; <i32> [#uses=1]
|
||||||
|
%toBool63 = icmp ne i32 %tmp6162, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool63, label %cond_true, label %cond_next
|
||||||
|
|
||||||
|
cond_true: ; preds = %bb55
|
||||||
|
store i32 0, i32* %total
|
||||||
|
%tmp64 = getelementptr [12 x i8], [12 x i8]* @.str45, i32 0, i32 0 ; <i8*> [#uses=1]
|
||||||
|
%tmp65 = call i32 (i8*, ...) @printf( i8* %tmp64 ) ; <i32> [#uses=0]
|
||||||
|
store i32 0, i32* %i
|
||||||
|
br label %bb79
|
||||||
|
|
||||||
|
bb66: ; preds = %bb79
|
||||||
|
%tmp67 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp68 = getelementptr [5 x i32], [5 x i32]* @counter, i32 0, i32 %tmp67 ; <i32*> [#uses=1]
|
||||||
|
%tmp69 = load i32, i32* %tmp68 ; <i32> [#uses=1]
|
||||||
|
%tmp70 = getelementptr [5 x i8], [5 x i8]* @.str46, i32 0, i32 0 ; <i8*> [#uses=1]
|
||||||
|
%tmp71 = call i32 (i8*, ...) @printf( i8* %tmp70, i32 %tmp69 ) ; <i32> [#uses=0]
|
||||||
|
%tmp72 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp73 = getelementptr [5 x i32], [5 x i32]* @counter, i32 0, i32 %tmp72 ; <i32*> [#uses=1]
|
||||||
|
%tmp74 = load i32, i32* %tmp73 ; <i32> [#uses=1]
|
||||||
|
%tmp75 = load i32, i32* %total ; <i32> [#uses=1]
|
||||||
|
%tmp76 = add i32 %tmp74, %tmp75 ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp76, i32* %total
|
||||||
|
%tmp77 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp78 = add i32 %tmp77, 1 ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp78, i32* %i
|
||||||
|
br label %bb79
|
||||||
|
|
||||||
|
bb79: ; preds = %bb66, %cond_true
|
||||||
|
%tmp80 = load i32, i32* @numi ; <i32> [#uses=1]
|
||||||
|
%tmp81 = load i32, i32* %i ; <i32> [#uses=1]
|
||||||
|
%tmp82 = icmp slt i32 %tmp81, %tmp80 ; <i1> [#uses=1]
|
||||||
|
%tmp8283 = zext i1 %tmp82 to i32 ; <i32> [#uses=1]
|
||||||
|
%toBool84 = icmp ne i32 %tmp8283, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool84, label %bb66, label %bb85
|
||||||
|
|
||||||
|
bb85: ; preds = %bb79
|
||||||
|
%tmp86 = getelementptr [12 x i8], [12 x i8]* @.str47, i32 0, i32 0 ; <i8*> [#uses=1]
|
||||||
|
%tmp87 = load i32, i32* %total ; <i32> [#uses=1]
|
||||||
|
%tmp88 = call i32 (i8*, ...) @printf( i8* %tmp86, i32 %tmp87 ) ; <i32> [#uses=0]
|
||||||
|
br label %cond_next
|
||||||
|
|
||||||
|
cond_next: ; preds = %bb85, %bb55
|
||||||
|
%tmp89 = load i32, i32* @numi ; <i32> [#uses=1]
|
||||||
|
%tmp90 = add i32 %tmp89, 1 ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp90, i32* @numi
|
||||||
|
br label %bb91
|
||||||
|
|
||||||
|
bb91: ; preds = %cond_next, %entry
|
||||||
|
%tmp92 = load i32, i32* @numi ; <i32> [#uses=1]
|
||||||
|
%tmp93 = icmp sgt i32 %tmp92, 5 ; <i1> [#uses=1]
|
||||||
|
%tmp9394 = zext i1 %tmp93 to i32 ; <i32> [#uses=1]
|
||||||
|
%toBool95 = icmp ne i32 %tmp9394, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool95, label %cond_true96, label %cond_next97
|
||||||
|
|
||||||
|
cond_true96: ; preds = %bb91
|
||||||
|
br label %bb102
|
||||||
|
|
||||||
|
cond_next97: ; preds = %bb91
|
||||||
|
%tmp98 = load i32, i32* %num_sol ; <i32> [#uses=1]
|
||||||
|
%tmp99 = icmp eq i32 %tmp98, 0 ; <i1> [#uses=1]
|
||||||
|
%tmp99100 = zext i1 %tmp99 to i32 ; <i32> [#uses=1]
|
||||||
|
%toBool101 = icmp ne i32 %tmp99100, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool101, label %bb, label %bb102
|
||||||
|
|
||||||
|
bb102: ; preds = %cond_next97, %cond_true96
|
||||||
|
store i32 0, i32* %tmp
|
||||||
|
%tmp103 = load i32, i32* %tmp ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp103, i32* %retval
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return: ; preds = %bb102
|
||||||
|
%retval104 = load i32, i32* %retval ; <i32> [#uses=1]
|
||||||
|
ret i32 %retval104
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @userfun(i32)
|
|
@ -0,0 +1,23 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
@img_width = external global i16 ; <i16*> [#uses=2]
|
||||||
|
|
||||||
|
define i32 @smpUMHEXBipredIntegerPelBlockMotionSearch(i16* %cur_pic, i16 signext %ref, i32 %list, i32 %pic_pix_x, i32 %pic_pix_y, i32 %blocktype, i16 signext %pred_mv_x1, i16 signext %pred_mv_y1, i16 signext %pred_mv_x2, i16 signext %pred_mv_y2, i16* %mv_x, i16* %mv_y, i16* %s_mv_x, i16* %s_mv_y, i32 %search_range, i32 %min_mcost, i32 %lambda_factor) {
|
||||||
|
cond_next143: ; preds = %entry
|
||||||
|
store i16 0, i16* @img_width, align 2
|
||||||
|
br i1 false, label %cond_next449, label %cond_false434
|
||||||
|
|
||||||
|
cond_false434: ; preds = %cond_true415
|
||||||
|
br label %cond_next449
|
||||||
|
|
||||||
|
cond_next449: ; preds = %cond_false434, %cond_true415
|
||||||
|
br i1 false, label %cond_next698, label %cond_false470
|
||||||
|
|
||||||
|
cond_false470: ; preds = %cond_next449
|
||||||
|
br label %cond_next698
|
||||||
|
|
||||||
|
cond_next698: ; preds = %cond_true492
|
||||||
|
%tmp701 = load i16, i16* @img_width, align 2 ; <i16> [#uses=0]
|
||||||
|
; CHECK-NOT: %tmp701 =
|
||||||
|
ret i32 0
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
; PR1996
|
||||||
|
|
||||||
|
%struct.anon = type { i32, i8, i8, i8, i8 }
|
||||||
|
|
||||||
|
define i32 @a() {
|
||||||
|
entry:
|
||||||
|
%c = alloca %struct.anon ; <%struct.anon*> [#uses=2]
|
||||||
|
%tmp = getelementptr %struct.anon, %struct.anon* %c, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
%tmp1 = getelementptr i32, i32* %tmp, i32 1 ; <i32*> [#uses=2]
|
||||||
|
%tmp2 = load i32, i32* %tmp1, align 4 ; <i32> [#uses=1]
|
||||||
|
; CHECK-NOT: load
|
||||||
|
%tmp3 = or i32 %tmp2, 11 ; <i32> [#uses=1]
|
||||||
|
%tmp4 = and i32 %tmp3, -21 ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp4, i32* %tmp1, align 4
|
||||||
|
%call = call i32 (...) @x( %struct.anon* %c ) ; <i32> [#uses=0]
|
||||||
|
ret i32 undef
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
declare i32 @x(...)
|
|
@ -0,0 +1,22 @@
|
||||||
|
; RUN: opt < %s -newgvn
|
||||||
|
; PR2032
|
||||||
|
|
||||||
|
define i32 @sscal(i32 %n, double %sa1, float* %sx, i32 %incx) {
|
||||||
|
entry:
|
||||||
|
%sx_addr = alloca float* ; <float**> [#uses=3]
|
||||||
|
store float* %sx, float** %sx_addr, align 4
|
||||||
|
br label %bb33
|
||||||
|
|
||||||
|
bb: ; preds = %bb33
|
||||||
|
%tmp27 = load float*, float** %sx_addr, align 4 ; <float*> [#uses=1]
|
||||||
|
store float 0.000000e+00, float* %tmp27, align 4
|
||||||
|
store float* null, float** %sx_addr, align 4
|
||||||
|
br label %bb33
|
||||||
|
|
||||||
|
bb33: ; preds = %bb, %entry
|
||||||
|
br i1 false, label %bb, label %return
|
||||||
|
|
||||||
|
return: ; preds = %bb33
|
||||||
|
%retval59 = load i32, i32* null, align 4 ; <i32> [#uses=1]
|
||||||
|
ret i32 %retval59
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
; PR2503
|
||||||
|
|
||||||
|
@g_3 = external global i8 ; <i8*> [#uses=2]
|
||||||
|
|
||||||
|
define i8 @func_1(i32 %x, i32 %y) nounwind {
|
||||||
|
entry:
|
||||||
|
%A = alloca i8
|
||||||
|
%cmp = icmp eq i32 %x, %y
|
||||||
|
br i1 %cmp, label %ifelse, label %ifthen
|
||||||
|
|
||||||
|
ifthen: ; preds = %entry
|
||||||
|
br label %ifend
|
||||||
|
|
||||||
|
ifelse: ; preds = %entry
|
||||||
|
%tmp3 = load i8, i8* @g_3 ; <i8> [#uses=0]
|
||||||
|
store i8 %tmp3, i8* %A
|
||||||
|
br label %afterfor
|
||||||
|
|
||||||
|
forcond: ; preds = %forinc
|
||||||
|
br i1 false, label %afterfor, label %forbody
|
||||||
|
|
||||||
|
forbody: ; preds = %forcond
|
||||||
|
br label %forinc
|
||||||
|
|
||||||
|
forinc: ; preds = %forbody
|
||||||
|
br label %forcond
|
||||||
|
|
||||||
|
afterfor: ; preds = %forcond, %forcond.thread
|
||||||
|
%tmp10 = load i8, i8* @g_3 ; <i8> [#uses=0]
|
||||||
|
ret i8 %tmp10
|
||||||
|
; CHECK: ret i8 %tmp3
|
||||||
|
|
||||||
|
ifend: ; preds = %afterfor, %ifthen
|
||||||
|
ret i8 0
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin9.5"
|
||||||
|
%struct.anon = type { i8*, i32 }
|
||||||
|
%struct.d_print_info = type { i32, i8*, i32, i32, %struct.d_print_template*, %struct.d_print_mod*, i32 }
|
||||||
|
%struct.d_print_mod = type { %struct.d_print_mod*, %struct.demangle_component*, i32, %struct.d_print_template* }
|
||||||
|
%struct.d_print_template = type { %struct.d_print_template*, %struct.demangle_component* }
|
||||||
|
%struct.demangle_component = type { i32, { %struct.anon } }
|
||||||
|
|
||||||
|
define void @d_print_mod_list(%struct.d_print_info* %dpi, %struct.d_print_mod* %mods, i32 %suffix) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1 ; <i8**> [#uses=1]
|
||||||
|
br i1 false, label %return, label %bb
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
%1 = load i8*, i8** %0, align 4 ; <i8*> [#uses=0]
|
||||||
|
%2 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1 ; <i8**> [#uses=0]
|
||||||
|
br label %bb21
|
||||||
|
|
||||||
|
bb21: ; preds = %bb21, %bb
|
||||||
|
br label %bb21
|
||||||
|
|
||||||
|
return: ; preds = %entry
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: define void @d_print_mod_list(%struct.d_print_info* %dpi, %struct.d_print_mod* %mods, i32 %suffix) #0 {
|
||||||
|
; CHECK: entry:
|
||||||
|
; CHECK: %0 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1
|
||||||
|
; CHECK: br i1 false, label %return, label %bb
|
||||||
|
; CHECK: bb:
|
||||||
|
; CHECK: br label %bb21
|
||||||
|
; CHECK: bb21:
|
||||||
|
; CHECK: br label %bb21
|
||||||
|
; CHECK: return:
|
||||||
|
; CHECK: ret void
|
||||||
|
; CHECK: }
|
|
@ -0,0 +1,35 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin7"
|
||||||
|
|
||||||
|
define i32 @main(i32 %argc, i8** %argv) nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb84
|
||||||
|
|
||||||
|
bb41: ; preds = %bb82
|
||||||
|
%tmp = load i8, i8* %opt.0, align 1 ; <i8> [#uses=0]
|
||||||
|
%tmp1 = getelementptr i8, i8* %opt.0, i32 1 ; <i8*> [#uses=2]
|
||||||
|
switch i32 0, label %bb81 [
|
||||||
|
i32 102, label %bb82
|
||||||
|
i32 110, label %bb79
|
||||||
|
i32 118, label %bb80
|
||||||
|
]
|
||||||
|
|
||||||
|
bb79: ; preds = %bb41
|
||||||
|
br label %bb82
|
||||||
|
|
||||||
|
bb80: ; preds = %bb41
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
bb81: ; preds = %bb41
|
||||||
|
ret i32 1
|
||||||
|
|
||||||
|
bb82: ; preds = %bb84, %bb79, %bb41
|
||||||
|
%opt.0 = phi i8* [ %tmp3, %bb84 ], [ %tmp1, %bb79 ], [ %tmp1, %bb41 ] ; <i8*> [#uses=3]
|
||||||
|
%tmp2 = load i8, i8* %opt.0, align 1 ; <i8> [#uses=0]
|
||||||
|
br i1 false, label %bb84, label %bb41
|
||||||
|
|
||||||
|
bb84: ; preds = %bb82, %entry
|
||||||
|
%tmp3 = getelementptr i8, i8* null, i32 1 ; <i8*> [#uses=1]
|
||||||
|
br label %bb82
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin7"
|
||||||
|
@sort_value = external global [256 x i32], align 32 ; <[256 x i32]*> [#uses=2]
|
||||||
|
|
||||||
|
define i32 @Quiesce(i32 %alpha, i32 %beta, i32 %wtm, i32 %ply) nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb22
|
||||||
|
|
||||||
|
bb22: ; preds = %bb23, %bb22, %entry
|
||||||
|
br i1 false, label %bb23, label %bb22
|
||||||
|
|
||||||
|
bb23: ; preds = %bb23, %bb22
|
||||||
|
%sortv.233 = phi i32* [ getelementptr ([256 x i32], [256 x i32]* @sort_value, i32 0, i32 0), %bb22 ], [ %sortv.2, %bb23 ] ; <i32*> [#uses=1]
|
||||||
|
%0 = load i32, i32* %sortv.233, align 4 ; <i32> [#uses=0]
|
||||||
|
%sortv.2 = getelementptr [256 x i32], [256 x i32]* @sort_value, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||||
|
br i1 false, label %bb23, label %bb22
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
; Cached results must be added to and verified against the visited sets.
|
||||||
|
; PR3217
|
||||||
|
|
||||||
|
define fastcc void @gen_field_die(i32* %decl) nounwind {
|
||||||
|
entry:
|
||||||
|
br i1 false, label %bb203, label %bb202
|
||||||
|
|
||||||
|
bb202: ; preds = %entry
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
bb203: ; preds = %entry
|
||||||
|
%tmp = getelementptr i32, i32* %decl, i32 1 ; <i32*> [#uses=1]
|
||||||
|
%tmp1 = load i32, i32* %tmp, align 4 ; <i32> [#uses=0]
|
||||||
|
br i1 false, label %bb207, label %bb204
|
||||||
|
|
||||||
|
bb204: ; preds = %bb203
|
||||||
|
%tmp2 = getelementptr i32, i32* %decl, i32 1 ; <i32*> [#uses=1]
|
||||||
|
br label %bb208
|
||||||
|
|
||||||
|
bb207: ; preds = %bb203
|
||||||
|
br label %bb208
|
||||||
|
|
||||||
|
bb208: ; preds = %bb207, %bb204
|
||||||
|
%iftmp.1374.0.in = phi i32* [ null, %bb207 ], [ %tmp2, %bb204 ] ; <i32*> [#uses=1]
|
||||||
|
%iftmp.1374.0 = load i32, i32* %iftmp.1374.0.in ; <i32> [#uses=0]
|
||||||
|
unreachable
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
; PR3358
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
%struct.re_pattern_buffer = type { i8*, i64, i64, i64, i8*, i8*, i64, i8 }
|
||||||
|
%struct.re_registers = type { i32, i32*, i32* }
|
||||||
|
|
||||||
|
define fastcc i32 @byte_re_match_2_internal(%struct.re_pattern_buffer* nocapture %bufp, i8* %string1, i32 %size1, i8* %string2, i32 %size2, i32 %pos, %struct.re_registers* %regs, i32 %stop) nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb159
|
||||||
|
|
||||||
|
succeed_label: ; preds = %bb159
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
bb159: ; preds = %bb664, %bb554, %bb159, %bb159, %bb159, %entry
|
||||||
|
%d.0 = phi i8* [ null, %entry ], [ %d.0, %bb159 ], [ %d.0, %bb554 ], [ %d.0, %bb159 ], [ %d.0, %bb159 ], [ %d.12, %bb664 ] ; <i8*> [#uses=5]
|
||||||
|
switch i32 0, label %bb661 [
|
||||||
|
i32 0, label %bb159
|
||||||
|
i32 1, label %succeed_label
|
||||||
|
i32 13, label %bb159
|
||||||
|
i32 14, label %bb159
|
||||||
|
i32 16, label %bb411
|
||||||
|
i32 24, label %bb622
|
||||||
|
i32 28, label %bb543
|
||||||
|
]
|
||||||
|
|
||||||
|
bb411: ; preds = %bb411, %bb159
|
||||||
|
br label %bb411
|
||||||
|
|
||||||
|
bb543: ; preds = %bb159
|
||||||
|
br i1 false, label %bb549, label %bb550
|
||||||
|
|
||||||
|
bb549: ; preds = %bb543
|
||||||
|
br label %bb554
|
||||||
|
|
||||||
|
bb550: ; preds = %bb543
|
||||||
|
br i1 false, label %bb554, label %bb552
|
||||||
|
|
||||||
|
bb552: ; preds = %bb550
|
||||||
|
%0 = load i8, i8* %d.0, align 8 ; <i8> [#uses=0]
|
||||||
|
br label %bb554
|
||||||
|
|
||||||
|
bb554: ; preds = %bb552, %bb550, %bb549
|
||||||
|
br i1 false, label %bb159, label %bb661
|
||||||
|
|
||||||
|
bb622: ; preds = %bb622, %bb159
|
||||||
|
br label %bb622
|
||||||
|
|
||||||
|
bb661: ; preds = %bb554, %bb159
|
||||||
|
%d.12 = select i1 false, i8* null, i8* null ; <i8*> [#uses=1]
|
||||||
|
br label %bb664
|
||||||
|
|
||||||
|
bb664: ; preds = %bb664, %bb661
|
||||||
|
br i1 false, label %bb159, label %bb664
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin7"
|
||||||
|
%struct..4sPragmaType = type { i8*, i32 }
|
||||||
|
%struct.AggInfo = type { i8, i8, i32, %struct.ExprList*, i32, %struct.AggInfo_col*, i32, i32, i32, %struct.AggInfo_func*, i32, i32 }
|
||||||
|
%struct.AggInfo_col = type { %struct.Table*, i32, i32, i32, i32, %struct.Expr* }
|
||||||
|
%struct.AggInfo_func = type { %struct.Expr*, %struct.FuncDef*, i32, i32 }
|
||||||
|
%struct.AuxData = type { i8*, void (i8*)* }
|
||||||
|
%struct.Bitvec = type { i32, i32, i32, { [125 x i32] } }
|
||||||
|
%struct.BtCursor = type { %struct.Btree*, %struct.BtShared*, %struct.BtCursor*, %struct.BtCursor*, i32 (i8*, i32, i8*, i32, i8*)*, i8*, i32, %struct.MemPage*, i32, %struct.CellInfo, i8, i8, i8*, i64, i32, i8, i32* }
|
||||||
|
%struct.BtLock = type { %struct.Btree*, i32, i8, %struct.BtLock* }
|
||||||
|
%struct.BtShared = type { %struct.Pager*, %struct.sqlite3*, %struct.BtCursor*, %struct.MemPage*, i8, i8, i8, i8, i8, i8, i8, i8, i32, i16, i16, i32, i32, i32, i32, i8, i32, i8*, void (i8*)*, %struct.sqlite3_mutex*, %struct.BusyHandler, i32, %struct.BtShared*, %struct.BtLock*, %struct.Btree* }
|
||||||
|
%struct.Btree = type { %struct.sqlite3*, %struct.BtShared*, i8, i8, i8, i32, %struct.Btree*, %struct.Btree* }
|
||||||
|
%struct.BtreeMutexArray = type { i32, [11 x %struct.Btree*] }
|
||||||
|
%struct.BusyHandler = type { i32 (i8*, i32)*, i8*, i32 }
|
||||||
|
%struct.CellInfo = type { i8*, i64, i32, i32, i16, i16, i16, i16 }
|
||||||
|
%struct.CollSeq = type { i8*, i8, i8, i8*, i32 (i8*, i32, i8*, i32, i8*)*, void (i8*)* }
|
||||||
|
%struct.Column = type { i8*, %struct.Expr*, i8*, i8*, i8, i8, i8, i8 }
|
||||||
|
%struct.Context = type { i64, i32, %struct.Fifo }
|
||||||
|
%struct.CountCtx = type { i64 }
|
||||||
|
%struct.Cursor = type { %struct.BtCursor*, i32, i64, i64, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i64, %struct.Btree*, i32, i8*, i64, i8*, %struct.KeyInfo*, i32, i64, %struct.sqlite3_vtab_cursor*, %struct.sqlite3_module*, i32, i32, i32*, i32*, i8* }
|
||||||
|
%struct.Db = type { i8*, %struct.Btree*, i8, i8, i8*, void (i8*)*, %struct.Schema* }
|
||||||
|
%struct.Expr = type { i8, i8, i16, %struct.CollSeq*, %struct.Expr*, %struct.Expr*, %struct.ExprList*, %struct..4sPragmaType, %struct..4sPragmaType, i32, i32, %struct.AggInfo*, i32, i32, %struct.Select*, %struct.Table*, i32 }
|
||||||
|
%struct.ExprList = type { i32, i32, i32, %struct.ExprList_item* }
|
||||||
|
%struct.ExprList_item = type { %struct.Expr*, i8*, i8, i8, i8 }
|
||||||
|
%struct.FKey = type { %struct.Table*, %struct.FKey*, i8*, %struct.FKey*, i32, %struct.sColMap*, i8, i8, i8, i8 }
|
||||||
|
%struct.Fifo = type { i32, %struct.FifoPage*, %struct.FifoPage* }
|
||||||
|
%struct.FifoPage = type { i32, i32, i32, %struct.FifoPage*, [1 x i64] }
|
||||||
|
%struct.FuncDef = type { i16, i8, i8, i8, i8*, %struct.FuncDef*, void (%struct.sqlite3_context*, i32, %struct.Mem**)*, void (%struct.sqlite3_context*, i32, %struct.Mem**)*, void (%struct.sqlite3_context*)*, [1 x i8] }
|
||||||
|
%struct.Hash = type { i8, i8, i32, i32, %struct.HashElem*, %struct._ht* }
|
||||||
|
%struct.HashElem = type { %struct.HashElem*, %struct.HashElem*, i8*, i8*, i32 }
|
||||||
|
%struct.IdList = type { %struct..4sPragmaType*, i32, i32 }
|
||||||
|
%struct.Index = type { i8*, i32, i32*, i32*, %struct.Table*, i32, i8, i8, i8*, %struct.Index*, %struct.Schema*, i8*, i8** }
|
||||||
|
%struct.KeyInfo = type { %struct.sqlite3*, i8, i8, i8, i32, i8*, [1 x %struct.CollSeq*] }
|
||||||
|
%struct.Mem = type { %struct.CountCtx, double, %struct.sqlite3*, i8*, i32, i16, i8, i8, void (i8*)* }
|
||||||
|
%struct.MemPage = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i16, i16, i16, i16, i16, i16, [5 x %struct._OvflCell], %struct.BtShared*, i8*, %struct.PgHdr*, i32, %struct.MemPage* }
|
||||||
|
%struct.Module = type { %struct.sqlite3_module*, i8*, i8*, void (i8*)* }
|
||||||
|
%struct.Op = type { i8, i8, i8, i8, i32, i32, i32, { i32 } }
|
||||||
|
%struct.Pager = type { %struct.sqlite3_vfs*, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %struct.Bitvec*, %struct.Bitvec*, i8*, i8*, i8*, i8*, %struct.sqlite3_file*, %struct.sqlite3_file*, %struct.sqlite3_file*, %struct.BusyHandler*, %struct.PagerLruList, %struct.PgHdr*, %struct.PgHdr*, %struct.PgHdr*, i64, i64, i64, i64, i64, i32, void (%struct.PgHdr*, i32)*, void (%struct.PgHdr*, i32)*, i32, %struct.PgHdr**, i8*, [16 x i8] }
|
||||||
|
%struct.PagerLruLink = type { %struct.PgHdr*, %struct.PgHdr* }
|
||||||
|
%struct.PagerLruList = type { %struct.PgHdr*, %struct.PgHdr*, %struct.PgHdr* }
|
||||||
|
%struct.Parse = type { %struct.sqlite3*, i32, i8*, %struct.Vdbe*, i8, i8, i8, i8, i8, i8, i8, [8 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [12 x i32], i32, %struct.TableLock*, i32, i32, i32, i32, i32, %struct.Expr**, i8, %struct..4sPragmaType, %struct..4sPragmaType, %struct..4sPragmaType, i8*, i8*, %struct.Table*, %struct.Trigger*, %struct.TriggerStack*, i8*, %struct..4sPragmaType, i8, %struct.Table*, i32 }
|
||||||
|
%struct.PgHdr = type { %struct.Pager*, i32, %struct.PgHdr*, %struct.PgHdr*, %struct.PagerLruLink, %struct.PgHdr*, i8, i8, i8, i8, i8, i16, %struct.PgHdr*, %struct.PgHdr*, i8* }
|
||||||
|
%struct.Schema = type { i32, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Table*, i8, i8, i16, i32, %struct.sqlite3* }
|
||||||
|
%struct.Select = type { %struct.ExprList*, i8, i8, i8, i8, i8, i8, i8, %struct.SrcList*, %struct.Expr*, %struct.ExprList*, %struct.Expr*, %struct.ExprList*, %struct.Select*, %struct.Select*, %struct.Select*, %struct.Expr*, %struct.Expr*, i32, i32, [3 x i32] }
|
||||||
|
%struct.SrcList = type { i16, i16, [1 x %struct.SrcList_item] }
|
||||||
|
%struct.SrcList_item = type { i8*, i8*, i8*, %struct.Table*, %struct.Select*, i8, i8, i32, %struct.Expr*, %struct.IdList*, i64 }
|
||||||
|
%struct.Table = type { i8*, i32, %struct.Column*, i32, %struct.Index*, i32, %struct.Select*, i32, %struct.Trigger*, %struct.FKey*, i8*, %struct.Expr*, i32, i8, i8, i8, i8, i8, i8, i8, %struct.Module*, %struct.sqlite3_vtab*, i32, i8**, %struct.Schema* }
|
||||||
|
%struct.TableLock = type { i32, i32, i8, i8* }
|
||||||
|
%struct.Trigger = type { i8*, i8*, i8, i8, %struct.Expr*, %struct.IdList*, %struct..4sPragmaType, %struct.Schema*, %struct.Schema*, %struct.TriggerStep*, %struct.Trigger* }
|
||||||
|
%struct.TriggerStack = type { %struct.Table*, i32, i32, i32, i32, i32, i32, %struct.Trigger*, %struct.TriggerStack* }
|
||||||
|
%struct.TriggerStep = type { i32, i32, %struct.Trigger*, %struct.Select*, %struct..4sPragmaType, %struct.Expr*, %struct.ExprList*, %struct.IdList*, %struct.TriggerStep*, %struct.TriggerStep* }
|
||||||
|
%struct.Vdbe = type { %struct.sqlite3*, %struct.Vdbe*, %struct.Vdbe*, i32, i32, %struct.Op*, i32, i32, i32*, %struct.Mem**, %struct.Mem*, i32, %struct.Cursor**, i32, %struct.Mem*, i8**, i32, i32, i32, %struct.Mem*, i32, i32, %struct.Fifo, i32, i32, %struct.Context*, i32, i32, i32, i32, i32, [25 x i32], i32, i32, i8**, i8*, %struct.Mem*, i8, i8, i8, i8, i8, i8, i32, i64, i32, %struct.BtreeMutexArray, i32, i8*, i32 }
|
||||||
|
%struct.VdbeFunc = type { %struct.FuncDef*, i32, [1 x %struct.AuxData] }
|
||||||
|
%struct._OvflCell = type { i8*, i16 }
|
||||||
|
%struct._ht = type { i32, %struct.HashElem* }
|
||||||
|
%struct.anon = type { double }
|
||||||
|
%struct.sColMap = type { i32, i8* }
|
||||||
|
%struct.sqlite3 = type { %struct.sqlite3_vfs*, i32, %struct.Db*, i32, i32, i32, i32, i8, i8, i8, i8, i32, %struct.CollSeq*, i64, i64, i32, i32, i32, %struct.sqlite3_mutex*, %struct.sqlite3InitInfo, i32, i8**, %struct.Vdbe*, i32, void (i8*, i8*)*, i8*, void (i8*, i8*, i64)*, i8*, i8*, i32 (i8*)*, i8*, void (i8*)*, i8*, void (i8*, i32, i8*, i8*, i64)*, void (i8*, %struct.sqlite3*, i32, i8*)*, void (i8*, %struct.sqlite3*, i32, i8*)*, i8*, %struct.Mem*, i8*, i8*, %struct.anon, i32 (i8*, i32, i8*, i8*, i8*, i8*)*, i8*, i32 (i8*)*, i8*, i32, %struct.Hash, %struct.Table*, %struct.sqlite3_vtab**, i32, %struct.Hash, %struct.Hash, %struct.BusyHandler, i32, [2 x %struct.Db], i8 }
|
||||||
|
%struct.sqlite3InitInfo = type { i32, i32, i8 }
|
||||||
|
%struct.sqlite3_context = type { %struct.FuncDef*, %struct.VdbeFunc*, %struct.Mem, %struct.Mem*, i32, %struct.CollSeq* }
|
||||||
|
%struct.sqlite3_file = type { %struct.sqlite3_io_methods* }
|
||||||
|
%struct.sqlite3_index_constraint = type { i32, i8, i8, i32 }
|
||||||
|
%struct.sqlite3_index_constraint_usage = type { i32, i8 }
|
||||||
|
%struct.sqlite3_index_info = type { i32, %struct.sqlite3_index_constraint*, i32, %struct.sqlite3_index_constraint_usage*, %struct.sqlite3_index_constraint_usage*, i32, i8*, i32, i32, double }
|
||||||
|
%struct.sqlite3_io_methods = type { i32, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*, i8*, i32, i64)*, i32 (%struct.sqlite3_file*, i8*, i32, i64)*, i32 (%struct.sqlite3_file*, i64)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*, i64*)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*, i32, i8*)*, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*)* }
|
||||||
|
%struct.sqlite3_module = type { i32, i32 (%struct.sqlite3*, i8*, i32, i8**, %struct.sqlite3_vtab**, i8**)*, i32 (%struct.sqlite3*, i8*, i32, i8**, %struct.sqlite3_vtab**, i8**)*, i32 (%struct.sqlite3_vtab*, %struct.sqlite3_index_info*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*, %struct.sqlite3_vtab_cursor**)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*, i32, i8*, i32, %struct.Mem**)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*, %struct.sqlite3_context*, i32)*, i32 (%struct.sqlite3_vtab_cursor*, i64*)*, i32 (%struct.sqlite3_vtab*, i32, %struct.Mem**, i64*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*, i32, i8*, void (%struct.sqlite3_context*, i32, %struct.Mem**)**, i8**)*, i32 (%struct.sqlite3_vtab*, i8*)* }
|
||||||
|
%struct.sqlite3_mutex = type opaque
|
||||||
|
%struct.sqlite3_vfs = type { i32, i32, i32, %struct.sqlite3_vfs*, i8*, i8*, i32 (%struct.sqlite3_vfs*, i8*, %struct.sqlite3_file*, i32, i32*)*, i32 (%struct.sqlite3_vfs*, i8*, i32)*, i32 (%struct.sqlite3_vfs*, i8*, i32)*, i32 (%struct.sqlite3_vfs*, i32, i8*)*, i32 (%struct.sqlite3_vfs*, i8*, i32, i8*)*, i8* (%struct.sqlite3_vfs*, i8*)*, void (%struct.sqlite3_vfs*, i32, i8*)*, i8* (%struct.sqlite3_vfs*, i8*, i8*)*, void (%struct.sqlite3_vfs*, i8*)*, i32 (%struct.sqlite3_vfs*, i32, i8*)*, i32 (%struct.sqlite3_vfs*, i32)*, i32 (%struct.sqlite3_vfs*, double*)* }
|
||||||
|
%struct.sqlite3_vtab = type { %struct.sqlite3_module*, i32, i8* }
|
||||||
|
%struct.sqlite3_vtab_cursor = type { %struct.sqlite3_vtab* }
|
||||||
|
|
||||||
|
define fastcc void @sqlite3Insert(%struct.Parse* %pParse, %struct.SrcList* %pTabList, %struct.ExprList* %pList, %struct.Select* %pSelect, %struct.IdList* %pColumn, i32 %onError) nounwind {
|
||||||
|
entry:
|
||||||
|
br i1 false, label %bb54, label %bb69.loopexit
|
||||||
|
|
||||||
|
bb54: ; preds = %entry
|
||||||
|
br label %bb69.loopexit
|
||||||
|
|
||||||
|
bb59: ; preds = %bb63.preheader
|
||||||
|
%0 = load %struct..4sPragmaType*, %struct..4sPragmaType** %3, align 4 ; <%struct..4sPragmaType*> [#uses=0]
|
||||||
|
br label %bb65
|
||||||
|
|
||||||
|
bb65: ; preds = %bb63.preheader, %bb59
|
||||||
|
%1 = load %struct..4sPragmaType*, %struct..4sPragmaType** %4, align 4 ; <%struct..4sPragmaType*> [#uses=0]
|
||||||
|
br i1 false, label %bb67, label %bb63.preheader
|
||||||
|
|
||||||
|
bb67: ; preds = %bb65
|
||||||
|
%2 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=0]
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
bb69.loopexit: ; preds = %bb54, %entry
|
||||||
|
%3 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=1]
|
||||||
|
%4 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=1]
|
||||||
|
br label %bb63.preheader
|
||||||
|
|
||||||
|
bb63.preheader: ; preds = %bb69.loopexit, %bb65
|
||||||
|
br i1 false, label %bb59, label %bb65
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
; RUN: opt < %s -newgvn -disable-output
|
||||||
|
; PR3775
|
||||||
|
|
||||||
|
; ModuleID = 'bugpoint-reduced-simplified.bc'
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
|
||||||
|
target triple = "i386-pc-linux-gnu"
|
||||||
|
%llvm.dbg.anchor.type = type { i32, i32 }
|
||||||
|
%"struct.__gnu_cxx::hash<void*>" = type <{ i8 }>
|
||||||
|
%struct.__sched_param = type { i32 }
|
||||||
|
%struct._pthread_descr_struct = type opaque
|
||||||
|
%struct.pthread_attr_t = type { i32, i32, %struct.__sched_param, i32, i32, i32, i32, i8*, i32 }
|
||||||
|
%struct.pthread_mutex_t = type { i32, i32, %struct._pthread_descr_struct*, i32, %llvm.dbg.anchor.type }
|
||||||
|
%"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >" = type { %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<void*>,false>" }
|
||||||
|
%"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<void*>,false>" = type { %"struct.__gnu_cxx::hash<void*>", %"struct.std::_Rb_tree_node_base", i32 }
|
||||||
|
%"struct.std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >" = type { %"struct.std::_Rb_tree_node_base"* }
|
||||||
|
%"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* }
|
||||||
|
%"struct.std::pair<std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>" = type { %"struct.std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >", i8 }
|
||||||
|
%"struct.std::pair<void* const,void*>" = type { i8*, i8* }
|
||||||
|
|
||||||
|
@_ZL20__gthrw_pthread_oncePiPFvvE = weak alias i32 (i32*, void ()*), i32 (i32*, void ()*)* @pthread_once ; <i32 (i32*, void ()*)*> [#uses=0]
|
||||||
|
@_ZL27__gthrw_pthread_getspecificj = weak alias i8* (i32), i8* (i32)* @pthread_getspecific ; <i8* (i32)*> [#uses=0]
|
||||||
|
@_ZL27__gthrw_pthread_setspecificjPKv = weak alias i32 (i32, i8*), i32 (i32, i8*)* @pthread_setspecific ; <i32 (i32, i8*)*> [#uses=0]
|
||||||
|
@_ZL22__gthrw_pthread_createPmPK16__pthread_attr_sPFPvS3_ES3_ = weak alias i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*), i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create ; <i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)*> [#uses=0]
|
||||||
|
@_ZL22__gthrw_pthread_cancelm = weak alias i32 (i32), i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=0]
|
||||||
|
@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_lock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0]
|
||||||
|
@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_trylock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0]
|
||||||
|
@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_unlock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0]
|
||||||
|
@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = weak alias i32 (%struct.pthread_mutex_t*, %struct.__sched_param*), i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)* @pthread_mutex_init ; <i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)*> [#uses=0]
|
||||||
|
@_ZL26__gthrw_pthread_key_createPjPFvPvE = weak alias i32 (i32*, void (i8*)*), i32 (i32*, void (i8*)*)* @pthread_key_create ; <i32 (i32*, void (i8*)*)*> [#uses=0]
|
||||||
|
@_ZL26__gthrw_pthread_key_deletej = weak alias i32 (i32), i32 (i32)* @pthread_key_delete ; <i32 (i32)*> [#uses=0]
|
||||||
|
@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*), i32 (%struct.__sched_param*)* @pthread_mutexattr_init ; <i32 (%struct.__sched_param*)*> [#uses=0]
|
||||||
|
@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = weak alias i32 (%struct.__sched_param*, i32), i32 (%struct.__sched_param*, i32)* @pthread_mutexattr_settype ; <i32 (%struct.__sched_param*, i32)*> [#uses=0]
|
||||||
|
@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*), i32 (%struct.__sched_param*)* @pthread_mutexattr_destroy ; <i32 (%struct.__sched_param*)*> [#uses=0]
|
||||||
|
|
||||||
|
declare fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind readnone
|
||||||
|
|
||||||
|
define fastcc void @_ZNSt8_Rb_treeIPvSt4pairIKS0_S0_ESt10_Select1stIS3_ESt4lessIS0_ESaIS3_EE16_M_insert_uniqueERKS3_(%"struct.std::pair<std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>"* noalias nocapture sret %agg.result, %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >"* %this, %"struct.std::pair<void* const,void*>"* %__v) nounwind {
|
||||||
|
entry:
|
||||||
|
br i1 false, label %bb7, label %bb
|
||||||
|
|
||||||
|
bb: ; preds = %bb, %entry
|
||||||
|
br i1 false, label %bb5, label %bb
|
||||||
|
|
||||||
|
bb5: ; preds = %bb
|
||||||
|
call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind
|
||||||
|
br i1 false, label %bb11, label %bb7
|
||||||
|
|
||||||
|
bb7: ; preds = %bb5, %entry
|
||||||
|
br label %bb11
|
||||||
|
|
||||||
|
bb11: ; preds = %bb7, %bb5
|
||||||
|
call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_once(i32*, void ()*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i8* @pthread_getspecific(i32) {
|
||||||
|
ret i8* null
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_setspecific(i32, i8*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_create(i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_cancel(i32) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_mutex_lock(%struct.pthread_mutex_t*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_mutex_trylock(%struct.pthread_mutex_t*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_mutex_unlock(%struct.pthread_mutex_t*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_mutex_init(%struct.pthread_mutex_t*, %struct.__sched_param*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_key_create(i32*, void (i8*)*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_key_delete(i32) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_mutexattr_init(%struct.__sched_param*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_mutexattr_settype(%struct.__sched_param*, i32) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pthread_mutexattr_destroy(%struct.__sched_param*) {
|
||||||
|
ret i32 0
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
; RUN: opt < %s -newgvn | llvm-dis
|
||||||
|
; PR4256
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
|
||||||
|
target triple = "i386-pc-linux-gnu"
|
||||||
|
%llvm.dbg.anchor.type = type { i32, i32 }
|
||||||
|
%struct.cset = type { i8*, i8, i8, i32, i8* }
|
||||||
|
%struct.lmat = type { %struct.re_guts*, i32, %llvm.dbg.anchor.type*, i8*, i8*, i8*, i8*, i8**, i32, i8*, i8*, i8*, i8*, i8* }
|
||||||
|
%struct.re_guts = type { i32*, %struct.cset*, i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8*, i8*, i32, i32, i32, i32, [1 x i8] }
|
||||||
|
|
||||||
|
define i8* @lbackref(%struct.lmat* %m, i8* %start, i8* %stop, i32 %startst, i32 %stopst, i32 %lev, i32 %rec) nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb63
|
||||||
|
|
||||||
|
bb: ; preds = %bb63
|
||||||
|
switch i32 0, label %bb62 [
|
||||||
|
i32 268435456, label %bb2
|
||||||
|
i32 805306368, label %bb9
|
||||||
|
i32 -1610612736, label %bb51
|
||||||
|
]
|
||||||
|
|
||||||
|
bb2: ; preds = %bb
|
||||||
|
br label %bb62
|
||||||
|
|
||||||
|
bb9: ; preds = %bb
|
||||||
|
%0 = load i8, i8* %sp.1, align 1 ; <i8> [#uses=0]
|
||||||
|
br label %bb62
|
||||||
|
|
||||||
|
bb51: ; preds = %bb
|
||||||
|
%1 = load i8, i8* %sp.1, align 1 ; <i8> [#uses=0]
|
||||||
|
ret i8* null
|
||||||
|
|
||||||
|
bb62: ; preds = %bb9, %bb2, %bb
|
||||||
|
br label %bb63
|
||||||
|
|
||||||
|
bb63: ; preds = %bb84, %bb69, %bb62, %entry
|
||||||
|
%sp.1 = phi i8* [ null, %bb62 ], [ %sp.1.lcssa, %bb84 ], [ %start, %entry ], [ %sp.1.lcssa, %bb69 ] ; <i8*> [#uses=3]
|
||||||
|
br i1 false, label %bb, label %bb65
|
||||||
|
|
||||||
|
bb65: ; preds = %bb63
|
||||||
|
%sp.1.lcssa = phi i8* [ %sp.1, %bb63 ] ; <i8*> [#uses=4]
|
||||||
|
br i1 false, label %bb66, label %bb69
|
||||||
|
|
||||||
|
bb66: ; preds = %bb65
|
||||||
|
ret i8* null
|
||||||
|
|
||||||
|
bb69: ; preds = %bb65
|
||||||
|
switch i32 0, label %bb108.loopexit2.loopexit.loopexit [
|
||||||
|
i32 1342177280, label %bb63
|
||||||
|
i32 1476395008, label %bb84
|
||||||
|
i32 1879048192, label %bb104
|
||||||
|
i32 2013265920, label %bb93
|
||||||
|
]
|
||||||
|
|
||||||
|
bb84: ; preds = %bb69
|
||||||
|
%2 = tail call i8* @lbackref(%struct.lmat* %m, i8* %sp.1.lcssa, i8* %stop, i32 0, i32 %stopst, i32 0, i32 0) nounwind ; <i8*> [#uses=0]
|
||||||
|
br label %bb63
|
||||||
|
|
||||||
|
bb93: ; preds = %bb69
|
||||||
|
ret i8* null
|
||||||
|
|
||||||
|
bb104: ; preds = %bb69
|
||||||
|
%sp.1.lcssa.lcssa33 = phi i8* [ %sp.1.lcssa, %bb69 ] ; <i8*> [#uses=0]
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
bb108.loopexit2.loopexit.loopexit: ; preds = %bb69
|
||||||
|
ret i8* null
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
; Test to make sure malloc's bitcast does not block detection of a store
|
||||||
|
; to aliased memory; GVN should not optimize away the load in this program.
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
define i64 @test() {
|
||||||
|
%1 = tail call i8* @malloc(i64 mul (i64 4, i64 ptrtoint (i64* getelementptr (i64, i64* null, i64 1) to i64))) ; <i8*> [#uses=2]
|
||||||
|
store i8 42, i8* %1
|
||||||
|
%X = bitcast i8* %1 to i64* ; <i64*> [#uses=1]
|
||||||
|
%Y = load i64, i64* %X ; <i64> [#uses=1]
|
||||||
|
ret i64 %Y
|
||||||
|
; CHECK: %Y = load i64, i64* %X
|
||||||
|
; CHECK: ret i64 %Y
|
||||||
|
}
|
||||||
|
|
||||||
|
declare noalias i8* @malloc(i64)
|
|
@ -0,0 +1,42 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK-NOT: phi
|
||||||
|
|
||||||
|
define i8* @cat(i8* %s1, ...) nounwind {
|
||||||
|
entry:
|
||||||
|
br i1 undef, label %bb, label %bb3
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
bb3: ; preds = %entry
|
||||||
|
store i8* undef, i8** undef, align 4
|
||||||
|
br i1 undef, label %bb5, label %bb6
|
||||||
|
|
||||||
|
bb5: ; preds = %bb3
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
bb6: ; preds = %bb3
|
||||||
|
br label %bb12
|
||||||
|
|
||||||
|
bb8: ; preds = %bb12
|
||||||
|
br i1 undef, label %bb9, label %bb10
|
||||||
|
|
||||||
|
bb9: ; preds = %bb8
|
||||||
|
%0 = load i8*, i8** undef, align 4 ; <i8*> [#uses=0]
|
||||||
|
%1 = load i8*, i8** undef, align 4 ; <i8*> [#uses=0]
|
||||||
|
br label %bb11
|
||||||
|
|
||||||
|
bb10: ; preds = %bb8
|
||||||
|
br label %bb11
|
||||||
|
|
||||||
|
bb11: ; preds = %bb10, %bb9
|
||||||
|
br label %bb12
|
||||||
|
|
||||||
|
bb12: ; preds = %bb11, %bb6
|
||||||
|
br i1 undef, label %bb8, label %bb13
|
||||||
|
|
||||||
|
bb13: ; preds = %bb12
|
||||||
|
ret i8* undef
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
; RUN: opt < %s -newgvn
|
||||||
|
; PR7052
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define i32 @main(i32 %argc, i8** nocapture %argv) personality i32 (...)* @__gxx_personality_v0 {
|
||||||
|
entry:
|
||||||
|
%0 = getelementptr inbounds i8, i8* undef, i64 5 ; <i8*> [#uses=1]
|
||||||
|
%1 = bitcast i8* %0 to i32* ; <i32*> [#uses=1]
|
||||||
|
store i32 undef, i32* %1, align 1
|
||||||
|
br i1 undef, label %k121.i.i, label %l117.i.i
|
||||||
|
|
||||||
|
l117.i.i: ; preds = %entry
|
||||||
|
invoke fastcc void @foo()
|
||||||
|
to label %.noexc5 unwind label %landing_pad
|
||||||
|
|
||||||
|
.noexc5: ; preds = %l117.i.i
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
k121.i.i: ; preds = %entry
|
||||||
|
br i1 undef, label %l129.i.i, label %k133.i.i
|
||||||
|
|
||||||
|
l129.i.i: ; preds = %k121.i.i
|
||||||
|
invoke fastcc void @foo()
|
||||||
|
to label %.noexc7 unwind label %landing_pad
|
||||||
|
|
||||||
|
.noexc7: ; preds = %l129.i.i
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
k133.i.i: ; preds = %k121.i.i
|
||||||
|
%2 = getelementptr i8, i8* undef, i64 5 ; <i8*> [#uses=1]
|
||||||
|
%3 = bitcast i8* %2 to i1* ; <i1*> [#uses=1]
|
||||||
|
%4 = load i1, i1* %3 ; <i1> [#uses=1]
|
||||||
|
br i1 %4, label %k151.i.i, label %l147.i.i
|
||||||
|
|
||||||
|
l147.i.i: ; preds = %k133.i.i
|
||||||
|
invoke fastcc void @foo()
|
||||||
|
to label %.noexc10 unwind label %landing_pad
|
||||||
|
|
||||||
|
.noexc10: ; preds = %l147.i.i
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
k151.i.i: ; preds = %k133.i.i
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
landing_pad: ; preds = %l147.i.i, %l129.i.i, %l117.i.i
|
||||||
|
%exn = landingpad {i8*, i32}
|
||||||
|
cleanup
|
||||||
|
switch i32 undef, label %fin [
|
||||||
|
i32 1, label %catch1
|
||||||
|
i32 2, label %catch
|
||||||
|
]
|
||||||
|
|
||||||
|
fin: ; preds = %landing_pad
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
catch: ; preds = %landing_pad
|
||||||
|
ret i32 1
|
||||||
|
|
||||||
|
catch1: ; preds = %landing_pad
|
||||||
|
ret i32 2
|
||||||
|
}
|
||||||
|
|
||||||
|
declare fastcc void @foo()
|
||||||
|
|
||||||
|
declare i32 @__gxx_personality_v0(...)
|
|
@ -0,0 +1,15 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
declare i32 @foo(i32) readnone
|
||||||
|
|
||||||
|
define i1 @bar() {
|
||||||
|
; CHECK-LABEL: @bar(
|
||||||
|
%a = call i32 @foo (i32 0) readnone
|
||||||
|
%b = call i32 @foo (i32 0) readnone
|
||||||
|
%c = and i32 %a, %b
|
||||||
|
%x = call i32 @foo (i32 %a) readnone
|
||||||
|
%y = call i32 @foo (i32 %c) readnone
|
||||||
|
%z = icmp eq i32 %x, %y
|
||||||
|
ret i1 %z
|
||||||
|
; CHECK: ret i1 true
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
; RUN: opt -newgvn -disable-output < %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
|
||||||
|
|
||||||
|
@nuls = external global [10 x i8]
|
||||||
|
|
||||||
|
define fastcc void @p_ere() nounwind {
|
||||||
|
entry:
|
||||||
|
br label %"<bb 5>"
|
||||||
|
|
||||||
|
"<L18>.i":
|
||||||
|
br i1 undef, label %"<bb 3>.i30.i", label %doemit.exit51.i
|
||||||
|
|
||||||
|
"<bb 3>.i30.i":
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
doemit.exit51.i:
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<L19>.i":
|
||||||
|
br i1 undef, label %"<bb 3>.i55.i", label %doemit.exit76.i
|
||||||
|
|
||||||
|
"<bb 3>.i55.i":
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
doemit.exit76.i:
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<L98>.i":
|
||||||
|
store i8* getelementptr inbounds ([10 x i8], [10 x i8]* @nuls, i64 0, i64 0), i8** undef, align 8
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<L99>.i":
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<L24>.i":
|
||||||
|
br i1 undef, label %"<bb 53>.i", label %"<bb 35>.i"
|
||||||
|
|
||||||
|
"<bb 35>.i":
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<L28>.i":
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<L29>.i":
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<L39>.i":
|
||||||
|
br label %"<bb 53>.i"
|
||||||
|
|
||||||
|
"<bb 53>.i":
|
||||||
|
%wascaret_2.i = phi i32 [ 0, %"<L39>.i" ], [ 0, %"<L29>.i" ], [ 0, %"<L28>.i" ], [ 0, %"<bb 35>.i" ], [ 0, %"<L99>.i" ], [ 0, %"<L98>.i" ], [ 0, %doemit.exit76.i ], [ 1, %doemit.exit51.i ], [ 0, %"<L24>.i" ]
|
||||||
|
%D.5496_84.i = load i8*, i8** undef, align 8
|
||||||
|
br i1 undef, label %"<bb 54>.i", label %"<bb 5>"
|
||||||
|
|
||||||
|
"<bb 54>.i":
|
||||||
|
br i1 undef, label %"<bb 5>", label %"<bb 58>.i"
|
||||||
|
|
||||||
|
"<bb 58>.i":
|
||||||
|
br i1 undef, label %"<bb 64>.i", label %"<bb 59>.i"
|
||||||
|
|
||||||
|
"<bb 59>.i":
|
||||||
|
br label %"<bb 64>.i"
|
||||||
|
|
||||||
|
"<bb 64>.i":
|
||||||
|
switch i32 undef, label %"<bb 5>" [
|
||||||
|
i32 42, label %"<L54>.i"
|
||||||
|
i32 43, label %"<L55>.i"
|
||||||
|
i32 63, label %"<L56>.i"
|
||||||
|
i32 123, label %"<bb 5>.i258.i"
|
||||||
|
]
|
||||||
|
|
||||||
|
"<L54>.i":
|
||||||
|
br i1 undef, label %"<bb 3>.i105.i", label %doemit.exit127.i
|
||||||
|
|
||||||
|
"<bb 3>.i105.i":
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
doemit.exit127.i:
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
"<L55>.i":
|
||||||
|
br i1 undef, label %"<bb 3>.i157.i", label %"<bb 5>"
|
||||||
|
|
||||||
|
"<bb 3>.i157.i":
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
"<L56>.i":
|
||||||
|
br label %"<bb 5>"
|
||||||
|
|
||||||
|
"<bb 5>.i258.i":
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
"<bb 5>":
|
||||||
|
switch i32 undef, label %"<L39>.i" [
|
||||||
|
i32 36, label %"<L19>.i"
|
||||||
|
i32 94, label %"<L18>.i"
|
||||||
|
i32 124, label %"<L98>.i"
|
||||||
|
i32 42, label %"<L99>.i"
|
||||||
|
i32 43, label %"<L99>.i"
|
||||||
|
i32 46, label %"<L24>.i"
|
||||||
|
i32 63, label %"<L99>.i"
|
||||||
|
i32 91, label %"<L28>.i"
|
||||||
|
i32 92, label %"<L29>.i"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
;
|
||||||
|
|
||||||
|
%0 = type { i64, i1 }
|
||||||
|
|
||||||
|
define i64 @test1(i64 %a, i64 %b) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
%uadd = tail call %0 @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
|
||||||
|
%uadd.0 = extractvalue %0 %uadd, 0
|
||||||
|
%add1 = add i64 %a, %b
|
||||||
|
ret i64 %add1
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
; CHECK-NOT: add1
|
||||||
|
; CHECK: ret
|
||||||
|
|
||||||
|
define i64 @test2(i64 %a, i64 %b) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
%usub = tail call %0 @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
|
||||||
|
%usub.0 = extractvalue %0 %usub, 0
|
||||||
|
%sub1 = sub i64 %a, %b
|
||||||
|
ret i64 %sub1
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test2(
|
||||||
|
; CHECK-NOT: sub1
|
||||||
|
; CHECK: ret
|
||||||
|
|
||||||
|
define i64 @test3(i64 %a, i64 %b) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
%umul = tail call %0 @llvm.umul.with.overflow.i64(i64 %a, i64 %b)
|
||||||
|
%umul.0 = extractvalue %0 %umul, 0
|
||||||
|
%mul1 = mul i64 %a, %b
|
||||||
|
ret i64 %mul1
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test3(
|
||||||
|
; CHECK-NOT: mul1
|
||||||
|
; CHECK: ret
|
||||||
|
|
||||||
|
define i64 @test4(i64 %a, i64 %b) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
%sadd = tail call %0 @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
|
||||||
|
%sadd.0 = extractvalue %0 %sadd, 0
|
||||||
|
%add1 = add i64 %a, %b
|
||||||
|
ret i64 %add1
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test4(
|
||||||
|
; CHECK-NOT: add1
|
||||||
|
; CHECK: ret
|
||||||
|
|
||||||
|
define i64 @test5(i64 %a, i64 %b) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
%ssub = tail call %0 @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
|
||||||
|
%ssub.0 = extractvalue %0 %ssub, 0
|
||||||
|
%sub1 = sub i64 %a, %b
|
||||||
|
ret i64 %sub1
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test5(
|
||||||
|
; CHECK-NOT: sub1
|
||||||
|
; CHECK: ret
|
||||||
|
|
||||||
|
define i64 @test6(i64 %a, i64 %b) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
%smul = tail call %0 @llvm.smul.with.overflow.i64(i64 %a, i64 %b)
|
||||||
|
%smul.0 = extractvalue %0 %smul, 0
|
||||||
|
%mul1 = mul i64 %a, %b
|
||||||
|
ret i64 %mul1
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test6(
|
||||||
|
; CHECK-NOT: mul1
|
||||||
|
; CHECK: ret
|
||||||
|
|
||||||
|
declare void @exit(i32) noreturn
|
||||||
|
declare %0 @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
|
||||||
|
declare %0 @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
|
||||||
|
declare %0 @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone
|
||||||
|
declare %0 @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
|
||||||
|
declare %0 @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
|
||||||
|
declare %0 @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo }
|
||||||
|
%struct.__type_info_pseudo = type { i8*, i8* }
|
||||||
|
|
||||||
|
@_ZTIi = external constant %struct.__fundamental_type_info_pseudo
|
||||||
|
@_ZTIb = external constant %struct.__fundamental_type_info_pseudo
|
||||||
|
|
||||||
|
declare void @_Z4barv()
|
||||||
|
|
||||||
|
declare void @_Z7cleanupv()
|
||||||
|
|
||||||
|
declare i32 @llvm.eh.typeid.for(i8*) nounwind readonly
|
||||||
|
|
||||||
|
declare i8* @__cxa_begin_catch(i8*) nounwind
|
||||||
|
|
||||||
|
declare void @__cxa_end_catch()
|
||||||
|
|
||||||
|
declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
|
||||||
|
|
||||||
|
define void @_Z3foov() uwtable personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 {
|
||||||
|
entry:
|
||||||
|
invoke void @_Z4barv()
|
||||||
|
to label %return unwind label %lpad
|
||||||
|
|
||||||
|
lpad: ; preds = %entry
|
||||||
|
%0 = landingpad { i8*, i32 }
|
||||||
|
catch %struct.__fundamental_type_info_pseudo* @_ZTIi
|
||||||
|
catch %struct.__fundamental_type_info_pseudo* @_ZTIb
|
||||||
|
catch %struct.__fundamental_type_info_pseudo* @_ZTIi
|
||||||
|
catch %struct.__fundamental_type_info_pseudo* @_ZTIb
|
||||||
|
%exc_ptr2.i = extractvalue { i8*, i32 } %0, 0
|
||||||
|
%filter3.i = extractvalue { i8*, i32 } %0, 1
|
||||||
|
%typeid.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
|
||||||
|
; CHECK: call i32 @llvm.eh.typeid.for
|
||||||
|
%1 = icmp eq i32 %filter3.i, %typeid.i
|
||||||
|
br i1 %1, label %ppad, label %next
|
||||||
|
|
||||||
|
next: ; preds = %lpad
|
||||||
|
%typeid1.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
|
||||||
|
; CHECK: call i32 @llvm.eh.typeid.for
|
||||||
|
%2 = icmp eq i32 %filter3.i, %typeid1.i
|
||||||
|
br i1 %2, label %ppad2, label %next2
|
||||||
|
|
||||||
|
ppad: ; preds = %lpad
|
||||||
|
%3 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
|
||||||
|
tail call void @__cxa_end_catch() nounwind
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
ppad2: ; preds = %next
|
||||||
|
%D.2073_5.i = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
|
||||||
|
tail call void @__cxa_end_catch() nounwind
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
next2: ; preds = %next
|
||||||
|
call void @_Z7cleanupv()
|
||||||
|
%typeid = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
|
||||||
|
; CHECK-NOT: call i32 @llvm.eh.typeid.for
|
||||||
|
%4 = icmp eq i32 %filter3.i, %typeid
|
||||||
|
br i1 %4, label %ppad3, label %next3
|
||||||
|
|
||||||
|
next3: ; preds = %next2
|
||||||
|
%typeid1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
|
||||||
|
%5 = icmp eq i32 %filter3.i, %typeid1
|
||||||
|
br i1 %5, label %ppad4, label %unwind
|
||||||
|
|
||||||
|
unwind: ; preds = %next3
|
||||||
|
resume { i8*, i32 } %0
|
||||||
|
|
||||||
|
ppad3: ; preds = %next2
|
||||||
|
%6 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
|
||||||
|
tail call void @__cxa_end_catch() nounwind
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
ppad4: ; preds = %next3
|
||||||
|
%D.2080_5 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
|
||||||
|
tail call void @__cxa_end_catch() nounwind
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return: ; preds = %ppad4, %ppad3, %ppad2, %ppad, %entry
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
; RUN: opt < %s -newgvn
|
||||||
|
; PR12858
|
||||||
|
|
||||||
|
define void @fn5(i16 signext %p1, i8 signext %p2) nounwind uwtable {
|
||||||
|
entry:
|
||||||
|
br i1 undef, label %if.else, label %if.then
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
%conv = sext i16 %p1 to i32
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
%conv1 = sext i16 %p1 to i32
|
||||||
|
br i1 undef, label %if.then3, label %if.else4
|
||||||
|
|
||||||
|
if.then3: ; preds = %if.end
|
||||||
|
br label %if.end12
|
||||||
|
|
||||||
|
if.else4: ; preds = %if.end
|
||||||
|
%conv7 = sext i8 %p2 to i32
|
||||||
|
%cmp8 = icmp eq i32 %conv1, %conv7
|
||||||
|
br i1 %cmp8, label %if.then10, label %if.end12
|
||||||
|
|
||||||
|
if.then10: ; preds = %if.else4
|
||||||
|
br label %if.end12
|
||||||
|
|
||||||
|
if.end12: ; preds = %if.then10, %if.else4, %if.then3
|
||||||
|
%conv13 = sext i8 %p2 to i32
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
declare void @llvm.masked.scatter.v2i32(<2 x i32> , <2 x i32*> , i32 , <2 x i1> )
|
||||||
|
declare <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*>, i32, <2 x i1>, <2 x i32>)
|
||||||
|
|
||||||
|
; This test ensures that masked scatter and gather operations, which take vectors of pointers,
|
||||||
|
; do not have pointer aliasing ignored when being processed.
|
||||||
|
; No scatter/gather calls should end up eliminated
|
||||||
|
; CHECK: llvm.masked.gather
|
||||||
|
; CHECK: llvm.masked.gather
|
||||||
|
; CHECK: llvm.masked.scatter
|
||||||
|
; CHECK: llvm.masked.gather
|
||||||
|
; CHECK: llvm.masked.scatter
|
||||||
|
; CHECK: llvm.masked.gather
|
||||||
|
define spir_kernel void @test(<2 x i32*> %in1, <2 x i32*> %in2, i32* %out) {
|
||||||
|
entry:
|
||||||
|
; Just some temporary storage
|
||||||
|
%tmp.0 = alloca i32
|
||||||
|
%tmp.1 = alloca i32
|
||||||
|
%tmp.i = insertelement <2 x i32*> undef, i32* %tmp.0, i32 0
|
||||||
|
%tmp = insertelement <2 x i32*> %tmp.i, i32* %tmp.1, i32 1
|
||||||
|
; Read from in1 and in2
|
||||||
|
%in1.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in1, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
|
||||||
|
%in2.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in2, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
|
||||||
|
; Store in1 to the allocas
|
||||||
|
call void @llvm.masked.scatter.v2i32(<2 x i32> %in1.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
|
||||||
|
; Read in1 from the allocas
|
||||||
|
; This gather should alias the scatter we just saw
|
||||||
|
%tmp.v.0 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
|
||||||
|
; Store in2 to the allocas
|
||||||
|
call void @llvm.masked.scatter.v2i32(<2 x i32> %in2.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
|
||||||
|
; Read in2 from the allocas
|
||||||
|
; This gather should alias the scatter we just saw, and not be eliminated
|
||||||
|
%tmp.v.1 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
|
||||||
|
; Store in2 to out for good measure
|
||||||
|
%tmp.v.1.0 = extractelement <2 x i32> %tmp.v.1, i32 0
|
||||||
|
%tmp.v.1.1 = extractelement <2 x i32> %tmp.v.1, i32 1
|
||||||
|
store i32 %tmp.v.1.0, i32* %out
|
||||||
|
%out.1 = getelementptr i32, i32* %out, i32 1
|
||||||
|
store i32 %tmp.v.1.1, i32* %out.1
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||||
|
target triple = "x86_64-apple-macosx10.7.0"
|
||||||
|
|
||||||
|
; rdar://12801584
|
||||||
|
; Value of %shouldExit can be changed by RunInMode.
|
||||||
|
; Make sure we do not replace load %shouldExit in while.cond.backedge
|
||||||
|
; with a phi node where the value from while.body is 0.
|
||||||
|
define i32 @test() nounwind ssp {
|
||||||
|
entry:
|
||||||
|
; CHECK: test()
|
||||||
|
; CHECK: while.body:
|
||||||
|
; CHECK: call void @RunInMode
|
||||||
|
; CHECK: br i1 %tobool, label %while.cond.backedge, label %if.then
|
||||||
|
; CHECK: while.cond.backedge:
|
||||||
|
; CHECK: load i32, i32* %shouldExit
|
||||||
|
; CHECK: br i1 %cmp, label %while.body
|
||||||
|
%shouldExit = alloca i32, align 4
|
||||||
|
%tasksIdle = alloca i32, align 4
|
||||||
|
store i32 0, i32* %shouldExit, align 4
|
||||||
|
store i32 0, i32* %tasksIdle, align 4
|
||||||
|
call void @CTestInitialize(i32* %tasksIdle) nounwind
|
||||||
|
%0 = load i32, i32* %shouldExit, align 4
|
||||||
|
%cmp1 = icmp eq i32 %0, 0
|
||||||
|
br i1 %cmp1, label %while.body.lr.ph, label %while.end
|
||||||
|
|
||||||
|
while.body.lr.ph:
|
||||||
|
br label %while.body
|
||||||
|
|
||||||
|
while.body:
|
||||||
|
call void @RunInMode(i32 100) nounwind
|
||||||
|
%1 = load i32, i32* %tasksIdle, align 4
|
||||||
|
%tobool = icmp eq i32 %1, 0
|
||||||
|
br i1 %tobool, label %while.cond.backedge, label %if.then
|
||||||
|
|
||||||
|
if.then:
|
||||||
|
store i32 0, i32* %tasksIdle, align 4
|
||||||
|
call void @TimerCreate(i32* %shouldExit) nounwind
|
||||||
|
br label %while.cond.backedge
|
||||||
|
|
||||||
|
while.cond.backedge:
|
||||||
|
%2 = load i32, i32* %shouldExit, align 4
|
||||||
|
%cmp = icmp eq i32 %2, 0
|
||||||
|
br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge
|
||||||
|
|
||||||
|
while.cond.while.end_crit_edge:
|
||||||
|
br label %while.end
|
||||||
|
|
||||||
|
while.end:
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
declare void @CTestInitialize(i32*)
|
||||||
|
declare void @RunInMode(i32)
|
||||||
|
declare void @TimerCreate(i32*)
|
|
@ -0,0 +1,276 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
%struct.A = type { i32 (...)** }
|
||||||
|
@_ZTV1A = available_externally unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)], align 8
|
||||||
|
@_ZTI1A = external constant i8*
|
||||||
|
|
||||||
|
; Checks if indirect calls can be replaced with direct
|
||||||
|
; assuming that %vtable == @_ZTV1A (with alignment).
|
||||||
|
; Checking const propagation across other BBs
|
||||||
|
; CHECK-LABEL: define void @_Z1gb(
|
||||||
|
|
||||||
|
define void @_Z1gb(i1 zeroext %p) {
|
||||||
|
entry:
|
||||||
|
%call = tail call noalias i8* @_Znwm(i64 8) #4
|
||||||
|
%0 = bitcast i8* %call to %struct.A*
|
||||||
|
tail call void @_ZN1AC1Ev(%struct.A* %0) #1
|
||||||
|
%1 = bitcast i8* %call to i8***
|
||||||
|
%vtable = load i8**, i8*** %1, align 8
|
||||||
|
%cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
|
||||||
|
tail call void @llvm.assume(i1 %cmp.vtables)
|
||||||
|
br i1 %p, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
%vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
|
||||||
|
%2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
|
||||||
|
|
||||||
|
; CHECK: call i32 @_ZN1A3fooEv(
|
||||||
|
%call2 = tail call i32 %2(%struct.A* %0) #1
|
||||||
|
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
%vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
|
||||||
|
%vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
|
||||||
|
|
||||||
|
; CHECK: call i32 @_ZN1A3barEv(
|
||||||
|
%3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
|
||||||
|
|
||||||
|
%call5 = tail call i32 %3(%struct.A* %0) #1
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Check integration with invariant.group handling
|
||||||
|
; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) {
|
||||||
|
define void @invariantGroupHandling(i1 zeroext %p) {
|
||||||
|
entry:
|
||||||
|
%call = tail call noalias i8* @_Znwm(i64 8) #4
|
||||||
|
%0 = bitcast i8* %call to %struct.A*
|
||||||
|
tail call void @_ZN1AC1Ev(%struct.A* %0) #1
|
||||||
|
%1 = bitcast i8* %call to i8***
|
||||||
|
%vtable = load i8**, i8*** %1, align 8, !invariant.group !0
|
||||||
|
%cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
|
||||||
|
tail call void @llvm.assume(i1 %cmp.vtables)
|
||||||
|
br i1 %p, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
%vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
|
||||||
|
%2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
|
||||||
|
|
||||||
|
; CHECK: call i32 @_ZN1A3fooEv(
|
||||||
|
%call2 = tail call i32 %2(%struct.A* %0) #1
|
||||||
|
%vtable1 = load i8**, i8*** %1, align 8, !invariant.group !0
|
||||||
|
%vtable2.cast = bitcast i8** %vtable1 to i32 (%struct.A*)**
|
||||||
|
%call1 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable2.cast, align 8
|
||||||
|
; FIXME: those loads could be also direct, but right now the invariant.group
|
||||||
|
; analysis works only on single block
|
||||||
|
; CHECK-NOT: call i32 @_ZN1A3fooEv(
|
||||||
|
%callx = tail call i32 %call1(%struct.A* %0) #1
|
||||||
|
|
||||||
|
%vtable2 = load i8**, i8*** %1, align 8, !invariant.group !0
|
||||||
|
%vtable3.cast = bitcast i8** %vtable2 to i32 (%struct.A*)**
|
||||||
|
%call4 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable3.cast, align 8
|
||||||
|
; CHECK-NOT: call i32 @_ZN1A3fooEv(
|
||||||
|
%cally = tail call i32 %call4(%struct.A* %0) #1
|
||||||
|
|
||||||
|
%b = bitcast i8* %call to %struct.A**
|
||||||
|
%vtable3 = load %struct.A*, %struct.A** %b, align 8, !invariant.group !0
|
||||||
|
%vtable4.cast = bitcast %struct.A* %vtable3 to i32 (%struct.A*)**
|
||||||
|
%vfun = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable4.cast, align 8
|
||||||
|
; CHECK-NOT: call i32 @_ZN1A3fooEv(
|
||||||
|
%unknown = tail call i32 %vfun(%struct.A* %0) #1
|
||||||
|
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
%vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
|
||||||
|
%vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
|
||||||
|
|
||||||
|
; CHECK: call i32 @_ZN1A3barEv(
|
||||||
|
%3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
|
||||||
|
|
||||||
|
%call5 = tail call i32 %3(%struct.A* %0) #1
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; Checking const propagation in the same BB
|
||||||
|
; CHECK-LABEL: define i32 @main()
|
||||||
|
|
||||||
|
define i32 @main() {
|
||||||
|
entry:
|
||||||
|
%call = tail call noalias i8* @_Znwm(i64 8)
|
||||||
|
%0 = bitcast i8* %call to %struct.A*
|
||||||
|
tail call void @_ZN1AC1Ev(%struct.A* %0)
|
||||||
|
%1 = bitcast i8* %call to i8***
|
||||||
|
%vtable = load i8**, i8*** %1, align 8
|
||||||
|
%cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
|
||||||
|
tail call void @llvm.assume(i1 %cmp.vtables)
|
||||||
|
%vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
|
||||||
|
|
||||||
|
; CHECK: call i32 @_ZN1A3fooEv(
|
||||||
|
%2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
|
||||||
|
|
||||||
|
%call2 = tail call i32 %2(%struct.A* %0)
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
; This tests checks const propatation with fcmp instruction.
|
||||||
|
; CHECK-LABEL: define float @_Z1gf(float %p)
|
||||||
|
|
||||||
|
define float @_Z1gf(float %p) {
|
||||||
|
entry:
|
||||||
|
%p.addr = alloca float, align 4
|
||||||
|
%f = alloca float, align 4
|
||||||
|
store float %p, float* %p.addr, align 4
|
||||||
|
|
||||||
|
store float 3.000000e+00, float* %f, align 4
|
||||||
|
%0 = load float, float* %p.addr, align 4
|
||||||
|
%1 = load float, float* %f, align 4
|
||||||
|
%cmp = fcmp oeq float %1, %0 ; note const on lhs
|
||||||
|
call void @llvm.assume(i1 %cmp)
|
||||||
|
|
||||||
|
; CHECK: ret float 3.000000e+00
|
||||||
|
ret float %0
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define float @_Z1hf(float %p)
|
||||||
|
|
||||||
|
define float @_Z1hf(float %p) {
|
||||||
|
entry:
|
||||||
|
%p.addr = alloca float, align 4
|
||||||
|
store float %p, float* %p.addr, align 4
|
||||||
|
|
||||||
|
%0 = load float, float* %p.addr, align 4
|
||||||
|
%cmp = fcmp nnan ueq float %0, 3.000000e+00
|
||||||
|
call void @llvm.assume(i1 %cmp)
|
||||||
|
|
||||||
|
; CHECK: ret float 3.000000e+00
|
||||||
|
ret float %0
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define float @_Z1if(float %p)
|
||||||
|
define float @_Z1if(float %p) {
|
||||||
|
entry:
|
||||||
|
%p.addr = alloca float, align 4
|
||||||
|
store float %p, float* %p.addr, align 4
|
||||||
|
|
||||||
|
%0 = load float, float* %p.addr, align 4
|
||||||
|
%cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate
|
||||||
|
call void @llvm.assume(i1 %cmp)
|
||||||
|
|
||||||
|
; CHECK-NOT: ret float 3.000000e+00
|
||||||
|
ret float %0
|
||||||
|
}
|
||||||
|
|
||||||
|
; This test checks if constant propagation works for multiple node edges
|
||||||
|
; CHECK-LABEL: define i32 @_Z1ii(i32 %p)
|
||||||
|
define i32 @_Z1ii(i32 %p) {
|
||||||
|
entry:
|
||||||
|
%cmp = icmp eq i32 %p, 42
|
||||||
|
call void @llvm.assume(i1 %cmp)
|
||||||
|
|
||||||
|
; CHECK: br i1 true, label %bb2, label %bb2
|
||||||
|
br i1 %cmp, label %bb2, label %bb2
|
||||||
|
bb2:
|
||||||
|
call void @llvm.assume(i1 true)
|
||||||
|
; CHECK: br i1 true, label %bb2, label %bb2
|
||||||
|
br i1 %cmp, label %bb2, label %bb2
|
||||||
|
|
||||||
|
; CHECK: ret i32 42
|
||||||
|
ret i32 %p
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i32 @_Z1ij(i32 %p)
|
||||||
|
define i32 @_Z1ij(i32 %p) {
|
||||||
|
entry:
|
||||||
|
%cmp = icmp eq i32 %p, 42
|
||||||
|
call void @llvm.assume(i1 %cmp)
|
||||||
|
|
||||||
|
; CHECK: br i1 true, label %bb2, label %bb2
|
||||||
|
br i1 %cmp, label %bb2, label %bb2
|
||||||
|
bb2:
|
||||||
|
; CHECK-NOT: %cmp2 =
|
||||||
|
%cmp2 = icmp eq i32 %p, 42
|
||||||
|
; CHECK-NOT: call void @llvm.assume(
|
||||||
|
call void @llvm.assume(i1 %cmp2)
|
||||||
|
|
||||||
|
; CHECK: br i1 true, label %bb2, label %bb2
|
||||||
|
br i1 %cmp, label %bb2, label %bb2
|
||||||
|
|
||||||
|
; CHECK: ret i32 42
|
||||||
|
ret i32 %p
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i32 @_Z1ik(i32 %p)
|
||||||
|
define i32 @_Z1ik(i32 %p) {
|
||||||
|
entry:
|
||||||
|
%cmp = icmp eq i32 %p, 42
|
||||||
|
call void @llvm.assume(i1 %cmp)
|
||||||
|
|
||||||
|
; CHECK: br i1 true, label %bb2, label %bb3
|
||||||
|
br i1 %cmp, label %bb2, label %bb3
|
||||||
|
bb2:
|
||||||
|
; CHECK-NOT: %cmp3 =
|
||||||
|
%cmp3 = icmp eq i32 %p, 43
|
||||||
|
; CHECK: store i8 undef, i8* null
|
||||||
|
call void @llvm.assume(i1 %cmp3)
|
||||||
|
ret i32 15
|
||||||
|
bb3:
|
||||||
|
ret i32 17
|
||||||
|
}
|
||||||
|
|
||||||
|
; This test checks if GVN can do the constant propagation correctly
|
||||||
|
; when there are multiple uses of the same assume value in the
|
||||||
|
; basic block that has a loop back-edge pointing to itself.
|
||||||
|
;
|
||||||
|
; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k)
|
||||||
|
define i32 @_Z1il(i32 %val, i1 %k) {
|
||||||
|
br label %next
|
||||||
|
|
||||||
|
next:
|
||||||
|
; CHECK: tail call void @llvm.assume(i1 %k)
|
||||||
|
; CHECK-NEXT: %cmp = icmp eq i32 %val, 50
|
||||||
|
tail call void @llvm.assume(i1 %k)
|
||||||
|
tail call void @llvm.assume(i1 %k)
|
||||||
|
%cmp = icmp eq i32 %val, 50
|
||||||
|
br i1 %cmp, label %next, label %meh
|
||||||
|
|
||||||
|
meh:
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
; This test checks if GVN can prevent the constant propagation correctly
|
||||||
|
; in the successor blocks that are not dominated by the basic block
|
||||||
|
; with the assume instruction.
|
||||||
|
;
|
||||||
|
; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j)
|
||||||
|
define i1 @_z1im(i32 %val, i1 %k, i1 %j) {
|
||||||
|
br i1 %j, label %next, label %meh
|
||||||
|
|
||||||
|
next:
|
||||||
|
; CHECK: tail call void @llvm.assume(i1 %k)
|
||||||
|
; CHECK-NEXT: br label %meh
|
||||||
|
tail call void @llvm.assume(i1 %k)
|
||||||
|
tail call void @llvm.assume(i1 %k)
|
||||||
|
br label %meh
|
||||||
|
|
||||||
|
meh:
|
||||||
|
; CHECK: ret i1 %k
|
||||||
|
ret i1 %k
|
||||||
|
}
|
||||||
|
|
||||||
|
declare noalias i8* @_Znwm(i64)
|
||||||
|
declare void @_ZN1AC1Ev(%struct.A*)
|
||||||
|
declare void @llvm.assume(i1)
|
||||||
|
declare i32 @_ZN1A3fooEv(%struct.A*)
|
||||||
|
declare i32 @_ZN1A3barEv(%struct.A*)
|
||||||
|
|
||||||
|
!0 = !{!"struct A"}
|
|
@ -0,0 +1,15 @@
|
||||||
|
; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
; ModuleID = 'test3.ll'
|
||||||
|
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
define i32 @main(i32 *%foo) {
|
||||||
|
entry:
|
||||||
|
; CHECK: load i32, i32* %foo, align 4
|
||||||
|
%0 = load i32, i32* %foo, align 4
|
||||||
|
store i32 5, i32* undef, align 4
|
||||||
|
; CHECK-NOT: load i32, i32* %foo, align 4
|
||||||
|
%1 = load i32, i32* %foo, align 4
|
||||||
|
; CHECK: add i32 %0, %0
|
||||||
|
%2 = add i32 %0, %1
|
||||||
|
ret i32 %2
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
; RUN: opt < %s -passes=gvn -S | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @main() {
|
||||||
|
block1:
|
||||||
|
%z1 = bitcast i32 0 to i32
|
||||||
|
br label %block2
|
||||||
|
block2:
|
||||||
|
%z2 = bitcast i32 0 to i32
|
||||||
|
ret i32 %z2
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: define i32 @main() {
|
||||||
|
; CHECK-NEXT: block1:
|
||||||
|
; CHECK-NEXT: ret i32 0
|
||||||
|
; CHECK-NEXT: }
|
|
@ -0,0 +1,40 @@
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "E-m:e-i64:64-n32:64"
|
||||||
|
target triple = "powerpc64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
;; Make sure we use correct bit shift based on storage size for
|
||||||
|
;; loads reusing a load value.
|
||||||
|
define i64 @test1({ i1, i8 }* %predA, { i1, i8 }* %predB) {
|
||||||
|
; CHECK-LABEL: @test1
|
||||||
|
; CHECK-NOT: [[V1:%.*]] = load i16, i16* %{{.*}}
|
||||||
|
; CHECK-NOT: [[V2:%.*]] = lshr i16 [[V1]], 8
|
||||||
|
; CHECK-NOT: trunc i16 [[V2]] to i1
|
||||||
|
|
||||||
|
%valueLoadA.fca.0.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predA, i64 0, i32 0
|
||||||
|
%valueLoadA.fca.0.load = load i1, i1* %valueLoadA.fca.0.gep, align 8
|
||||||
|
%valueLoadB.fca.0.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predB, i64 0, i32 0
|
||||||
|
%valueLoadB.fca.0.load = load i1, i1* %valueLoadB.fca.0.gep, align 8
|
||||||
|
%isTrue = and i1 %valueLoadA.fca.0.load, %valueLoadB.fca.0.load
|
||||||
|
%valueLoadA.fca.1.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predA, i64 0, i32 1
|
||||||
|
%valueLoadA.fca.1.load = load i8, i8* %valueLoadA.fca.1.gep, align 1
|
||||||
|
%isNotNullA = icmp ne i8 %valueLoadA.fca.1.load, 0
|
||||||
|
%valueLoadB.fca.1.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predB, i64 0, i32 1
|
||||||
|
%valueLoadB.fca.1.load = load i8, i8* %valueLoadB.fca.1.gep, align 1
|
||||||
|
%isNotNullB = icmp ne i8 %valueLoadB.fca.1.load, 0
|
||||||
|
%isNotNull = and i1 %isNotNullA, %isNotNullB
|
||||||
|
%isTrueAndNotNull = and i1 %isTrue, %isNotNull
|
||||||
|
%ret = zext i1 %isTrueAndNotNull to i64
|
||||||
|
ret i64 %ret
|
||||||
|
}
|
||||||
|
|
||||||
|
;; And likewise for loads reusing a store value.
|
||||||
|
define i1 @test2(i8 %V, i8* %P) {
|
||||||
|
; CHECK-LABEL: @test2
|
||||||
|
; CHECK-NOT: lshr
|
||||||
|
store i8 %V, i8* %P
|
||||||
|
%P2 = bitcast i8* %P to i1*
|
||||||
|
%A = load i1, i1* %P2
|
||||||
|
ret i1 %A
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
; PR2213
|
||||||
|
|
||||||
|
define i32* @f(i8* %x) {
|
||||||
|
entry:
|
||||||
|
%tmp = call i8* @m( i32 12 ) ; <i8*> [#uses=2]
|
||||||
|
%tmp1 = bitcast i8* %tmp to i32* ; <i32*> [#uses=0]
|
||||||
|
%tmp2 = bitcast i8* %tmp to i32* ; <i32*> [#uses=0]
|
||||||
|
; CHECK-NOT: %tmp2
|
||||||
|
ret i32* %tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i8* @m(i32)
|
|
@ -0,0 +1,38 @@
|
||||||
|
; RUN: opt -newgvn -S -o - %s | FileCheck %s
|
||||||
|
|
||||||
|
; If a branch has two identical successors, we cannot declare either dead.
|
||||||
|
|
||||||
|
define void @widget(i1 %p) {
|
||||||
|
entry:
|
||||||
|
br label %bb2
|
||||||
|
|
||||||
|
bb2:
|
||||||
|
%t1 = phi i64 [ 0, %entry ], [ %t5, %bb7 ]
|
||||||
|
%t2 = add i64 %t1, 1
|
||||||
|
%t3 = icmp ult i64 0, %t2
|
||||||
|
br i1 %t3, label %bb3, label %bb4
|
||||||
|
|
||||||
|
bb3:
|
||||||
|
%t4 = call i64 @f()
|
||||||
|
br label %bb4
|
||||||
|
|
||||||
|
bb4:
|
||||||
|
; CHECK-NOT: phi {{.*}} undef
|
||||||
|
%foo = phi i64 [ %t4, %bb3 ], [ 0, %bb2 ]
|
||||||
|
br i1 %p, label %bb5, label %bb6
|
||||||
|
|
||||||
|
bb5:
|
||||||
|
br i1 true, label %bb7, label %bb7
|
||||||
|
|
||||||
|
bb6:
|
||||||
|
br i1 true, label %bb7, label %bb7
|
||||||
|
|
||||||
|
bb7:
|
||||||
|
%t5 = add i64 %t1, 1
|
||||||
|
br i1 %p, label %bb2, label %bb8
|
||||||
|
|
||||||
|
bb8:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i64 @f()
|
|
@ -0,0 +1,26 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s
|
||||||
|
; RUN: opt -S -basicaa -newgvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS
|
||||||
|
; Check that loads from calloc are recognized as being zero.
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
; Function Attrs: nounwind uwtable
|
||||||
|
define i32 @test1() {
|
||||||
|
%1 = tail call noalias i8* @calloc(i64 1, i64 4)
|
||||||
|
%2 = bitcast i8* %1 to i32*
|
||||||
|
; This load is trivially constant zero
|
||||||
|
%3 = load i32, i32* %2, align 4
|
||||||
|
ret i32 %3
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
; CHECK-NOT: %3 = load i32, i32* %2, align 4
|
||||||
|
; CHECK: ret i32 0
|
||||||
|
|
||||||
|
; CHECK_NO_LIBCALLS-LABEL: @test1(
|
||||||
|
; CHECK_NO_LIBCALLS: load
|
||||||
|
; CHECK_NO_LIBCALLS: ret i32 %
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
declare noalias i8* @calloc(i64, i64)
|
|
@ -0,0 +1,76 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; Two occurrences of strlen should be zapped.
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin9"
|
||||||
|
|
||||||
|
define i32 @test(i32 %g, i8* %P) nounwind {
|
||||||
|
entry:
|
||||||
|
%tmp2 = call i32 @strlen( i8* %P ) nounwind readonly ; <i32> [#uses=1]
|
||||||
|
%tmp3 = icmp eq i32 %tmp2, 100 ; <i1> [#uses=1]
|
||||||
|
%tmp34 = zext i1 %tmp3 to i8 ; <i8> [#uses=1]
|
||||||
|
%toBool = icmp ne i8 %tmp34, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool, label %bb, label %bb6
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
br label %bb27
|
||||||
|
|
||||||
|
bb6: ; preds = %entry
|
||||||
|
%tmp8 = add i32 %g, 42 ; <i32> [#uses=2]
|
||||||
|
%tmp10 = call i32 @strlen( i8* %P ) nounwind readonly ; <i32> [#uses=1]
|
||||||
|
%tmp11 = icmp eq i32 %tmp10, 100 ; <i1> [#uses=1]
|
||||||
|
%tmp1112 = zext i1 %tmp11 to i8 ; <i8> [#uses=1]
|
||||||
|
%toBool13 = icmp ne i8 %tmp1112, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool13, label %bb14, label %bb16
|
||||||
|
|
||||||
|
bb14: ; preds = %bb6
|
||||||
|
br label %bb27
|
||||||
|
|
||||||
|
bb16: ; preds = %bb6
|
||||||
|
%tmp18 = mul i32 %tmp8, 2 ; <i32> [#uses=1]
|
||||||
|
%tmp20 = call i32 @strlen( i8* %P ) nounwind readonly ; <i32> [#uses=1]
|
||||||
|
%tmp21 = icmp eq i32 %tmp20, 100 ; <i1> [#uses=1]
|
||||||
|
%tmp2122 = zext i1 %tmp21 to i8 ; <i8> [#uses=1]
|
||||||
|
%toBool23 = icmp ne i8 %tmp2122, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %toBool23, label %bb24, label %bb26
|
||||||
|
|
||||||
|
bb24: ; preds = %bb16
|
||||||
|
br label %bb27
|
||||||
|
|
||||||
|
bb26: ; preds = %bb16
|
||||||
|
br label %bb27
|
||||||
|
|
||||||
|
bb27: ; preds = %bb26, %bb24, %bb14, %bb
|
||||||
|
%tmp.0 = phi i32 [ 11, %bb26 ], [ %tmp18, %bb24 ], [ %tmp8, %bb14 ], [ %g, %bb ] ; <i32> [#uses=1]
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return: ; preds = %bb27
|
||||||
|
ret i32 %tmp.0
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: define i32 @test(i32 %g, i8* %P) #0 {
|
||||||
|
; CHECK: entry:
|
||||||
|
; CHECK: %tmp2 = call i32 @strlen(i8* %P) #1
|
||||||
|
; CHECK: %tmp3 = icmp eq i32 %tmp2, 100
|
||||||
|
; CHECK: %tmp34 = zext i1 %tmp3 to i8
|
||||||
|
; CHECK: br i1 %tmp3, label %bb, label %bb6
|
||||||
|
; CHECK: bb:
|
||||||
|
; CHECK: br label %bb27
|
||||||
|
; CHECK: bb6:
|
||||||
|
; CHECK: %tmp8 = add i32 %g, 42
|
||||||
|
; CHECK: br i1 false, label %bb14, label %bb16
|
||||||
|
; CHECK: bb14:
|
||||||
|
; CHECK: br label %bb27
|
||||||
|
; CHECK: bb16:
|
||||||
|
; CHECK: %tmp18 = mul i32 %tmp8, 2
|
||||||
|
; CHECK: br i1 false, label %bb24, label %bb26
|
||||||
|
; CHECK: bb24:
|
||||||
|
; CHECK: br label %bb27
|
||||||
|
; CHECK: bb26:
|
||||||
|
; CHECK: br label %bb27
|
||||||
|
; CHECK: bb27:
|
||||||
|
; CHECK: %tmp.0 = phi i32 [ 11, %bb26 ], [ undef, %bb24 ], [ undef, %bb14 ], [ %g, %bb ]
|
||||||
|
; CHECK: ret i32 %tmp.0
|
||||||
|
; CHECK: }
|
||||||
|
|
||||||
|
declare i32 @strlen(i8*) nounwind readonly
|
|
@ -0,0 +1,45 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
; Should delete the second call to strlen even though the intervening strchr call exists.
|
||||||
|
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin7"
|
||||||
|
|
||||||
|
define i8* @test(i8* %P, i8* %Q, i32 %x, i32 %y) nounwind readonly {
|
||||||
|
entry:
|
||||||
|
%0 = tail call i32 @strlen(i8* %P) ; <i32> [#uses=2]
|
||||||
|
%1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %1, label %bb, label %bb1
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
%2 = sdiv i32 %x, %y ; <i32> [#uses=1]
|
||||||
|
br label %bb1
|
||||||
|
|
||||||
|
bb1: ; preds = %bb, %entry
|
||||||
|
%x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ] ; <i32> [#uses=1]
|
||||||
|
%3 = tail call i8* @strchr(i8* %Q, i32 97) ; <i8*> [#uses=1]
|
||||||
|
%4 = tail call i32 @strlen(i8* %P) ; <i32> [#uses=1]
|
||||||
|
%5 = add i32 %x_addr.0, %0 ; <i32> [#uses=1]
|
||||||
|
%.sum = sub i32 %5, %4 ; <i32> [#uses=1]
|
||||||
|
%6 = getelementptr i8, i8* %3, i32 %.sum ; <i8*> [#uses=1]
|
||||||
|
ret i8* %6
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: define i8* @test(i8* %P, i8* %Q, i32 %x, i32 %y) #0 {
|
||||||
|
; CHECK: entry:
|
||||||
|
; CHECK-NEXT: %0 = tail call i32 @strlen(i8* %P)
|
||||||
|
; CHECK-NEXT: %1 = icmp eq i32 %0, 0
|
||||||
|
; CHECK-NEXT: br i1 %1, label %bb, label %bb1
|
||||||
|
; CHECK: bb:
|
||||||
|
; CHECK-NEXT: %2 = sdiv i32 %x, %y
|
||||||
|
; CHECK-NEXT: br label %bb1
|
||||||
|
; CHECK: bb1:
|
||||||
|
; CHECK-NEXT: %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ]
|
||||||
|
; CHECK-NEXT: %3 = tail call i8* @strchr(i8* %Q, i32 97)
|
||||||
|
; CHECK-NEXT: %4 = add i32 %x_addr.0, %0
|
||||||
|
; CHECK-NEXT: %5 = getelementptr i8, i8* %3, i32 %x_addr.0
|
||||||
|
; CHECK-NEXT: ret i8* %5
|
||||||
|
; CHECK: }
|
||||||
|
|
||||||
|
declare i32 @strlen(i8*) nounwind readonly
|
||||||
|
|
||||||
|
declare i8* @strchr(i8*, i32) nounwind readonly
|
|
@ -0,0 +1,23 @@
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
declare void @use(i32, i32)
|
||||||
|
|
||||||
|
define void @foo(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @foo(
|
||||||
|
%add1 = add i32 %x, %y
|
||||||
|
%add2 = add i32 %y, %x
|
||||||
|
call void @use(i32 %add1, i32 %add2)
|
||||||
|
; CHECK: @use(i32 %add1, i32 %add1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @vse(i1, i1)
|
||||||
|
|
||||||
|
define void @bar(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @bar(
|
||||||
|
%cmp1 = icmp ult i32 %x, %y
|
||||||
|
%cmp2 = icmp ugt i32 %y, %x
|
||||||
|
call void @vse(i1 %cmp1, i1 %cmp2)
|
||||||
|
; CHECK: @vse(i1 %cmp1, i1 %cmp1)
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
@y = external global i32
|
||||||
|
@z = external global i32
|
||||||
|
|
||||||
|
; Function Attrs: nounwind ssp uwtable
|
||||||
|
define void @foo(i32 %x) {
|
||||||
|
; CHECK: @foo(i32 %x)
|
||||||
|
; CHECK: %.pre = load i32, i32* @y
|
||||||
|
; CHECK: call void @bar(i32 %.pre)
|
||||||
|
|
||||||
|
%t = sub i32 %x, %x
|
||||||
|
%.pre = load i32, i32* @y, align 4
|
||||||
|
%cmp = icmp sgt i32 %t, 2
|
||||||
|
br i1 %cmp, label %if.then, label %entry.if.end_crit_edge
|
||||||
|
|
||||||
|
entry.if.end_crit_edge: ; preds = %entry
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
%add = add nsw i32 %x, 3
|
||||||
|
store i32 %add, i32* @y, align 4
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %entry.if.end_crit_edge, %if.then
|
||||||
|
%1 = phi i32 [ %.pre, %entry.if.end_crit_edge ], [ %add, %if.then ]
|
||||||
|
tail call void @bar(i32 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @foo2(i32 %x) {
|
||||||
|
; CHECK: @foo2(i32 %x)
|
||||||
|
; CHECK: %.pre = load i32, i32* @y
|
||||||
|
; CHECK: tail call void @bar(i32 %.pre)
|
||||||
|
entry:
|
||||||
|
%t = sub i32 %x, %x
|
||||||
|
%.pre = load i32, i32* @y, align 4
|
||||||
|
%cmp = icmp sgt i32 %t, 2
|
||||||
|
br i1 %cmp, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
%add = add nsw i32 %x, 3
|
||||||
|
store i32 %add, i32* @y, align 4
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
store i32 1, i32* @z, align 4
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
%0 = phi i32 [ %.pre, %if.else ], [ %add, %if.then ]
|
||||||
|
tail call void @bar(i32 %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @bar(i32)
|
|
@ -0,0 +1,141 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
%"class.llvm::SmallVector" = type { %"class.llvm::SmallVectorImpl", [1 x %"union.llvm::SmallVectorBase::U"] }
|
||||||
|
%"class.llvm::SmallVectorImpl" = type { %"class.llvm::SmallVectorTemplateBase" }
|
||||||
|
%"class.llvm::SmallVectorTemplateBase" = type { %"class.llvm::SmallVectorTemplateCommon" }
|
||||||
|
%"class.llvm::SmallVectorTemplateCommon" = type { %"class.llvm::SmallVectorBase" }
|
||||||
|
%"class.llvm::SmallVectorBase" = type { i8*, i8*, i8*, %"union.llvm::SmallVectorBase::U" }
|
||||||
|
%"union.llvm::SmallVectorBase::U" = type { x86_fp80 }
|
||||||
|
|
||||||
|
; Function Attrs: ssp uwtable
|
||||||
|
define void @_Z4testv() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||||
|
; CHECK: @_Z4testv()
|
||||||
|
; CHECK: invoke.cont:
|
||||||
|
; CHECK: br i1 true, label %new.notnull.i11, label %if.end.i14
|
||||||
|
; CHECK: Retry.i10:
|
||||||
|
|
||||||
|
entry:
|
||||||
|
%sv = alloca %"class.llvm::SmallVector", align 16
|
||||||
|
%0 = bitcast %"class.llvm::SmallVector"* %sv to i8*
|
||||||
|
call void @llvm.lifetime.start(i64 64, i8* %0) #1
|
||||||
|
%BeginX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 0
|
||||||
|
%FirstEl.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 3
|
||||||
|
%1 = bitcast %"union.llvm::SmallVectorBase::U"* %FirstEl.i.i.i.i.i.i to i8*
|
||||||
|
store i8* %1, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4
|
||||||
|
%EndX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 1
|
||||||
|
store i8* %1, i8** %EndX.i.i.i.i.i.i, align 8, !tbaa !4
|
||||||
|
%CapacityX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 2
|
||||||
|
%add.ptr.i.i.i.i2.i.i = getelementptr inbounds %"union.llvm::SmallVectorBase::U", %"union.llvm::SmallVectorBase::U"* %FirstEl.i.i.i.i.i.i, i64 2
|
||||||
|
%add.ptr.i.i.i.i.i.i = bitcast %"union.llvm::SmallVectorBase::U"* %add.ptr.i.i.i.i2.i.i to i8*
|
||||||
|
store i8* %add.ptr.i.i.i.i.i.i, i8** %CapacityX.i.i.i.i.i.i, align 16, !tbaa !4
|
||||||
|
%EndX.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 1
|
||||||
|
%2 = load i8*, i8** %EndX.i, align 8, !tbaa !4
|
||||||
|
%CapacityX.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 2
|
||||||
|
%cmp.i = icmp ult i8* %2, %add.ptr.i.i.i.i.i.i
|
||||||
|
br i1 %cmp.i, label %Retry.i, label %if.end.i
|
||||||
|
|
||||||
|
Retry.i: ; preds = %.noexc, %entry
|
||||||
|
%3 = phi i8* [ %2, %entry ], [ %.pre.i, %.noexc ]
|
||||||
|
%new.isnull.i = icmp eq i8* %3, null
|
||||||
|
br i1 %new.isnull.i, label %invoke.cont, label %new.notnull.i
|
||||||
|
|
||||||
|
new.notnull.i: ; preds = %Retry.i
|
||||||
|
%4 = bitcast i8* %3 to i32*
|
||||||
|
store i32 1, i32* %4, align 4, !tbaa !5
|
||||||
|
br label %invoke.cont
|
||||||
|
|
||||||
|
if.end.i: ; preds = %entry
|
||||||
|
%5 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0
|
||||||
|
invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"* %5, i64 0, i64 4)
|
||||||
|
to label %.noexc unwind label %lpad
|
||||||
|
|
||||||
|
.noexc: ; preds = %if.end.i
|
||||||
|
%.pre.i = load i8*, i8** %EndX.i, align 8, !tbaa !4
|
||||||
|
br label %Retry.i
|
||||||
|
|
||||||
|
invoke.cont: ; preds = %new.notnull.i, %Retry.i
|
||||||
|
%add.ptr.i = getelementptr inbounds i8, i8* %3, i64 4
|
||||||
|
store i8* %add.ptr.i, i8** %EndX.i, align 8, !tbaa !4
|
||||||
|
%6 = load i8*, i8** %CapacityX.i, align 16, !tbaa !4
|
||||||
|
%cmp.i8 = icmp ult i8* %add.ptr.i, %6
|
||||||
|
br i1 %cmp.i8, label %new.notnull.i11, label %if.end.i14
|
||||||
|
|
||||||
|
Retry.i10: ; preds = %if.end.i14
|
||||||
|
%.pre.i13 = load i8*, i8** %EndX.i, align 8, !tbaa !4
|
||||||
|
%new.isnull.i9 = icmp eq i8* %.pre.i13, null
|
||||||
|
br i1 %new.isnull.i9, label %invoke.cont2, label %new.notnull.i11
|
||||||
|
|
||||||
|
new.notnull.i11: ; preds = %invoke.cont, %Retry.i10
|
||||||
|
%7 = phi i8* [ %.pre.i13, %Retry.i10 ], [ %add.ptr.i, %invoke.cont ]
|
||||||
|
%8 = bitcast i8* %7 to i32*
|
||||||
|
store i32 2, i32* %8, align 4, !tbaa !5
|
||||||
|
br label %invoke.cont2
|
||||||
|
|
||||||
|
if.end.i14: ; preds = %invoke.cont
|
||||||
|
%9 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0
|
||||||
|
invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"* %9, i64 0, i64 4)
|
||||||
|
to label %Retry.i10 unwind label %lpad
|
||||||
|
|
||||||
|
invoke.cont2: ; preds = %new.notnull.i11, %Retry.i10
|
||||||
|
%10 = phi i8* [ null, %Retry.i10 ], [ %7, %new.notnull.i11 ]
|
||||||
|
%add.ptr.i12 = getelementptr inbounds i8, i8* %10, i64 4
|
||||||
|
store i8* %add.ptr.i12, i8** %EndX.i, align 8, !tbaa !4
|
||||||
|
invoke void @_Z1gRN4llvm11SmallVectorIiLj8EEE(%"class.llvm::SmallVector"* %sv)
|
||||||
|
to label %invoke.cont3 unwind label %lpad
|
||||||
|
|
||||||
|
invoke.cont3: ; preds = %invoke.cont2
|
||||||
|
%11 = load i8*, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4
|
||||||
|
%cmp.i.i.i.i19 = icmp eq i8* %11, %1
|
||||||
|
br i1 %cmp.i.i.i.i19, label %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21, label %if.then.i.i.i20
|
||||||
|
|
||||||
|
if.then.i.i.i20: ; preds = %invoke.cont3
|
||||||
|
call void @free(i8* %11) #1
|
||||||
|
br label %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21
|
||||||
|
|
||||||
|
_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21: ; preds = %invoke.cont3, %if.then.i.i.i20
|
||||||
|
call void @llvm.lifetime.end(i64 64, i8* %0) #1
|
||||||
|
ret void
|
||||||
|
|
||||||
|
lpad: ; preds = %if.end.i14, %if.end.i, %invoke.cont2
|
||||||
|
%12 = landingpad { i8*, i32 }
|
||||||
|
cleanup
|
||||||
|
%13 = load i8*, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4
|
||||||
|
%cmp.i.i.i.i = icmp eq i8* %13, %1
|
||||||
|
br i1 %cmp.i.i.i.i, label %eh.resume, label %if.then.i.i.i
|
||||||
|
|
||||||
|
if.then.i.i.i: ; preds = %lpad
|
||||||
|
call void @free(i8* %13) #1
|
||||||
|
br label %eh.resume
|
||||||
|
|
||||||
|
eh.resume: ; preds = %if.then.i.i.i, %lpad
|
||||||
|
resume { i8*, i32 } %12
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
declare void @llvm.lifetime.start(i64, i8* nocapture) #1
|
||||||
|
|
||||||
|
declare i32 @__gxx_personality_v0(...)
|
||||||
|
|
||||||
|
declare void @_Z1gRN4llvm11SmallVectorIiLj8EEE(%"class.llvm::SmallVector"*) #2
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
declare void @llvm.lifetime.end(i64, i8* nocapture) #1
|
||||||
|
|
||||||
|
declare void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"*, i64, i64) #2
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
declare void @free(i8* nocapture) #3
|
||||||
|
|
||||||
|
attributes #0 = { ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||||
|
attributes #1 = { nounwind }
|
||||||
|
attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||||
|
attributes #3 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||||
|
|
||||||
|
!0 = !{!"any pointer", !1}
|
||||||
|
!1 = !{!"omnipotent char", !2}
|
||||||
|
!2 = !{!"Simple C/C++ TBAA"}
|
||||||
|
!3 = !{!"int", !1}
|
||||||
|
!4 = !{!0, !0, i64 0}
|
||||||
|
!5 = !{!3, !3, i64 0}
|
|
@ -0,0 +1,300 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
@a = external global i32 ; <i32*> [#uses=7]
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
define i32 @test1() nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = load i32, i32* @a, align 4
|
||||||
|
%1 = icmp eq i32 %0, 4
|
||||||
|
br i1 %1, label %bb, label %bb1
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
br label %bb8
|
||||||
|
|
||||||
|
bb1: ; preds = %entry
|
||||||
|
%2 = load i32, i32* @a, align 4
|
||||||
|
%3 = icmp eq i32 %2, 5
|
||||||
|
br i1 %3, label %bb2, label %bb3
|
||||||
|
|
||||||
|
bb2: ; preds = %bb1
|
||||||
|
br label %bb8
|
||||||
|
|
||||||
|
bb3: ; preds = %bb1
|
||||||
|
%4 = load i32, i32* @a, align 4
|
||||||
|
%5 = icmp eq i32 %4, 4
|
||||||
|
; CHECK: br i1 false, label %bb4, label %bb5
|
||||||
|
br i1 %5, label %bb4, label %bb5
|
||||||
|
|
||||||
|
bb4: ; preds = %bb3
|
||||||
|
%6 = load i32, i32* @a, align 4
|
||||||
|
%7 = add i32 %6, 5
|
||||||
|
br label %bb8
|
||||||
|
|
||||||
|
bb5: ; preds = %bb3
|
||||||
|
%8 = load i32, i32* @a, align 4
|
||||||
|
%9 = icmp eq i32 %8, 5
|
||||||
|
; CHECK: br i1 false, label %bb6, label %bb7
|
||||||
|
br i1 %9, label %bb6, label %bb7
|
||||||
|
|
||||||
|
bb6: ; preds = %bb5
|
||||||
|
%10 = load i32, i32* @a, align 4
|
||||||
|
%11 = add i32 %10, 4
|
||||||
|
br label %bb8
|
||||||
|
|
||||||
|
bb7: ; preds = %bb5
|
||||||
|
%12 = load i32, i32* @a, align 4
|
||||||
|
br label %bb8
|
||||||
|
|
||||||
|
bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb
|
||||||
|
%.0 = phi i32 [ %12, %bb7 ], [ %11, %bb6 ], [ %7, %bb4 ], [ 4, %bb2 ], [ 5, %bb ]
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return: ; preds = %bb8
|
||||||
|
ret i32 %.0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @foo(i1)
|
||||||
|
declare void @bar(i32)
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test3(
|
||||||
|
define void @test3(i32 %x, i32 %y) {
|
||||||
|
%xz = icmp eq i32 %x, 0
|
||||||
|
%yz = icmp eq i32 %y, 0
|
||||||
|
%z = and i1 %xz, %yz
|
||||||
|
br i1 %z, label %both_zero, label %nope
|
||||||
|
both_zero:
|
||||||
|
call void @foo(i1 %xz)
|
||||||
|
; CHECK: call void @foo(i1 true)
|
||||||
|
call void @foo(i1 %yz)
|
||||||
|
; CHECK: call void @foo(i1 true)
|
||||||
|
call void @bar(i32 %x)
|
||||||
|
; CHECK: call void @bar(i32 0)
|
||||||
|
call void @bar(i32 %y)
|
||||||
|
; CHECK: call void @bar(i32 0)
|
||||||
|
ret void
|
||||||
|
nope:
|
||||||
|
call void @foo(i1 %z)
|
||||||
|
; CHECK: call void @foo(i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test4(
|
||||||
|
define void @test4(i1 %b, i32 %x) {
|
||||||
|
br i1 %b, label %sw, label %case3
|
||||||
|
sw:
|
||||||
|
switch i32 %x, label %default [
|
||||||
|
i32 0, label %case0
|
||||||
|
i32 1, label %case1
|
||||||
|
i32 2, label %case0
|
||||||
|
i32 3, label %case3
|
||||||
|
i32 4, label %default
|
||||||
|
]
|
||||||
|
default:
|
||||||
|
; CHECK: default:
|
||||||
|
call void @bar(i32 %x)
|
||||||
|
; CHECK: call void @bar(i32 %x)
|
||||||
|
ret void
|
||||||
|
case0:
|
||||||
|
; CHECK: case0:
|
||||||
|
call void @bar(i32 %x)
|
||||||
|
; CHECK: call void @bar(i32 %x)
|
||||||
|
ret void
|
||||||
|
case1:
|
||||||
|
; CHECK: case1:
|
||||||
|
call void @bar(i32 %x)
|
||||||
|
; CHECK: call void @bar(i32 1)
|
||||||
|
ret void
|
||||||
|
case3:
|
||||||
|
; CHECK: case3:
|
||||||
|
call void @bar(i32 %x)
|
||||||
|
; CHECK: call void @bar(i32 %x)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test5(
|
||||||
|
define i1 @test5(i32 %x, i32 %y) {
|
||||||
|
%cmp = icmp eq i32 %x, %y
|
||||||
|
br i1 %cmp, label %same, label %different
|
||||||
|
|
||||||
|
same:
|
||||||
|
%cmp2 = icmp ne i32 %x, %y
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp2
|
||||||
|
|
||||||
|
different:
|
||||||
|
%cmp3 = icmp eq i32 %x, %y
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test6(
|
||||||
|
define i1 @test6(i32 %x, i32 %y) {
|
||||||
|
%cmp2 = icmp ne i32 %x, %y
|
||||||
|
%cmp = icmp eq i32 %x, %y
|
||||||
|
%cmp3 = icmp eq i32 %x, %y
|
||||||
|
br i1 %cmp, label %same, label %different
|
||||||
|
|
||||||
|
same:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp2
|
||||||
|
|
||||||
|
different:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test6_fp(
|
||||||
|
define i1 @test6_fp(float %x, float %y) {
|
||||||
|
%cmp2 = fcmp une float %x, %y
|
||||||
|
%cmp = fcmp oeq float %x, %y
|
||||||
|
%cmp3 = fcmp oeq float %x, %y
|
||||||
|
br i1 %cmp, label %same, label %different
|
||||||
|
|
||||||
|
same:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp2
|
||||||
|
|
||||||
|
different:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test7(
|
||||||
|
define i1 @test7(i32 %x, i32 %y) {
|
||||||
|
%cmp = icmp sgt i32 %x, %y
|
||||||
|
br i1 %cmp, label %same, label %different
|
||||||
|
|
||||||
|
same:
|
||||||
|
%cmp2 = icmp sle i32 %x, %y
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp2
|
||||||
|
|
||||||
|
different:
|
||||||
|
%cmp3 = icmp sgt i32 %x, %y
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test7_fp(
|
||||||
|
define i1 @test7_fp(float %x, float %y) {
|
||||||
|
%cmp = fcmp ogt float %x, %y
|
||||||
|
br i1 %cmp, label %same, label %different
|
||||||
|
|
||||||
|
same:
|
||||||
|
%cmp2 = fcmp ule float %x, %y
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp2
|
||||||
|
|
||||||
|
different:
|
||||||
|
%cmp3 = fcmp ogt float %x, %y
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test8(
|
||||||
|
define i1 @test8(i32 %x, i32 %y) {
|
||||||
|
%cmp2 = icmp sle i32 %x, %y
|
||||||
|
%cmp = icmp sgt i32 %x, %y
|
||||||
|
%cmp3 = icmp sgt i32 %x, %y
|
||||||
|
br i1 %cmp, label %same, label %different
|
||||||
|
|
||||||
|
same:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp2
|
||||||
|
|
||||||
|
different:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test8_fp(
|
||||||
|
define i1 @test8_fp(float %x, float %y) {
|
||||||
|
%cmp2 = fcmp ule float %x, %y
|
||||||
|
%cmp = fcmp ogt float %x, %y
|
||||||
|
%cmp3 = fcmp ogt float %x, %y
|
||||||
|
br i1 %cmp, label %same, label %different
|
||||||
|
|
||||||
|
same:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp2
|
||||||
|
|
||||||
|
different:
|
||||||
|
; CHECK: ret i1 false
|
||||||
|
ret i1 %cmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
; PR1768
|
||||||
|
; CHECK-LABEL: @test9(
|
||||||
|
define i32 @test9(i32 %i, i32 %j) {
|
||||||
|
%cmp = icmp eq i32 %i, %j
|
||||||
|
br i1 %cmp, label %cond_true, label %ret
|
||||||
|
|
||||||
|
cond_true:
|
||||||
|
%diff = sub i32 %i, %j
|
||||||
|
ret i32 %diff
|
||||||
|
; CHECK: ret i32 0
|
||||||
|
|
||||||
|
ret:
|
||||||
|
ret i32 5
|
||||||
|
; CHECK: ret i32 5
|
||||||
|
}
|
||||||
|
|
||||||
|
; PR1768
|
||||||
|
; CHECK-LABEL: @test10(
|
||||||
|
define i32 @test10(i32 %j, i32 %i) {
|
||||||
|
%cmp = icmp eq i32 %i, %j
|
||||||
|
br i1 %cmp, label %cond_true, label %ret
|
||||||
|
|
||||||
|
cond_true:
|
||||||
|
%diff = sub i32 %i, %j
|
||||||
|
ret i32 %diff
|
||||||
|
; CHECK: ret i32 0
|
||||||
|
|
||||||
|
ret:
|
||||||
|
ret i32 5
|
||||||
|
; CHECK: ret i32 5
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @yogibar()
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test11(
|
||||||
|
define i32 @test11(i32 %x) {
|
||||||
|
%v0 = call i32 @yogibar()
|
||||||
|
%v1 = call i32 @yogibar()
|
||||||
|
%cmp = icmp eq i32 %v0, %v1
|
||||||
|
br i1 %cmp, label %cond_true, label %next
|
||||||
|
|
||||||
|
cond_true:
|
||||||
|
ret i32 %v1
|
||||||
|
; CHECK: ret i32 %v0
|
||||||
|
|
||||||
|
next:
|
||||||
|
%cmp2 = icmp eq i32 %x, %v0
|
||||||
|
br i1 %cmp2, label %cond_true2, label %next2
|
||||||
|
|
||||||
|
cond_true2:
|
||||||
|
ret i32 %v0
|
||||||
|
; CHECK: ret i32 %x
|
||||||
|
|
||||||
|
next2:
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test12(
|
||||||
|
define i32 @test12(i32 %x) {
|
||||||
|
%cmp = icmp eq i32 %x, 0
|
||||||
|
br i1 %cmp, label %cond_true, label %cond_false
|
||||||
|
|
||||||
|
cond_true:
|
||||||
|
br label %ret
|
||||||
|
|
||||||
|
cond_false:
|
||||||
|
br label %ret
|
||||||
|
|
||||||
|
ret:
|
||||||
|
%res = phi i32 [ %x, %cond_true ], [ %x, %cond_false ]
|
||||||
|
; CHECK: %res = phi i32 [ 0, %cond_true ], [ %x, %cond_false ]
|
||||||
|
ret i32 %res
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
; RUN: opt -disable-basicaa -newgvn -S < %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||||
|
target triple = "x86_64-unknown-freebsd8.0"
|
||||||
|
|
||||||
|
; PR5744
|
||||||
|
define i32 @test1({i16, i32} *%P) {
|
||||||
|
%P2 = getelementptr {i16, i32}, {i16, i32} *%P, i32 0, i32 0
|
||||||
|
store i16 42, i16* %P2
|
||||||
|
|
||||||
|
%P3 = getelementptr {i16, i32}, {i16, i32} *%P, i32 0, i32 1
|
||||||
|
%V = load i32, i32* %P3
|
||||||
|
ret i32 %V
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
; RUN: opt -newgvn -disable-output < %s
|
||||||
|
|
||||||
|
; PR5631
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||||
|
target triple = "x86_64-apple-darwin10.0"
|
||||||
|
|
||||||
|
define i32* @test1(i8* %name, i32 %namelen, i32* %o, i32 %expected_type) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
br i1 undef, label %if.end13, label %while.body.preheader
|
||||||
|
|
||||||
|
|
||||||
|
if.end13: ; preds = %if.then6
|
||||||
|
br label %while.body.preheader
|
||||||
|
|
||||||
|
while.body.preheader: ; preds = %if.end13, %if.end
|
||||||
|
br label %while.body
|
||||||
|
|
||||||
|
while.body: ; preds = %while.body.backedge, %while.body.preheader
|
||||||
|
%o.addr.0 = phi i32* [ undef, %while.body.preheader ], [ %o.addr.0.be, %while.body.backedge ] ; <i32*> [#uses=2]
|
||||||
|
br i1 false, label %return.loopexit, label %lor.lhs.false
|
||||||
|
|
||||||
|
lor.lhs.false: ; preds = %while.body
|
||||||
|
%tmp20 = bitcast i32* %o.addr.0 to i32* ; <i32*> [#uses=1]
|
||||||
|
%tmp22 = load i32, i32* %tmp20 ; <i32> [#uses=0]
|
||||||
|
br i1 undef, label %land.lhs.true24, label %if.end31
|
||||||
|
|
||||||
|
land.lhs.true24: ; preds = %lor.lhs.false
|
||||||
|
%call28 = call i32* @parse_object(i8* undef) nounwind ; <i32*> [#uses=0]
|
||||||
|
br i1 undef, label %return.loopexit, label %if.end31
|
||||||
|
|
||||||
|
if.end31: ; preds = %land.lhs.true24, %lor.lhs.false
|
||||||
|
br i1 undef, label %return.loopexit, label %if.end41
|
||||||
|
|
||||||
|
if.end41: ; preds = %if.end31
|
||||||
|
%tmp43 = bitcast i32* %o.addr.0 to i32* ; <i32*> [#uses=1]
|
||||||
|
%tmp45 = load i32, i32* %tmp43 ; <i32> [#uses=0]
|
||||||
|
br i1 undef, label %if.then50, label %if.else
|
||||||
|
|
||||||
|
if.then50: ; preds = %if.end41
|
||||||
|
%tmp53 = load i32*, i32** undef ; <i32*> [#uses=1]
|
||||||
|
br label %while.body.backedge
|
||||||
|
|
||||||
|
if.else: ; preds = %if.end41
|
||||||
|
br i1 undef, label %if.then62, label %if.else67
|
||||||
|
|
||||||
|
if.then62: ; preds = %if.else
|
||||||
|
br label %while.body.backedge
|
||||||
|
|
||||||
|
while.body.backedge: ; preds = %if.then62, %if.then50
|
||||||
|
%o.addr.0.be = phi i32* [ %tmp53, %if.then50 ], [ undef, %if.then62 ] ; <i32*> [#uses=1]
|
||||||
|
br label %while.body
|
||||||
|
|
||||||
|
if.else67: ; preds = %if.else
|
||||||
|
ret i32* null
|
||||||
|
|
||||||
|
return.loopexit: ; preds = %if.end31, %land.lhs.true24, %while.body
|
||||||
|
ret i32* undef
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32* @parse_object(i8*)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%struct.attribute_spec = type { i8*, i32, i32, i8, i8, i8 }
|
||||||
|
|
||||||
|
@attribute_tables = external global [4 x %struct.attribute_spec*] ; <[4 x %struct.attribute_spec*]*> [#uses=2]
|
||||||
|
|
||||||
|
define void @test2() nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb69.i
|
||||||
|
|
||||||
|
bb69.i: ; preds = %bb57.i.preheader
|
||||||
|
%tmp4 = getelementptr inbounds [4 x %struct.attribute_spec*], [4 x %struct.attribute_spec*]* @attribute_tables, i32 0, i32 undef ; <%struct.attribute_spec**> [#uses=1]
|
||||||
|
%tmp3 = load %struct.attribute_spec*, %struct.attribute_spec** %tmp4, align 4 ; <%struct.attribute_spec*> [#uses=1]
|
||||||
|
br label %bb65.i
|
||||||
|
|
||||||
|
bb65.i: ; preds = %bb65.i.preheader, %bb64.i
|
||||||
|
%storemerge6.i = phi i32 [ 1, %bb64.i ], [ 0, %bb69.i ] ; <i32> [#uses=3]
|
||||||
|
%scevgep14 = getelementptr inbounds %struct.attribute_spec, %struct.attribute_spec* %tmp3, i32 %storemerge6.i, i32 0 ; <i8**> [#uses=1]
|
||||||
|
%tmp2 = load i8*, i8** %scevgep14, align 4 ; <i8*> [#uses=0]
|
||||||
|
%tmp = load %struct.attribute_spec*, %struct.attribute_spec** %tmp4, align 4 ; <%struct.attribute_spec*> [#uses=1]
|
||||||
|
%scevgep1516 = getelementptr inbounds %struct.attribute_spec, %struct.attribute_spec* %tmp, i32 %storemerge6.i, i32 0 ; <i8**> [#uses=0]
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
bb64.i: ; Unreachable
|
||||||
|
br label %bb65.i
|
||||||
|
|
||||||
|
bb66.i: ; Unreachable
|
||||||
|
br label %bb69.i
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; rdar://7438974
|
||||||
|
|
||||||
|
@g = external global i64, align 8
|
||||||
|
|
||||||
|
define i32* @test3() {
|
||||||
|
do.end17.i:
|
||||||
|
%tmp18.i = load i7*, i7** undef
|
||||||
|
%tmp1 = bitcast i7* %tmp18.i to i8*
|
||||||
|
br i1 undef, label %do.body36.i, label %if.then21.i
|
||||||
|
|
||||||
|
if.then21.i:
|
||||||
|
%tmp2 = bitcast i7* %tmp18.i to i8*
|
||||||
|
ret i32* undef
|
||||||
|
|
||||||
|
do.body36.i:
|
||||||
|
%ivar38.i = load i64, i64* @g
|
||||||
|
%tmp3 = bitcast i7* %tmp18.i to i8*
|
||||||
|
%add.ptr39.sum.i = add i64 %ivar38.i, 8
|
||||||
|
%tmp40.i = getelementptr inbounds i8, i8* %tmp3, i64 %add.ptr39.sum.i
|
||||||
|
%tmp4 = bitcast i8* %tmp40.i to i64*
|
||||||
|
%tmp41.i = load i64, i64* %tmp4
|
||||||
|
br i1 undef, label %if.then48.i, label %do.body57.i
|
||||||
|
|
||||||
|
if.then48.i:
|
||||||
|
%call54.i = call i32 @foo2()
|
||||||
|
br label %do.body57.i
|
||||||
|
|
||||||
|
do.body57.i:
|
||||||
|
%tmp58.i = load i7*, i7** undef
|
||||||
|
%ivar59.i = load i64, i64* @g
|
||||||
|
%tmp5 = bitcast i7* %tmp58.i to i8*
|
||||||
|
%add.ptr65.sum.i = add i64 %ivar59.i, 8
|
||||||
|
%tmp66.i = getelementptr inbounds i8, i8* %tmp5, i64 %add.ptr65.sum.i
|
||||||
|
%tmp6 = bitcast i8* %tmp66.i to i64*
|
||||||
|
%tmp67.i = load i64, i64* %tmp6
|
||||||
|
ret i32* undef
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @foo2()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
define i32 @test4() {
|
||||||
|
entry:
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
dead:
|
||||||
|
%P2 = getelementptr i32, i32 *%P2, i32 52
|
||||||
|
%Q2 = getelementptr i32, i32 *%Q2, i32 52
|
||||||
|
store i32 4, i32* %P2
|
||||||
|
%A = load i32, i32* %Q2
|
||||||
|
br i1 true, label %dead, label %dead2
|
||||||
|
|
||||||
|
dead2:
|
||||||
|
ret i32 %A
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; PR9841
|
||||||
|
define fastcc i8 @test5(i8* %P) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = load i8, i8* %P, align 2
|
||||||
|
|
||||||
|
%Q = getelementptr i8, i8* %P, i32 1
|
||||||
|
%1 = load i8, i8* %Q, align 1
|
||||||
|
ret i8 %1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; Test that a GEP in an unreachable block with the following form doesn't crash
|
||||||
|
; GVN:
|
||||||
|
;
|
||||||
|
; %x = gep %some.type %x, ...
|
||||||
|
|
||||||
|
%struct.type = type { i64, i32, i32 }
|
||||||
|
|
||||||
|
define fastcc void @func() nounwind uwtable ssp align 2 {
|
||||||
|
entry:
|
||||||
|
br label %reachable.bb
|
||||||
|
|
||||||
|
;; Unreachable code.
|
||||||
|
|
||||||
|
unreachable.bb:
|
||||||
|
%gep.val = getelementptr inbounds %struct.type, %struct.type* %gep.val, i64 1
|
||||||
|
br i1 undef, label %u2.bb, label %u1.bb
|
||||||
|
|
||||||
|
u1.bb:
|
||||||
|
%tmp1 = getelementptr inbounds %struct.type, %struct.type* %gep.val, i64 0, i32 0
|
||||||
|
store i64 -1, i64* %tmp1, align 8
|
||||||
|
br label %unreachable.bb
|
||||||
|
|
||||||
|
u2.bb:
|
||||||
|
%0 = load i32, i32* undef, align 4
|
||||||
|
%conv.i.i.i.i.i = zext i32 %0 to i64
|
||||||
|
br label %u2.bb
|
||||||
|
|
||||||
|
;; Reachable code.
|
||||||
|
|
||||||
|
reachable.bb:
|
||||||
|
br label %r1.bb
|
||||||
|
|
||||||
|
r1.bb:
|
||||||
|
br label %u2.bb
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
; Check that the redundant load from %if.then is removed.
|
||||||
|
; Also, check that the debug location associated to load %0 still refers to
|
||||||
|
; line 3 and not line 6.
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
; CHECK: @test_redundant_load(
|
||||||
|
; CHECK-LABEL: entry:
|
||||||
|
; CHECK-NEXT: load i32, i32* %Y, align 4, !dbg ![[LOC:[0-9]+]]
|
||||||
|
; CHECK-LABEL: if.then:
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK-LABEL: if.end:
|
||||||
|
; CHECK: ![[LOC]] = !DILocation(line: 3, scope: !{{.*}})
|
||||||
|
|
||||||
|
define i32 @test_redundant_load(i32 %X, i32* %Y) !dbg !6 {
|
||||||
|
entry:
|
||||||
|
%0 = load i32, i32* %Y, align 4, !dbg !8
|
||||||
|
%cmp = icmp sgt i32 %X, -1, !dbg !9
|
||||||
|
br i1 %cmp, label %if.then, label %if.end, !dbg !9
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
%1 = load i32, i32* %Y, align 4, !dbg !10
|
||||||
|
%add = add nsw i32 %0, %1, !dbg !10
|
||||||
|
call void @foo(), !dbg !11
|
||||||
|
br label %if.end, !dbg !12
|
||||||
|
|
||||||
|
if.end: ; preds = %if.then, %entry
|
||||||
|
%Result.0 = phi i32 [ %add, %if.then ], [ %0, %entry ]
|
||||||
|
ret i32 %Result.0, !dbg !13
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @foo()
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!3, !4, !5}
|
||||||
|
|
||||||
|
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
|
||||||
|
!1 = !DIFile(filename: "test.cpp", directory: "")
|
||||||
|
!2 = !{}
|
||||||
|
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||||
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!5 = !{i32 1, !"PIC Level", i32 2}
|
||||||
|
!6 = distinct !DISubprogram(name: "test_redundant_load", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
|
||||||
|
!7 = !DISubroutineType(types: !2)
|
||||||
|
!8 = !DILocation(line: 3, scope: !6)
|
||||||
|
!9 = !DILocation(line: 5, scope: !6)
|
||||||
|
!10 = !DILocation(line: 6, scope: !6)
|
||||||
|
!11 = !DILocation(line: 7, scope: !6)
|
||||||
|
!12 = !DILocation(line: 8, scope: !6)
|
||||||
|
!13 = !DILocation(line: 10, scope: !6)
|
|
@ -0,0 +1,171 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @f1(i32 %x) {
|
||||||
|
; CHECK-LABEL: define i32 @f1(
|
||||||
|
bb0:
|
||||||
|
%cmp = icmp eq i32 %x, 0
|
||||||
|
br i1 %cmp, label %bb2, label %bb1
|
||||||
|
bb1:
|
||||||
|
br label %bb2
|
||||||
|
bb2:
|
||||||
|
%cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
|
||||||
|
%foo = add i32 %cond, %x
|
||||||
|
ret i32 %foo
|
||||||
|
; CHECK: bb2:
|
||||||
|
; CHECK: ret i32 %x
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @f2(i32 %x) {
|
||||||
|
; CHECK-LABEL: define i32 @f2(
|
||||||
|
bb0:
|
||||||
|
%cmp = icmp ne i32 %x, 0
|
||||||
|
br i1 %cmp, label %bb1, label %bb2
|
||||||
|
bb1:
|
||||||
|
br label %bb2
|
||||||
|
bb2:
|
||||||
|
%cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
|
||||||
|
%foo = add i32 %cond, %x
|
||||||
|
ret i32 %foo
|
||||||
|
; CHECK: bb2:
|
||||||
|
; CHECK: ret i32 %x
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @f3(i32 %x) {
|
||||||
|
; CHECK-LABEL: define i32 @f3(
|
||||||
|
bb0:
|
||||||
|
switch i32 %x, label %bb1 [ i32 0, label %bb2]
|
||||||
|
bb1:
|
||||||
|
br label %bb2
|
||||||
|
bb2:
|
||||||
|
%cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
|
||||||
|
%foo = add i32 %cond, %x
|
||||||
|
ret i32 %foo
|
||||||
|
; CHECK: bb2:
|
||||||
|
; CHECK: ret i32 %x
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @g(i1)
|
||||||
|
define void @f4(i8 * %x) {
|
||||||
|
; CHECK-LABEL: define void @f4(
|
||||||
|
bb0:
|
||||||
|
%y = icmp eq i8* null, %x
|
||||||
|
br i1 %y, label %bb2, label %bb1
|
||||||
|
bb1:
|
||||||
|
br label %bb2
|
||||||
|
bb2:
|
||||||
|
%zed = icmp eq i8* null, %x
|
||||||
|
call void @g(i1 %zed)
|
||||||
|
; CHECK: call void @g(i1 %y)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @fcmp_oeq_not_zero(double %x, double %y) {
|
||||||
|
entry:
|
||||||
|
%cmp = fcmp oeq double %y, 2.0
|
||||||
|
br i1 %cmp, label %if, label %return
|
||||||
|
|
||||||
|
if:
|
||||||
|
%div = fdiv double %x, %y
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return:
|
||||||
|
%retval = phi double [ %div, %if ], [ %x, %entry ]
|
||||||
|
ret double %retval
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @fcmp_oeq_not_zero(
|
||||||
|
; CHECK: %div = fdiv double %x, 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @fcmp_une_not_zero(double %x, double %y) {
|
||||||
|
entry:
|
||||||
|
%cmp = fcmp une double %y, 2.0
|
||||||
|
br i1 %cmp, label %return, label %else
|
||||||
|
|
||||||
|
else:
|
||||||
|
%div = fdiv double %x, %y
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return:
|
||||||
|
%retval = phi double [ %div, %else ], [ %x, %entry ]
|
||||||
|
ret double %retval
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @fcmp_une_not_zero(
|
||||||
|
; CHECK: %div = fdiv double %x, 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
; PR22376 - We can't propagate zero constants because -0.0
|
||||||
|
; compares equal to 0.0. If %y is -0.0 in this test case,
|
||||||
|
; we would produce the wrong sign on the infinity return value.
|
||||||
|
define double @fcmp_oeq_zero(double %x, double %y) {
|
||||||
|
entry:
|
||||||
|
%cmp = fcmp oeq double %y, 0.0
|
||||||
|
br i1 %cmp, label %if, label %return
|
||||||
|
|
||||||
|
if:
|
||||||
|
%div = fdiv double %x, %y
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return:
|
||||||
|
%retval = phi double [ %div, %if ], [ %x, %entry ]
|
||||||
|
ret double %retval
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @fcmp_oeq_zero(
|
||||||
|
; CHECK: %div = fdiv double %x, %y
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @fcmp_une_zero(double %x, double %y) {
|
||||||
|
entry:
|
||||||
|
%cmp = fcmp une double %y, -0.0
|
||||||
|
br i1 %cmp, label %return, label %else
|
||||||
|
|
||||||
|
else:
|
||||||
|
%div = fdiv double %x, %y
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return:
|
||||||
|
%retval = phi double [ %div, %else ], [ %x, %entry ]
|
||||||
|
ret double %retval
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @fcmp_une_zero(
|
||||||
|
; CHECK: %div = fdiv double %x, %y
|
||||||
|
}
|
||||||
|
|
||||||
|
; We also cannot propagate a value if it's not a constant.
|
||||||
|
; This is because the value could be 0.0 or -0.0.
|
||||||
|
|
||||||
|
define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) {
|
||||||
|
entry:
|
||||||
|
%z = fadd double %z1, %z2
|
||||||
|
%cmp = fcmp oeq double %y, %z
|
||||||
|
br i1 %cmp, label %if, label %return
|
||||||
|
|
||||||
|
if:
|
||||||
|
%div = fdiv double %x, %z
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return:
|
||||||
|
%retval = phi double [ %div, %if ], [ %x, %entry ]
|
||||||
|
ret double %retval
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @fcmp_oeq_maybe_zero(
|
||||||
|
; CHECK: %div = fdiv double %x, %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) {
|
||||||
|
entry:
|
||||||
|
%z = fadd double %z1, %z2
|
||||||
|
%cmp = fcmp une double %y, %z
|
||||||
|
br i1 %cmp, label %return, label %else
|
||||||
|
|
||||||
|
else:
|
||||||
|
%div = fdiv double %x, %z
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return:
|
||||||
|
%retval = phi double [ %div, %else ], [ %x, %entry ]
|
||||||
|
ret double %retval
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @fcmp_une_maybe_zero(
|
||||||
|
; CHECK: %div = fdiv double %x, %z
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s
|
||||||
|
|
||||||
|
; We can value forward across the fence since we can (semantically)
|
||||||
|
; reorder the following load before the fence.
|
||||||
|
define i32 @test(i32* %addr.i) {
|
||||||
|
; CHECK-LABEL: @test
|
||||||
|
; CHECK: store
|
||||||
|
; CHECK: fence
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK: ret
|
||||||
|
store i32 5, i32* %addr.i, align 4
|
||||||
|
fence release
|
||||||
|
%a = load i32, i32* %addr.i, align 4
|
||||||
|
ret i32 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; Same as above
|
||||||
|
define i32 @test2(i32* %addr.i) {
|
||||||
|
; CHECK-LABEL: @test2
|
||||||
|
; CHECK-NEXT: fence
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK: ret
|
||||||
|
%a = load i32, i32* %addr.i, align 4
|
||||||
|
fence release
|
||||||
|
%a2 = load i32, i32* %addr.i, align 4
|
||||||
|
%res = sub i32 %a, %a2
|
||||||
|
ret i32 %res
|
||||||
|
}
|
||||||
|
|
||||||
|
; We can not value forward across an acquire barrier since we might
|
||||||
|
; be syncronizing with another thread storing to the same variable
|
||||||
|
; followed by a release fence. This is not so much enforcing an
|
||||||
|
; ordering property (though it is that too), but a liveness
|
||||||
|
; property. We expect to eventually see the value of store by
|
||||||
|
; another thread when spinning on that location.
|
||||||
|
define i32 @test3(i32* noalias %addr.i, i32* noalias %otheraddr) {
|
||||||
|
; CHECK-LABEL: @test3
|
||||||
|
; CHECK: load
|
||||||
|
; CHECK: fence
|
||||||
|
; CHECK: load
|
||||||
|
; CHECK: ret i32 %res
|
||||||
|
; the following code is intented to model the unrolling of
|
||||||
|
; two iterations in a spin loop of the form:
|
||||||
|
; do { fence acquire: tmp = *%addr.i; ) while (!tmp);
|
||||||
|
; It's hopefully clear that allowing PRE to turn this into:
|
||||||
|
; if (!*%addr.i) while(true) {} would be unfortunate
|
||||||
|
fence acquire
|
||||||
|
%a = load i32, i32* %addr.i, align 4
|
||||||
|
fence acquire
|
||||||
|
%a2 = load i32, i32* %addr.i, align 4
|
||||||
|
%res = sub i32 %a, %a2
|
||||||
|
ret i32 %res
|
||||||
|
}
|
||||||
|
|
||||||
|
; Another example of why forwarding across an acquire fence is problematic
|
||||||
|
; can be seen in a normal locking operation. Say we had:
|
||||||
|
; *p = 5; unlock(l); lock(l); use(p);
|
||||||
|
; forwarding the store to p would be invalid. A reasonable implementation
|
||||||
|
; of unlock and lock might be:
|
||||||
|
; unlock() { atomicrmw sub %l, 1 unordered; fence release }
|
||||||
|
; lock() {
|
||||||
|
; do {
|
||||||
|
; %res = cmpxchg %p, 0, 1, monotonic monotonic
|
||||||
|
; } while(!%res.success)
|
||||||
|
; fence acquire;
|
||||||
|
; }
|
||||||
|
; Given we chose to forward across the release fence, we clearly can't forward
|
||||||
|
; across the acquire fence as well.
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
declare void @use(i1)
|
||||||
|
|
||||||
|
define void @test1(float %x, float %y) {
|
||||||
|
entry:
|
||||||
|
%cmp1 = fcmp nnan oeq float %y, %x
|
||||||
|
%cmp2 = fcmp oeq float %x, %y
|
||||||
|
call void @use(i1 %cmp1)
|
||||||
|
call void @use(i1 %cmp2)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define void @test1(
|
||||||
|
; CHECK: %[[cmp:.*]] = fcmp oeq float %y, %x
|
||||||
|
; CHECK-NEXT: call void @use(i1 %[[cmp]])
|
||||||
|
; CHECK-NEXT: call void @use(i1 %[[cmp]])
|
||||||
|
; CHECK-NEXT: ret void
|
|
@ -0,0 +1,100 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; GVN failed to do constant expression folding and expanded
|
||||||
|
; them unfolded in many places, producing exponentially large const
|
||||||
|
; expressions. As a result, the compilation never fisished.
|
||||||
|
; This test checks that we are folding constant expression
|
||||||
|
; PR 28418
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
%2 = type { i32, i32, i32, i32, i32 }
|
||||||
|
define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) {
|
||||||
|
%tmp1 = alloca %2, align 4
|
||||||
|
%tmp114 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
|
||||||
|
%tmp115 = bitcast i32* %tmp114 to <4 x i32>*
|
||||||
|
store <4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0>, <4 x i32>* %tmp115, align 4
|
||||||
|
%tmp1683 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
|
||||||
|
%tmp1688 = load i32, i32* %tmp1683, align 4
|
||||||
|
%tmp1693 = shl i32 %tmp1688, 5
|
||||||
|
%tmp1694 = xor i32 %tmp1693, %tmp1688
|
||||||
|
%tmp1695 = lshr i32 %tmp1694, 7
|
||||||
|
%tmp1696 = xor i32 %tmp1695, %tmp1694
|
||||||
|
%tmp1697 = shl i32 %tmp1696, 22
|
||||||
|
%tmp1698 = xor i32 %tmp1697, %tmp1696
|
||||||
|
%tmp1707 = shl i32 %tmp1698, 5
|
||||||
|
%tmp1708 = xor i32 %tmp1707, %tmp1698
|
||||||
|
%tmp1709 = lshr i32 %tmp1708, 7
|
||||||
|
%tmp1710 = xor i32 %tmp1709, %tmp1708
|
||||||
|
%tmp1711 = shl i32 %tmp1710, 22
|
||||||
|
%tmp1712 = xor i32 %tmp1711, %tmp1710
|
||||||
|
%tmp1721 = shl i32 %tmp1712, 5
|
||||||
|
%tmp1722 = xor i32 %tmp1721, %tmp1712
|
||||||
|
%tmp1723 = lshr i32 %tmp1722, 7
|
||||||
|
%tmp1724 = xor i32 %tmp1723, %tmp1722
|
||||||
|
%tmp1725 = shl i32 %tmp1724, 22
|
||||||
|
%tmp1726 = xor i32 %tmp1725, %tmp1724
|
||||||
|
%tmp1735 = shl i32 %tmp1726, 5
|
||||||
|
%tmp1736 = xor i32 %tmp1735, %tmp1726
|
||||||
|
%tmp1737 = lshr i32 %tmp1736, 7
|
||||||
|
%tmp1738 = xor i32 %tmp1737, %tmp1736
|
||||||
|
%tmp1739 = shl i32 %tmp1738, 22
|
||||||
|
%tmp1740 = xor i32 %tmp1739, %tmp1738
|
||||||
|
store i32 %tmp1740, i32* %tmp1683, align 4
|
||||||
|
; CHECK: store i32 310393545, i32* %tmp114, align 4
|
||||||
|
%tmp1756 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
|
||||||
|
%tmp1761 = load i32, i32* %tmp1756, align 4
|
||||||
|
%tmp1766 = shl i32 %tmp1761, 5
|
||||||
|
%tmp1767 = xor i32 %tmp1766, %tmp1761
|
||||||
|
%tmp1768 = lshr i32 %tmp1767, 7
|
||||||
|
%tmp1769 = xor i32 %tmp1768, %tmp1767
|
||||||
|
%tmp1770 = shl i32 %tmp1769, 22
|
||||||
|
%tmp1771 = xor i32 %tmp1770, %tmp1769
|
||||||
|
%tmp1780 = shl i32 %tmp1771, 5
|
||||||
|
%tmp1781 = xor i32 %tmp1780, %tmp1771
|
||||||
|
%tmp1782 = lshr i32 %tmp1781, 7
|
||||||
|
%tmp1783 = xor i32 %tmp1782, %tmp1781
|
||||||
|
%tmp1784 = shl i32 %tmp1783, 22
|
||||||
|
%tmp1785 = xor i32 %tmp1784, %tmp1783
|
||||||
|
%tmp1794 = shl i32 %tmp1785, 5
|
||||||
|
%tmp1795 = xor i32 %tmp1794, %tmp1785
|
||||||
|
%tmp1796 = lshr i32 %tmp1795, 7
|
||||||
|
%tmp1797 = xor i32 %tmp1796, %tmp1795
|
||||||
|
%tmp1798 = shl i32 %tmp1797, 22
|
||||||
|
%tmp1799 = xor i32 %tmp1798, %tmp1797
|
||||||
|
%tmp1808 = shl i32 %tmp1799, 5
|
||||||
|
%tmp1809 = xor i32 %tmp1808, %tmp1799
|
||||||
|
%tmp1810 = lshr i32 %tmp1809, 7
|
||||||
|
%tmp1811 = xor i32 %tmp1810, %tmp1809
|
||||||
|
%tmp1812 = shl i32 %tmp1811, 22
|
||||||
|
%tmp1813 = xor i32 %tmp1812, %tmp1811
|
||||||
|
store i32 %tmp1813, i32* %tmp1756, align 4
|
||||||
|
; CHECK: store i32 -383584258, i32* %tmp114, align 4
|
||||||
|
%tmp2645 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
|
||||||
|
%tmp2650 = load i32, i32* %tmp2645, align 4
|
||||||
|
%tmp2655 = shl i32 %tmp2650, 5
|
||||||
|
%tmp2656 = xor i32 %tmp2655, %tmp2650
|
||||||
|
%tmp2657 = lshr i32 %tmp2656, 7
|
||||||
|
%tmp2658 = xor i32 %tmp2657, %tmp2656
|
||||||
|
%tmp2659 = shl i32 %tmp2658, 22
|
||||||
|
%tmp2660 = xor i32 %tmp2659, %tmp2658
|
||||||
|
%tmp2669 = shl i32 %tmp2660, 5
|
||||||
|
%tmp2670 = xor i32 %tmp2669, %tmp2660
|
||||||
|
%tmp2671 = lshr i32 %tmp2670, 7
|
||||||
|
%tmp2672 = xor i32 %tmp2671, %tmp2670
|
||||||
|
%tmp2673 = shl i32 %tmp2672, 22
|
||||||
|
%tmp2674 = xor i32 %tmp2673, %tmp2672
|
||||||
|
%tmp2683 = shl i32 %tmp2674, 5
|
||||||
|
%tmp2684 = xor i32 %tmp2683, %tmp2674
|
||||||
|
%tmp2685 = lshr i32 %tmp2684, 7
|
||||||
|
%tmp2686 = xor i32 %tmp2685, %tmp2684
|
||||||
|
%tmp2687 = shl i32 %tmp2686, 22
|
||||||
|
%tmp2688 = xor i32 %tmp2687, %tmp2686
|
||||||
|
%tmp2697 = shl i32 %tmp2688, 5
|
||||||
|
%tmp2698 = xor i32 %tmp2697, %tmp2688
|
||||||
|
%tmp2699 = lshr i32 %tmp2698, 7
|
||||||
|
%tmp2700 = xor i32 %tmp2699, %tmp2698
|
||||||
|
%tmp2701 = shl i32 %tmp2700, 22
|
||||||
|
%tmp2702 = xor i32 %tmp2701, %tmp2700
|
||||||
|
store i32 %tmp2702, i32* %tmp2645, align 4
|
||||||
|
; CHECK: store i32 -57163022, i32* %tmp114, align 4
|
||||||
|
ret i32 0
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
define double @test1(double %x, double %y) {
|
||||||
|
; CHECK: @test1(double %x, double %y)
|
||||||
|
; CHECK: %add1 = fadd double %x, %y
|
||||||
|
; CHECK-NOT: fpmath
|
||||||
|
; CHECK: %foo = fadd double %add1, %add1
|
||||||
|
%add1 = fadd double %x, %y, !fpmath !0
|
||||||
|
%add2 = fadd double %x, %y
|
||||||
|
%foo = fadd double %add1, %add2
|
||||||
|
ret double %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @test2(double %x, double %y) {
|
||||||
|
; CHECK: @test2(double %x, double %y)
|
||||||
|
; CHECK: %add1 = fadd double %x, %y, !fpmath !0
|
||||||
|
; CHECK: %foo = fadd double %add1, %add1
|
||||||
|
%add1 = fadd double %x, %y, !fpmath !0
|
||||||
|
%add2 = fadd double %x, %y, !fpmath !0
|
||||||
|
%foo = fadd double %add1, %add2
|
||||||
|
ret double %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @test3(double %x, double %y) {
|
||||||
|
; CHECK: @test3(double %x, double %y)
|
||||||
|
; CHECK: %add1 = fadd double %x, %y, !fpmath !1
|
||||||
|
; CHECK: %foo = fadd double %add1, %add1
|
||||||
|
%add1 = fadd double %x, %y, !fpmath !1
|
||||||
|
%add2 = fadd double %x, %y, !fpmath !0
|
||||||
|
%foo = fadd double %add1, %add2
|
||||||
|
ret double %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @test4(double %x, double %y) {
|
||||||
|
; CHECK: @test4(double %x, double %y)
|
||||||
|
; CHECK: %add1 = fadd double %x, %y, !fpmath !1
|
||||||
|
; CHECK: %foo = fadd double %add1, %add1
|
||||||
|
%add1 = fadd double %x, %y, !fpmath !0
|
||||||
|
%add2 = fadd double %x, %y, !fpmath !1
|
||||||
|
%foo = fadd double %add1, %add2
|
||||||
|
ret double %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
!0 = !{ float 5.0 }
|
||||||
|
!1 = !{ float 2.5 }
|
|
@ -0,0 +1,44 @@
|
||||||
|
; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
||||||
|
target triple = "i686-pc-windows-msvc"
|
||||||
|
|
||||||
|
%eh.ThrowInfo = type { i32, i8*, i8*, i8* }
|
||||||
|
%struct.A = type { i32* }
|
||||||
|
|
||||||
|
@"_TI1?AUA@@" = external constant %eh.ThrowInfo
|
||||||
|
|
||||||
|
define i8 @f() personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
|
entry:
|
||||||
|
%b = alloca i8
|
||||||
|
%c = alloca i8
|
||||||
|
store i8 42, i8* %b
|
||||||
|
store i8 13, i8* %c
|
||||||
|
invoke void @_CxxThrowException(i8* %b, %eh.ThrowInfo* nonnull @"_TI1?AUA@@")
|
||||||
|
to label %unreachable unwind label %catch.dispatch
|
||||||
|
|
||||||
|
catch.dispatch: ; preds = %entry
|
||||||
|
%cs1 = catchswitch within none [label %catch] unwind to caller
|
||||||
|
|
||||||
|
catch: ; preds = %catch.dispatch
|
||||||
|
%catchpad = catchpad within %cs1 [i8* null, i32 64, i8* null]
|
||||||
|
store i8 5, i8* %b
|
||||||
|
catchret from %catchpad to label %try.cont
|
||||||
|
|
||||||
|
try.cont: ; preds = %catch
|
||||||
|
%load_b = load i8, i8* %b
|
||||||
|
%load_c = load i8, i8* %c
|
||||||
|
%add = add i8 %load_b, %load_c
|
||||||
|
ret i8 %add
|
||||||
|
|
||||||
|
unreachable: ; preds = %entry
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
; CHECK-LABEL: define i8 @f(
|
||||||
|
; CHECK: %[[load_b:.*]] = load i8, i8* %b
|
||||||
|
; CHECK-NEXT: %[[load_c:.*]] = load i8, i8* %c
|
||||||
|
; CHECK-NEXT: %[[add:.*]] = add i8 %[[load_b]], %[[load_c]]
|
||||||
|
; CHECK-NEXT: ret i8 %[[add]]
|
||||||
|
|
||||||
|
declare i32 @__CxxFrameHandler3(...)
|
||||||
|
|
||||||
|
declare x86_stdcallcc void @_CxxThrowException(i8*, %eh.ThrowInfo*)
|
|
@ -0,0 +1,338 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
%struct.A = type { i32 (...)** }
|
||||||
|
@_ZTV1A = available_externally unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 8
|
||||||
|
@_ZTI1A = external constant i8*
|
||||||
|
|
||||||
|
@unknownPtr = external global i8
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @simple() {
|
||||||
|
define i8 @simple() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
|
||||||
|
%a = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
%b = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
%c = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
; CHECK: ret i8 42
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @optimizable1() {
|
||||||
|
define i8 @optimizable1() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
%ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
|
||||||
|
%a = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
|
||||||
|
call void @foo(i8* %ptr2); call to use %ptr2
|
||||||
|
; CHECK: ret i8 42
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @optimizable2() {
|
||||||
|
define i8 @optimizable2() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
|
||||||
|
store i8 13, i8* %ptr ; can't use this store with invariant.group
|
||||||
|
%a = load i8, i8* %ptr
|
||||||
|
call void @bar(i8 %a) ; call to use %a
|
||||||
|
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
%b = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
|
||||||
|
; CHECK: ret i8 42
|
||||||
|
ret i8 %b
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @unoptimizable1() {
|
||||||
|
define i8 @unoptimizable1() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
%a = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
; CHECK: ret i8 %a
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define void @indirectLoads() {
|
||||||
|
define void @indirectLoads() {
|
||||||
|
entry:
|
||||||
|
%a = alloca %struct.A*, align 8
|
||||||
|
%0 = bitcast %struct.A** %a to i8*
|
||||||
|
|
||||||
|
%call = call i8* @getPointer(i8* null)
|
||||||
|
%1 = bitcast i8* %call to %struct.A*
|
||||||
|
call void @_ZN1AC1Ev(%struct.A* %1)
|
||||||
|
%2 = bitcast %struct.A* %1 to i8***
|
||||||
|
|
||||||
|
; CHECK: %vtable = load {{.*}} !invariant.group
|
||||||
|
%vtable = load i8**, i8*** %2, align 8, !invariant.group !2
|
||||||
|
%cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
|
||||||
|
call void @llvm.assume(i1 %cmp.vtables)
|
||||||
|
|
||||||
|
store %struct.A* %1, %struct.A** %a, align 8
|
||||||
|
%3 = load %struct.A*, %struct.A** %a, align 8
|
||||||
|
%4 = bitcast %struct.A* %3 to void (%struct.A*)***
|
||||||
|
|
||||||
|
; CHECK: call void @_ZN1A3fooEv(
|
||||||
|
%vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2
|
||||||
|
%vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
|
||||||
|
%5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
|
||||||
|
call void %5(%struct.A* %3)
|
||||||
|
%6 = load %struct.A*, %struct.A** %a, align 8
|
||||||
|
%7 = bitcast %struct.A* %6 to void (%struct.A*)***
|
||||||
|
|
||||||
|
; CHECK: call void @_ZN1A3fooEv(
|
||||||
|
%vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !2
|
||||||
|
%vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0
|
||||||
|
%8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8
|
||||||
|
|
||||||
|
call void %8(%struct.A* %6)
|
||||||
|
%9 = load %struct.A*, %struct.A** %a, align 8
|
||||||
|
%10 = bitcast %struct.A* %9 to void (%struct.A*)***
|
||||||
|
|
||||||
|
%vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !2
|
||||||
|
%vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0
|
||||||
|
%11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8
|
||||||
|
; CHECK: call void @_ZN1A3fooEv(
|
||||||
|
call void %11(%struct.A* %9)
|
||||||
|
|
||||||
|
%vtable5 = load i8**, i8*** %2, align 8, !invariant.group !2
|
||||||
|
%vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0
|
||||||
|
%12 = bitcast i8** %vfn6 to void (%struct.A*)**
|
||||||
|
%13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8
|
||||||
|
; CHECK: call void @_ZN1A3fooEv(
|
||||||
|
call void %13(%struct.A* %9)
|
||||||
|
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define void @combiningBitCastWithLoad() {
|
||||||
|
define void @combiningBitCastWithLoad() {
|
||||||
|
entry:
|
||||||
|
%a = alloca %struct.A*, align 8
|
||||||
|
%0 = bitcast %struct.A** %a to i8*
|
||||||
|
|
||||||
|
%call = call i8* @getPointer(i8* null)
|
||||||
|
%1 = bitcast i8* %call to %struct.A*
|
||||||
|
call void @_ZN1AC1Ev(%struct.A* %1)
|
||||||
|
%2 = bitcast %struct.A* %1 to i8***
|
||||||
|
|
||||||
|
; CHECK: %vtable = load {{.*}} !invariant.group
|
||||||
|
%vtable = load i8**, i8*** %2, align 8, !invariant.group !2
|
||||||
|
%cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
|
||||||
|
|
||||||
|
store %struct.A* %1, %struct.A** %a, align 8
|
||||||
|
; CHECK-NOT: !invariant.group
|
||||||
|
%3 = load %struct.A*, %struct.A** %a, align 8
|
||||||
|
%4 = bitcast %struct.A* %3 to void (%struct.A*)***
|
||||||
|
|
||||||
|
%vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2
|
||||||
|
%vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
|
||||||
|
%5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
|
||||||
|
call void %5(%struct.A* %3)
|
||||||
|
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL:define void @loadCombine() {
|
||||||
|
define void @loadCombine() {
|
||||||
|
enter:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group
|
||||||
|
%a = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
; CHECK-NOT: load
|
||||||
|
%b = load i8, i8* %ptr, !invariant.group !1
|
||||||
|
; CHECK: call void @bar(i8 %[[A]])
|
||||||
|
call void @bar(i8 %a)
|
||||||
|
; CHECK: call void @bar(i8 %[[A]])
|
||||||
|
call void @bar(i8 %b)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define void @loadCombine1() {
|
||||||
|
define void @loadCombine1() {
|
||||||
|
enter:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group
|
||||||
|
%c = load i8, i8* %ptr
|
||||||
|
; CHECK-NOT: load
|
||||||
|
%d = load i8, i8* %ptr, !invariant.group !1
|
||||||
|
; CHECK: call void @bar(i8 %[[D]])
|
||||||
|
call void @bar(i8 %c)
|
||||||
|
; CHECK: call void @bar(i8 %[[D]])
|
||||||
|
call void @bar(i8 %d)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define void @loadCombine2() {
|
||||||
|
define void @loadCombine2() {
|
||||||
|
enter:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
|
||||||
|
%e = load i8, i8* %ptr, !invariant.group !1
|
||||||
|
; CHECK-NOT: load
|
||||||
|
%f = load i8, i8* %ptr
|
||||||
|
; CHECK: call void @bar(i8 %[[E]])
|
||||||
|
call void @bar(i8 %e)
|
||||||
|
; CHECK: call void @bar(i8 %[[E]])
|
||||||
|
call void @bar(i8 %f)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define void @loadCombine3() {
|
||||||
|
define void @loadCombine3() {
|
||||||
|
enter:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group ![[OneMD:[0-9]]]
|
||||||
|
%e = load i8, i8* %ptr, !invariant.group !1
|
||||||
|
; CHECK-NOT: load
|
||||||
|
%f = load i8, i8* %ptr, !invariant.group !1
|
||||||
|
; CHECK: call void @bar(i8 %[[E]])
|
||||||
|
call void @bar(i8 %e)
|
||||||
|
; CHECK: call void @bar(i8 %[[E]])
|
||||||
|
call void @bar(i8 %f)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @unoptimizable2() {
|
||||||
|
define i8 @unoptimizable2() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
%a = load i8, i8* %ptr
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
%b = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
|
||||||
|
; CHECK: ret i8 %a
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @unoptimizable3() {
|
||||||
|
define i8 @unoptimizable3() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
%ptr2 = call i8* @getPointer(i8* %ptr)
|
||||||
|
%a = load i8, i8* %ptr2, !invariant.group !0
|
||||||
|
|
||||||
|
; CHECK: ret i8 %a
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @unoptimizable4() {
|
||||||
|
define i8 @unoptimizable4() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
%ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
|
||||||
|
%a = load i8, i8* %ptr2, !invariant.group !0
|
||||||
|
|
||||||
|
; CHECK: ret i8 %a
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @volatile1() {
|
||||||
|
define i8 @volatile1() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
%a = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
%b = load volatile i8, i8* %ptr
|
||||||
|
; CHECK: call void @bar(i8 %b)
|
||||||
|
call void @bar(i8 %b)
|
||||||
|
|
||||||
|
%c = load volatile i8, i8* %ptr, !invariant.group !0
|
||||||
|
; FIXME: we could change %c to 42, preserving volatile load
|
||||||
|
; CHECK: call void @bar(i8 %c)
|
||||||
|
call void @bar(i8 %c)
|
||||||
|
; CHECK: ret i8 42
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @volatile2() {
|
||||||
|
define i8 @volatile2() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
%a = load i8, i8* %ptr, !invariant.group !0
|
||||||
|
%b = load volatile i8, i8* %ptr
|
||||||
|
; CHECK: call void @bar(i8 %b)
|
||||||
|
call void @bar(i8 %b)
|
||||||
|
|
||||||
|
%c = load volatile i8, i8* %ptr, !invariant.group !0
|
||||||
|
; FIXME: we could change %c to 42, preserving volatile load
|
||||||
|
; CHECK: call void @bar(i8 %c)
|
||||||
|
call void @bar(i8 %c)
|
||||||
|
; CHECK: ret i8 42
|
||||||
|
ret i8 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define i8 @fun() {
|
||||||
|
define i8 @fun() {
|
||||||
|
entry:
|
||||||
|
%ptr = alloca i8
|
||||||
|
store i8 42, i8* %ptr, !invariant.group !0
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
|
||||||
|
%a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change
|
||||||
|
; CHECK: call void @bar(i8 42)
|
||||||
|
call void @bar(i8 %a)
|
||||||
|
|
||||||
|
call void @foo(i8* %ptr)
|
||||||
|
%b = load i8, i8* %ptr, !invariant.group !1 ; Can't assume anything, because group changed
|
||||||
|
; CHECK: call void @bar(i8 %b)
|
||||||
|
call void @bar(i8 %b)
|
||||||
|
|
||||||
|
%newPtr = call i8* @getPointer(i8* %ptr)
|
||||||
|
%c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr
|
||||||
|
; CHECK: call void @bar(i8 %c)
|
||||||
|
call void @bar(i8 %c)
|
||||||
|
|
||||||
|
%unknownValue = load i8, i8* @unknownPtr
|
||||||
|
; FIXME: Can assume that %unknownValue == 42
|
||||||
|
; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0
|
||||||
|
store i8 %unknownValue, i8* %ptr, !invariant.group !0
|
||||||
|
|
||||||
|
%newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
|
||||||
|
%d = load i8, i8* %newPtr2, !invariant.group !0 ; Can't step through invariant.group.barrier to get value of %ptr
|
||||||
|
; CHECK: ret i8 %d
|
||||||
|
ret i8 %d
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @foo(i8*)
|
||||||
|
declare void @bar(i8)
|
||||||
|
declare i8* @getPointer(i8*)
|
||||||
|
declare void @_ZN1A3fooEv(%struct.A*)
|
||||||
|
declare void @_ZN1AC1Ev(%struct.A*)
|
||||||
|
declare i8* @llvm.invariant.group.barrier(i8*)
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
declare void @llvm.assume(i1 %cmp.vtables) #0
|
||||||
|
|
||||||
|
|
||||||
|
attributes #0 = { nounwind }
|
||||||
|
; CHECK: ![[OneMD]] = !{!"other ptr"}
|
||||||
|
!0 = !{!"magic ptr"}
|
||||||
|
!1 = !{!"other ptr"}
|
||||||
|
!2 = !{!"vtable_of_a"}
|
|
@ -0,0 +1,59 @@
|
||||||
|
; Test to make sure llvm.invariant.start calls are not treated as clobbers.
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
|
||||||
|
declare {}* @llvm.invariant.start.p0i8(i64, i8* nocapture) nounwind readonly
|
||||||
|
declare void @llvm.invariant.end.p0i8({}*, i64, i8* nocapture) nounwind
|
||||||
|
|
||||||
|
; We forward store to the load across the invariant.start intrinsic
|
||||||
|
define i8 @forward_store() {
|
||||||
|
; CHECK-LABEL: @forward_store
|
||||||
|
; CHECK: call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK: ret i8 0
|
||||||
|
%a = alloca i8
|
||||||
|
store i8 0, i8* %a
|
||||||
|
%i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
|
||||||
|
%r = load i8, i8* %a
|
||||||
|
ret i8 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i8 @dummy(i8* nocapture) nounwind readonly
|
||||||
|
|
||||||
|
; We forward store to the load in the non-local analysis case,
|
||||||
|
; i.e. invariant.start is in another basic block.
|
||||||
|
define i8 @forward_store_nonlocal(i1 %cond) {
|
||||||
|
; CHECK-LABEL: forward_store_nonlocal
|
||||||
|
; CHECK: call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
|
||||||
|
; CHECK: ret i8 0
|
||||||
|
; CHECK: ret i8 %val
|
||||||
|
%a = alloca i8
|
||||||
|
store i8 0, i8* %a
|
||||||
|
%i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
|
||||||
|
br i1 %cond, label %loadblock, label %exit
|
||||||
|
|
||||||
|
loadblock:
|
||||||
|
%r = load i8, i8* %a
|
||||||
|
ret i8 %r
|
||||||
|
|
||||||
|
exit:
|
||||||
|
%val = call i8 @dummy(i8* %a)
|
||||||
|
ret i8 %val
|
||||||
|
}
|
||||||
|
|
||||||
|
; We should not value forward %foo to the invariant.end corresponding to %bar.
|
||||||
|
define i8 @forward_store1() {
|
||||||
|
; CHECK-LABEL: forward_store1
|
||||||
|
; CHECK: %foo = call {}* @llvm.invariant.start.p0i8
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK: %bar = call {}* @llvm.invariant.start.p0i8
|
||||||
|
; CHECK: call void @llvm.invariant.end.p0i8({}* %bar, i64 1, i8* %a)
|
||||||
|
; CHECK: ret i8 0
|
||||||
|
%a = alloca i8
|
||||||
|
store i8 0, i8* %a
|
||||||
|
%foo = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
|
||||||
|
%r = load i8, i8* %a
|
||||||
|
%bar = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
|
||||||
|
call void @llvm.invariant.end.p0i8({}* %bar, i64 1, i8* %a)
|
||||||
|
ret i8 %r
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin7"
|
||||||
|
|
||||||
|
define i8 @test(i8* %P) nounwind {
|
||||||
|
; CHECK: lifetime.start
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK: lifetime.end
|
||||||
|
entry:
|
||||||
|
call void @llvm.lifetime.start(i64 32, i8* %P)
|
||||||
|
%0 = load i8, i8* %P
|
||||||
|
store i8 1, i8* %P
|
||||||
|
call void @llvm.lifetime.end(i64 32, i8* %P)
|
||||||
|
%1 = load i8, i8* %P
|
||||||
|
ret i8 %1
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.lifetime.start(i64 %S, i8* nocapture %P) readonly
|
||||||
|
declare void @llvm.lifetime.end(i64 %S, i8* nocapture %P)
|
|
@ -0,0 +1,19 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -instcombine -S | FileCheck %s
|
||||||
|
; PR4189
|
||||||
|
@G = external constant [4 x i32]
|
||||||
|
|
||||||
|
define i32 @test(i8* %p, i32 %i) nounwind {
|
||||||
|
entry:
|
||||||
|
%P = getelementptr [4 x i32], [4 x i32]* @G, i32 0, i32 %i
|
||||||
|
%A = load i32, i32* %P
|
||||||
|
store i8 4, i8* %p
|
||||||
|
%B = load i32, i32* %P
|
||||||
|
%C = sub i32 %A, %B
|
||||||
|
ret i32 %C
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: define i32 @test(i8* %p, i32 %i) #0 {
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: store i8 4, i8* %p, align 1
|
||||||
|
; CHECK-NEXT: ret i32 0
|
||||||
|
; CHECK-NEXT: }
|
|
@ -0,0 +1,20 @@
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
; Check that an unreachable predecessor to a PHI node doesn't cause a crash.
|
||||||
|
; PR21625.
|
||||||
|
|
||||||
|
define i32 @f(i32** %f) {
|
||||||
|
; CHECK: bb0:
|
||||||
|
; Load should be removed, since it's ignored.
|
||||||
|
; CHECK-NEXT: br label
|
||||||
|
bb0:
|
||||||
|
%bar = load i32*, i32** %f
|
||||||
|
br label %bb2
|
||||||
|
bb1:
|
||||||
|
%zed = load i32*, i32** %f
|
||||||
|
br i1 false, label %bb1, label %bb2
|
||||||
|
bb2:
|
||||||
|
%foo = phi i32* [ null, %bb0 ], [ %zed, %bb1 ]
|
||||||
|
%storemerge = load i32, i32* %foo
|
||||||
|
ret i32 %storemerge
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s
|
||||||
|
; RUN: opt -S -basicaa -newgvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS
|
||||||
|
; PR13694
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-apple-macosx10.8.0"
|
||||||
|
|
||||||
|
declare i8* @malloc(i64) nounwind
|
||||||
|
|
||||||
|
define noalias i8* @test1() nounwind uwtable ssp {
|
||||||
|
entry:
|
||||||
|
%call = tail call i8* @malloc(i64 100) nounwind
|
||||||
|
%0 = load i8, i8* %call, align 1
|
||||||
|
%tobool = icmp eq i8 %0, 0
|
||||||
|
br i1 %tobool, label %if.end, label %if.then
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
store i8 0, i8* %call, align 1
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.then, %entry
|
||||||
|
ret i8* %call
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK-NOT: icmp
|
||||||
|
|
||||||
|
; CHECK_NO_LIBCALLS-LABEL: @test1(
|
||||||
|
; CHECK_NO_LIBCALLS: load
|
||||||
|
; CHECK_NO_LIBCALLS: icmp
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i8* @_Znwm(i64) nounwind
|
||||||
|
|
||||||
|
define noalias i8* @test2() nounwind uwtable ssp {
|
||||||
|
entry:
|
||||||
|
%call = tail call i8* @_Znwm(i64 100) nounwind
|
||||||
|
%0 = load i8, i8* %call, align 1
|
||||||
|
%tobool = icmp eq i8 %0, 0
|
||||||
|
br i1 %tobool, label %if.end, label %if.then
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
store i8 0, i8* %call, align 1
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.then, %entry
|
||||||
|
ret i8* %call
|
||||||
|
|
||||||
|
; CHECK-LABEL: @test2(
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK-NOT: icmp
|
||||||
|
|
||||||
|
; CHECK_NO_LIBCALLS-LABEL: @test2(
|
||||||
|
; CHECK_NO_LIBCALLS: load
|
||||||
|
; CHECK_NO_LIBCALLS: icmp
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
; RUN: opt -O3 -S %s | FileCheck %s
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
declare noalias i8* @_Znam(i64) #1
|
||||||
|
|
||||||
|
define i32 @TestNoAsan() {
|
||||||
|
%1 = tail call noalias i8* @_Znam(i64 2)
|
||||||
|
%2 = getelementptr inbounds i8, i8* %1, i64 1
|
||||||
|
store i8 0, i8* %2, align 1
|
||||||
|
store i8 0, i8* %1, align 1
|
||||||
|
%3 = bitcast i8* %1 to i16*
|
||||||
|
%4 = load i16, i16* %3, align 4
|
||||||
|
%5 = icmp eq i16 %4, 0
|
||||||
|
br i1 %5, label %11, label %6
|
||||||
|
|
||||||
|
; <label>:6 ; preds = %0
|
||||||
|
%7 = getelementptr inbounds i8, i8* %1, i64 2
|
||||||
|
%8 = bitcast i8* %7 to i16*
|
||||||
|
%9 = load i16, i16* %8, align 2
|
||||||
|
%10 = sext i16 %9 to i32
|
||||||
|
br label %11
|
||||||
|
|
||||||
|
; <label>:11 ; preds = %0, %6
|
||||||
|
%12 = phi i32 [ %10, %6 ], [ 0, %0 ]
|
||||||
|
ret i32 %12
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @TestNoAsan
|
||||||
|
; CHECK: ret i32 0
|
||||||
|
|
||||||
|
define i32 @TestAsan() sanitize_address {
|
||||||
|
%1 = tail call noalias i8* @_Znam(i64 2)
|
||||||
|
%2 = getelementptr inbounds i8, i8* %1, i64 1
|
||||||
|
store i8 0, i8* %2, align 1
|
||||||
|
store i8 0, i8* %1, align 1
|
||||||
|
%3 = bitcast i8* %1 to i16*
|
||||||
|
%4 = load i16, i16* %3, align 4
|
||||||
|
%5 = icmp eq i16 %4, 0
|
||||||
|
br i1 %5, label %11, label %6
|
||||||
|
|
||||||
|
; <label>:6 ; preds = %0
|
||||||
|
%7 = getelementptr inbounds i8, i8* %1, i64 2
|
||||||
|
%8 = bitcast i8* %7 to i16*
|
||||||
|
%9 = load i16, i16* %8, align 2
|
||||||
|
%10 = sext i16 %9 to i32
|
||||||
|
br label %11
|
||||||
|
|
||||||
|
; <label>:11 ; preds = %0, %6
|
||||||
|
%12 = phi i32 [ %10, %6 ], [ 0, %0 ]
|
||||||
|
ret i32 %12
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @TestAsan
|
||||||
|
; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
|
||||||
|
; CHECK: {{.*}} = phi
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
; RUN: opt -scoped-noalias -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @test1(i32* %p, i32* %q) {
|
||||||
|
; CHECK-LABEL: @test1(i32* %p, i32* %q)
|
||||||
|
; CHECK: load i32, i32* %p
|
||||||
|
; CHECK-NOT: noalias
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !noalias !0
|
||||||
|
%b = load i32, i32* %p
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test2(i32* %p, i32* %q) {
|
||||||
|
; CHECK-LABEL: @test2(i32* %p, i32* %q)
|
||||||
|
; CHECK: load i32, i32* %p, !alias.scope !0
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !alias.scope !0
|
||||||
|
%b = load i32, i32* %p, !alias.scope !0
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: In this case we can do better than intersecting the scopes, and can
|
||||||
|
; concatenate them instead. Both loads are in the same basic block, the first
|
||||||
|
; makes the second safe to speculatively execute, and there are no calls that may
|
||||||
|
; throw in between.
|
||||||
|
define i32 @test3(i32* %p, i32* %q) {
|
||||||
|
; CHECK-LABEL: @test3(i32* %p, i32* %q)
|
||||||
|
; CHECK: load i32, i32* %p, !alias.scope !1
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !alias.scope !1
|
||||||
|
%b = load i32, i32* %p, !alias.scope !2
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @foo(i32*) readonly
|
||||||
|
|
||||||
|
!0 = !{!0}
|
||||||
|
!1 = !{!1}
|
||||||
|
!2 = !{!0, !1}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64"
|
||||||
|
|
||||||
|
; GVN should ignore the store to p[1] to see that the load from p[0] is
|
||||||
|
; fully redundant.
|
||||||
|
|
||||||
|
; CHECK-LABEL: @yes(
|
||||||
|
; CHECK: if.then:
|
||||||
|
; CHECK-NEXT: store i32 0, i32* %q
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
|
||||||
|
define void @yes(i1 %c, i32* %p, i32* %q) nounwind {
|
||||||
|
entry:
|
||||||
|
store i32 0, i32* %p
|
||||||
|
%p1 = getelementptr inbounds i32, i32* %p, i64 1
|
||||||
|
store i32 1, i32* %p1
|
||||||
|
br i1 %c, label %if.else, label %if.then
|
||||||
|
|
||||||
|
if.then:
|
||||||
|
%t = load i32, i32* %p
|
||||||
|
store i32 %t, i32* %q
|
||||||
|
ret void
|
||||||
|
|
||||||
|
if.else:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; GVN should ignore the store to p[1] to see that the first load from p[0] is
|
||||||
|
; fully redundant. However, the second load is larger, so it's not a simple
|
||||||
|
; redundancy.
|
||||||
|
|
||||||
|
; CHECK-LABEL: @watch_out_for_size_change(
|
||||||
|
; CHECK: if.then:
|
||||||
|
; CHECK-NEXT: store i32 0, i32* %q
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
; CHECK: if.else:
|
||||||
|
; CHECK: load i64, i64* %pc
|
||||||
|
; CHECK: store i64
|
||||||
|
|
||||||
|
define void @watch_out_for_size_change(i1 %c, i32* %p, i32* %q) nounwind {
|
||||||
|
entry:
|
||||||
|
store i32 0, i32* %p
|
||||||
|
%p1 = getelementptr inbounds i32, i32* %p, i64 1
|
||||||
|
store i32 1, i32* %p1
|
||||||
|
br i1 %c, label %if.else, label %if.then
|
||||||
|
|
||||||
|
if.then:
|
||||||
|
%t = load i32, i32* %p
|
||||||
|
store i32 %t, i32* %q
|
||||||
|
ret void
|
||||||
|
|
||||||
|
if.else:
|
||||||
|
%pc = bitcast i32* %p to i64*
|
||||||
|
%qc = bitcast i32* %q to i64*
|
||||||
|
%t64 = load i64, i64* %pc
|
||||||
|
store i64 %t64, i64* %qc
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; REQUIRES: asserts
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -stats -disable-output 2>&1 | FileCheck %s
|
||||||
|
; rdar://7363102
|
||||||
|
|
||||||
|
; CHECK: Number of loads deleted
|
||||||
|
|
||||||
|
; GVN should be able to eliminate load %tmp22.i, because it is redundant with
|
||||||
|
; load %tmp8.i. This requires being able to prove that %tmp7.i doesn't
|
||||||
|
; alias the malloc'd value %tmp.i20.i.i, which it can do since %tmp7.i
|
||||||
|
; is derived from %tmp5.i which is computed from a load, and %tmp.i20.i.i
|
||||||
|
; is never stored and does not escape.
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
||||||
|
target triple = "x86_64-apple-darwin10.0"
|
||||||
|
|
||||||
|
%"struct.llvm::MallocAllocator" = type <{ i8 }>
|
||||||
|
%"struct.llvm::StringMap<void*,llvm::MallocAllocator>" = type { %"struct.llvm::StringMapImpl", %"struct.llvm::MallocAllocator" }
|
||||||
|
%"struct.llvm::StringMapEntry<void*>" = type { %"struct.llvm::StringMapEntryBase", i8* }
|
||||||
|
%"struct.llvm::StringMapEntryBase" = type { i32 }
|
||||||
|
%"struct.llvm::StringMapImpl" = type { %"struct.llvm::StringMapImpl::ItemBucket"*, i32, i32, i32, i32 }
|
||||||
|
%"struct.llvm::StringMapImpl::ItemBucket" = type { i32, %"struct.llvm::StringMapEntryBase"* }
|
||||||
|
%"struct.llvm::StringRef" = type { i8*, i64 }
|
||||||
|
|
||||||
|
define %"struct.llvm::StringMapEntry<void*>"* @_Z3fooRN4llvm9StringMapIPvNS_15MallocAllocatorEEEPKc(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %X, i8* %P) ssp {
|
||||||
|
entry:
|
||||||
|
%tmp = alloca %"struct.llvm::StringRef", align 8
|
||||||
|
%tmp.i = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %tmp, i64 0, i32 0
|
||||||
|
store i8* %P, i8** %tmp.i, align 8
|
||||||
|
%tmp1.i = call i64 @strlen(i8* %P) nounwind readonly
|
||||||
|
%tmp2.i = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %tmp, i64 0, i32 1
|
||||||
|
store i64 %tmp1.i, i64* %tmp2.i, align 8
|
||||||
|
%tmp1 = call %"struct.llvm::StringMapEntry<void*>"* @_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueERKNS_9StringRefE(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %X, %"struct.llvm::StringRef"* %tmp) ssp
|
||||||
|
ret %"struct.llvm::StringMapEntry<void*>"* %tmp1
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i64 @strlen(i8* nocapture) nounwind readonly
|
||||||
|
|
||||||
|
declare noalias i8* @malloc(i64) nounwind
|
||||||
|
|
||||||
|
declare i32 @_ZN4llvm13StringMapImpl15LookupBucketForENS_9StringRefE(%"struct.llvm::StringMapImpl"*, i64, i64)
|
||||||
|
|
||||||
|
define linkonce_odr %"struct.llvm::StringMapEntry<void*>"* @_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueERKNS_9StringRefE(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, %"struct.llvm::StringRef"* nocapture %Key) ssp align 2 {
|
||||||
|
entry:
|
||||||
|
%elt = bitcast %"struct.llvm::StringRef"* %Key to i64*
|
||||||
|
%val = load i64, i64* %elt
|
||||||
|
%tmp = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %Key, i64 0, i32 1
|
||||||
|
%val2 = load i64, i64* %tmp
|
||||||
|
%tmp2.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0
|
||||||
|
%tmp3.i = tail call i32 @_ZN4llvm13StringMapImpl15LookupBucketForENS_9StringRefE(%"struct.llvm::StringMapImpl"* %tmp2.i, i64 %val, i64 %val2)
|
||||||
|
%tmp4.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0, i32 0
|
||||||
|
%tmp5.i = load %"struct.llvm::StringMapImpl::ItemBucket"*, %"struct.llvm::StringMapImpl::ItemBucket"** %tmp4.i, align 8
|
||||||
|
%tmp6.i = zext i32 %tmp3.i to i64
|
||||||
|
%tmp7.i = getelementptr inbounds %"struct.llvm::StringMapImpl::ItemBucket", %"struct.llvm::StringMapImpl::ItemBucket"* %tmp5.i, i64 %tmp6.i, i32 1
|
||||||
|
%tmp8.i = load %"struct.llvm::StringMapEntryBase"*, %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8
|
||||||
|
%tmp9.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, null
|
||||||
|
%tmp13.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*)
|
||||||
|
%or.cond.i = or i1 %tmp9.i, %tmp13.i
|
||||||
|
br i1 %or.cond.i, label %bb4.i, label %bb6.i
|
||||||
|
|
||||||
|
bb4.i: ; preds = %entry
|
||||||
|
%tmp41.i = inttoptr i64 %val to i8*
|
||||||
|
%tmp4.i35.i = getelementptr inbounds i8, i8* %tmp41.i, i64 %val2
|
||||||
|
%tmp.i.i = ptrtoint i8* %tmp4.i35.i to i64
|
||||||
|
%tmp1.i.i = trunc i64 %tmp.i.i to i32
|
||||||
|
%tmp3.i.i = trunc i64 %val to i32
|
||||||
|
%tmp4.i.i = sub i32 %tmp1.i.i, %tmp3.i.i
|
||||||
|
%tmp5.i.i = add i32 %tmp4.i.i, 17
|
||||||
|
%tmp8.i.i = zext i32 %tmp5.i.i to i64
|
||||||
|
%tmp.i20.i.i = tail call noalias i8* @malloc(i64 %tmp8.i.i) nounwind
|
||||||
|
%tmp10.i.i = bitcast i8* %tmp.i20.i.i to %"struct.llvm::StringMapEntry<void*>"*
|
||||||
|
%tmp12.i.i = icmp eq i8* %tmp.i20.i.i, null
|
||||||
|
br i1 %tmp12.i.i, label %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i, label %bb.i.i
|
||||||
|
|
||||||
|
bb.i.i: ; preds = %bb4.i
|
||||||
|
%tmp.i.i.i.i = bitcast i8* %tmp.i20.i.i to i32*
|
||||||
|
store i32 %tmp4.i.i, i32* %tmp.i.i.i.i, align 4
|
||||||
|
%tmp1.i19.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 8
|
||||||
|
%0 = bitcast i8* %tmp1.i19.i.i to i8**
|
||||||
|
store i8* null, i8** %0, align 8
|
||||||
|
br label %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i
|
||||||
|
|
||||||
|
_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i: ; preds = %bb.i.i, %bb4.i
|
||||||
|
%tmp.i18.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 16
|
||||||
|
%tmp15.i.i = zext i32 %tmp4.i.i to i64
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp.i18.i.i, i8* %tmp41.i, i64 %tmp15.i.i, i32 1, i1 false)
|
||||||
|
%tmp.i18.sum.i.i = add i64 %tmp15.i.i, 16
|
||||||
|
%tmp17.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 %tmp.i18.sum.i.i
|
||||||
|
store i8 0, i8* %tmp17.i.i, align 1
|
||||||
|
%tmp.i.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 8
|
||||||
|
%1 = bitcast i8* %tmp.i.i.i to i8**
|
||||||
|
store i8* null, i8** %1, align 8
|
||||||
|
%tmp22.i = load %"struct.llvm::StringMapEntryBase"*, %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8
|
||||||
|
%tmp24.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp22.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*)
|
||||||
|
br i1 %tmp24.i, label %bb9.i, label %_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueIS1_EERNS_14StringMapEntryIS1_EENS_9StringRefET_.exit
|
||||||
|
|
||||||
|
bb6.i: ; preds = %entry
|
||||||
|
%tmp16.i = bitcast %"struct.llvm::StringMapEntryBase"* %tmp8.i to %"struct.llvm::StringMapEntry<void*>"*
|
||||||
|
ret %"struct.llvm::StringMapEntry<void*>"* %tmp16.i
|
||||||
|
|
||||||
|
bb9.i: ; preds = %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i
|
||||||
|
%tmp25.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0, i32 3
|
||||||
|
%tmp26.i = load i32, i32* %tmp25.i, align 8
|
||||||
|
%tmp27.i = add i32 %tmp26.i, -1
|
||||||
|
store i32 %tmp27.i, i32* %tmp25.i, align 8
|
||||||
|
ret %"struct.llvm::StringMapEntry<void*>"* %tmp10.i.i
|
||||||
|
|
||||||
|
_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueIS1_EERNS_14StringMapEntryIS1_EENS_9StringRefET_.exit: ; preds = %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i
|
||||||
|
ret %"struct.llvm::StringMapEntry<void*>"* %tmp10.i.i
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
|
|
@ -0,0 +1,20 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
%t = type { i32 }
|
||||||
|
declare void @test1f(i8*)
|
||||||
|
|
||||||
|
define void @test1(%t* noalias %stuff ) {
|
||||||
|
%p = getelementptr inbounds %t, %t* %stuff, i32 0, i32 0
|
||||||
|
%before = load i32, i32* %p
|
||||||
|
|
||||||
|
call void @test1f(i8* null)
|
||||||
|
|
||||||
|
%after = load i32, i32* %p ; <--- This should be a dead load
|
||||||
|
%sum = add i32 %before, %after
|
||||||
|
|
||||||
|
store i32 %sum, i32* %p
|
||||||
|
ret void
|
||||||
|
; CHECK: load
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -o /dev/null -pass-remarks-output=%t -S -pass-remarks=gvn \
|
||||||
|
; RUN: 2>&1 | FileCheck %s
|
||||||
|
; RUN: cat %t | FileCheck -check-prefix=YAML %s
|
||||||
|
|
||||||
|
; CHECK: remark: <unknown>:0:0: load of type i32 eliminated{{$}}
|
||||||
|
; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}}
|
||||||
|
; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}}
|
||||||
|
; CHECK-NOT: remark:
|
||||||
|
|
||||||
|
; YAML: --- !Passed
|
||||||
|
; YAML-NEXT: Pass: gvn
|
||||||
|
; YAML-NEXT: Name: LoadElim
|
||||||
|
; YAML-NEXT: Function: arg
|
||||||
|
; YAML-NEXT: Args:
|
||||||
|
; YAML-NEXT: - String: 'load of type '
|
||||||
|
; YAML-NEXT: - Type: i32
|
||||||
|
; YAML-NEXT: - String: ' eliminated'
|
||||||
|
; YAML-NEXT: - String: ' in favor of '
|
||||||
|
; YAML-NEXT: - InfavorOfValue: i
|
||||||
|
; YAML-NEXT: ...
|
||||||
|
; YAML-NEXT: --- !Passed
|
||||||
|
; YAML-NEXT: Pass: gvn
|
||||||
|
; YAML-NEXT: Name: LoadElim
|
||||||
|
; YAML-NEXT: Function: const
|
||||||
|
; YAML-NEXT: Args:
|
||||||
|
; YAML-NEXT: - String: 'load of type '
|
||||||
|
; YAML-NEXT: - Type: i32
|
||||||
|
; YAML-NEXT: - String: ' eliminated'
|
||||||
|
; YAML-NEXT: - String: ' in favor of '
|
||||||
|
; YAML-NEXT: - InfavorOfValue: '4'
|
||||||
|
; YAML-NEXT: ...
|
||||||
|
; YAML-NEXT: --- !Passed
|
||||||
|
; YAML-NEXT: Pass: gvn
|
||||||
|
; YAML-NEXT: Name: LoadElim
|
||||||
|
; YAML-NEXT: Function: inst
|
||||||
|
; YAML-NEXT: Args:
|
||||||
|
; YAML-NEXT: - String: 'load of type '
|
||||||
|
; YAML-NEXT: - Type: i32
|
||||||
|
; YAML-NEXT: - String: ' eliminated'
|
||||||
|
; YAML-NEXT: - String: ' in favor of '
|
||||||
|
; YAML-NEXT: - InfavorOfValue: load
|
||||||
|
; YAML-NEXT: ...
|
||||||
|
; YAML-NEXT: --- !Missed
|
||||||
|
; YAML-NEXT: Pass: gvn
|
||||||
|
; YAML-NEXT: Name: LoadClobbered
|
||||||
|
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 3 }
|
||||||
|
; YAML-NEXT: Function: may_alias
|
||||||
|
; YAML-NEXT: Args:
|
||||||
|
; YAML-NEXT: - String: 'load of type '
|
||||||
|
; YAML-NEXT: - Type: i32
|
||||||
|
; YAML-NEXT: - String: ' not eliminated'
|
||||||
|
; YAML-NEXT: - String: ' in favor of '
|
||||||
|
; YAML-NEXT: - OtherAccess: load
|
||||||
|
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 1, Column: 13 }
|
||||||
|
; YAML-NEXT: - String: ' because it is clobbered by '
|
||||||
|
; YAML-NEXT: - ClobberedBy: store
|
||||||
|
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 2, Column: 10 }
|
||||||
|
; YAML-NEXT: ...
|
||||||
|
|
||||||
|
define i32 @arg(i32* %p, i32 %i) {
|
||||||
|
entry:
|
||||||
|
store i32 %i, i32* %p
|
||||||
|
%load = load i32, i32* %p
|
||||||
|
ret i32 %load
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @const(i32* %p) {
|
||||||
|
entry:
|
||||||
|
store i32 4, i32* %p
|
||||||
|
%load = load i32, i32* %p
|
||||||
|
ret i32 %load
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @inst(i32* %p) {
|
||||||
|
entry:
|
||||||
|
%load1 = load i32, i32* %p
|
||||||
|
%load = load i32, i32* %p
|
||||||
|
%add = add i32 %load1, %load
|
||||||
|
ret i32 %add
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @may_alias(i32* %p, i32* %r) !dbg !7 {
|
||||||
|
entry:
|
||||||
|
%load1 = load i32, i32* %p, !tbaa !13, !dbg !9
|
||||||
|
store i32 4, i32* %r, !tbaa !13, !dbg !10
|
||||||
|
%load = load i32, i32* %p, !tbaa !13, !dbg !11
|
||||||
|
%add = add i32 %load1, %load
|
||||||
|
ret i32 %add
|
||||||
|
}
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!3, !4, !5}
|
||||||
|
!llvm.ident = !{!6}
|
||||||
|
|
||||||
|
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
|
||||||
|
!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
|
||||||
|
!2 = !{}
|
||||||
|
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||||
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!5 = !{i32 1, !"PIC Level", i32 2}
|
||||||
|
!6 = !{!"clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)"}
|
||||||
|
!7 = distinct !DISubprogram(name: "may_alias", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, variables: !2)
|
||||||
|
!8 = !DISubroutineType(types: !2)
|
||||||
|
!9 = !DILocation(line: 1, column: 13, scope: !7)
|
||||||
|
!10 = !DILocation(line: 2, column: 10, scope: !7)
|
||||||
|
!11 = !DILocation(line: 3, column: 3, scope: !7)
|
||||||
|
|
||||||
|
!12 = !{ !"tbaa root" }
|
||||||
|
!13 = !{ !"int", !12 }
|
|
@ -0,0 +1,27 @@
|
||||||
|
; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
|
||||||
|
|
||||||
|
; GVN shouldn't PRE the load around the loop backedge because it's
|
||||||
|
; not actually redundant around the loop backedge, despite appearances
|
||||||
|
; if phi-translation is ignored.
|
||||||
|
|
||||||
|
; CHECK: define void @test0(i8* %begin)
|
||||||
|
; CHECK: loop:
|
||||||
|
; CHECK: %l0 = load i8, i8* %phi
|
||||||
|
; CHECK: call void @bar(i8 %l0)
|
||||||
|
; CHECK: %l1 = load i8, i8* %phi
|
||||||
|
define void @test0(i8* %begin) {
|
||||||
|
entry:
|
||||||
|
br label %loop
|
||||||
|
|
||||||
|
loop:
|
||||||
|
%phi = phi i8* [ %begin, %entry ], [ %next, %loop ]
|
||||||
|
%l0 = load i8, i8* %phi
|
||||||
|
call void @bar(i8 %l0)
|
||||||
|
%l1 = load i8, i8* %phi
|
||||||
|
%next = getelementptr inbounds i8, i8* %phi, i8 %l1
|
||||||
|
br label %loop
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @bar(i8)
|
|
@ -0,0 +1,19 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout =
|
||||||
|
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
@g = external global i31
|
||||||
|
|
||||||
|
define void @main() nounwind uwtable {
|
||||||
|
entry:
|
||||||
|
; CHECK: store i32
|
||||||
|
store i32 402662078, i32* bitcast (i31* @g to i32*), align 8
|
||||||
|
; CHECK-NOT: load i31
|
||||||
|
%0 = load i31, i31* @g, align 8
|
||||||
|
; CHECK: store i31
|
||||||
|
store i31 %0, i31* undef, align 1
|
||||||
|
unreachable
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @test1(i32 %x, i32 %y) {
|
||||||
|
; CHECK: @test1(i32 %x, i32 %y)
|
||||||
|
; CHECK: %add1 = add i32 %x, %y
|
||||||
|
; CHECK: %foo = add i32 %add1, %add1
|
||||||
|
|
||||||
|
%add1 = add nsw i32 %x, %y
|
||||||
|
%add2 = add i32 %x, %y
|
||||||
|
%foo = add i32 %add1, %add2
|
||||||
|
ret i32 %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test2(i32 %x, i32 %y) {
|
||||||
|
; CHECK: @test2(i32 %x, i32 %y)
|
||||||
|
; CHECK: %add1 = add i32 %x, %y
|
||||||
|
; CHECK: %foo = add i32 %add1, %add1
|
||||||
|
|
||||||
|
%add1 = add nuw i32 %x, %y
|
||||||
|
%add2 = add i32 %x, %y
|
||||||
|
%foo = add i32 %add1, %add2
|
||||||
|
ret i32 %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test3(i32 %x, i32 %y) {
|
||||||
|
; CHECK: @test3(i32 %x, i32 %y)
|
||||||
|
; CHECK: %add1 = add i32 %x, %y
|
||||||
|
; CHECK: %foo = add i32 %add1, %add1
|
||||||
|
|
||||||
|
%add1 = add nuw nsw i32 %x, %y
|
||||||
|
%add2 = add i32 %x, %y
|
||||||
|
%foo = add i32 %add1, %add2
|
||||||
|
ret i32 %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test4(i32 %x, i32 %y) {
|
||||||
|
; CHECK: @test4(i32 %x, i32 %y)
|
||||||
|
; CHECK: %add1 = add nsw i32 %x, %y
|
||||||
|
; CHECK: %foo = add i32 %add1, %add1
|
||||||
|
|
||||||
|
%add1 = add nsw i32 %x, %y
|
||||||
|
%add2 = add nsw i32 %x, %y
|
||||||
|
%foo = add i32 %add1, %add2
|
||||||
|
ret i32 %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test5(i32 %x, i32 %y) {
|
||||||
|
; CHECK: @test5(i32 %x, i32 %y)
|
||||||
|
; CHECK: %add1 = add i32 %x, %y
|
||||||
|
; CHECK: %foo = add i32 %add1, %add1
|
||||||
|
|
||||||
|
%add1 = add nuw i32 %x, %y
|
||||||
|
%add2 = add nsw i32 %x, %y
|
||||||
|
%foo = add i32 %add1, %add2
|
||||||
|
ret i32 %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test6(i32 %x, i32 %y) {
|
||||||
|
; CHECK: @test6(i32 %x, i32 %y)
|
||||||
|
; CHECK: %add1 = add nsw i32 %x, %y
|
||||||
|
; CHECK: %foo = add i32 %add1, %add1
|
||||||
|
|
||||||
|
%add1 = add nuw nsw i32 %x, %y
|
||||||
|
%add2 = add nsw i32 %x, %y
|
||||||
|
%foo = add i32 %add1, %add2
|
||||||
|
ret i32 %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test7(i32 %x, i32 %y) {
|
||||||
|
; CHECK: @test7(i32 %x, i32 %y)
|
||||||
|
; CHECK: %add1 = add i32 %x, %y
|
||||||
|
; CHECK-NOT: what_is_this
|
||||||
|
; CHECK: %foo = add i32 %add1, %add1
|
||||||
|
|
||||||
|
%add1 = add i32 %x, %y, !what_is_this !{}
|
||||||
|
%add2 = add i32 %x, %y
|
||||||
|
%foo = add i32 %add1, %add2
|
||||||
|
ret i32 %foo
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @mumble(i2, i2)
|
||||||
|
|
||||||
|
define void @test8(i2 %x) {
|
||||||
|
; CHECK-LABEL: @test8(
|
||||||
|
; CHECK: %[[ashr:.*]] = ashr i2 %x, 1
|
||||||
|
; CHECK-NEXT: call void @mumble(i2 %[[ashr]], i2 %[[ashr]])
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
|
||||||
|
%ashr0 = ashr exact i2 %x, 1
|
||||||
|
%ashr1 = ashr i2 %x, 1
|
||||||
|
call void @mumble(i2 %ashr0, i2 %ashr1)
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -disable-basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
target datalayout = "e-p:32:32:32"
|
||||||
|
target triple = "i386-pc-linux-gnu"
|
||||||
|
define <2 x i32> @test1() {
|
||||||
|
%v1 = alloca <2 x i32>
|
||||||
|
call void @anything(<2 x i32>* %v1)
|
||||||
|
%v2 = load <2 x i32>, <2 x i32>* %v1
|
||||||
|
%v3 = inttoptr <2 x i32> %v2 to <2 x i8*>
|
||||||
|
%v4 = bitcast <2 x i32>* %v1 to <2 x i8*>*
|
||||||
|
store <2 x i8*> %v3, <2 x i8*>* %v4
|
||||||
|
%v5 = load <2 x i32>, <2 x i32>* %v1
|
||||||
|
ret <2 x i32> %v5
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
; CHECK: %v1 = alloca <2 x i32>
|
||||||
|
; CHECK: call void @anything(<2 x i32>* %v1)
|
||||||
|
; CHECK: %v2 = load <2 x i32>, <2 x i32>* %v1
|
||||||
|
; CHECK: %v3 = inttoptr <2 x i32> %v2 to <2 x i8*>
|
||||||
|
; CHECK: %v4 = bitcast <2 x i32>* %v1 to <2 x i8*>*
|
||||||
|
; CHECK: store <2 x i8*> %v3, <2 x i8*>* %v4
|
||||||
|
; CHECK: ret <2 x i32> %v2
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @anything(<2 x i32>*)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -newgvn -S -o - < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
%struct.with_array = type { [2 x i8], i32, i8 }
|
||||||
|
%struct.with_vector = type { <2 x i8>, i32, i8 }
|
||||||
|
|
||||||
|
@main.obj_with_array = private unnamed_addr constant { [2 x i8], i32, i8, [3 x i8] } { [2 x i8] zeroinitializer, i32 0, i8 1, [3 x i8] undef }, align 4
|
||||||
|
@array_with_zeroinit = common global %struct.with_array zeroinitializer, align 4
|
||||||
|
|
||||||
|
@main.obj_with_vector = private unnamed_addr constant { <2 x i8>, i32, i8, [3 x i8] } { <2 x i8> zeroinitializer, i32 0, i8 1, [3 x i8] undef }, align 4
|
||||||
|
@vector_with_zeroinit = common global %struct.with_vector zeroinitializer, align 4
|
||||||
|
|
||||||
|
define i32 @main() {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.with_array, %struct.with_array* @array_with_zeroinit, i64 0, i32 0, i64 0), i8* getelementptr inbounds ({ [2 x i8], i32, i8, [3 x i8] }, { [2 x i8], i32, i8, [3 x i8] }* @main.obj_with_array, i64 0, i32 0, i64 0), i64 12, i32 4, i1 false)
|
||||||
|
%0 = load i8, i8* getelementptr inbounds (%struct.with_array, %struct.with_array* @array_with_zeroinit, i64 0, i32 2), align 4
|
||||||
|
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.with_vector, %struct.with_vector* @vector_with_zeroinit, i64 0, i32 0, i64 0), i8* getelementptr inbounds ({ <2 x i8>, i32, i8, [3 x i8] }, { <2 x i8>, i32, i8, [3 x i8] }* @main.obj_with_vector, i64 0, i32 0, i64 0), i64 12, i32 4, i1 false)
|
||||||
|
%1 = load i8, i8* getelementptr inbounds (%struct.with_vector, %struct.with_vector* @vector_with_zeroinit, i64 0, i32 2), align 4
|
||||||
|
%conv0 = sext i8 %0 to i32
|
||||||
|
%conv1 = sext i8 %1 to i32
|
||||||
|
%and = and i32 %conv0, %conv1
|
||||||
|
ret i32 %and
|
||||||
|
; CHECK-LABEL: define i32 @main(
|
||||||
|
; CHECK: ret i32 1
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
|
|
@ -0,0 +1,66 @@
|
||||||
|
; RUN: opt < %s -basicaa -newgvn
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||||
|
%struct.S0 = type { [2 x i8], [2 x i8], [4 x i8], [2 x i8], i32, i32, i32, i32 }
|
||||||
|
define void @fn1(%struct.S0* byval align 8 %p1) {
|
||||||
|
br label %for.cond
|
||||||
|
for.cond: ; preds = %1, %0
|
||||||
|
br label %for.end
|
||||||
|
%f2 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
|
||||||
|
%f9 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 7
|
||||||
|
br label %for.cond
|
||||||
|
for.end: ; preds = %for.cond
|
||||||
|
br i1 true, label %if.else, label %if.then
|
||||||
|
if.then: ; preds = %for.end
|
||||||
|
%f22 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
|
||||||
|
%f7 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 5
|
||||||
|
%tmp7 = load i32, i32* %f7, align 8
|
||||||
|
br label %if.end40
|
||||||
|
if.else: ; preds = %for.end
|
||||||
|
br i1 false, label %for.cond18, label %if.then6
|
||||||
|
if.then6: ; preds = %if.else
|
||||||
|
%f3 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
|
||||||
|
%tmp10 = bitcast %struct.S0* %p1 to i16*
|
||||||
|
%f5 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
|
||||||
|
%tmp11 = bitcast [2 x i8]* %f5 to i16*
|
||||||
|
%bf.load13 = load i16, i16* %tmp11, align 8
|
||||||
|
br label %if.end36
|
||||||
|
for.cond18: ; preds = %if.else
|
||||||
|
call void @fn4()
|
||||||
|
br i1 true, label %if.end, label %if.end36
|
||||||
|
if.end: ; preds = %for.cond18
|
||||||
|
%f321 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
|
||||||
|
%f925 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 7
|
||||||
|
%f526 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
|
||||||
|
%tmp15 = bitcast [2 x i8]* %f526 to i16*
|
||||||
|
%bf.load27 = load i16, i16* %tmp15, align 8
|
||||||
|
%tmp16 = bitcast %struct.S0* %p1 to i16*
|
||||||
|
br label %if.end36
|
||||||
|
if.end36: ; preds = %if.end, %for.cond18, %if.then6
|
||||||
|
%f537 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
|
||||||
|
%tmp17 = bitcast [2 x i8]* %f537 to i16*
|
||||||
|
%bf.load38 = load i16, i16* %tmp17, align 8
|
||||||
|
%bf.clear39 = and i16 %bf.load38, -16384
|
||||||
|
br label %if.end40
|
||||||
|
if.end40: ; preds = %if.end36, %if.then
|
||||||
|
%f6 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 4
|
||||||
|
%tmp18 = load i32, i32* %f6, align 4
|
||||||
|
call void @fn2(i32 %tmp18)
|
||||||
|
%f8 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 6
|
||||||
|
%tmp19 = load i32, i32* %f8, align 4
|
||||||
|
%tobool41 = icmp eq i32 %tmp19, 0
|
||||||
|
br i1 true, label %if.end50, label %if.then42
|
||||||
|
if.then42: ; preds = %if.end40
|
||||||
|
%tmp20 = bitcast %struct.S0* %p1 to i16*
|
||||||
|
%f547 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
|
||||||
|
%tmp21 = bitcast [2 x i8]* %f547 to i16*
|
||||||
|
%bf.load48 = load i16, i16* %tmp21, align 8
|
||||||
|
br label %if.end50
|
||||||
|
if.end50: ; preds = %if.then42, %if.end40
|
||||||
|
%f551 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
|
||||||
|
%tmp22 = bitcast [2 x i8]* %f551 to i16*
|
||||||
|
%bf.load52 = load i16, i16* %tmp22, align 8
|
||||||
|
%bf.clear53 = and i16 %bf.load52, -16384
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
declare void @fn2(i32)
|
||||||
|
declare void @fn4()
|
|
@ -0,0 +1,18 @@
|
||||||
|
; RUN: opt -basicaa -newgvn -disable-output < %s
|
||||||
|
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define i64 @foo(i64** %arrayidx) {
|
||||||
|
entry:
|
||||||
|
%p = load i64*, i64** %arrayidx, align 8
|
||||||
|
%cmpnull = icmp eq i64* %p, null
|
||||||
|
br label %BB2
|
||||||
|
|
||||||
|
entry2: ; No predecessors!
|
||||||
|
br label %BB2
|
||||||
|
|
||||||
|
BB2: ; preds = %entry2, %entry
|
||||||
|
%bc = bitcast i64** %arrayidx to i64*
|
||||||
|
%load = load i64, i64* %bc, align 8
|
||||||
|
ret i64 %load
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
; RUN: opt < %s -memcpyopt -mldst-motion -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
declare void @check(i8)
|
||||||
|
|
||||||
|
declare void @write(i8* %res)
|
||||||
|
|
||||||
|
define void @test1() {
|
||||||
|
%1 = alloca [10 x i8]
|
||||||
|
%2 = bitcast [10 x i8]* %1 to i8*
|
||||||
|
call void @write(i8* %2)
|
||||||
|
%3 = load i8, i8* %2
|
||||||
|
|
||||||
|
; CHECK-NOT: undef
|
||||||
|
call void @check(i8 %3)
|
||||||
|
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
;RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64"
|
||||||
|
target triple = "thumbv7--linux-gnueabi"
|
||||||
|
|
||||||
|
%struct.a = type { i16, i16, [1 x %union.a] }
|
||||||
|
%union.a = type { i32 }
|
||||||
|
|
||||||
|
@length = external global [0 x i32], align 4
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define fastcc void @foo(%struct.a* nocapture readonly %x) {
|
||||||
|
;CHECK-LABEL: foo
|
||||||
|
entry:
|
||||||
|
br label %bb0
|
||||||
|
|
||||||
|
bb0: ; preds = %land.lhs.true, %entry
|
||||||
|
;CHECK: bb0:
|
||||||
|
%x.tr = phi %struct.a* [ %x, %entry ], [ null, %land.lhs.true ]
|
||||||
|
%code1 = getelementptr inbounds %struct.a, %struct.a* %x.tr, i32 0, i32 0
|
||||||
|
%0 = load i16, i16* %code1, align 4
|
||||||
|
; CHECK: load i16, i16*
|
||||||
|
%conv = zext i16 %0 to i32
|
||||||
|
switch i32 %conv, label %if.end.50 [
|
||||||
|
i32 43, label %cleanup
|
||||||
|
i32 52, label %if.then.5
|
||||||
|
]
|
||||||
|
|
||||||
|
if.then.5: ; preds = %bb0
|
||||||
|
br i1 undef, label %land.lhs.true, label %if.then.26
|
||||||
|
|
||||||
|
land.lhs.true: ; preds = %if.then.5
|
||||||
|
br i1 undef, label %cleanup, label %bb0
|
||||||
|
|
||||||
|
if.then.26: ; preds = %if.then.5
|
||||||
|
%x.tr.lcssa163 = phi %struct.a* [ %x.tr, %if.then.5 ]
|
||||||
|
br i1 undef, label %cond.end, label %cond.false
|
||||||
|
|
||||||
|
cond.false: ; preds = %if.then.26
|
||||||
|
; CHECK: cond.false:
|
||||||
|
; CHECK: load i16
|
||||||
|
%mode = getelementptr inbounds %struct.a, %struct.a* %x.tr.lcssa163, i32 0, i32 1
|
||||||
|
%bf.load = load i16, i16* %mode, align 2
|
||||||
|
%bf.shl = shl i16 %bf.load, 8
|
||||||
|
br label %cond.end
|
||||||
|
|
||||||
|
cond.end: ; preds = %cond.false, %if.then.26
|
||||||
|
br i1 undef, label %if.then.44, label %cleanup
|
||||||
|
|
||||||
|
if.then.44: ; preds = %cond.end
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
if.end.50: ; preds = %bb0
|
||||||
|
;%CHECK: if.end.50:
|
||||||
|
%conv.lcssa = phi i32 [ %conv, %bb0 ]
|
||||||
|
%arrayidx52 = getelementptr inbounds [0 x i32], [0 x i32]* @length, i32 0, i32 %conv.lcssa
|
||||||
|
%1 = load i32, i32* %arrayidx52, align 4
|
||||||
|
br i1 undef, label %for.body.57, label %cleanup
|
||||||
|
|
||||||
|
for.body.57: ; preds = %if.end.50
|
||||||
|
%i.2157 = add nsw i32 %1, -1
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
cleanup: ; preds = %if.end.50, %cond.end, %land.lhs.true, %bb0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
@yy_c_buf_p = external unnamed_addr global i8*, align 4
|
||||||
|
@dfg_text = external global i8*, align 4
|
||||||
|
|
||||||
|
define void @dfg_lex() {
|
||||||
|
;CHECK-LABEL: dfg_lex
|
||||||
|
entry:
|
||||||
|
br label %while.bodythread-pre-split
|
||||||
|
|
||||||
|
while.bodythread-pre-split: ; preds = %while.end, %while.end, %entry
|
||||||
|
br i1 undef, label %if.then.14, label %if.end.15
|
||||||
|
|
||||||
|
if.then.14: ; preds = %while.end, %while.bodythread-pre-split
|
||||||
|
%v1 = load i32, i32* bitcast (i8** @dfg_text to i32*), align 4
|
||||||
|
%sub.ptr.sub = sub i32 undef, %v1
|
||||||
|
br label %if.end.15
|
||||||
|
|
||||||
|
if.end.15: ; preds = %if.then.14, %while.bodythread-pre-split
|
||||||
|
%v2 = load i8*, i8** @yy_c_buf_p, align 4
|
||||||
|
br label %while.cond.16
|
||||||
|
|
||||||
|
while.cond.16: ; preds = %while.cond.16, %if.end.15
|
||||||
|
br i1 undef, label %while.cond.16, label %while.end
|
||||||
|
|
||||||
|
while.end: ; preds = %while.cond.16
|
||||||
|
%add.ptr = getelementptr inbounds i8, i8* %v2, i32 undef
|
||||||
|
store i8* %add.ptr, i8** @dfg_text, align 4
|
||||||
|
%sub.ptr.rhs.cast25 = ptrtoint i8* %add.ptr to i32
|
||||||
|
%sub.ptr.sub26 = sub i32 0, %sub.ptr.rhs.cast25
|
||||||
|
switch i32 undef, label %sw.default [
|
||||||
|
i32 65, label %while.bodythread-pre-split
|
||||||
|
i32 3, label %return
|
||||||
|
i32 57, label %while.bodythread-pre-split
|
||||||
|
i32 60, label %if.then.14
|
||||||
|
]
|
||||||
|
|
||||||
|
sw.default: ; preds = %while.end
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
return: ; preds = %while.end
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
; RUN: opt -S -newgvn < %s | FileCheck %s
|
||||||
|
define i32* @test1(i32* %a) {
|
||||||
|
%x1 = getelementptr inbounds i32, i32* %a, i32 10
|
||||||
|
%x2 = getelementptr i32, i32* %a, i32 10
|
||||||
|
ret i32* %x2
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
; CHECK: %[[x:.*]] = getelementptr i32, i32* %a, i32 10
|
||||||
|
; CHECK: ret i32* %[[x]]
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
; RUN: opt -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
; C source:
|
||||||
|
;
|
||||||
|
; void f(int x) {
|
||||||
|
; if (x != 1)
|
||||||
|
; puts (x == 2 ? "a" : "b");
|
||||||
|
; for (;;) {
|
||||||
|
; puts("step 1");
|
||||||
|
; if (x == 2)
|
||||||
|
; continue;
|
||||||
|
; printf("step 2: %d\n", x);
|
||||||
|
; }
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; If we PRE %cmp3, CodeGenPrepare won't be able to sink the compare down to its
|
||||||
|
; uses, and we are forced to keep both %x and %cmp3 in registers in the loop.
|
||||||
|
;
|
||||||
|
; It is just as cheap to recompute the icmp against %x as it is to compare a
|
||||||
|
; GPR against 0. On x86-64, the br i1 %cmp3 becomes:
|
||||||
|
;
|
||||||
|
; testb %r12b, %r12b
|
||||||
|
; jne LBB0_3
|
||||||
|
;
|
||||||
|
; The sunk icmp is:
|
||||||
|
;
|
||||||
|
; cmpl $2, %ebx
|
||||||
|
; je LBB0_3
|
||||||
|
;
|
||||||
|
; This is just as good, and it doesn't require a separate register.
|
||||||
|
;
|
||||||
|
; CHECK-NOT: phi i1
|
||||||
|
|
||||||
|
@.str = private unnamed_addr constant [2 x i8] c"a\00", align 1
|
||||||
|
@.str1 = private unnamed_addr constant [2 x i8] c"b\00", align 1
|
||||||
|
@.str2 = private unnamed_addr constant [7 x i8] c"step 1\00", align 1
|
||||||
|
@.str3 = private unnamed_addr constant [12 x i8] c"step 2: %d\0A\00", align 1
|
||||||
|
|
||||||
|
define void @f(i32 %x) noreturn nounwind uwtable ssp {
|
||||||
|
entry:
|
||||||
|
%cmp = icmp eq i32 %x, 1
|
||||||
|
br i1 %cmp, label %for.cond.preheader, label %if.then
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
%cmp1 = icmp eq i32 %x, 2
|
||||||
|
%cond = select i1 %cmp1, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str1, i64 0, i64 0)
|
||||||
|
%call = tail call i32 @puts(i8* %cond) nounwind
|
||||||
|
br label %for.cond.preheader
|
||||||
|
|
||||||
|
for.cond.preheader: ; preds = %entry, %if.then
|
||||||
|
%cmp3 = icmp eq i32 %x, 2
|
||||||
|
br label %for.cond
|
||||||
|
|
||||||
|
for.cond: ; preds = %for.cond.backedge, %for.cond.preheader
|
||||||
|
%call2 = tail call i32 @puts(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str2, i64 0, i64 0)) nounwind
|
||||||
|
br i1 %cmp3, label %for.cond.backedge, label %if.end5
|
||||||
|
|
||||||
|
if.end5: ; preds = %for.cond
|
||||||
|
%call6 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i64 0, i64 0), i32 %x) nounwind
|
||||||
|
br label %for.cond.backedge
|
||||||
|
|
||||||
|
for.cond.backedge: ; preds = %if.end5, %for.cond
|
||||||
|
br label %for.cond
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @puts(i8* nocapture) nounwind
|
||||||
|
|
||||||
|
declare i32 @printf(i8* nocapture, ...) nounwind
|
|
@ -0,0 +1,30 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -basicaa -newgvn -S %s | FileCheck %s
|
||||||
|
|
||||||
|
%MyStruct = type { i32, i32 }
|
||||||
|
define i8 @foo(i64 %in, i8* %arr) {
|
||||||
|
%addr = alloca %MyStruct
|
||||||
|
%dead = trunc i64 %in to i32
|
||||||
|
br i1 undef, label %next, label %tmp
|
||||||
|
|
||||||
|
tmp:
|
||||||
|
call void @bar()
|
||||||
|
br label %next
|
||||||
|
|
||||||
|
next:
|
||||||
|
%addr64 = bitcast %MyStruct* %addr to i64*
|
||||||
|
store i64 %in, i64* %addr64
|
||||||
|
br label %final
|
||||||
|
|
||||||
|
final:
|
||||||
|
%addr32 = getelementptr %MyStruct, %MyStruct* %addr, i32 0, i32 0
|
||||||
|
%idx32 = load i32, i32* %addr32
|
||||||
|
|
||||||
|
; CHECK: %resptr = getelementptr i8, i8* %arr, i32 %dead
|
||||||
|
%resptr = getelementptr i8, i8* %arr, i32 %idx32
|
||||||
|
%res = load i8, i8* %resptr
|
||||||
|
|
||||||
|
ret i8 %res
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @bar()
|
|
@ -0,0 +1,29 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-LABEL: func_fast
|
||||||
|
; CHECK: fadd fast double
|
||||||
|
; CHECK-NEXT: store
|
||||||
|
; CHECK-NEXT: ret
|
||||||
|
define double @func_fast(double %a, double %b) {
|
||||||
|
entry:
|
||||||
|
%a.addr = alloca double, align 8
|
||||||
|
%add = fadd fast double %b, 3.000000e+00
|
||||||
|
store double %add, double* %a.addr, align 8
|
||||||
|
%load_add = load double, double* %a.addr, align 8
|
||||||
|
ret double %load_add
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: func_no_fast
|
||||||
|
; CHECK: fadd double
|
||||||
|
; CHECK-NEXT: store
|
||||||
|
; CHECK-NEXT: ret
|
||||||
|
define double @func_no_fast(double %a, double %b) {
|
||||||
|
entry:
|
||||||
|
%a.addr = alloca double, align 8
|
||||||
|
%add = fadd fast double %b, 3.000000e+00
|
||||||
|
store double %add, double* %a.addr, align 8
|
||||||
|
%duplicated_add = fadd double %b, 3.000000e+00
|
||||||
|
ret double %duplicated_add
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @test1(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test1(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p, !range !0
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !0
|
||||||
|
%b = load i32, i32* %p, !range !0
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test2(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test2(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p
|
||||||
|
; CHECK-NOT: range
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !0
|
||||||
|
%b = load i32, i32* %p
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test3(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test3(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p, !range ![[DISJOINT_RANGE:[0-9]+]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !0
|
||||||
|
%b = load i32, i32* %p, !range !1
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test4(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test4(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p, !range ![[MERGED_RANGE:[0-9]+]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !0
|
||||||
|
%b = load i32, i32* %p, !range !2
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test5(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test5(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p, !range ![[MERGED_SIGNED_RANGE:[0-9]+]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !3
|
||||||
|
%b = load i32, i32* %p, !range !4
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test6(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test6(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p, !range ![[MERGED_TEST6:[0-9]+]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !5
|
||||||
|
%b = load i32, i32* %p, !range !6
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test7(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test7(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p, !range ![[MERGED_TEST7:[0-9]+]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !7
|
||||||
|
%b = load i32, i32* %p, !range !8
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test8(i32* %p) {
|
||||||
|
; CHECK-LABEL: @test8(i32* %p)
|
||||||
|
; CHECK: %a = load i32, i32* %p
|
||||||
|
; CHECK-NOT: range
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = load i32, i32* %p, !range !9
|
||||||
|
%b = load i32, i32* %p, !range !10
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: ![[DISJOINT_RANGE]] = !{i32 0, i32 2, i32 3, i32 5}
|
||||||
|
; CHECK: ![[MERGED_RANGE]] = !{i32 0, i32 5}
|
||||||
|
; CHECK: ![[MERGED_SIGNED_RANGE]] = !{i32 -5, i32 -2, i32 1, i32 5}
|
||||||
|
; CHECK: ![[MERGED_TEST6]] = !{i32 10, i32 1}
|
||||||
|
; CHECK: ![[MERGED_TEST7]] = !{i32 3, i32 4, i32 5, i32 2}
|
||||||
|
|
||||||
|
!0 = !{i32 0, i32 2}
|
||||||
|
!1 = !{i32 3, i32 5}
|
||||||
|
!2 = !{i32 2, i32 5}
|
||||||
|
!3 = !{i32 -5, i32 -2}
|
||||||
|
!4 = !{i32 1, i32 5}
|
||||||
|
!5 = !{i32 10, i32 1}
|
||||||
|
!6 = !{i32 12, i32 16}
|
||||||
|
!7 = !{i32 1, i32 2, i32 3, i32 4}
|
||||||
|
!8 = !{i32 5, i32 1}
|
||||||
|
!9 = !{i32 1, i32 5}
|
||||||
|
!10 = !{i32 5, i32 1}
|
|
@ -0,0 +1,18 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -newgvn -S -o - < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
declare void @use(i8* readonly nocapture)
|
||||||
|
|
||||||
|
define i8 @test() {
|
||||||
|
%a = alloca i8
|
||||||
|
store i8 1, i8* %a
|
||||||
|
call void @use(i8* %a)
|
||||||
|
%b = load i8, i8* %a
|
||||||
|
ret i8 %b
|
||||||
|
; CHECK-LABEL: define i8 @test(
|
||||||
|
; CHECK: call void @use(i8* %a)
|
||||||
|
; CHECK-NEXT: ret i8 1
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
; GVN should eliminate the fully redundant %9 GEP which
|
||||||
|
; allows DEAD to be removed. This is PR3198.
|
||||||
|
|
||||||
|
; The %7 and %4 loads combine to make %DEAD unneeded.
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin7"
|
||||||
|
@H = common global [100 x i32] zeroinitializer, align 32 ; <[100 x i32]*> [#uses=3]
|
||||||
|
@G = common global i32 0 ; <i32*> [#uses=2]
|
||||||
|
|
||||||
|
define i32 @test(i32 %i) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = tail call i32 (...) @foo() nounwind ; <i32> [#uses=1]
|
||||||
|
%1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %1, label %bb1, label %bb
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
%2 = tail call i32 (...) @bar() nounwind ; <i32> [#uses=0]
|
||||||
|
%3 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i ; <i32*> [#uses=1]
|
||||||
|
%4 = load i32, i32* %3, align 4 ; <i32> [#uses=1]
|
||||||
|
store i32 %4, i32* @G, align 4
|
||||||
|
br label %bb3
|
||||||
|
|
||||||
|
bb1: ; preds = %entry
|
||||||
|
%5 = tail call i32 (...) @baz() nounwind ; <i32> [#uses=0]
|
||||||
|
%6 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i ; <i32*> [#uses=1]
|
||||||
|
%7 = load i32, i32* %6, align 4 ; <i32> [#uses=2]
|
||||||
|
store i32 %7, i32* @G, align 4
|
||||||
|
%8 = icmp eq i32 %7, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %8, label %bb3, label %bb4
|
||||||
|
|
||||||
|
bb3: ; preds = %bb1, %bb
|
||||||
|
%9 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i ; <i32*> [#uses=1]
|
||||||
|
%DEAD = load i32, i32* %9, align 4 ; <i32> [#uses=1]
|
||||||
|
; CHECK: %DEAD = phi i32 [ 0, %bb1 ], [ %4, %bb ]
|
||||||
|
ret i32 %DEAD
|
||||||
|
|
||||||
|
bb4: ; preds = %bb1
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @foo(...)
|
||||||
|
|
||||||
|
declare i32 @bar(...)
|
||||||
|
|
||||||
|
declare i32 @baz(...)
|
|
@ -0,0 +1,28 @@
|
||||||
|
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||||
|
; XFAIL: *
|
||||||
|
; FIXME: This should be promotable, but memdep/gvn don't track values
|
||||||
|
; path/edge sensitively enough.
|
||||||
|
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||||
|
target triple = "i386-apple-darwin7"
|
||||||
|
|
||||||
|
define i32 @g(i32* %b, i32* %c) nounwind {
|
||||||
|
entry:
|
||||||
|
store i32 1, i32* %b
|
||||||
|
store i32 2, i32* %c
|
||||||
|
|
||||||
|
%t1 = icmp eq i32* %b, null ; <i1> [#uses=1]
|
||||||
|
br i1 %t1, label %bb, label %bb2
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
br label %bb2
|
||||||
|
|
||||||
|
bb2: ; preds = %bb1, %bb
|
||||||
|
%c_addr.0 = phi i32* [ %b, %entry ], [ %c, %bb ] ; <i32*> [#uses=1]
|
||||||
|
%cv = load i32, i32* %c_addr.0, align 4 ; <i32> [#uses=1]
|
||||||
|
ret i32 %cv
|
||||||
|
; CHECK: bb2:
|
||||||
|
; CHECK-NOT: load i32
|
||||||
|
; CHECK: ret i32
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @main(i32** %p, i32 %x, i32 %y) {
|
||||||
|
block1:
|
||||||
|
%cmp = icmp eq i32 %x, %y
|
||||||
|
br i1 %cmp , label %block2, label %block3
|
||||||
|
|
||||||
|
block2:
|
||||||
|
%a = load i32*, i32** %p
|
||||||
|
br label %block4
|
||||||
|
|
||||||
|
block3:
|
||||||
|
%b = load i32*, i32** %p
|
||||||
|
br label %block4
|
||||||
|
|
||||||
|
block4:
|
||||||
|
; CHECK-NOT: %existingPHI = phi
|
||||||
|
; CHECK: %DEAD = phi
|
||||||
|
%existingPHI = phi i32* [ %a, %block2 ], [ %b, %block3 ]
|
||||||
|
%DEAD = load i32*, i32** %p
|
||||||
|
%c = load i32, i32* %DEAD
|
||||||
|
%d = load i32, i32* %existingPHI
|
||||||
|
%e = add i32 %c, %d
|
||||||
|
ret i32 %e
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
; RUN: opt -loops -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
; This used to fail with ASAN enabled and if for some reason LoopInfo remained
|
||||||
|
; available during GVN. In this case BasicAA will use LI but
|
||||||
|
; MergeBlockIntoPredecessor in GVN failed to update LI.
|
||||||
|
|
||||||
|
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
%struct.wibble.1028 = type { i32, i32, %struct.barney.881 }
|
||||||
|
%struct.barney.881 = type { %struct.zot.882 }
|
||||||
|
%struct.zot.882 = type { [64 x i8] }
|
||||||
|
|
||||||
|
; Function Attrs: argmemonly
|
||||||
|
declare void @snork.1(i8*) local_unnamed_addr #0
|
||||||
|
|
||||||
|
define hidden zeroext i1 @eggs(%struct.wibble.1028* %arg, i1 %arg2) unnamed_addr align 2 {
|
||||||
|
bb:
|
||||||
|
br i1 %arg2, label %bb14, label %bb3
|
||||||
|
|
||||||
|
bb3: ; preds = %bb
|
||||||
|
%tmp = getelementptr inbounds %struct.wibble.1028, %struct.wibble.1028* %arg, i64 0, i32 2, i32 0, i32 0, i64 0
|
||||||
|
%tmp5 = bitcast i8* %tmp to %struct.wibble.1028**
|
||||||
|
br label %bb6
|
||||||
|
|
||||||
|
bb6: ; preds = %bb12, %bb3
|
||||||
|
br label %bb7
|
||||||
|
|
||||||
|
bb7: ; preds = %bb6
|
||||||
|
br i1 undef, label %bb11, label %bb8
|
||||||
|
|
||||||
|
bb8: ; preds = %bb7
|
||||||
|
%tmp9 = load %struct.wibble.1028*, %struct.wibble.1028** %tmp5, align 8
|
||||||
|
; CHECK: %tmp9 = load %struct.wibble.1028*, %struct.wibble.1028** %tmp5, align 8
|
||||||
|
%tmp10 = bitcast %struct.wibble.1028* %tmp9 to i8*
|
||||||
|
br label %bb12
|
||||||
|
|
||||||
|
bb11: ; preds = %bb7
|
||||||
|
br label %bb12
|
||||||
|
|
||||||
|
bb12: ; preds = %bb11, %bb8
|
||||||
|
%tmp13 = phi i8* [ %tmp, %bb11 ], [ %tmp10, %bb8 ]
|
||||||
|
call void @snork.1(i8* %tmp13) #1
|
||||||
|
br label %bb6
|
||||||
|
|
||||||
|
bb14: ; preds = %bb
|
||||||
|
ret i1 false
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes #0 = { argmemonly }
|
||||||
|
attributes #1 = { nounwind }
|
|
@ -0,0 +1,130 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -tbaa -basicaa -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @test1(i8* %p, i8* %q) {
|
||||||
|
; CHECK: @test1(i8* %p, i8* %q)
|
||||||
|
; CHECK: call i32 @foo(i8* %p)
|
||||||
|
; CHECK-NOT: tbaa
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = call i32 @foo(i8* %p), !tbaa !0
|
||||||
|
%b = call i32 @foo(i8* %p)
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test2(i8* %p, i8* %q) {
|
||||||
|
; CHECK: @test2(i8* %p, i8* %q)
|
||||||
|
; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGC:!.*]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = call i32 @foo(i8* %p), !tbaa !0
|
||||||
|
%b = call i32 @foo(i8* %p), !tbaa !0
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test3(i8* %p, i8* %q) {
|
||||||
|
; CHECK: @test3(i8* %p, i8* %q)
|
||||||
|
; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGB:!.*]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = call i32 @foo(i8* %p), !tbaa !3
|
||||||
|
%b = call i32 @foo(i8* %p), !tbaa !3
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test4(i8* %p, i8* %q) {
|
||||||
|
; CHECK: @test4(i8* %p, i8* %q)
|
||||||
|
; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA:!.*]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = call i32 @foo(i8* %p), !tbaa !1
|
||||||
|
%b = call i32 @foo(i8* %p), !tbaa !0
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test5(i8* %p, i8* %q) {
|
||||||
|
; CHECK: @test5(i8* %p, i8* %q)
|
||||||
|
; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA:!.*]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = call i32 @foo(i8* %p), !tbaa !0
|
||||||
|
%b = call i32 @foo(i8* %p), !tbaa !1
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test6(i8* %p, i8* %q) {
|
||||||
|
; CHECK: @test6(i8* %p, i8* %q)
|
||||||
|
; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA:!.*]]
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = call i32 @foo(i8* %p), !tbaa !0
|
||||||
|
%b = call i32 @foo(i8* %p), !tbaa !3
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test7(i8* %p, i8* %q) {
|
||||||
|
; CHECK: @test7(i8* %p, i8* %q)
|
||||||
|
; CHECK: call i32 @foo(i8* %p)
|
||||||
|
; CHECK-NOT: tbaa
|
||||||
|
; CHECK: %c = add i32 %a, %a
|
||||||
|
%a = call i32 @foo(i8* %p), !tbaa !4
|
||||||
|
%b = call i32 @foo(i8* %p), !tbaa !3
|
||||||
|
%c = add i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
define i32 @test8(i32* %p, i32* %q) {
|
||||||
|
; CHECK-LABEL: test8
|
||||||
|
; CHECK-NEXT: store i32 15, i32* %p
|
||||||
|
; CHECK-NEXT: ret i32 0
|
||||||
|
; Since we know the location is invariant, we can forward the
|
||||||
|
; load across the potentially aliasing store.
|
||||||
|
|
||||||
|
%a = load i32, i32* %q, !tbaa !10
|
||||||
|
store i32 15, i32* %p
|
||||||
|
%b = load i32, i32* %q, !tbaa !10
|
||||||
|
%c = sub i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
define i32 @test9(i32* %p, i32* %q) {
|
||||||
|
; CHECK-LABEL: test9
|
||||||
|
; CHECK-NEXT: call void @clobber()
|
||||||
|
; CHECK-NEXT: ret i32 0
|
||||||
|
; Since we know the location is invariant, we can forward the
|
||||||
|
; load across the potentially aliasing store (within the call).
|
||||||
|
|
||||||
|
%a = load i32, i32* %q, !tbaa !10
|
||||||
|
call void @clobber()
|
||||||
|
%b = load i32, i32* %q, !tbaa !10
|
||||||
|
%c = sub i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
declare void @clobber()
|
||||||
|
declare i32 @foo(i8*) readonly
|
||||||
|
|
||||||
|
; CHECK: [[TAGC]] = !{[[TYPEC:!.*]], [[TYPEC]], i64 0}
|
||||||
|
; CHECK: [[TYPEC]] = !{!"C", [[TYPEA:!.*]]}
|
||||||
|
; CHECK: [[TYPEA]] = !{!"A", !{{.*}}}
|
||||||
|
; CHECK: [[TAGB]] = !{[[TYPEB:!.*]], [[TYPEB]], i64 0}
|
||||||
|
; CHECK: [[TYPEB]] = !{!"B", [[TYPEA]]}
|
||||||
|
; CHECK: [[TAGA]] = !{[[TYPEA]], [[TYPEA]], i64 0}
|
||||||
|
!0 = !{!5, !5, i64 0}
|
||||||
|
!1 = !{!6, !6, i64 0}
|
||||||
|
!2 = !{!"tbaa root"}
|
||||||
|
!3 = !{!7, !7, i64 0}
|
||||||
|
!4 = !{!11, !11, i64 0}
|
||||||
|
!5 = !{!"C", !6}
|
||||||
|
!6 = !{!"A", !2}
|
||||||
|
!7 = !{!"B", !6}
|
||||||
|
!8 = !{!"another root"}
|
||||||
|
!11 = !{!"scalar type", !8}
|
||||||
|
|
||||||
|
|
||||||
|
;; A TBAA structure who's only point is to have a constant location
|
||||||
|
!9 = !{!"yet another root"}
|
||||||
|
!10 = !{!"node", !9, i64 1}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
; RUN: opt -memdep -newgvn -disable-output < %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||||
|
target triple = "x86_64-apple-darwin10.0"
|
||||||
|
|
||||||
|
define i32 @test2() nounwind ssp {
|
||||||
|
entry:
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
unreachable_block:
|
||||||
|
%a = add i32 %a, 1
|
||||||
|
ret i32 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pr23096_test0() {
|
||||||
|
entry:
|
||||||
|
br label %bb0
|
||||||
|
|
||||||
|
bb1:
|
||||||
|
%ptr1 = ptrtoint i32* %ptr2 to i64
|
||||||
|
%ptr2 = inttoptr i64 %ptr1 to i32*
|
||||||
|
br i1 undef, label %bb0, label %bb1
|
||||||
|
|
||||||
|
bb0:
|
||||||
|
%phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ]
|
||||||
|
%load = load i32, i32* %phi
|
||||||
|
ret i32 %load
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @pr23096_test1() {
|
||||||
|
entry:
|
||||||
|
br label %bb0
|
||||||
|
|
||||||
|
bb1:
|
||||||
|
%ptr1 = getelementptr i32, i32* %ptr2, i32 0
|
||||||
|
%ptr2 = getelementptr i32, i32* %ptr1, i32 0
|
||||||
|
br i1 undef, label %bb0, label %bb1
|
||||||
|
|
||||||
|
bb0:
|
||||||
|
%phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ]
|
||||||
|
%load = load i32, i32* %phi
|
||||||
|
ret i32 %load
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
; XFAIL: *
|
||||||
|
; RUN: opt -tbaa -newgvn -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
%struct.t = type { i32* }
|
||||||
|
|
||||||
|
; The loaded address and the location of the address itself are not aliased,
|
||||||
|
; so the second reload is not necessary. Check that it can be eliminated.
|
||||||
|
; CHECK-LABEL: test1
|
||||||
|
; CHECK: load
|
||||||
|
; CHECK-NOT: load
|
||||||
|
define void @test1(%struct.t* nocapture readonly %p, i32 %v) #0 {
|
||||||
|
entry:
|
||||||
|
%m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
|
||||||
|
%0 = load i32*, i32** %m, align 4, !tbaa !1
|
||||||
|
store volatile i32 %v, i32* %0, align 4, !tbaa !6
|
||||||
|
%1 = load i32*, i32** %m, align 4, !tbaa !1
|
||||||
|
store volatile i32 %v, i32* %1, align 4, !tbaa !6
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; The store via the loaded address may overwrite the address itself.
|
||||||
|
; Make sure that both loads remain.
|
||||||
|
; CHECK-LABEL: test2
|
||||||
|
; CHECK: load
|
||||||
|
; CHECK: store
|
||||||
|
; CHECK: load
|
||||||
|
define void @test2(%struct.t* nocapture readonly %p, i32 %v) #0 {
|
||||||
|
entry:
|
||||||
|
%m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
|
||||||
|
%0 = load i32*, i32** %m, align 4, !tbaa !1
|
||||||
|
store volatile i32 %v, i32* %0, align 4, !tbaa !1
|
||||||
|
%1 = load i32*, i32** %m, align 4, !tbaa !1
|
||||||
|
store volatile i32 %v, i32* %1, align 4, !tbaa !1
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; The loads are ordered and non-monotonic. Although they are not aliased to
|
||||||
|
; the stores, make sure both are preserved.
|
||||||
|
; CHECK-LABEL: test3
|
||||||
|
; CHECK: load
|
||||||
|
; CHECK: store
|
||||||
|
; CHECK: load
|
||||||
|
define void @test3(%struct.t* nocapture readonly %p, i32 %v) #0 {
|
||||||
|
entry:
|
||||||
|
%m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
|
||||||
|
%0 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1
|
||||||
|
store volatile i32 %v, i32* %0, align 4, !tbaa !6
|
||||||
|
%1 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1
|
||||||
|
store volatile i32 %v, i32* %1, align 4, !tbaa !6
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes #0 = { norecurse nounwind }
|
||||||
|
|
||||||
|
!1 = !{!2, !3, i64 0}
|
||||||
|
!2 = !{!"", !3, i64 0}
|
||||||
|
!3 = !{!"any pointer", !4, i64 0}
|
||||||
|
!4 = !{!"omnipotent char", !5, i64 0}
|
||||||
|
!5 = !{!"Simple C/C++ TBAA"}
|
||||||
|
!6 = !{!7, !7, i64 0}
|
||||||
|
!7 = !{!"int", !4, i64 0}
|
||||||
|
|
Loading…
Reference in New Issue