1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

Revert "Add a pass to lower is.constant and objectsize intrinsics"

This reverts commit r374743. It broke the build with Ocaml enabled:
http://lab.llvm.org:8011/builders/clang-x86_64-debian-fast/builds/19218

llvm-svn: 374768
This commit is contained in:
Dmitri Gribenko 2019-10-14 12:22:48 +00:00
parent dd292a30dc
commit d8ea0e7773
38 changed files with 457 additions and 399 deletions

View File

@ -191,11 +191,6 @@ external add_lower_expect_intrinsic
: [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
= "llvm_add_lower_expect_intrinsic"
(** See the [llvm::createLowerConstantIntrinsicsPass] function. *)
external add_lower_constant_intrinsics
: [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
= "llvm_add_lower_constant_intrinsics"
(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *)
external add_type_based_alias_analysis
: [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit

View File

@ -236,12 +236,6 @@ CAMLprim value llvm_add_lower_expect_intrinsic(LLVMPassManagerRef PM) {
return Val_unit;
}
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
CAMLprim value llvm_add_lower_constant_intrinsics(LLVMPassManagerRef PM) {
LLVMAddLowerConstantIntrinsicsPass(PM);
return Val_unit;
}
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) {
LLVMAddTypeBasedAliasAnalysisPass(PM);

View File

@ -147,9 +147,6 @@ void LLVMAddEarlyCSEMemSSAPass(LLVMPassManagerRef PM);
/** See llvm::createLowerExpectIntrinsicPass function */
void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM);
/** See llvm::createLowerConstantIntrinsicsPass function */
void LLVMAddLowerConstantIntrinsicsPass(LLVMPassManagerRef PM);
/** See llvm::createTypeBasedAliasAnalysisPass function */
void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM);

View File

@ -243,7 +243,6 @@ void initializeLoopVectorizePass(PassRegistry&);
void initializeLoopVersioningLICMPass(PassRegistry&);
void initializeLoopVersioningPassPass(PassRegistry&);
void initializeLowerAtomicLegacyPassPass(PassRegistry&);
void initializeLowerConstantIntrinsicsPass(PassRegistry&);
void initializeLowerEmuTLSPass(PassRegistry&);
void initializeLowerExpectIntrinsicPass(PassRegistry&);
void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&);

View File

@ -140,7 +140,6 @@ namespace {
(void) llvm::createLoopVersioningLICMPass();
(void) llvm::createLoopIdiomPass();
(void) llvm::createLoopRotatePass();
(void) llvm::createLowerConstantIntrinsicsPass();
(void) llvm::createLowerExpectIntrinsicPass();
(void) llvm::createLowerInvokePass();
(void) llvm::createLowerSwitchPass();

View File

@ -395,13 +395,6 @@ extern char &InferAddressSpacesID;
// "block_weights" metadata.
FunctionPass *createLowerExpectIntrinsicPass();
//===----------------------------------------------------------------------===//
//
// LowerConstantIntrinsicss - Expand any remaining llvm.objectsize and
// llvm.is.constant intrinsic calls, even for the unknown cases.
//
FunctionPass *createLowerConstantIntrinsicsPass();
//===----------------------------------------------------------------------===//
//
// PartiallyInlineLibCalls - Tries to inline the fast path of library

View File

@ -1,41 +0,0 @@
//===- LowerConstantIntrinsics.h - Lower constant int. pass -*- C++ -*-========//
//
// 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
//
//===----------------------------------------------------------------------===//
/// \file
///
/// The header file for the LowerConstantIntrinsics pass as used by the new pass
/// manager.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_SCALAR_LOWERCONSTANTINTRINSICS_H
#define LLVM_TRANSFORMS_SCALAR_LOWERCONSTANTINTRINSICS_H
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
struct LowerConstantIntrinsicsPass :
PassInfoMixin<LowerConstantIntrinsicsPass> {
public:
explicit LowerConstantIntrinsicsPass() {}
/// Run the pass over the function.
///
/// This will lower all remaining 'objectsize' and 'is.constant'`
/// intrinsic calls in this function, even when the argument has no known
/// size or is not a constant respectively. The resulting constant is
/// propagated and conditional branches are resolved where possible.
/// This complements the Instruction Simplification and
/// Instruction Combination passes of the optimized pass chain.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
};
}
#endif

View File

@ -1868,10 +1868,24 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool &ModifiedDT) {
});
return true;
}
case Intrinsic::objectsize:
llvm_unreachable("llvm.objectsize.* should have been lowered already");
case Intrinsic::is_constant:
llvm_unreachable("llvm.is.constant.* should have been lowered already");
case Intrinsic::objectsize: {
// Lower all uses of llvm.objectsize.*
Value *RetVal =
lowerObjectSizeCall(II, *DL, TLInfo, /*MustSucceed=*/true);
resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
});
return true;
}
case Intrinsic::is_constant: {
// If is_constant hasn't folded away yet, lower it to false now.
Constant *RetVal = ConstantInt::get(II->getType(), 0);
resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
});
return true;
}
case Intrinsic::aarch64_stlxr:
case Intrinsic::aarch64_stxr: {
ZExtInst *ExtVal = dyn_cast<ZExtInst>(CI->getArgOperand(0));

View File

@ -1437,12 +1437,18 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MIRBuilder.buildConstant(Reg, TypeID);
return true;
}
case Intrinsic::objectsize:
llvm_unreachable("llvm.objectsize.* should have been lowered already");
case Intrinsic::objectsize: {
// If we don't know by now, we're never going to know.
const ConstantInt *Min = cast<ConstantInt>(CI.getArgOperand(1));
MIRBuilder.buildConstant(getOrCreateVReg(CI), Min->isZero() ? -1ULL : 0);
return true;
}
case Intrinsic::is_constant:
llvm_unreachable("llvm.is.constant.* should have been lowered already");
// If this wasn't constant-folded away by now, then it's not a
// constant.
MIRBuilder.buildConstant(getOrCreateVReg(CI), 0);
return true;
case Intrinsic::stackguard:
getStackGuard(getOrCreateVReg(CI), MIRBuilder);
return true;

View File

@ -1454,12 +1454,24 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
TII.get(TargetOpcode::DBG_LABEL)).addMetadata(DI->getLabel());
return true;
}
case Intrinsic::objectsize:
llvm_unreachable("llvm.objectsize.* should have been lowered already");
case Intrinsic::is_constant:
llvm_unreachable("llvm.is.constant.* should have been lowered already");
case Intrinsic::objectsize: {
ConstantInt *CI = cast<ConstantInt>(II->getArgOperand(1));
unsigned long long Res = CI->isZero() ? -1ULL : 0;
Constant *ResCI = ConstantInt::get(II->getType(), Res);
unsigned ResultReg = getRegForValue(ResCI);
if (!ResultReg)
return false;
updateValueMap(II, ResultReg);
return true;
}
case Intrinsic::is_constant: {
Constant *ResCI = ConstantInt::get(II->getType(), 0);
unsigned ResultReg = getRegForValue(ResCI);
if (!ResultReg)
return false;
updateValueMap(II, ResultReg);
return true;
}
case Intrinsic::launder_invariant_group:
case Intrinsic::strip_invariant_group:
case Intrinsic::expect: {

View File

@ -6388,11 +6388,29 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
DAG.setRoot(Res);
return;
}
case Intrinsic::objectsize:
llvm_unreachable("llvm.objectsize.* should have been lowered already");
case Intrinsic::objectsize: {
// If we don't know by now, we're never going to know.
ConstantInt *CI = dyn_cast<ConstantInt>(I.getArgOperand(1));
assert(CI && "Non-constant type in __builtin_object_size?");
SDValue Arg = getValue(I.getCalledValue());
EVT Ty = Arg.getValueType();
if (CI->isZero())
Res = DAG.getConstant(-1ULL, sdl, Ty);
else
Res = DAG.getConstant(0, sdl, Ty);
setValue(&I, Res);
return;
}
case Intrinsic::is_constant:
llvm_unreachable("llvm.is.constant.* should have been lowered already");
// If this wasn't constant-folded away by now, then it's not a
// constant.
setValue(&I, DAG.getConstant(0, sdl, MVT::i1));
return;
case Intrinsic::annotation:
case Intrinsic::ptr_annotation:

View File

@ -657,7 +657,6 @@ void TargetPassConfig::addIRPasses() {
// TODO: add a pass insertion point here
addPass(createGCLoweringPass());
addPass(createShadowStackGCLoweringPass());
addPass(createLowerConstantIntrinsicsPass());
// Make sure that no unreachable blocks are instruction selected.
addPass(createUnreachableBlockEliminationPass());

View File

@ -142,7 +142,6 @@
#include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h"
#include "llvm/Transforms/Scalar/LoopUnrollPass.h"
#include "llvm/Transforms/Scalar/LowerAtomic.h"
#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
#include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"
#include "llvm/Transforms/Scalar/LowerWidenableCondition.h"
@ -892,8 +891,6 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline(
FunctionPassManager OptimizePM(DebugLogging);
OptimizePM.addPass(Float2IntPass());
OptimizePM.addPass(LowerConstantIntrinsicsPass());
// FIXME: We need to run some loop optimizations to re-rotate loops after
// simplify-cfg and others undo their rotation.

View File

@ -187,7 +187,6 @@ FUNCTION_PASS("libcalls-shrinkwrap", LibCallsShrinkWrapPass())
FUNCTION_PASS("loweratomic", LowerAtomicPass())
FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass())
FUNCTION_PASS("lower-guard-intrinsic", LowerGuardIntrinsicPass())
FUNCTION_PASS("lower-constant-intrinsics", LowerConstantIntrinsicsPass())
FUNCTION_PASS("lower-widenable-condition", LowerWidenableConditionPass())
FUNCTION_PASS("guard-widening", GuardWideningPass())
FUNCTION_PASS("gvn", GVN())

View File

@ -654,7 +654,6 @@ void PassManagerBuilder::populateModulePassManager(
MPM.add(createGlobalsAAWrapperPass());
MPM.add(createFloat2IntPass());
MPM.add(createLowerConstantIntrinsicsPass());
addExtensionsToPM(EP_VectorizerStart, MPM);

View File

@ -44,7 +44,6 @@ add_llvm_library(LLVMScalarOpts
LoopUnswitch.cpp
LoopVersioningLICM.cpp
LowerAtomic.cpp
LowerConstantIntrinsics.cpp
LowerExpectIntrinsic.cpp
LowerGuardIntrinsic.cpp
LowerWidenableCondition.cpp

View File

@ -1,170 +0,0 @@
//===- LowerConstantIntrinsics.cpp - Lower constant intrinsic 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 lowers all remaining 'objectsize' 'is.constant' intrinsic calls
// and provides constant propagation and basic CFG cleanup on the result.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;
using namespace llvm::PatternMatch;
#define DEBUG_TYPE "lower-is-constant-intrinsic"
STATISTIC(IsConstantIntrinsicsHandled,
"Number of 'is.constant' intrinsic calls handled");
STATISTIC(ObjectSizeIntrinsicsHandled,
"Number of 'objectsize' intrinsic calls handled");
static Value *lowerIsConstantIntrinsic(IntrinsicInst *II) {
Value *Op = II->getOperand(0);
return isa<Constant>(Op) ? ConstantInt::getTrue(II->getType())
: ConstantInt::getFalse(II->getType());
}
static bool replaceConditionalBranchesOnConstant(Instruction *II,
Value *NewValue) {
bool HasDeadBlocks = false;
SmallSetVector<Instruction *, 8> Worklist;
replaceAndRecursivelySimplify(II, NewValue, nullptr, nullptr, nullptr,
&Worklist);
for (auto I : Worklist) {
BranchInst *BI = dyn_cast<BranchInst>(I);
if (!BI)
continue;
if (BI->isUnconditional())
continue;
BasicBlock *Target, *Other;
if (match(BI->getOperand(0), m_Zero())) {
Target = BI->getSuccessor(1);
Other = BI->getSuccessor(0);
} else if (match(BI->getOperand(0), m_One())) {
Target = BI->getSuccessor(0);
Other = BI->getSuccessor(1);
} else {
Target = nullptr;
Other = nullptr;
}
if (Target && Target != Other) {
BasicBlock *Source = BI->getParent();
Other->removePredecessor(Source);
BI->eraseFromParent();
BranchInst::Create(Target, Source);
if (pred_begin(Other) == pred_end(Other))
HasDeadBlocks = true;
}
}
return HasDeadBlocks;
}
static bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo *TLI) {
bool HasDeadBlocks = false;
const auto &DL = F.getParent()->getDataLayout();
SmallVector<WeakTrackingVH, 8> Worklist;
ReversePostOrderTraversal<Function *> RPOT(&F);
for (BasicBlock *BB : RPOT) {
for (Instruction &I: *BB) {
IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
if (!II)
continue;
switch (II->getIntrinsicID()) {
default:
break;
case Intrinsic::is_constant:
case Intrinsic::objectsize:
Worklist.push_back(WeakTrackingVH(&I));
break;
}
}
}
for (WeakTrackingVH &VH: Worklist) {
// Items on the worklist can be mutated by earlier recursive replaces.
// This can remove the intrinsic as dead (VH == null), but also replace
// the intrinsic in place.
if (!VH)
continue;
IntrinsicInst *II = dyn_cast<IntrinsicInst>(&*VH);
if (!II)
continue;
Value *NewValue;
switch (II->getIntrinsicID()) {
default:
continue;
case Intrinsic::is_constant:
NewValue = lowerIsConstantIntrinsic(II);
IsConstantIntrinsicsHandled++;
break;
case Intrinsic::objectsize:
NewValue = lowerObjectSizeCall(II, DL, TLI, true);
ObjectSizeIntrinsicsHandled++;
break;
}
HasDeadBlocks |= replaceConditionalBranchesOnConstant(II, NewValue);
}
if (HasDeadBlocks)
removeUnreachableBlocks(F);
return !Worklist.empty();
}
PreservedAnalyses
LowerConstantIntrinsicsPass::run(Function &F, FunctionAnalysisManager &AM) {
if (lowerConstantIntrinsics(F, AM.getCachedResult<TargetLibraryAnalysis>(F)))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
namespace {
/// Legacy pass for lowering is.constant intrinsics out of the IR.
///
/// When this pass is run over a function it converts is.constant intrinsics
/// into 'true' or 'false'. This is completements the normal constand folding
/// to 'true' as part of Instruction Simplify passes.
class LowerConstantIntrinsics : public FunctionPass {
public:
static char ID;
LowerConstantIntrinsics() : FunctionPass(ID) {
initializeLowerConstantIntrinsicsPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override {
auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI(F) : nullptr;
return lowerConstantIntrinsics(F, TLI);
}
};
} // namespace
char LowerConstantIntrinsics::ID = 0;
INITIALIZE_PASS(LowerConstantIntrinsics, "lower-constant-intrinsics",
"Lower constant intrinsics", false, false)
FunctionPass *llvm::createLowerConstantIntrinsicsPass() {
return new LowerConstantIntrinsics();
}

View File

@ -79,7 +79,6 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
initializeLoopVersioningLICMPass(Registry);
initializeLoopIdiomRecognizeLegacyPassPass(Registry);
initializeLowerAtomicLegacyPassPass(Registry);
initializeLowerConstantIntrinsicsPass(Registry);
initializeLowerExpectIntrinsicPass(Registry);
initializeLowerGuardIntrinsicLegacyPassPass(Registry);
initializeLowerWidenableConditionLegacyPassPass(Registry);
@ -285,10 +284,6 @@ void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createBasicAAWrapperPass());
}
void LLVMAddLowerConstantIntrinsicsPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createLowerConstantIntrinsicsPass());
}
void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createLowerExpectIntrinsicPass());
}

View File

@ -1183,6 +1183,23 @@ define void @test_memset(i8* %dst, i8 %val, i64 %size) {
ret void
}
declare i64 @llvm.objectsize.i64(i8*, i1)
declare i32 @llvm.objectsize.i32(i8*, i1)
define void @test_objectsize(i8* %addr0, i8* %addr1) {
; CHECK-LABEL: name: test_objectsize
; CHECK: [[ADDR0:%[0-9]+]]:_(p0) = COPY $x0
; CHECK: [[ADDR1:%[0-9]+]]:_(p0) = COPY $x1
; CHECK: {{%[0-9]+}}:_(s64) = G_CONSTANT i64 -1
; CHECK: {{%[0-9]+}}:_(s64) = G_CONSTANT i64 0
; CHECK: {{%[0-9]+}}:_(s32) = G_CONSTANT i32 -1
; CHECK: {{%[0-9]+}}:_(s32) = G_CONSTANT i32 0
%size64.0 = call i64 @llvm.objectsize.i64(i8* %addr0, i1 0)
%size64.intmin = call i64 @llvm.objectsize.i64(i8* %addr0, i1 1)
%size32.0 = call i32 @llvm.objectsize.i32(i8* %addr0, i1 0)
%size32.intmin = call i32 @llvm.objectsize.i32(i8* %addr0, i1 1)
ret void
}
define void @test_large_const(i128* %addr) {
; CHECK-LABEL: name: test_large_const
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0

View File

@ -21,7 +21,6 @@
; CHECK-NEXT: Module Verifier
; CHECK-NEXT: Lower Garbage Collection Instructions
; CHECK-NEXT: Shadow Stack GC Lowering
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Remove unreachable blocks from the CFG
; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; CHECK-NEXT: Scalarize Masked Memory Intrinsics

View File

@ -38,7 +38,6 @@
; CHECK-NEXT: Expand memcmp() to load/stores
; CHECK-NEXT: Lower Garbage Collection Instructions
; CHECK-NEXT: Shadow Stack GC Lowering
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Remove unreachable blocks from the CFG
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Natural Loop Information

View File

@ -22,7 +22,6 @@
; CHECK-NEXT: Expand memcmp() to load/stores
; CHECK-NEXT: Lower Garbage Collection Instructions
; CHECK-NEXT: Shadow Stack GC Lowering
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Remove unreachable blocks from the CFG
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Natural Loop Information

View File

@ -0,0 +1,114 @@
; RUN: opt -O2 -S < %s | FileCheck %s
; RUN: llc -o /dev/null 2>&1 < %s
; RUN: llc -O0 -o /dev/null 2>&1 < %s
;; The llc runs above are just to ensure it doesn't blow up upon
;; seeing an is_constant intrinsic.
declare i1 @llvm.is.constant.i32(i32 %a)
declare i1 @llvm.is.constant.i64(i64 %a)
declare i1 @llvm.is.constant.i256(i256 %a)
declare i1 @llvm.is.constant.v2i64(<2 x i64> %a)
declare i1 @llvm.is.constant.f32(float %a)
declare i1 @llvm.is.constant.sl_i32i32s({i32, i32} %a)
declare i1 @llvm.is.constant.a2i64([2 x i64] %a)
declare i1 @llvm.is.constant.p0i64(i64* %a)
;; Basic test that optimization folds away the is.constant when given
;; a constant.
define i1 @test_constant() #0 {
; CHECK-LABEL: @test_constant(
; CHECK-NOT: llvm.is.constant
; CHECK: ret i1 true
%y = call i1 @llvm.is.constant.i32(i32 44)
ret i1 %y
}
;; And test that the intrinsic sticks around when given a
;; non-constant.
define i1 @test_nonconstant(i32 %x) #0 {
; CHECK-LABEL: @test_nonconstant(
; CHECK: @llvm.is.constant
%y = call i1 @llvm.is.constant.i32(i32 %x)
ret i1 %y
}
;; Ensure that nested is.constants fold.
define i32 @test_nested() #0 {
; CHECK-LABEL: @test_nested(
; CHECK-NOT: llvm.is.constant
; CHECK: ret i32 13
%val1 = call i1 @llvm.is.constant.i32(i32 27)
%val2 = zext i1 %val1 to i32
%val3 = add i32 %val2, 12
%1 = call i1 @llvm.is.constant.i32(i32 %val3)
%2 = zext i1 %1 to i32
%3 = add i32 %2, 12
ret i32 %3
}
@G = global [2 x i64] zeroinitializer
define i1 @test_global() #0 {
; CHECK-LABEL: @test_global(
; CHECK: llvm.is.constant
%ret = call i1 @llvm.is.constant.p0i64(i64* getelementptr ([2 x i64], [2 x i64]* @G, i32 0, i32 0))
ret i1 %ret
}
define i1 @test_diff() #0 {
; CHECK-LABEL: @test_diff(
%ret = call i1 @llvm.is.constant.i64(i64 sub (
i64 ptrtoint (i64* getelementptr inbounds ([2 x i64], [2 x i64]* @G, i64 0, i64 1) to i64),
i64 ptrtoint ([2 x i64]* @G to i64)))
ret i1 %ret
}
define i1 @test_various_types(i256 %int, float %float, <2 x i64> %vec, {i32, i32} %struct, [2 x i64] %arr, i64* %ptr) #0 {
; CHECK-LABEL: @test_various_types(
; CHECK: llvm.is.constant
; CHECK: llvm.is.constant
; CHECK: llvm.is.constant
; CHECK: llvm.is.constant
; CHECK: llvm.is.constant
; CHECK: llvm.is.constant
; CHECK-NOT: llvm.is.constant
%v1 = call i1 @llvm.is.constant.i256(i256 %int)
%v2 = call i1 @llvm.is.constant.f32(float %float)
%v3 = call i1 @llvm.is.constant.v2i64(<2 x i64> %vec)
%v4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} %struct)
%v5 = call i1 @llvm.is.constant.a2i64([2 x i64] %arr)
%v6 = call i1 @llvm.is.constant.p0i64(i64* %ptr)
%c1 = call i1 @llvm.is.constant.i256(i256 -1)
%c2 = call i1 @llvm.is.constant.f32(float 17.0)
%c3 = call i1 @llvm.is.constant.v2i64(<2 x i64> <i64 -1, i64 44>)
%c4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} {i32 -1, i32 32})
%c5 = call i1 @llvm.is.constant.a2i64([2 x i64] [i64 -1, i64 32])
%c6 = call i1 @llvm.is.constant.p0i64(i64* inttoptr (i32 42 to i64*))
%x1 = add i1 %v1, %c1
%x2 = add i1 %v2, %c2
%x3 = add i1 %v3, %c3
%x4 = add i1 %v4, %c4
%x5 = add i1 %v5, %c5
%x6 = add i1 %v6, %c6
%res2 = add i1 %x1, %x2
%res3 = add i1 %res2, %x3
%res4 = add i1 %res3, %x4
%res5 = add i1 %res4, %x5
%res6 = add i1 %res5, %x6
ret i1 %res6
}
define i1 @test_various_types2() #0 {
; CHECK-LABEL: @test_various_types2(
; CHECK: ret i1 false
%r = call i1 @test_various_types(i256 -1, float 22.0, <2 x i64> <i64 -1, i64 44>,
{i32, i32} {i32 -1, i32 55}, [2 x i64] [i64 -1, i64 55],
i64* inttoptr (i64 42 to i64*))
ret i1 %r
}
attributes #0 = { nounwind uwtable }

View File

@ -24,7 +24,6 @@
; CHECK-NEXT: Module Verifier
; CHECK-NEXT: Lower Garbage Collection Instructions
; CHECK-NEXT: Shadow Stack GC Lowering
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Remove unreachable blocks from the CFG
; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; CHECK-NEXT: Scalarize Masked Memory Intrinsics

View File

@ -35,7 +35,6 @@
; CHECK-NEXT: Expand memcmp() to load/stores
; CHECK-NEXT: Lower Garbage Collection Instructions
; CHECK-NEXT: Shadow Stack GC Lowering
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Remove unreachable blocks from the CFG
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Natural Loop Information

View File

@ -0,0 +1,50 @@
; RUN: llc -O2 < %s | FileCheck %s --check-prefix=CHECK-O2 --check-prefix=CHECK
; RUN: llc -O0 -fast-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK
; RUN: llc -O0 -fast-isel=0 < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK
; RUN: llc -O0 -global-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK
;; Ensure that an unfoldable is.constant gets lowered reasonably in
;; optimized codegen, in particular, that the "true" branch is
;; eliminated.
;;
;; This isn't asserting any specific output from non-optimized runs,
;; (e.g., currently the not-taken branch does not get eliminated). But
;; it does ensure that lowering succeeds in all 3 codegen paths.
target triple = "x86_64-unknown-linux-gnu"
declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone
declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone
declare i32 @subfun_1()
declare i32 @subfun_2()
define i32 @test_branch(i32 %in) nounwind {
; CHECK-LABEL: test_branch:
; CHECK-O2: %bb.0:
; CHECK-O2-NEXT: jmp subfun_2
%v = call i1 @llvm.is.constant.i32(i32 %in)
br i1 %v, label %True, label %False
True:
%call1 = tail call i32 @subfun_1()
ret i32 %call1
False:
%call2 = tail call i32 @subfun_2()
ret i32 %call2
}
;; llvm.objectsize is another tricky case which gets folded to -1 very
;; late in the game. We'd like to ensure that llvm.is.constant of
;; llvm.objectsize is true.
define i1 @test_objectsize(i8* %obj) nounwind {
; CHECK-LABEL: test_objectsize:
; CHECK-O2: %bb.0:
; CHECK-O2: movb $1, %al
; CHECK-O2-NEXT: retq
%os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false)
%v = call i1 @llvm.is.constant.i64(i64 %os)
ret i1 %v
}

View File

@ -0,0 +1,55 @@
; RUN: llc -O0 < %s | FileCheck %s
; ModuleID = 'ts.c'
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"
@p = common global i8* null, align 8 ; <i8**> [#uses=4]
@.str = private constant [3 x i8] c"Hi\00" ; <[3 x i8]*> [#uses=1]
define void @bar() nounwind ssp {
entry:
%tmp = load i8*, i8** @p ; <i8*> [#uses=1]
%0 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp, i1 0) ; <i64> [#uses=1]
%cmp = icmp ne i64 %0, -1 ; <i1> [#uses=1]
; CHECK: movq $-1, [[RAX:%r..]]
; CHECK: cmpq $-1, [[RAX]]
br i1 %cmp, label %cond.true, label %cond.false
cond.true: ; preds = %entry
%tmp1 = load i8*, i8** @p ; <i8*> [#uses=1]
%tmp2 = load i8*, i8** @p ; <i8*> [#uses=1]
%1 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 1) ; <i64> [#uses=1]
%call = call i8* @__strcpy_chk(i8* %tmp1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i64 %1) ssp ; <i8*> [#uses=1]
br label %cond.end
cond.false: ; preds = %entry
%tmp3 = load i8*, i8** @p ; <i8*> [#uses=1]
%call4 = call i8* @__inline_strcpy_chk(i8* %tmp3, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0)) ssp ; <i8*> [#uses=1]
br label %cond.end
cond.end: ; preds = %cond.false, %cond.true
%cond = phi i8* [ %call, %cond.true ], [ %call4, %cond.false ] ; <i8*> [#uses=0]
ret void
}
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readonly
declare i8* @__strcpy_chk(i8*, i8*, i64) ssp
define internal i8* @__inline_strcpy_chk(i8* %__dest, i8* %__src) nounwind ssp {
entry:
%retval = alloca i8* ; <i8**> [#uses=2]
%__dest.addr = alloca i8* ; <i8**> [#uses=3]
%__src.addr = alloca i8* ; <i8**> [#uses=2]
store i8* %__dest, i8** %__dest.addr
store i8* %__src, i8** %__src.addr
%tmp = load i8*, i8** %__dest.addr ; <i8*> [#uses=1]
%tmp1 = load i8*, i8** %__src.addr ; <i8*> [#uses=1]
%tmp2 = load i8*, i8** %__dest.addr ; <i8*> [#uses=1]
%0 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 1) ; <i64> [#uses=1]
%call = call i8* @__strcpy_chk(i8* %tmp, i8* %tmp1, i64 %0) ssp ; <i8*> [#uses=1]
store i8* %call, i8** %retval
%1 = load i8*, i8** %retval ; <i8*> [#uses=1]
ret i8* %1
}

View File

@ -231,7 +231,6 @@
; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
; CHECK-O-NEXT: Starting llvm::Function pass manager run.
; CHECK-O-NEXT: Running pass: Float2IntPass
; CHECK-O-NEXT: Running pass: LowerConstantIntrinsicsPass on foo
; CHECK-EP-VECTORIZER-START-NEXT: Running pass: NoOpFunctionPass
; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopRotatePass
; CHECK-O-NEXT: Starting llvm::Function pass manager run.

View File

@ -205,7 +205,6 @@
; CHECK-POSTLINK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
; CHECK-POSTLINK-O-NEXT: Starting llvm::Function pass manager run.
; CHECK-POSTLINK-O-NEXT: Running pass: Float2IntPass
; CHECK-POSTLINK-O-NEXT: Running pass: LowerConstantIntrinsicsPass
; CHECK-POSTLINK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopRotatePass
; CHECK-POSTLINK-O-NEXT: Starting llvm::Function pass manager run
; CHECK-POSTLINK-O-NEXT: Running pass: LoopSimplifyPass

View File

@ -187,8 +187,6 @@
; CHECK-NEXT: FunctionPass Manager
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Float to int
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Basic Alias Analysis (stateless AA impl)
; CHECK-NEXT: Function Alias Analysis Results
; CHECK-NEXT: Memory SSA

View File

@ -192,8 +192,6 @@
; CHECK-NEXT: FunctionPass Manager
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Float to int
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Basic Alias Analysis (stateless AA impl)
; CHECK-NEXT: Function Alias Analysis Results
; CHECK-NEXT: Memory SSA

View File

@ -174,8 +174,6 @@
; CHECK-NEXT: FunctionPass Manager
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Float to int
; CHECK-NEXT: Lower constant intrinsics
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Basic Alias Analysis (stateless AA impl)
; CHECK-NEXT: Function Alias Analysis Results
; CHECK-NEXT: Memory SSA

View File

@ -514,6 +514,26 @@ exit:
ret void
}
; This was crashing when trying to delay instruction removal/deletion.
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #0
define hidden fastcc void @crash() {
; CHECK-LABEL: @crash(
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 undef, i64 undef)
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
; CHECK-NEXT: [[T2:%.*]] = select i1 undef, i1 undef, i1 [[OV]]
; CHECK-NEXT: unreachable
;
%t0 = add i64 undef, undef
%t1 = icmp ult i64 %t0, undef
%t2 = select i1 undef, i1 undef, i1 %t1
%t3 = call i64 @llvm.objectsize.i64.p0i8(i8* nonnull undef, i1 false, i1 false, i1 false)
%t4 = icmp ugt i64 %t3, 7
unreachable
}
; Check that every instruction inserted by -codegenprepare has a debug location.
; DEBUG: CheckModuleDebugify: PASS

View File

@ -1,15 +1,12 @@
; RUN: opt -lower-constant-intrinsics -S < %s | FileCheck %s
; RUN: opt -codegenprepare -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"
target triple = "x86_64-apple-darwin10.0.0"
declare i64 @llvm.objectsize.i64(i8*, i1, i1, i1) nounwind readonly
declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
declare void @llvm.trap() nounwind
; CHECK-LABEL: @test1(
; objectsize should fold to a constant, which causes the branch to fold to an
; uncond branch.
; uncond branch. Next, we fold the control flow alltogether.
; rdar://8785296
define i32 @test1(i8* %ptr) nounwind ssp noredzone align 2 {
entry:
%0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false, i1 false, i1 false)
@ -17,7 +14,7 @@ entry:
br i1 %1, label %T, label %trap
; CHECK: entry:
; CHECK-NOT: label %trap
; CHECK-NOT: br label %
trap: ; preds = %0, %entry
tail call void @llvm.trap() noreturn nounwind
@ -81,3 +78,9 @@ entry:
i1 false, i1 false)
ret i64 %0
}
declare i64 @llvm.objectsize.i64(i8*, i1, i1, i1) nounwind readonly
declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
declare void @llvm.trap() nounwind

View File

@ -0,0 +1,123 @@
; RUN: opt -codegenprepare -S < %s | FileCheck %s
; Ensure we act sanely on overflow.
; CHECK-LABEL: define i32 @bar
define i32 @bar() {
entry:
; CHECK: ret i32 -1
%az = alloca [2147483649 x i32], align 16
%a = alloca i8*, align 8
%arraydecay = getelementptr inbounds [2147483649 x i32], [2147483649 x i32]* %az, i32 0, i32 0
%0 = bitcast i32* %arraydecay to i8*
store i8* %0, i8** %a, align 8
%1 = load i8*, i8** %a, align 8
%2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false)
ret i32 %2
}
; CHECK-LABEL: define i32 @baz
define i32 @baz(i32 %n) {
entry:
; CHECK: ret i32 -1
%az = alloca [1 x i32], align 16
%bz = alloca [4294967297 x i32], align 16
%tobool = icmp ne i32 %n, 0
%arraydecay = getelementptr inbounds [1 x i32], [1 x i32]* %az, i64 0, i64 0
%arraydecay1 = getelementptr inbounds [4294967297 x i32], [4294967297 x i32]* %bz, i64 0, i64 0
%cond = select i1 %tobool, i32* %arraydecay, i32* %arraydecay1
%0 = bitcast i32* %cond to i8*
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false)
ret i32 %1
}
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1)
; The following tests were generated by:
; #include<stdlib.h>
; #define STATIC_BUF_SIZE 10
; #define LARGER_BUF_SIZE 30
;
; size_t foo1(int flag) {
; char *cptr;
; char chararray[LARGER_BUF_SIZE];
; char chararray2[STATIC_BUF_SIZE];
; if(flag)
; cptr = chararray2;
; else
; cptr = chararray;
;
; return __builtin_object_size(cptr, 2);
; }
;
; size_t foo2(int n) {
; char Small[10];
; char Large[20];
; char *Ptr = n ? Small : Large + 19;
; return __builtin_object_size(Ptr, 0);
; }
;
; void foo() {
; size_t ret;
; size_t ret1;
; ret = foo1(0);
; ret1 = foo2(0);
; printf("\n%d %d\n", ret, ret1);
; }
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@.str = private unnamed_addr constant [8 x i8] c"\0A%d %d\0A\00", align 1
define i64 @foo1(i32 %flag) {
entry:
%chararray = alloca [30 x i8], align 16
%chararray2 = alloca [10 x i8], align 1
%0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64 0, i64 0
call void @llvm.lifetime.start.p0i8(i64 30, i8* %0)
%1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64 0, i64 0
call void @llvm.lifetime.start.p0i8(i64 10, i8* %1)
%tobool = icmp eq i32 %flag, 0
%cptr.0 = select i1 %tobool, i8* %0, i8* %1
%2 = call i64 @llvm.objectsize.i64.p0i8(i8* %cptr.0, i1 true)
call void @llvm.lifetime.end.p0i8(i64 10, i8* %1)
call void @llvm.lifetime.end.p0i8(i64 30, i8* %0)
ret i64 %2
; CHECK-LABEL: foo1
; CHECK: ret i64 10
}
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1)
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
define i64 @foo2(i32 %n) {
entry:
%Small = alloca [10 x i8], align 1
%Large = alloca [20 x i8], align 16
%0 = getelementptr inbounds [10 x i8], [10 x i8]* %Small, i64 0, i64 0
call void @llvm.lifetime.start.p0i8(i64 10, i8* %0)
%1 = getelementptr inbounds [20 x i8], [20 x i8]* %Large, i64 0, i64 0
call void @llvm.lifetime.start.p0i8(i64 20, i8* %1)
%tobool = icmp ne i32 %n, 0
%add.ptr = getelementptr inbounds [20 x i8], [20 x i8]* %Large, i64 0, i64 19
%cond = select i1 %tobool, i8* %0, i8* %add.ptr
%2 = call i64 @llvm.objectsize.i64.p0i8(i8* %cond, i1 false)
call void @llvm.lifetime.end.p0i8(i64 20, i8* %1)
call void @llvm.lifetime.end.p0i8(i64 10, i8* %0)
ret i64 %2
; CHECK-LABEL: foo2
; CHECK: ret i64 10
}
define void @foo() {
entry:
%call = tail call i64 @foo1(i32 0)
%call1 = tail call i64 @foo2(i32 0)
%call2 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i64 %call, i64 %call1)
ret void
}
declare i32 @printf(i8* nocapture readonly, ...)

View File

@ -1,4 +1,4 @@
; RUN: opt -S -lower-constant-intrinsics %s -o - | FileCheck %s
; RUN: opt -S -codegenprepare %s -o - | FileCheck %s
;
; Ensure that we don't {crash,return a bad value} when given an alloca larger
; than what a pointer can represent.

View File

@ -1,114 +0,0 @@
; RUN: opt -lower-constant-intrinsics -S < %s | FileCheck %s
;; Ensure that an unfoldable is.constant gets lowered reasonably in
;; optimized codegen, in particular, that the "true" branch is
;; eliminated.
;; Also ensure that any unfoldable objectsize is resolved in order.
;; CHECK-NOT: tail call i32 @subfun_1()
;; CHECK: tail call i32 @subfun_2()
;; CHECK-NOT: tail call i32 @subfun_1()
declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone
declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone
declare i1 @llvm.is.constant.i256(i256 %a) nounwind readnone
declare i1 @llvm.is.constant.v2i64(<2 x i64> %a) nounwind readnone
declare i1 @llvm.is.constant.f32(float %a) nounwind readnone
declare i1 @llvm.is.constant.sl_i32i32s({i32, i32} %a) nounwind readnone
declare i1 @llvm.is.constant.a2i64([2 x i64] %a) nounwind readnone
declare i1 @llvm.is.constant.p0i64(i64* %a) nounwind readnone
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone
declare i32 @subfun_1()
declare i32 @subfun_2()
define i32 @test_branch(i32 %in) nounwind {
%v = call i1 @llvm.is.constant.i32(i32 %in)
br i1 %v, label %True, label %False
True:
%call1 = tail call i32 @subfun_1()
ret i32 %call1
False:
%call2 = tail call i32 @subfun_2()
ret i32 %call2
}
;; llvm.objectsize is another tricky case which gets folded to -1 very
;; late in the game. We'd like to ensure that llvm.is.constant of
;; llvm.objectsize is true.
define i1 @test_objectsize(i8* %obj) nounwind {
;; CHECK-LABEL: test_objectsize
;; CHECK-NOT: llvm.objectsize
;; CHECK-NOT: llvm.is.constant
;; CHECK: ret i1 true
%os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false)
%os1 = add i64 %os, 1
%v = call i1 @llvm.is.constant.i64(i64 %os1)
ret i1 %v
}
@test_phi_a = dso_local global i32 0, align 4
declare dso_local i32 @test_phi_b(...)
; Function Attrs: nounwind uwtable
define dso_local i32 @test_phi() {
entry:
%0 = load i32, i32* @test_phi_a, align 4
%1 = tail call i1 @llvm.is.constant.i32(i32 %0)
br i1 %1, label %cond.end, label %cond.false
cond.false: ; preds = %entry
%call = tail call i32 bitcast (i32 (...)* @test_phi_b to i32 ()*)() #3
%.pre = load i32, i32* @test_phi_a, align 4
br label %cond.end
cond.end: ; preds = %entry, %cond.false
%2 = phi i32 [ %.pre, %cond.false ], [ %0, %entry ]
%cond = phi i32 [ %call, %cond.false ], [ 1, %entry ]
%cmp = icmp eq i32 %cond, %2
br i1 %cmp, label %cond.true1, label %cond.end4
cond.true1: ; preds = %cond.end
%call2 = tail call i32 bitcast (i32 (...)* @test_phi_b to i32 ()*)() #3
br label %cond.end4
cond.end4: ; preds = %cond.end, %cond.true1
ret i32 undef
}
define i1 @test_various_types(i256 %int, float %float, <2 x i64> %vec, {i32, i32} %struct, [2 x i64] %arr, i64* %ptr) #0 {
; CHECK-LABEL: @test_various_types(
; CHECK-NOT: llvm.is.constant
%v1 = call i1 @llvm.is.constant.i256(i256 %int)
%v2 = call i1 @llvm.is.constant.f32(float %float)
%v3 = call i1 @llvm.is.constant.v2i64(<2 x i64> %vec)
%v4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} %struct)
%v5 = call i1 @llvm.is.constant.a2i64([2 x i64] %arr)
%v6 = call i1 @llvm.is.constant.p0i64(i64* %ptr)
%c1 = call i1 @llvm.is.constant.i256(i256 -1)
%c2 = call i1 @llvm.is.constant.f32(float 17.0)
%c3 = call i1 @llvm.is.constant.v2i64(<2 x i64> <i64 -1, i64 44>)
%c4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} {i32 -1, i32 32})
%c5 = call i1 @llvm.is.constant.a2i64([2 x i64] [i64 -1, i64 32])
%c6 = call i1 @llvm.is.constant.p0i64(i64* inttoptr (i32 42 to i64*))
%x1 = add i1 %v1, %c1
%x2 = add i1 %v2, %c2
%x3 = add i1 %v3, %c3
%x4 = add i1 %v4, %c4
%x5 = add i1 %v5, %c5
%x6 = add i1 %v6, %c6
%res2 = add i1 %x1, %x2
%res3 = add i1 %res2, %x3
%res4 = add i1 %res3, %x4
%res5 = add i1 %res4, %x5
%res6 = add i1 %res5, %x6
ret i1 %res6
}

View File

@ -57,7 +57,6 @@ static_library("Scalar") {
"LowerAtomic.cpp",
"LowerExpectIntrinsic.cpp",
"LowerGuardIntrinsic.cpp",
"LowerConstantIntrinsics.cpp",
"LowerWidenableCondition.cpp",
"MakeGuardsExplicit.cpp",
"MemCpyOptimizer.cpp",