mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Recommit "[IPConstProp] Remove and move tests to SCCP."
This reverts commit 59d6e814ce0e7b40b7cc3ab136b9af2ffab9c6f8. The cause for the revert (3 clang tests running opt -ipconstprop) was fixed by removing those lines.
This commit is contained in:
parent
5f096386c6
commit
5eea1c2f70
@ -32,7 +32,6 @@ func (pm PassManager) AddFunctionAttrsPass() { C.LLVMAddFunctionAttrsPas
|
||||
func (pm PassManager) AddFunctionInliningPass() { C.LLVMAddFunctionInliningPass(pm.C) }
|
||||
func (pm PassManager) AddGlobalDCEPass() { C.LLVMAddGlobalDCEPass(pm.C) }
|
||||
func (pm PassManager) AddGlobalOptimizerPass() { C.LLVMAddGlobalOptimizerPass(pm.C) }
|
||||
func (pm PassManager) AddIPConstantPropagationPass() { C.LLVMAddIPConstantPropagationPass(pm.C) }
|
||||
func (pm PassManager) AddPruneEHPass() { C.LLVMAddPruneEHPass(pm.C) }
|
||||
func (pm PassManager) AddIPSCCPPass() { C.LLVMAddIPSCCPPass(pm.C) }
|
||||
func (pm PassManager) AddInternalizePass(allButMain bool) {
|
||||
|
@ -73,12 +73,6 @@ CAMLprim value llvm_add_global_optimizer(LLVMPassManagerRef PM) {
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_ip_constant_propagation(LLVMPassManagerRef PM) {
|
||||
LLVMAddIPConstantPropagationPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_prune_eh(LLVMPassManagerRef PM) {
|
||||
LLVMAddPruneEHPass(PM);
|
||||
|
@ -56,11 +56,6 @@ external add_global_optimizer
|
||||
: [ `Module ] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_global_optimizer"
|
||||
|
||||
(** See the [llvm::createIPConstantPropagationPass] function. *)
|
||||
external add_ipc_propagation
|
||||
: [ `Module ] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_ip_constant_propagation"
|
||||
|
||||
(** See the [llvm::createPruneEHPass] function. *)
|
||||
external add_prune_eh
|
||||
: [ `Module ] Llvm.PassManager.t -> unit
|
||||
|
@ -676,15 +676,6 @@ This pass loops over all of the functions in the input module, looking for a
|
||||
main function. If a main function is found, all other functions and all global
|
||||
variables with initializers are marked as internal.
|
||||
|
||||
``-ipconstprop``: Interprocedural constant propagation
|
||||
------------------------------------------------------
|
||||
|
||||
This pass implements an *extremely* simple interprocedural constant propagation
|
||||
pass. It could certainly be improved in many different ways, like using a
|
||||
worklist. This pass makes arguments dead, but does not remove them. The
|
||||
existing dead argument elimination pass should be run after this to clean up
|
||||
the mess.
|
||||
|
||||
``-ipsccp``: Interprocedural Sparse Conditional Constant Propagation
|
||||
--------------------------------------------------------------------
|
||||
|
||||
|
@ -57,9 +57,6 @@ void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createGlobalOptimizerPass function. */
|
||||
void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createIPConstantPropagationPass function. */
|
||||
void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createPruneEHPass function. */
|
||||
void LLVMAddPruneEHPass(LLVMPassManagerRef PM);
|
||||
|
||||
|
@ -179,7 +179,6 @@ void initializeGuardWideningLegacyPassPass(PassRegistry&);
|
||||
void initializeHardwareLoopsPass(PassRegistry&);
|
||||
void initializeHotColdSplittingLegacyPassPass(PassRegistry&);
|
||||
void initializeHWAddressSanitizerLegacyPassPass(PassRegistry &);
|
||||
void initializeIPCPPass(PassRegistry&);
|
||||
void initializeIPSCCPLegacyPassPass(PassRegistry&);
|
||||
void initializeIRCELegacyPassPass(PassRegistry&);
|
||||
void initializeIRTranslatorPass(PassRegistry&);
|
||||
|
@ -116,7 +116,6 @@ namespace {
|
||||
(void) llvm::createGlobalsAAWrapperPass();
|
||||
(void) llvm::createGuardWideningPass();
|
||||
(void) llvm::createLoopGuardWideningPass();
|
||||
(void) llvm::createIPConstantPropagationPass();
|
||||
(void) llvm::createIPSCCPPass();
|
||||
(void) llvm::createInductiveRangeCheckEliminationPass();
|
||||
(void) llvm::createIndVarSimplifyPass();
|
||||
|
@ -155,12 +155,6 @@ Pass *createArgumentPromotionPass(unsigned maxElements = 3);
|
||||
/// createOpenMPOptLegacyPass - OpenMP specific optimizations.
|
||||
Pass *createOpenMPOptLegacyPass();
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// createIPConstantPropagationPass - This pass propagates constants from call
|
||||
/// sites into the bodies of functions.
|
||||
///
|
||||
ModulePass *createIPConstantPropagationPass();
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// createIPSCCPPass - This pass propagates constants from call sites into the
|
||||
/// bodies of functions, and keeps track of whether basic blocks are executable
|
||||
|
@ -18,7 +18,6 @@ add_llvm_component_library(LLVMipo
|
||||
GlobalOpt.cpp
|
||||
GlobalSplit.cpp
|
||||
HotColdSplitting.cpp
|
||||
IPConstantPropagation.cpp
|
||||
IPO.cpp
|
||||
InferFunctionAttrs.cpp
|
||||
InlineSimple.cpp
|
||||
|
@ -1,308 +0,0 @@
|
||||
//===-- IPConstantPropagation.cpp - Propagate constants through calls -----===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass implements an _extremely_ simple interprocedural constant
|
||||
// propagation pass. It could certainly be improved in many different ways,
|
||||
// like using a worklist. This pass makes arguments dead, but does not remove
|
||||
// them. The existing dead argument elimination pass should be run after this
|
||||
// to clean up the mess.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/AbstractCallSite.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "ipconstprop"
|
||||
|
||||
STATISTIC(NumArgumentsProped, "Number of args turned into constants");
|
||||
STATISTIC(NumReturnValProped, "Number of return values turned into constants");
|
||||
|
||||
namespace {
|
||||
/// IPCP - The interprocedural constant propagation pass
|
||||
///
|
||||
struct IPCP : public ModulePass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
IPCP() : ModulePass(ID) {
|
||||
initializeIPCPPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnModule(Module &M) override;
|
||||
};
|
||||
}
|
||||
|
||||
/// PropagateConstantsIntoArguments - Look at all uses of the specified
|
||||
/// function. If all uses are direct call sites, and all pass a particular
|
||||
/// constant in for an argument, propagate that constant in as the argument.
|
||||
///
|
||||
static bool PropagateConstantsIntoArguments(Function &F) {
|
||||
if (F.arg_empty() || F.use_empty()) return false; // No arguments? Early exit.
|
||||
|
||||
// For each argument, keep track of its constant value and whether it is a
|
||||
// constant or not. The bool is driven to true when found to be non-constant.
|
||||
SmallVector<PointerIntPair<Constant *, 1, bool>, 16> ArgumentConstants;
|
||||
ArgumentConstants.resize(F.arg_size());
|
||||
|
||||
unsigned NumNonconstant = 0;
|
||||
for (Use &U : F.uses()) {
|
||||
User *UR = U.getUser();
|
||||
// Ignore blockaddress uses.
|
||||
if (isa<BlockAddress>(UR)) continue;
|
||||
|
||||
// If no abstract call site was created we did not understand the use, bail.
|
||||
AbstractCallSite ACS(&U);
|
||||
if (!ACS)
|
||||
return false;
|
||||
|
||||
// Mismatched argument count is undefined behavior. Simply bail out to avoid
|
||||
// handling of such situations below (avoiding asserts/crashes).
|
||||
unsigned NumActualArgs = ACS.getNumArgOperands();
|
||||
if (F.isVarArg() ? ArgumentConstants.size() > NumActualArgs
|
||||
: ArgumentConstants.size() != NumActualArgs)
|
||||
return false;
|
||||
|
||||
// Check out all of the potentially constant arguments. Note that we don't
|
||||
// inspect varargs here.
|
||||
Function::arg_iterator Arg = F.arg_begin();
|
||||
for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++Arg) {
|
||||
|
||||
// If this argument is known non-constant, ignore it.
|
||||
if (ArgumentConstants[i].getInt())
|
||||
continue;
|
||||
|
||||
Value *V = ACS.getCallArgOperand(i);
|
||||
Constant *C = dyn_cast_or_null<Constant>(V);
|
||||
|
||||
// Mismatched argument type is undefined behavior. Simply bail out to avoid
|
||||
// handling of such situations below (avoiding asserts/crashes).
|
||||
if (C && Arg->getType() != C->getType())
|
||||
return false;
|
||||
|
||||
// We can only propagate thread independent values through callbacks.
|
||||
// This is different to direct/indirect call sites because for them we
|
||||
// know the thread executing the caller and callee is the same. For
|
||||
// callbacks this is not guaranteed, thus a thread dependent value could
|
||||
// be different for the caller and callee, making it invalid to propagate.
|
||||
if (C && ACS.isCallbackCall() && C->isThreadDependent()) {
|
||||
// Argument became non-constant. If all arguments are non-constant now,
|
||||
// give up on this function.
|
||||
if (++NumNonconstant == ArgumentConstants.size())
|
||||
return false;
|
||||
|
||||
ArgumentConstants[i].setInt(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (C && ArgumentConstants[i].getPointer() == nullptr) {
|
||||
ArgumentConstants[i].setPointer(C); // First constant seen.
|
||||
} else if (C && ArgumentConstants[i].getPointer() == C) {
|
||||
// Still the constant value we think it is.
|
||||
} else if (V == &*Arg) {
|
||||
// Ignore recursive calls passing argument down.
|
||||
} else {
|
||||
// Argument became non-constant. If all arguments are non-constant now,
|
||||
// give up on this function.
|
||||
if (++NumNonconstant == ArgumentConstants.size())
|
||||
return false;
|
||||
ArgumentConstants[i].setInt(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we got to this point, there is a constant argument!
|
||||
assert(NumNonconstant != ArgumentConstants.size());
|
||||
bool MadeChange = false;
|
||||
Function::arg_iterator AI = F.arg_begin();
|
||||
for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI) {
|
||||
// Do we have a constant argument?
|
||||
if (ArgumentConstants[i].getInt() || AI->use_empty() ||
|
||||
(AI->hasByValAttr() && !F.onlyReadsMemory()))
|
||||
continue;
|
||||
|
||||
Value *V = ArgumentConstants[i].getPointer();
|
||||
if (!V) V = UndefValue::get(AI->getType());
|
||||
AI->replaceAllUsesWith(V);
|
||||
++NumArgumentsProped;
|
||||
MadeChange = true;
|
||||
}
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
|
||||
// Check to see if this function returns one or more constants. If so, replace
|
||||
// all callers that use those return values with the constant value. This will
|
||||
// leave in the actual return values and instructions, but deadargelim will
|
||||
// clean that up.
|
||||
//
|
||||
// Additionally if a function always returns one of its arguments directly,
|
||||
// callers will be updated to use the value they pass in directly instead of
|
||||
// using the return value.
|
||||
static bool PropagateConstantReturn(Function &F) {
|
||||
if (F.getReturnType()->isVoidTy())
|
||||
return false; // No return value.
|
||||
|
||||
// We can infer and propagate the return value only when we know that the
|
||||
// definition we'll get at link time is *exactly* the definition we see now.
|
||||
// For more details, see GlobalValue::mayBeDerefined.
|
||||
if (!F.isDefinitionExact())
|
||||
return false;
|
||||
|
||||
// Don't touch naked functions. The may contain asm returning
|
||||
// value we don't see, so we may end up interprocedurally propagating
|
||||
// the return value incorrectly.
|
||||
if (F.hasFnAttribute(Attribute::Naked))
|
||||
return false;
|
||||
|
||||
// Check to see if this function returns a constant.
|
||||
SmallVector<Value *,4> RetVals;
|
||||
StructType *STy = dyn_cast<StructType>(F.getReturnType());
|
||||
if (STy)
|
||||
for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i)
|
||||
RetVals.push_back(UndefValue::get(STy->getElementType(i)));
|
||||
else
|
||||
RetVals.push_back(UndefValue::get(F.getReturnType()));
|
||||
|
||||
unsigned NumNonConstant = 0;
|
||||
for (BasicBlock &BB : F)
|
||||
if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
|
||||
for (unsigned i = 0, e = RetVals.size(); i != e; ++i) {
|
||||
// Already found conflicting return values?
|
||||
Value *RV = RetVals[i];
|
||||
if (!RV)
|
||||
continue;
|
||||
|
||||
// Find the returned value
|
||||
Value *V;
|
||||
if (!STy)
|
||||
V = RI->getOperand(0);
|
||||
else
|
||||
V = FindInsertedValue(RI->getOperand(0), i);
|
||||
|
||||
if (V) {
|
||||
// Ignore undefs, we can change them into anything
|
||||
if (isa<UndefValue>(V))
|
||||
continue;
|
||||
|
||||
// Try to see if all the rets return the same constant or argument.
|
||||
if (isa<Constant>(V) || isa<Argument>(V)) {
|
||||
if (isa<UndefValue>(RV)) {
|
||||
// No value found yet? Try the current one.
|
||||
RetVals[i] = V;
|
||||
continue;
|
||||
}
|
||||
// Returning the same value? Good.
|
||||
if (RV == V)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Different or no known return value? Don't propagate this return
|
||||
// value.
|
||||
RetVals[i] = nullptr;
|
||||
// All values non-constant? Stop looking.
|
||||
if (++NumNonConstant == RetVals.size())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, the function returns at least one constant value. Loop
|
||||
// over all users, replacing any uses of the return value with the returned
|
||||
// constant.
|
||||
bool MadeChange = false;
|
||||
for (Use &U : F.uses()) {
|
||||
CallBase *CB = dyn_cast<CallBase>(U.getUser());
|
||||
|
||||
// Not a call instruction or a call instruction that's not calling F
|
||||
// directly?
|
||||
if (!CB || !CB->isCallee(&U))
|
||||
continue;
|
||||
|
||||
// Call result not used?
|
||||
if (CB->use_empty())
|
||||
continue;
|
||||
|
||||
MadeChange = true;
|
||||
|
||||
if (!STy) {
|
||||
Value* New = RetVals[0];
|
||||
if (Argument *A = dyn_cast<Argument>(New))
|
||||
// Was an argument returned? Then find the corresponding argument in
|
||||
// the call instruction and use that.
|
||||
New = CB->getArgOperand(A->getArgNo());
|
||||
CB->replaceAllUsesWith(New);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto I = CB->user_begin(), E = CB->user_end(); I != E;) {
|
||||
Instruction *Ins = cast<Instruction>(*I);
|
||||
|
||||
// Increment now, so we can remove the use
|
||||
++I;
|
||||
|
||||
// Find the index of the retval to replace with
|
||||
int index = -1;
|
||||
if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Ins))
|
||||
if (EV->getNumIndices() == 1)
|
||||
index = *EV->idx_begin();
|
||||
|
||||
// If this use uses a specific return value, and we have a replacement,
|
||||
// replace it.
|
||||
if (index != -1) {
|
||||
Value *New = RetVals[index];
|
||||
if (New) {
|
||||
if (Argument *A = dyn_cast<Argument>(New))
|
||||
// Was an argument returned? Then find the corresponding argument in
|
||||
// the call instruction and use that.
|
||||
New = CB->getArgOperand(A->getArgNo());
|
||||
Ins->replaceAllUsesWith(New);
|
||||
Ins->eraseFromParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (MadeChange) ++NumReturnValProped;
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
char IPCP::ID = 0;
|
||||
INITIALIZE_PASS(IPCP, "ipconstprop",
|
||||
"Interprocedural constant propagation", false, false)
|
||||
|
||||
ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); }
|
||||
|
||||
bool IPCP::runOnModule(Module &M) {
|
||||
if (skipModule(M))
|
||||
return false;
|
||||
|
||||
bool Changed = false;
|
||||
bool LocalChange = true;
|
||||
|
||||
// FIXME: instead of using smart algorithms, we just iterate until we stop
|
||||
// making changes.
|
||||
while (LocalChange) {
|
||||
LocalChange = false;
|
||||
for (Function &F : M)
|
||||
if (!F.isDeclaration()) {
|
||||
// Delete any klingons.
|
||||
F.removeDeadConstantUsers();
|
||||
if (F.hasLocalLinkage())
|
||||
LocalChange |= PropagateConstantsIntoArguments(F);
|
||||
Changed |= PropagateConstantReturn(F);
|
||||
}
|
||||
Changed |= LocalChange;
|
||||
}
|
||||
return Changed;
|
||||
}
|
@ -35,7 +35,6 @@ void llvm::initializeIPO(PassRegistry &Registry) {
|
||||
initializeGlobalOptLegacyPassPass(Registry);
|
||||
initializeGlobalSplitPass(Registry);
|
||||
initializeHotColdSplittingLegacyPassPass(Registry);
|
||||
initializeIPCPPass(Registry);
|
||||
initializeAlwaysInlinerLegacyPassPass(Registry);
|
||||
initializeSimpleInlinerPass(Registry);
|
||||
initializeInferFunctionAttrsLegacyPassPass(Registry);
|
||||
@ -104,10 +103,6 @@ void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createGlobalOptimizerPass());
|
||||
}
|
||||
|
||||
void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createIPConstantPropagationPass());
|
||||
}
|
||||
|
||||
void LLVMAddPruneEHPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createPruneEHPass());
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -S | FileCheck %s
|
||||
|
||||
; See PR26774
|
||||
|
||||
define i32 @baz() {
|
||||
; CHECK-LABEL: @baz(
|
||||
; CHECK-NEXT: ret i32 10
|
||||
;
|
||||
ret i32 10
|
||||
}
|
||||
|
||||
; We can const-prop @baz's return value *into* @foo, but cannot
|
||||
; constprop @foo's return value into bar.
|
||||
|
||||
define linkonce_odr i32 @foo() {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: [[VAL:%.*]] = call i32 @baz()
|
||||
; CHECK-NEXT: ret i32 10
|
||||
;
|
||||
|
||||
%val = call i32 @baz()
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
define i32 @bar() {
|
||||
; CHECK-LABEL: @bar(
|
||||
; CHECK-NEXT: [[VAL:%.*]] = call i32 @foo()
|
||||
; CHECK-NEXT: ret i32 [[VAL]]
|
||||
;
|
||||
|
||||
%val = call i32 @foo()
|
||||
ret i32 %val
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -S | FileCheck %s
|
||||
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
||||
; Should not propagate the result of a weak function.
|
||||
; PR2411
|
||||
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -S -ipconstprop | FileCheck %s
|
||||
; RUN: opt < %s -S -ipsccp | FileCheck %s
|
||||
|
||||
%struct.wobble = type { i32 }
|
||||
%struct.zot = type { %struct.wobble, %struct.wobble, %struct.wobble }
|
||||
@ -19,7 +19,7 @@ define void @baz(<8 x i32> %arg) local_unnamed_addr {
|
||||
; CHECK-LABEL: @baz(
|
||||
; CHECK-NEXT: bb:
|
||||
; CHECK-NEXT: [[TMP:%.*]] = call [[STRUCT_ZOT:%.*]] @widget(<8 x i32> [[ARG:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_ZOT]] %tmp, 0, 0
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_ZOT]] undef, 0, 0
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
bb:
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -S -o - | FileCheck %s
|
||||
; RUN: opt < %s -ipsccp -S -o - | FileCheck %s
|
||||
|
||||
; The original C source looked like this:
|
||||
;
|
||||
@ -53,7 +53,7 @@ define internal i16 @bar(i16 %p1, i16 %p2) {
|
||||
|
||||
define internal i16 @vararg_prop(i16 %p1, ...) {
|
||||
; CHECK-LABEL: @vararg_prop(
|
||||
; CHECK-NEXT: ret i16 7
|
||||
; CHECK-NEXT: ret i16 undef
|
||||
;
|
||||
ret i16 %p1
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -S -o - | FileCheck %s
|
||||
; RUN: opt < %s -ipsccp -S -o - | FileCheck %s
|
||||
|
||||
; This test is just to verify that we do not crash/assert due to mismatch in
|
||||
; argument type between the caller and callee.
|
@ -1,8 +1,12 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
||||
|
||||
; See PR26774
|
||||
|
||||
define i32 @baz() {
|
||||
; CHECK-LABEL: @baz(
|
||||
; CHECK-NEXT: ret i32 10
|
||||
;
|
||||
ret i32 10
|
||||
}
|
||||
|
||||
@ -11,8 +15,9 @@ define i32 @baz() {
|
||||
|
||||
define linkonce_odr i32 @foo() {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: %val = call i32 @baz()
|
||||
; CHECK-NEXT: ret i32 10
|
||||
; CHECK-NEXT: [[VAL:%.*]] = call i32 @baz()
|
||||
; CHECK-NEXT: ret i32 10
|
||||
;
|
||||
|
||||
%val = call i32 @baz()
|
||||
ret i32 %val
|
||||
@ -20,8 +25,9 @@ define linkonce_odr i32 @foo() {
|
||||
|
||||
define i32 @bar() {
|
||||
; CHECK-LABEL: @bar(
|
||||
; CHECK-NEXT: %val = call i32 @foo()
|
||||
; CHECK-NEXT: ret i32 %val
|
||||
; CHECK-NEXT: [[VAL:%.*]] = call i32 @foo()
|
||||
; CHECK-NEXT: ret i32 [[VAL]]
|
||||
;
|
||||
|
||||
%val = call i32 @foo()
|
||||
ret i32 %val
|
||||
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -disable-output
|
||||
; RUN: opt < %s -ipsccp -disable-output
|
||||
define internal void @foo(i32 %X) {
|
||||
call void @foo( i32 %X )
|
||||
ret void
|
@ -1,5 +1,6 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -ipconstprop -S < %s | FileCheck %s
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes
|
||||
; RUN: opt -ipsccp -S %s | FileCheck %s
|
||||
;
|
||||
;
|
||||
; /---------------------------------------|
|
||||
; | /----------------------|----|
|
||||
@ -38,7 +39,7 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
define internal i32 @cb0(i32 %zero) {
|
||||
; CHECK-LABEL: @cb0(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
; CHECK-NEXT: ret i32 [[ZERO:%.*]]
|
||||
;
|
||||
entry:
|
||||
ret i32 %zero
|
@ -1,6 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -ipsccp -S %s | FileCheck %s
|
||||
; RUN: opt -ipconstprop -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-msvc19.0.24215"
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -ipconstprop < %s | FileCheck %s
|
||||
; RUN: opt -S -ipsccp < %s | FileCheck %s
|
||||
;
|
||||
; void bar(int, float, double);
|
||||
;
|
||||
@ -53,7 +53,7 @@ define internal void @.omp_outlined.(i32* noalias %.global_tid., i32* noalias %.
|
||||
; CHECK-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: store i64 4617315517961601024, i64* [[Q_ADDR]], align 8
|
||||
; CHECK-NEXT: store i64 [[Q:%.*]], i64* [[Q_ADDR]], align 8
|
||||
; CHECK-NEXT: [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double*
|
||||
; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[N:%.*]], align 4
|
||||
; CHECK-NEXT: [[SUB3:%.*]] = add nsw i32 [[TMP]], -3
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -ipconstprop -S < %s | FileCheck %s
|
||||
; RUN: opt -ipsccp -S < %s | FileCheck %s
|
||||
;
|
||||
; #include <pthread.h>
|
||||
;
|
||||
@ -44,7 +44,7 @@ declare !callback !0 dso_local i32 @pthread_create(i64*, %union.pthread_attr_t*,
|
||||
define internal i8* @foo(i8* %arg) {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i8* null
|
||||
; CHECK-NEXT: ret i8* [[ARG:%.*]]
|
||||
;
|
||||
entry:
|
||||
ret i8* %arg
|
||||
@ -53,7 +53,7 @@ entry:
|
||||
define internal i8* @bar(i8* %arg) {
|
||||
; CHECK-LABEL: @bar(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*)
|
||||
; CHECK-NEXT: ret i8* [[ARG:%.*]]
|
||||
;
|
||||
entry:
|
||||
ret i8* %arg
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -deadargelim -S | FileCheck %s
|
||||
; RUN: opt < %s -ipsccp -deadargelim -S | FileCheck %s
|
||||
|
||||
; CHECK-NOT: %X
|
||||
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -S | FileCheck %s
|
||||
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
||||
|
||||
;; This function returns its second argument on all return statements
|
||||
define internal i32* @incdec(i1 %C, i32* %V) {
|
||||
@ -49,11 +49,13 @@ define void @caller(i1 %C) personality i32 (...)* @__gxx_personality_v0 {
|
||||
; CHECK-NEXT: [[Q:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[W:%.*]] = call i32* @incdec(i1 [[C:%.*]], i32* [[Q]])
|
||||
; CHECK-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 1, i32 2)
|
||||
; CHECK-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0
|
||||
; CHECK-NEXT: [[S2:%.*]] = invoke { i32, i32 } @foo(i32 3, i32 4)
|
||||
; CHECK-NEXT: to label [[OK:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: OK:
|
||||
; CHECK-NEXT: [[Z:%.*]] = add i32 1, 3
|
||||
; CHECK-NEXT: store i32 [[Z]], i32* [[Q]], align 4
|
||||
; CHECK-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0
|
||||
; CHECK-NEXT: [[Z:%.*]] = add i32 [[X1]], [[X2]]
|
||||
; CHECK-NEXT: store i32 [[Z]], i32* [[W]], align 4
|
||||
; CHECK-NEXT: br label [[RET:%.*]]
|
||||
; CHECK: LPAD:
|
||||
; CHECK-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 }
|
@ -1,13 +1,13 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -instcombine -S | FileCheck %s
|
||||
; RUN: opt < %s -ipsccp -instcombine -S | FileCheck %s
|
||||
|
||||
define internal i32 @foo(i1 %C) {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: br i1 [[C:%.*]], label [[T:%.*]], label [[F:%.*]]
|
||||
; CHECK: T:
|
||||
; CHECK-NEXT: ret i32 52
|
||||
; CHECK-NEXT: ret i32 undef
|
||||
; CHECK: F:
|
||||
; CHECK-NEXT: ret i32 52
|
||||
; CHECK-NEXT: ret i32 undef
|
||||
;
|
||||
br i1 %C, label %T, label %F
|
||||
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -ipconstprop -S | FileCheck %s
|
||||
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
||||
|
||||
%0 = type { i32, i32 }
|
||||
|
||||
@ -7,13 +7,9 @@ define internal %0 @foo(i1 %Q) {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: br i1 [[Q:%.*]], label [[T:%.*]], label [[F:%.*]]
|
||||
; CHECK: T:
|
||||
; CHECK-NEXT: [[MRV:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0
|
||||
; CHECK-NEXT: [[MRV1:%.*]] = insertvalue [[TMP0]] %mrv, i32 22, 1
|
||||
; CHECK-NEXT: ret [[TMP0]] %mrv1
|
||||
; CHECK-NEXT: ret [[TMP0:%.*]] { i32 21, i32 22 }
|
||||
; CHECK: F:
|
||||
; CHECK-NEXT: [[MRV2:%.*]] = insertvalue [[TMP0]] undef, i32 21, 0
|
||||
; CHECK-NEXT: [[MRV3:%.*]] = insertvalue [[TMP0]] %mrv2, i32 23, 1
|
||||
; CHECK-NEXT: ret [[TMP0]] %mrv3
|
||||
; CHECK-NEXT: ret [[TMP0]] { i32 21, i32 23 }
|
||||
;
|
||||
br i1 %Q, label %T, label %F
|
||||
|
||||
@ -30,14 +26,11 @@ F: ; preds = %0
|
||||
|
||||
define internal %0 @bar(i1 %Q) {
|
||||
; CHECK-LABEL: @bar(
|
||||
; CHECK-NEXT: [[A:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0
|
||||
; CHECK-NEXT: br i1 [[Q:%.*]], label [[T:%.*]], label [[F:%.*]]
|
||||
; CHECK: T:
|
||||
; CHECK-NEXT: [[B:%.*]] = insertvalue [[TMP0]] %A, i32 22, 1
|
||||
; CHECK-NEXT: ret [[TMP0]] %B
|
||||
; CHECK-NEXT: ret [[TMP0:%.*]] { i32 21, i32 22 }
|
||||
; CHECK: F:
|
||||
; CHECK-NEXT: [[C:%.*]] = insertvalue [[TMP0]] %A, i32 23, 1
|
||||
; CHECK-NEXT: ret [[TMP0]] %C
|
||||
; CHECK-NEXT: ret [[TMP0]] { i32 21, i32 23 }
|
||||
;
|
||||
%A = insertvalue %0 undef, i32 21, 0
|
||||
br i1 %Q, label %T, label %F
|
||||
@ -57,7 +50,6 @@ define %0 @caller(i1 %Q) {
|
||||
; CHECK-NEXT: [[B:%.*]] = extractvalue [[TMP0]] %X, 1
|
||||
; CHECK-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]])
|
||||
; CHECK-NEXT: [[D:%.*]] = extractvalue [[TMP0]] %Y, 1
|
||||
; CHECK-NEXT: [[M:%.*]] = add i32 21, 21
|
||||
; CHECK-NEXT: [[N:%.*]] = add i32 [[B]], [[D]]
|
||||
; CHECK-NEXT: ret [[TMP0]] %X
|
||||
;
|
@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -ipconstprop -S < %s | FileCheck %s
|
||||
; RUN: opt -ipsccp -S < %s | FileCheck %s
|
||||
;
|
||||
; #include <threads.h>
|
||||
; thread_local int gtl = 0;
|
||||
@ -24,7 +24,7 @@ define internal i32 @callee(i32* %thread_local_ptr, i32* %shared_ptr) {
|
||||
; CHECK-LABEL: @callee(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[THREAD_LOCAL_PTR:%.*]], align 4
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @gsh, align 4
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[SHARED_PTR:%.*]], align 4
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP]], [[TMP1]]
|
||||
; CHECK-NEXT: ret i32 [[ADD]]
|
||||
;
|
@ -70,7 +70,7 @@ dis2="$llvm2/Debug/bin/llvm-dis"
|
||||
opt1="$llvm1/Debug/bin/opt"
|
||||
opt2="$llvm2/Debug/bin/opt"
|
||||
|
||||
all_switches="-verify -lowersetjmp -simplifycfg -mem2reg -globalopt -globaldce -ipconstprop -deadargelim -instcombine -simplifycfg -prune-eh -inline -simplify-libcalls -argpromotion -tailduplicate -simplifycfg -sroa -instcombine -predsimplify -condprop -tailcallelim -simplifycfg -reassociate -licm -loop-unswitch -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -condprop -dse -dce -simplifycfg -deadtypeelim -constmerge -internalize -ipsccp -globalopt -constmerge -deadargelim -inline -prune-eh -globalopt -globaldce -argpromotion -instcombine -predsimplify -sroa -globalsmodref-aa -licm -load-vn -gcse -dse -instcombine -simplifycfg -verify"
|
||||
all_switches="-verify -lowersetjmp -simplifycfg -mem2reg -globalopt -globaldce -deadargelim -instcombine -simplifycfg -prune-eh -inline -simplify-libcalls -argpromotion -tailduplicate -simplifycfg -sroa -instcombine -predsimplify -condprop -tailcallelim -simplifycfg -reassociate -licm -loop-unswitch -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -condprop -dse -dce -simplifycfg -deadtypeelim -constmerge -internalize -ipsccp -globalopt -constmerge -deadargelim -inline -prune-eh -globalopt -globaldce -argpromotion -instcombine -predsimplify -sroa -globalsmodref-aa -licm -load-vn -gcse -dse -instcombine -simplifycfg -verify"
|
||||
|
||||
#counter=0
|
||||
function tryit {
|
||||
|
@ -38,7 +38,6 @@ static_library("IPO") {
|
||||
"GlobalOpt.cpp",
|
||||
"GlobalSplit.cpp",
|
||||
"HotColdSplitting.cpp",
|
||||
"IPConstantPropagation.cpp",
|
||||
"IPO.cpp",
|
||||
"InferFunctionAttrs.cpp",
|
||||
"InlineSimple.cpp",
|
||||
|
Loading…
Reference in New Issue
Block a user