llvm.org GIT mirror llvm / 732f95f
Reapply r374743 with a fix for the ocaml binding Add a pass to lower is.constant and objectsize intrinsics This pass lowers is.constant and objectsize intrinsics not simplified by earlier constant folding, i.e. if the object given is not constant or if not using the optimized pass chain. The result is recursively simplified and constant conditionals are pruned, so that dead blocks are removed even for -O0. This allows inline asm blocks with operand constraints to work all the time. The new pass replaces the existing lowering in the codegen-prepare pass and fallbacks in SDAG/GlobalISEL and FastISel. The latter now assert on the intrinsics. Differential Revision: https://reviews.llvm.org/D65280 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374784 91177308-0d34-0410-b5e6-96231b3b80d8 Joerg Sonnenberger 1 year, 1 month ago
41 changed file(s) with 494 addition(s) and 549 deletion(s). Raw diff Collapse all Expand all
113113 external add_lower_expect_intrinsic
114114 : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
115115 = "llvm_add_lower_expect_intrinsic"
116 external add_lower_constant_intrinsics
117 : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
118 = "llvm_add_lower_constant_intrinsics"
116119 external add_type_based_alias_analysis
117120 : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
118121 = "llvm_add_type_based_alias_analysis"
190190 : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
191191 = "llvm_add_lower_expect_intrinsic"
192192
193 (** See the [llvm::createLowerConstantIntrinsicsPass] function. *)
194 external add_lower_constant_intrinsics
195 : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
196 = "llvm_add_lower_constant_intrinsics"
197
193198 (** See the [llvm::createTypeBasedAliasAnalysisPass] function. *)
194199 external add_type_based_alias_analysis
195200 : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit
236236 }
237237
238238 /* [ unit */
239 CAMLprim value llvm_add_lower_constant_intrinsics(LLVMPassManagerRef PM) {
240 LLVMAddLowerConstantIntrinsicsPass(PM);
241 return Val_unit;
242 }
243
244 /* [ unit */
239245 CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) {
240246 LLVMAddTypeBasedAliasAnalysisPass(PM);
241247 return Val_unit;
242242 void initializeLoopVersioningLICMPass(PassRegistry&);
243243 void initializeLoopVersioningPassPass(PassRegistry&);
244244 void initializeLowerAtomicLegacyPassPass(PassRegistry&);
245 void initializeLowerConstantIntrinsicsPass(PassRegistry&);
245246 void initializeLowerEmuTLSPass(PassRegistry&);
246247 void initializeLowerExpectIntrinsicPass(PassRegistry&);
247248 void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&);
139139 (void) llvm::createLoopVersioningLICMPass();
140140 (void) llvm::createLoopIdiomPass();
141141 (void) llvm::createLoopRotatePass();
142 (void) llvm::createLowerConstantIntrinsicsPass();
142143 (void) llvm::createLowerExpectIntrinsicPass();
143144 (void) llvm::createLowerInvokePass();
144145 (void) llvm::createLowerSwitchPass();
0 //===- LowerConstantIntrinsics.h - Lower constant int. pass -*- C++ -*-========//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 /// \file
8 ///
9 /// The header file for the LowerConstantIntrinsics pass as used by the new pass
10 /// manager.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_TRANSFORMS_SCALAR_LOWERCONSTANTINTRINSICS_H
15 #define LLVM_TRANSFORMS_SCALAR_LOWERCONSTANTINTRINSICS_H
16
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/PassManager.h"
19
20 namespace llvm {
21
22 struct LowerConstantIntrinsicsPass :
23 PassInfoMixin {
24 public:
25 explicit LowerConstantIntrinsicsPass() {}
26
27 /// Run the pass over the function.
28 ///
29 /// This will lower all remaining 'objectsize' and 'is.constant'`
30 /// intrinsic calls in this function, even when the argument has no known
31 /// size or is not a constant respectively. The resulting constant is
32 /// propagated and conditional branches are resolved where possible.
33 /// This complements the Instruction Simplification and
34 /// Instruction Combination passes of the optimized pass chain.
35 PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
36 };
37
38 }
39
40 #endif
396396
397397 //===----------------------------------------------------------------------===//
398398 //
399 // LowerConstantIntrinsicss - Expand any remaining llvm.objectsize and
400 // llvm.is.constant intrinsic calls, even for the unknown cases.
401 //
402 FunctionPass *createLowerConstantIntrinsicsPass();
403
404 //===----------------------------------------------------------------------===//
405 //
399406 // PartiallyInlineLibCalls - Tries to inline the fast path of library
400407 // calls such as sqrt.
401408 //
146146 /** See llvm::createLowerExpectIntrinsicPass function */
147147 void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM);
148148
149 /** See llvm::createLowerConstantIntrinsicsPass function */
150 void LLVMAddLowerConstantIntrinsicsPass(LLVMPassManagerRef PM);
151
149152 /** See llvm::createTypeBasedAliasAnalysisPass function */
150153 void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM);
151154
18671867 });
18681868 return true;
18691869 }
1870 case Intrinsic::objectsize: {
1871 // Lower all uses of llvm.objectsize.*
1872 Value *RetVal =
1873 lowerObjectSizeCall(II, *DL, TLInfo, /*MustSucceed=*/true);
1874
1875 resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
1876 replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1877 });
1878 return true;
1879 }
1880 case Intrinsic::is_constant: {
1881 // If is_constant hasn't folded away yet, lower it to false now.
1882 Constant *RetVal = ConstantInt::get(II->getType(), 0);
1883 resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
1884 replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1885 });
1886 return true;
1887 }
1870 case Intrinsic::objectsize:
1871 llvm_unreachable("llvm.objectsize.* should have been lowered already");
1872 case Intrinsic::is_constant:
1873 llvm_unreachable("llvm.is.constant.* should have been lowered already");
18881874 case Intrinsic::aarch64_stlxr:
18891875 case Intrinsic::aarch64_stxr: {
18901876 ZExtInst *ExtVal = dyn_cast(CI->getArgOperand(0));
14361436 MIRBuilder.buildConstant(Reg, TypeID);
14371437 return true;
14381438 }
1439 case Intrinsic::objectsize: {
1440 // If we don't know by now, we're never going to know.
1441 const ConstantInt *Min = cast(CI.getArgOperand(1));
1442
1443 MIRBuilder.buildConstant(getOrCreateVReg(CI), Min->isZero() ? -1ULL : 0);
1444 return true;
1445 }
1439 case Intrinsic::objectsize:
1440 llvm_unreachable("llvm.objectsize.* should have been lowered already");
1441
14461442 case Intrinsic::is_constant:
1447 // If this wasn't constant-folded away by now, then it's not a
1448 // constant.
1449 MIRBuilder.buildConstant(getOrCreateVReg(CI), 0);
1450 return true;
1443 llvm_unreachable("llvm.is.constant.* should have been lowered already");
1444
14511445 case Intrinsic::stackguard:
14521446 getStackGuard(getOrCreateVReg(CI), MIRBuilder);
14531447 return true;
14531453 TII.get(TargetOpcode::DBG_LABEL)).addMetadata(DI->getLabel());
14541454 return true;
14551455 }
1456 case Intrinsic::objectsize: {
1457 ConstantInt *CI = cast(II->getArgOperand(1));
1458 unsigned long long Res = CI->isZero() ? -1ULL : 0;
1459 Constant *ResCI = ConstantInt::get(II->getType(), Res);
1460 unsigned ResultReg = getRegForValue(ResCI);
1461 if (!ResultReg)
1462 return false;
1463 updateValueMap(II, ResultReg);
1464 return true;
1465 }
1466 case Intrinsic::is_constant: {
1467 Constant *ResCI = ConstantInt::get(II->getType(), 0);
1468 unsigned ResultReg = getRegForValue(ResCI);
1469 if (!ResultReg)
1470 return false;
1471 updateValueMap(II, ResultReg);
1472 return true;
1473 }
1456 case Intrinsic::objectsize:
1457 llvm_unreachable("llvm.objectsize.* should have been lowered already");
1458
1459 case Intrinsic::is_constant:
1460 llvm_unreachable("llvm.is.constant.* should have been lowered already");
1461
14741462 case Intrinsic::launder_invariant_group:
14751463 case Intrinsic::strip_invariant_group:
14761464 case Intrinsic::expect: {
63876387 DAG.setRoot(Res);
63886388 return;
63896389 }
6390 case Intrinsic::objectsize: {
6391 // If we don't know by now, we're never going to know.
6392 ConstantInt *CI = dyn_cast(I.getArgOperand(1));
6393
6394 assert(CI && "Non-constant type in __builtin_object_size?");
6395
6396 SDValue Arg = getValue(I.getCalledValue());
6397 EVT Ty = Arg.getValueType();
6398
6399 if (CI->isZero())
6400 Res = DAG.getConstant(-1ULL, sdl, Ty);
6401 else
6402 Res = DAG.getConstant(0, sdl, Ty);
6403
6404 setValue(&I, Res);
6405 return;
6406 }
6390 case Intrinsic::objectsize:
6391 llvm_unreachable("llvm.objectsize.* should have been lowered already");
64076392
64086393 case Intrinsic::is_constant:
6409 // If this wasn't constant-folded away by now, then it's not a
6410 // constant.
6411 setValue(&I, DAG.getConstant(0, sdl, MVT::i1));
6412 return;
6394 llvm_unreachable("llvm.is.constant.* should have been lowered already");
64136395
64146396 case Intrinsic::annotation:
64156397 case Intrinsic::ptr_annotation:
656656 // TODO: add a pass insertion point here
657657 addPass(createGCLoweringPass());
658658 addPass(createShadowStackGCLoweringPass());
659 addPass(createLowerConstantIntrinsicsPass());
659660
660661 // Make sure that no unreachable blocks are instruction selected.
661662 addPass(createUnreachableBlockEliminationPass());
141141 #include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h"
142142 #include "llvm/Transforms/Scalar/LoopUnrollPass.h"
143143 #include "llvm/Transforms/Scalar/LowerAtomic.h"
144 #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
144145 #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
145146 #include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"
146147 #include "llvm/Transforms/Scalar/LowerWidenableCondition.h"
890891
891892 FunctionPassManager OptimizePM(DebugLogging);
892893 OptimizePM.addPass(Float2IntPass());
894 OptimizePM.addPass(LowerConstantIntrinsicsPass());
895
893896 // FIXME: We need to run some loop optimizations to re-rotate loops after
894897 // simplify-cfg and others undo their rotation.
895898
186186 FUNCTION_PASS("loweratomic", LowerAtomicPass())
187187 FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass())
188188 FUNCTION_PASS("lower-guard-intrinsic", LowerGuardIntrinsicPass())
189 FUNCTION_PASS("lower-constant-intrinsics", LowerConstantIntrinsicsPass())
189190 FUNCTION_PASS("lower-widenable-condition", LowerWidenableConditionPass())
190191 FUNCTION_PASS("guard-widening", GuardWideningPass())
191192 FUNCTION_PASS("gvn", GVN())
653653 MPM.add(createGlobalsAAWrapperPass());
654654
655655 MPM.add(createFloat2IntPass());
656 MPM.add(createLowerConstantIntrinsicsPass());
656657
657658 addExtensionsToPM(EP_VectorizerStart, MPM);
658659
4343 LoopUnswitch.cpp
4444 LoopVersioningLICM.cpp
4545 LowerAtomic.cpp
46 LowerConstantIntrinsics.cpp
4647 LowerExpectIntrinsic.cpp
4748 LowerGuardIntrinsic.cpp
4849 LowerWidenableCondition.cpp
0 //===- LowerConstantIntrinsics.cpp - Lower constant intrinsic calls -------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This pass lowers all remaining 'objectsize' 'is.constant' intrinsic calls
9 // and provides constant propagation and basic CFG cleanup on the result.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
14 #include "llvm/ADT/PostOrderIterator.h"
15 #include "llvm/ADT/Statistic.h"
16 #include "llvm/Analysis/InstructionSimplify.h"
17 #include "llvm/Analysis/MemoryBuiltins.h"
18 #include "llvm/Analysis/TargetLibraryInfo.h"
19 #include "llvm/IR/BasicBlock.h"
20 #include "llvm/IR/Constants.h"
21 #include "llvm/IR/Function.h"
22 #include "llvm/IR/Instructions.h"
23 #include "llvm/IR/IntrinsicInst.h"
24 #include "llvm/IR/Intrinsics.h"
25 #include "llvm/IR/PatternMatch.h"
26 #include "llvm/Pass.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Transforms/Scalar.h"
29 #include "llvm/Transforms/Utils/Local.h"
30
31 using namespace llvm;
32 using namespace llvm::PatternMatch;
33
34 #define DEBUG_TYPE "lower-is-constant-intrinsic"
35
36 STATISTIC(IsConstantIntrinsicsHandled,
37 "Number of 'is.constant' intrinsic calls handled");
38 STATISTIC(ObjectSizeIntrinsicsHandled,
39 "Number of 'objectsize' intrinsic calls handled");
40
41 static Value *lowerIsConstantIntrinsic(IntrinsicInst *II) {
42 Value *Op = II->getOperand(0);
43
44 return isa(Op) ? ConstantInt::getTrue(II->getType())
45 : ConstantInt::getFalse(II->getType());
46 }
47
48 static bool replaceConditionalBranchesOnConstant(Instruction *II,
49 Value *NewValue) {
50 bool HasDeadBlocks = false;
51 SmallSetVector Worklist;
52 replaceAndRecursivelySimplify(II, NewValue, nullptr, nullptr, nullptr,
53 &Worklist);
54 for (auto I : Worklist) {
55 BranchInst *BI = dyn_cast(I);
56 if (!BI)
57 continue;
58 if (BI->isUnconditional())
59 continue;
60
61 BasicBlock *Target, *Other;
62 if (match(BI->getOperand(0), m_Zero())) {
63 Target = BI->getSuccessor(1);
64 Other = BI->getSuccessor(0);
65 } else if (match(BI->getOperand(0), m_One())) {
66 Target = BI->getSuccessor(0);
67 Other = BI->getSuccessor(1);
68 } else {
69 Target = nullptr;
70 Other = nullptr;
71 }
72 if (Target && Target != Other) {
73 BasicBlock *Source = BI->getParent();
74 Other->removePredecessor(Source);
75 BI->eraseFromParent();
76 BranchInst::Create(Target, Source);
77 if (pred_begin(Other) == pred_end(Other))
78 HasDeadBlocks = true;
79 }
80 }
81 return HasDeadBlocks;
82 }
83
84 static bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo *TLI) {
85 bool HasDeadBlocks = false;
86 const auto &DL = F.getParent()->getDataLayout();
87 SmallVector Worklist;
88
89 ReversePostOrderTraversal RPOT(&F);
90 for (BasicBlock *BB : RPOT) {
91 for (Instruction &I: *BB) {
92 IntrinsicInst *II = dyn_cast(&I);
93 if (!II)
94 continue;
95 switch (II->getIntrinsicID()) {
96 default:
97 break;
98 case Intrinsic::is_constant:
99 case Intrinsic::objectsize:
100 Worklist.push_back(WeakTrackingVH(&I));
101 break;
102 }
103 }
104 }
105 for (WeakTrackingVH &VH: Worklist) {
106 // Items on the worklist can be mutated by earlier recursive replaces.
107 // This can remove the intrinsic as dead (VH == null), but also replace
108 // the intrinsic in place.
109 if (!VH)
110 continue;
111 IntrinsicInst *II = dyn_cast(&*VH);
112 if (!II)
113 continue;
114 Value *NewValue;
115 switch (II->getIntrinsicID()) {
116 default:
117 continue;
118 case Intrinsic::is_constant:
119 NewValue = lowerIsConstantIntrinsic(II);
120 IsConstantIntrinsicsHandled++;
121 break;
122 case Intrinsic::objectsize:
123 NewValue = lowerObjectSizeCall(II, DL, TLI, true);
124 ObjectSizeIntrinsicsHandled++;
125 break;
126 }
127 HasDeadBlocks |= replaceConditionalBranchesOnConstant(II, NewValue);
128 }
129 if (HasDeadBlocks)
130 removeUnreachableBlocks(F);
131 return !Worklist.empty();
132 }
133
134 PreservedAnalyses
135 LowerConstantIntrinsicsPass::run(Function &F, FunctionAnalysisManager &AM) {
136 if (lowerConstantIntrinsics(F, AM.getCachedResult(F)))
137 return PreservedAnalyses::none();
138
139 return PreservedAnalyses::all();
140 }
141
142 namespace {
143 /// Legacy pass for lowering is.constant intrinsics out of the IR.
144 ///
145 /// When this pass is run over a function it converts is.constant intrinsics
146 /// into 'true' or 'false'. This is completements the normal constand folding
147 /// to 'true' as part of Instruction Simplify passes.
148 class LowerConstantIntrinsics : public FunctionPass {
149 public:
150 static char ID;
151 LowerConstantIntrinsics() : FunctionPass(ID) {
152 initializeLowerConstantIntrinsicsPass(*PassRegistry::getPassRegistry());
153 }
154
155 bool runOnFunction(Function &F) override {
156 auto *TLIP = getAnalysisIfAvailable();
157 const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI(F) : nullptr;
158 return lowerConstantIntrinsics(F, TLI);
159 }
160 };
161 } // namespace
162
163 char LowerConstantIntrinsics::ID = 0;
164 INITIALIZE_PASS(LowerConstantIntrinsics, "lower-constant-intrinsics",
165 "Lower constant intrinsics", false, false)
166
167 FunctionPass *llvm::createLowerConstantIntrinsicsPass() {
168 return new LowerConstantIntrinsics();
169 }
7878 initializeLoopVersioningLICMPass(Registry);
7979 initializeLoopIdiomRecognizeLegacyPassPass(Registry);
8080 initializeLowerAtomicLegacyPassPass(Registry);
81 initializeLowerConstantIntrinsicsPass(Registry);
8182 initializeLowerExpectIntrinsicPass(Registry);
8283 initializeLowerGuardIntrinsicLegacyPassPass(Registry);
8384 initializeLowerWidenableConditionLegacyPassPass(Registry);
283284 unwrap(PM)->add(createBasicAAWrapperPass());
284285 }
285286
287 void LLVMAddLowerConstantIntrinsicsPass(LLVMPassManagerRef PM) {
288 unwrap(PM)->add(createLowerConstantIntrinsicsPass());
289 }
290
286291 void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM) {
287292 unwrap(PM)->add(createLowerExpectIntrinsicPass());
288293 }
11791179 ; CHECK: [[SIZE:%[0-9]+]]:_(s64) = COPY $x2
11801180 ; CHECK: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.memset), [[DST]](p0), [[SRC]](s8), [[SIZE]](s64), 0 :: (store 1 into %ir.dst)
11811181 call void @llvm.memset.p0i8.i64(i8* %dst, i8 %val, i64 %size, i1 0)
1182 ret void
1183 }
1184
1185 declare i64 @llvm.objectsize.i64(i8*, i1)
1186 declare i32 @llvm.objectsize.i32(i8*, i1)
1187 define void @test_objectsize(i8* %addr0, i8* %addr1) {
1188 ; CHECK-LABEL: name: test_objectsize
1189 ; CHECK: [[ADDR0:%[0-9]+]]:_(p0) = COPY $x0
1190 ; CHECK: [[ADDR1:%[0-9]+]]:_(p0) = COPY $x1
1191 ; CHECK: {{%[0-9]+}}:_(s64) = G_CONSTANT i64 -1
1192 ; CHECK: {{%[0-9]+}}:_(s64) = G_CONSTANT i64 0
1193 ; CHECK: {{%[0-9]+}}:_(s32) = G_CONSTANT i32 -1
1194 ; CHECK: {{%[0-9]+}}:_(s32) = G_CONSTANT i32 0
1195 %size64.0 = call i64 @llvm.objectsize.i64(i8* %addr0, i1 0)
1196 %size64.intmin = call i64 @llvm.objectsize.i64(i8* %addr0, i1 1)
1197 %size32.0 = call i32 @llvm.objectsize.i32(i8* %addr0, i1 0)
1198 %size32.intmin = call i32 @llvm.objectsize.i32(i8* %addr0, i1 1)
11991182 ret void
12001183 }
12011184
2020 ; CHECK-NEXT: Module Verifier
2121 ; CHECK-NEXT: Lower Garbage Collection Instructions
2222 ; CHECK-NEXT: Shadow Stack GC Lowering
23 ; CHECK-NEXT: Lower constant intrinsics
2324 ; CHECK-NEXT: Remove unreachable blocks from the CFG
2425 ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
2526 ; CHECK-NEXT: Scalarize Masked Memory Intrinsics
3737 ; CHECK-NEXT: Expand memcmp() to load/stores
3838 ; CHECK-NEXT: Lower Garbage Collection Instructions
3939 ; CHECK-NEXT: Shadow Stack GC Lowering
40 ; CHECK-NEXT: Lower constant intrinsics
4041 ; CHECK-NEXT: Remove unreachable blocks from the CFG
4142 ; CHECK-NEXT: Dominator Tree Construction
4243 ; CHECK-NEXT: Natural Loop Information
2121 ; CHECK-NEXT: Expand memcmp() to load/stores
2222 ; CHECK-NEXT: Lower Garbage Collection Instructions
2323 ; CHECK-NEXT: Shadow Stack GC Lowering
24 ; CHECK-NEXT: Lower constant intrinsics
2425 ; CHECK-NEXT: Remove unreachable blocks from the CFG
2526 ; CHECK-NEXT: Dominator Tree Construction
2627 ; CHECK-NEXT: Natural Loop Information
+0
-114
test/CodeGen/Generic/is-constant.ll less more
None ; RUN: opt -O2 -S < %s | FileCheck %s
1 ; RUN: llc -o /dev/null 2>&1 < %s
2 ; RUN: llc -O0 -o /dev/null 2>&1 < %s
3
4 ;; The llc runs above are just to ensure it doesn't blow up upon
5 ;; seeing an is_constant intrinsic.
6
7 declare i1 @llvm.is.constant.i32(i32 %a)
8 declare i1 @llvm.is.constant.i64(i64 %a)
9 declare i1 @llvm.is.constant.i256(i256 %a)
10 declare i1 @llvm.is.constant.v2i64(<2 x i64> %a)
11 declare i1 @llvm.is.constant.f32(float %a)
12 declare i1 @llvm.is.constant.sl_i32i32s({i32, i32} %a)
13 declare i1 @llvm.is.constant.a2i64([2 x i64] %a)
14 declare i1 @llvm.is.constant.p0i64(i64* %a)
15
16 ;; Basic test that optimization folds away the is.constant when given
17 ;; a constant.
18 define i1 @test_constant() #0 {
19 ; CHECK-LABEL: @test_constant(
20 ; CHECK-NOT: llvm.is.constant
21 ; CHECK: ret i1 true
22 %y = call i1 @llvm.is.constant.i32(i32 44)
23 ret i1 %y
24 }
25
26 ;; And test that the intrinsic sticks around when given a
27 ;; non-constant.
28 define i1 @test_nonconstant(i32 %x) #0 {
29 ; CHECK-LABEL: @test_nonconstant(
30 ; CHECK: @llvm.is.constant
31 %y = call i1 @llvm.is.constant.i32(i32 %x)
32 ret i1 %y
33 }
34
35 ;; Ensure that nested is.constants fold.
36 define i32 @test_nested() #0 {
37 ; CHECK-LABEL: @test_nested(
38 ; CHECK-NOT: llvm.is.constant
39 ; CHECK: ret i32 13
40 %val1 = call i1 @llvm.is.constant.i32(i32 27)
41 %val2 = zext i1 %val1 to i32
42 %val3 = add i32 %val2, 12
43 %1 = call i1 @llvm.is.constant.i32(i32 %val3)
44 %2 = zext i1 %1 to i32
45 %3 = add i32 %2, 12
46 ret i32 %3
47 }
48
49 @G = global [2 x i64] zeroinitializer
50 define i1 @test_global() #0 {
51 ; CHECK-LABEL: @test_global(
52 ; CHECK: llvm.is.constant
53 %ret = call i1 @llvm.is.constant.p0i64(i64* getelementptr ([2 x i64], [2 x i64]* @G, i32 0, i32 0))
54 ret i1 %ret
55 }
56
57 define i1 @test_diff() #0 {
58 ; CHECK-LABEL: @test_diff(
59 %ret = call i1 @llvm.is.constant.i64(i64 sub (
60 i64 ptrtoint (i64* getelementptr inbounds ([2 x i64], [2 x i64]* @G, i64 0, i64 1) to i64),
61 i64 ptrtoint ([2 x i64]* @G to i64)))
62 ret i1 %ret
63 }
64
65 define i1 @test_various_types(i256 %int, float %float, <2 x i64> %vec, {i32, i32} %struct, [2 x i64] %arr, i64* %ptr) #0 {
66 ; CHECK-LABEL: @test_various_types(
67 ; CHECK: llvm.is.constant
68 ; CHECK: llvm.is.constant
69 ; CHECK: llvm.is.constant
70 ; CHECK: llvm.is.constant
71 ; CHECK: llvm.is.constant
72 ; CHECK: llvm.is.constant
73 ; CHECK-NOT: llvm.is.constant
74 %v1 = call i1 @llvm.is.constant.i256(i256 %int)
75 %v2 = call i1 @llvm.is.constant.f32(float %float)
76 %v3 = call i1 @llvm.is.constant.v2i64(<2 x i64> %vec)
77 %v4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} %struct)
78 %v5 = call i1 @llvm.is.constant.a2i64([2 x i64] %arr)
79 %v6 = call i1 @llvm.is.constant.p0i64(i64* %ptr)
80
81 %c1 = call i1 @llvm.is.constant.i256(i256 -1)
82 %c2 = call i1 @llvm.is.constant.f32(float 17.0)
83 %c3 = call i1 @llvm.is.constant.v2i64(<2 x i64> )
84 %c4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} {i32 -1, i32 32})
85 %c5 = call i1 @llvm.is.constant.a2i64([2 x i64] [i64 -1, i64 32])
86 %c6 = call i1 @llvm.is.constant.p0i64(i64* inttoptr (i32 42 to i64*))
87
88 %x1 = add i1 %v1, %c1
89 %x2 = add i1 %v2, %c2
90 %x3 = add i1 %v3, %c3
91 %x4 = add i1 %v4, %c4
92 %x5 = add i1 %v5, %c5
93 %x6 = add i1 %v6, %c6
94
95 %res2 = add i1 %x1, %x2
96 %res3 = add i1 %res2, %x3
97 %res4 = add i1 %res3, %x4
98 %res5 = add i1 %res4, %x5
99 %res6 = add i1 %res5, %x6
100
101 ret i1 %res6
102 }
103
104 define i1 @test_various_types2() #0 {
105 ; CHECK-LABEL: @test_various_types2(
106 ; CHECK: ret i1 false
107 %r = call i1 @test_various_types(i256 -1, float 22.0, <2 x i64> ,
108 {i32, i32} {i32 -1, i32 55}, [2 x i64] [i64 -1, i64 55],
109 i64* inttoptr (i64 42 to i64*))
110 ret i1 %r
111 }
112
113 attributes #0 = { nounwind uwtable }
2323 ; CHECK-NEXT: Module Verifier
2424 ; CHECK-NEXT: Lower Garbage Collection Instructions
2525 ; CHECK-NEXT: Shadow Stack GC Lowering
26 ; CHECK-NEXT: Lower constant intrinsics
2627 ; CHECK-NEXT: Remove unreachable blocks from the CFG
2728 ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
2829 ; CHECK-NEXT: Scalarize Masked Memory Intrinsics
3434 ; CHECK-NEXT: Expand memcmp() to load/stores
3535 ; CHECK-NEXT: Lower Garbage Collection Instructions
3636 ; CHECK-NEXT: Shadow Stack GC Lowering
37 ; CHECK-NEXT: Lower constant intrinsics
3738 ; CHECK-NEXT: Remove unreachable blocks from the CFG
3839 ; CHECK-NEXT: Dominator Tree Construction
3940 ; CHECK-NEXT: Natural Loop Information
+0
-50
test/CodeGen/X86/is-constant.ll less more
None ; RUN: llc -O2 < %s | FileCheck %s --check-prefix=CHECK-O2 --check-prefix=CHECK
1 ; RUN: llc -O0 -fast-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK
2 ; RUN: llc -O0 -fast-isel=0 < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK
3 ; RUN: llc -O0 -global-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK
4
5 ;; Ensure that an unfoldable is.constant gets lowered reasonably in
6 ;; optimized codegen, in particular, that the "true" branch is
7 ;; eliminated.
8 ;;
9 ;; This isn't asserting any specific output from non-optimized runs,
10 ;; (e.g., currently the not-taken branch does not get eliminated). But
11 ;; it does ensure that lowering succeeds in all 3 codegen paths.
12
13 target triple = "x86_64-unknown-linux-gnu"
14
15 declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone
16 declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone
17 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone
18
19 declare i32 @subfun_1()
20 declare i32 @subfun_2()
21
22 define i32 @test_branch(i32 %in) nounwind {
23 ; CHECK-LABEL: test_branch:
24 ; CHECK-O2: %bb.0:
25 ; CHECK-O2-NEXT: jmp subfun_2
26 %v = call i1 @llvm.is.constant.i32(i32 %in)
27 br i1 %v, label %True, label %False
28
29 True:
30 %call1 = tail call i32 @subfun_1()
31 ret i32 %call1
32
33 False:
34 %call2 = tail call i32 @subfun_2()
35 ret i32 %call2
36 }
37
38 ;; llvm.objectsize is another tricky case which gets folded to -1 very
39 ;; late in the game. We'd like to ensure that llvm.is.constant of
40 ;; llvm.objectsize is true.
41 define i1 @test_objectsize(i8* %obj) nounwind {
42 ; CHECK-LABEL: test_objectsize:
43 ; CHECK-O2: %bb.0:
44 ; CHECK-O2: movb $1, %al
45 ; CHECK-O2-NEXT: retq
46 %os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false)
47 %v = call i1 @llvm.is.constant.i64(i64 %os)
48 ret i1 %v
49 }
+0
-55
test/CodeGen/X86/object-size.ll less more
None ; RUN: llc -O0 < %s | FileCheck %s
1
2 ; ModuleID = 'ts.c'
3 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"
4 target triple = "x86_64-apple-darwin10.0"
5
6 @p = common global i8* null, align 8 ; [#uses=4]
7 @.str = private constant [3 x i8] c"Hi\00" ; <[3 x i8]*> [#uses=1]
8
9 define void @bar() nounwind ssp {
10 entry:
11 %tmp = load i8*, i8** @p ; [#uses=1]
12 %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp, i1 0) ; [#uses=1]
13 %cmp = icmp ne i64 %0, -1 ; [#uses=1]
14 ; CHECK: movq $-1, [[RAX:%r..]]
15 ; CHECK: cmpq $-1, [[RAX]]
16 br i1 %cmp, label %cond.true, label %cond.false
17
18 cond.true: ; preds = %entry
19 %tmp1 = load i8*, i8** @p ; [#uses=1]
20 %tmp2 = load i8*, i8** @p ; [#uses=1]
21 %1 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 1) ; [#uses=1]
22 %call = call i8* @__strcpy_chk(i8* %tmp1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i64 %1) ssp ; [#uses=1]
23 br label %cond.end
24
25 cond.false: ; preds = %entry
26 %tmp3 = load i8*, i8** @p ; [#uses=1]
27 %call4 = call i8* @__inline_strcpy_chk(i8* %tmp3, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0)) ssp ; [#uses=1]
28 br label %cond.end
29
30 cond.end: ; preds = %cond.false, %cond.true
31 %cond = phi i8* [ %call, %cond.true ], [ %call4, %cond.false ] ; [#uses=0]
32 ret void
33 }
34
35 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readonly
36
37 declare i8* @__strcpy_chk(i8*, i8*, i64) ssp
38
39 define internal i8* @__inline_strcpy_chk(i8* %__dest, i8* %__src) nounwind ssp {
40 entry:
41 %retval = alloca i8* ; [#uses=2]
42 %__dest.addr = alloca i8* ; [#uses=3]
43 %__src.addr = alloca i8* ; [#uses=2]
44 store i8* %__dest, i8** %__dest.addr
45 store i8* %__src, i8** %__src.addr
46 %tmp = load i8*, i8** %__dest.addr ; [#uses=1]
47 %tmp1 = load i8*, i8** %__src.addr ; [#uses=1]
48 %tmp2 = load i8*, i8** %__dest.addr ; [#uses=1]
49 %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 1) ; [#uses=1]
50 %call = call i8* @__strcpy_chk(i8* %tmp, i8* %tmp1, i64 %0) ssp ; [#uses=1]
51 store i8* %call, i8** %retval
52 %1 = load i8*, i8** %retval ; [#uses=1]
53 ret i8* %1
54 }
230230 ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
231231 ; CHECK-O-NEXT: Starting llvm::Function pass manager run.
232232 ; CHECK-O-NEXT: Running pass: Float2IntPass
233 ; CHECK-O-NEXT: Running pass: LowerConstantIntrinsicsPass on foo
233234 ; CHECK-EP-VECTORIZER-START-NEXT: Running pass: NoOpFunctionPass
234235 ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopRotatePass
235236 ; CHECK-O-NEXT: Starting llvm::Function pass manager run.
204204 ; CHECK-POSTLINK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
205205 ; CHECK-POSTLINK-O-NEXT: Starting llvm::Function pass manager run.
206206 ; CHECK-POSTLINK-O-NEXT: Running pass: Float2IntPass
207 ; CHECK-POSTLINK-O-NEXT: Running pass: LowerConstantIntrinsicsPass
207208 ; CHECK-POSTLINK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopRotatePass
208209 ; CHECK-POSTLINK-O-NEXT: Starting llvm::Function pass manager run
209210 ; CHECK-POSTLINK-O-NEXT: Running pass: LoopSimplifyPass
186186 ; CHECK-NEXT: FunctionPass Manager
187187 ; CHECK-NEXT: Dominator Tree Construction
188188 ; CHECK-NEXT: Float to int
189 ; CHECK-NEXT: Lower constant intrinsics
190 ; CHECK-NEXT: Dominator Tree Construction
189191 ; CHECK-NEXT: Basic Alias Analysis (stateless AA impl)
190192 ; CHECK-NEXT: Function Alias Analysis Results
191193 ; CHECK-NEXT: Memory SSA
191191 ; CHECK-NEXT: FunctionPass Manager
192192 ; CHECK-NEXT: Dominator Tree Construction
193193 ; CHECK-NEXT: Float to int
194 ; CHECK-NEXT: Lower constant intrinsics
195 ; CHECK-NEXT: Dominator Tree Construction
194196 ; CHECK-NEXT: Basic Alias Analysis (stateless AA impl)
195197 ; CHECK-NEXT: Function Alias Analysis Results
196198 ; CHECK-NEXT: Memory SSA
173173 ; CHECK-NEXT: FunctionPass Manager
174174 ; CHECK-NEXT: Dominator Tree Construction
175175 ; CHECK-NEXT: Float to int
176 ; CHECK-NEXT: Lower constant intrinsics
177 ; CHECK-NEXT: Dominator Tree Construction
176178 ; CHECK-NEXT: Basic Alias Analysis (stateless AA impl)
177179 ; CHECK-NEXT: Function Alias Analysis Results
178180 ; CHECK-NEXT: Memory SSA
513513 ret void
514514 }
515515
516 ; This was crashing when trying to delay instruction removal/deletion.
517
518 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #0
519
520 define hidden fastcc void @crash() {
521 ; CHECK-LABEL: @crash(
522 ; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 undef, i64 undef)
523 ; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
524 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
525 ; CHECK-NEXT: [[T2:%.*]] = select i1 undef, i1 undef, i1 [[OV]]
526 ; CHECK-NEXT: unreachable
527 ;
528 %t0 = add i64 undef, undef
529 %t1 = icmp ult i64 %t0, undef
530 %t2 = select i1 undef, i1 undef, i1 %t1
531 %t3 = call i64 @llvm.objectsize.i64.p0i8(i8* nonnull undef, i1 false, i1 false, i1 false)
532 %t4 = icmp ugt i64 %t3, 7
533 unreachable
534 }
535
536516 ; Check that every instruction inserted by -codegenprepare has a debug location.
537517 ; DEBUG: CheckModuleDebugify: PASS
538518
+0
-86
test/Transforms/CodeGenPrepare/basic.ll less more
None ; RUN: opt -codegenprepare -S < %s | FileCheck %s
1
2 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"
3 target triple = "x86_64-apple-darwin10.0.0"
4
5 ; CHECK-LABEL: @test1(
6 ; objectsize should fold to a constant, which causes the branch to fold to an
7 ; uncond branch. Next, we fold the control flow alltogether.
8 ; rdar://8785296
9 define i32 @test1(i8* %ptr) nounwind ssp noredzone align 2 {
10 entry:
11 %0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false, i1 false, i1 false)
12 %1 = icmp ugt i64 %0, 3
13 br i1 %1, label %T, label %trap
14
15 ; CHECK: entry:
16 ; CHECK-NOT: br label %
17
18 trap: ; preds = %0, %entry
19 tail call void @llvm.trap() noreturn nounwind
20 unreachable
21
22 T:
23 ; CHECK: ret i32 4
24 ret i32 4
25 }
26
27 ; CHECK-LABEL: @test_objectsize_null_flag(
28 define i64 @test_objectsize_null_flag(i8* %ptr) {
29 entry:
30 ; CHECK: ret i64 -1
31 %0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 false, i1 true, i1 false)
32 ret i64 %0
33 }
34
35 ; CHECK-LABEL: @test_objectsize_null_flag_min(
36 define i64 @test_objectsize_null_flag_min(i8* %ptr) {
37 entry:
38 ; CHECK: ret i64 0
39 %0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 true, i1 true, i1 false)
40 ret i64 %0
41 }
42
43 ; Test foldable null pointers because we evaluate them with non-exact modes in
44 ; CodeGenPrepare.
45 ; CHECK-LABEL: @test_objectsize_null_flag_noas0(
46 define i64 @test_objectsize_null_flag_noas0() {
47 entry:
48 ; CHECK: ret i64 -1
49 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false,
50 i1 true, i1 false)
51 ret i64 %0
52 }
53
54 ; CHECK-LABEL: @test_objectsize_null_flag_min_noas0(
55 define i64 @test_objectsize_null_flag_min_noas0() {
56 entry:
57 ; CHECK: ret i64 0
58 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true,
59 i1 true, i1 false)
60 ret i64 %0
61 }
62
63 ; CHECK-LABEL: @test_objectsize_null_known_flag_noas0
64 define i64 @test_objectsize_null_known_flag_noas0() {
65 entry:
66 ; CHECK: ret i64 -1
67 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false,
68 i1 false, i1 false)
69 ret i64 %0
70 }
71
72 ; CHECK-LABEL: @test_objectsize_null_known_flag_min_noas0
73 define i64 @test_objectsize_null_known_flag_min_noas0() {
74 entry:
75 ; CHECK: ret i64 0
76 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true,
77 i1 false, i1 false)
78 ret i64 %0
79 }
80
81
82 declare i64 @llvm.objectsize.i64(i8*, i1, i1, i1) nounwind readonly
83 declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
84
85 declare void @llvm.trap() nounwind
+0
-123
test/Transforms/CodeGenPrepare/builtin-condition.ll less more
None ; RUN: opt -codegenprepare -S < %s | FileCheck %s
1
2 ; Ensure we act sanely on overflow.
3 ; CHECK-LABEL: define i32 @bar
4 define i32 @bar() {
5 entry:
6 ; CHECK: ret i32 -1
7 %az = alloca [2147483649 x i32], align 16
8 %a = alloca i8*, align 8
9 %arraydecay = getelementptr inbounds [2147483649 x i32], [2147483649 x i32]* %az, i32 0, i32 0
10 %0 = bitcast i32* %arraydecay to i8*
11 store i8* %0, i8** %a, align 8
12 %1 = load i8*, i8** %a, align 8
13 %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false)
14 ret i32 %2
15 }
16
17 ; CHECK-LABEL: define i32 @baz
18 define i32 @baz(i32 %n) {
19 entry:
20 ; CHECK: ret i32 -1
21 %az = alloca [1 x i32], align 16
22 %bz = alloca [4294967297 x i32], align 16
23 %tobool = icmp ne i32 %n, 0
24 %arraydecay = getelementptr inbounds [1 x i32], [1 x i32]* %az, i64 0, i64 0
25 %arraydecay1 = getelementptr inbounds [4294967297 x i32], [4294967297 x i32]* %bz, i64 0, i64 0
26 %cond = select i1 %tobool, i32* %arraydecay, i32* %arraydecay1
27 %0 = bitcast i32* %cond to i8*
28 %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false)
29 ret i32 %1
30 }
31
32 declare i32 @llvm.objectsize.i32.p0i8(i8*, i1)
33
34 ; The following tests were generated by:
35 ; #include
36 ; #define STATIC_BUF_SIZE 10
37 ; #define LARGER_BUF_SIZE 30
38 ;
39 ; size_t foo1(int flag) {
40 ; char *cptr;
41 ; char chararray[LARGER_BUF_SIZE];
42 ; char chararray2[STATIC_BUF_SIZE];
43 ; if(flag)
44 ; cptr = chararray2;
45 ; else
46 ; cptr = chararray;
47 ;
48 ; return __builtin_object_size(cptr, 2);
49 ; }
50 ;
51 ; size_t foo2(int n) {
52 ; char Small[10];
53 ; char Large[20];
54 ; char *Ptr = n ? Small : Large + 19;
55 ; return __builtin_object_size(Ptr, 0);
56 ; }
57 ;
58 ; void foo() {
59 ; size_t ret;
60 ; size_t ret1;
61 ; ret = foo1(0);
62 ; ret1 = foo2(0);
63 ; printf("\n%d %d\n", ret, ret1);
64 ; }
65
66 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
67 target triple = "x86_64-unknown-linux-gnu"
68
69 @.str = private unnamed_addr constant [8 x i8] c"\0A%d %d\0A\00", align 1
70
71 define i64 @foo1(i32 %flag) {
72 entry:
73 %chararray = alloca [30 x i8], align 16
74 %chararray2 = alloca [10 x i8], align 1
75 %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64 0, i64 0
76 call void @llvm.lifetime.start.p0i8(i64 30, i8* %0)
77 %1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64 0, i64 0
78 call void @llvm.lifetime.start.p0i8(i64 10, i8* %1)
79 %tobool = icmp eq i32 %flag, 0
80 %cptr.0 = select i1 %tobool, i8* %0, i8* %1
81 %2 = call i64 @llvm.objectsize.i64.p0i8(i8* %cptr.0, i1 true)
82 call void @llvm.lifetime.end.p0i8(i64 10, i8* %1)
83 call void @llvm.lifetime.end.p0i8(i64 30, i8* %0)
84 ret i64 %2
85 ; CHECK-LABEL: foo1
86 ; CHECK: ret i64 10
87 }
88
89 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
90
91 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1)
92
93 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
94
95 define i64 @foo2(i32 %n) {
96 entry:
97 %Small = alloca [10 x i8], align 1
98 %Large = alloca [20 x i8], align 16
99 %0 = getelementptr inbounds [10 x i8], [10 x i8]* %Small, i64 0, i64 0
100 call void @llvm.lifetime.start.p0i8(i64 10, i8* %0)
101 %1 = getelementptr inbounds [20 x i8], [20 x i8]* %Large, i64 0, i64 0
102 call void @llvm.lifetime.start.p0i8(i64 20, i8* %1)
103 %tobool = icmp ne i32 %n, 0
104 %add.ptr = getelementptr inbounds [20 x i8], [20 x i8]* %Large, i64 0, i64 19
105 %cond = select i1 %tobool, i8* %0, i8* %add.ptr
106 %2 = call i64 @llvm.objectsize.i64.p0i8(i8* %cond, i1 false)
107 call void @llvm.lifetime.end.p0i8(i64 20, i8* %1)
108 call void @llvm.lifetime.end.p0i8(i64 10, i8* %0)
109 ret i64 %2
110 ; CHECK-LABEL: foo2
111 ; CHECK: ret i64 10
112 }
113
114 define void @foo() {
115 entry:
116 %call = tail call i64 @foo1(i32 0)
117 %call1 = tail call i64 @foo2(i32 0)
118 %call2 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i64 %call, i64 %call1)
119 ret void
120 }
121
122 declare i32 @printf(i8* nocapture readonly, ...)
+0
-16
test/Transforms/CodeGenPrepare/crash-on-large-allocas.ll less more
None ; RUN: opt -S -codegenprepare %s -o - | FileCheck %s
1 ;
2 ; Ensure that we don't {crash,return a bad value} when given an alloca larger
3 ; than what a pointer can represent.
4
5 target datalayout = "p:16:16"
6
7 ; CHECK-LABEL: @alloca_overflow_is_unknown(
8 define i16 @alloca_overflow_is_unknown() {
9 %i = alloca i8, i32 65537
10 %j = call i16 @llvm.objectsize.i16.p0i8(i8* %i, i1 false, i1 false, i1 false)
11 ; CHECK: ret i16 -1
12 ret i16 %j
13 }
14
15 declare i16 @llvm.objectsize.i16.p0i8(i8*, i1, i1, i1)
0 ; RUN: opt -lower-constant-intrinsics -S < %s | FileCheck %s
1
2 ;; Ensure that an unfoldable is.constant gets lowered reasonably in
3 ;; optimized codegen, in particular, that the "true" branch is
4 ;; eliminated.
5
6 ;; Also ensure that any unfoldable objectsize is resolved in order.
7
8 ;; CHECK-NOT: tail call i32 @subfun_1()
9 ;; CHECK: tail call i32 @subfun_2()
10 ;; CHECK-NOT: tail call i32 @subfun_1()
11
12 declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone
13 declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone
14 declare i1 @llvm.is.constant.i256(i256 %a) nounwind readnone
15 declare i1 @llvm.is.constant.v2i64(<2 x i64> %a) nounwind readnone
16 declare i1 @llvm.is.constant.f32(float %a) nounwind readnone
17 declare i1 @llvm.is.constant.sl_i32i32s({i32, i32} %a) nounwind readnone
18 declare i1 @llvm.is.constant.a2i64([2 x i64] %a) nounwind readnone
19 declare i1 @llvm.is.constant.p0i64(i64* %a) nounwind readnone
20
21 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone
22
23 declare i32 @subfun_1()
24 declare i32 @subfun_2()
25
26 define i32 @test_branch(i32 %in) nounwind {
27 %v = call i1 @llvm.is.constant.i32(i32 %in)
28 br i1 %v, label %True, label %False
29
30 True:
31 %call1 = tail call i32 @subfun_1()
32 ret i32 %call1
33
34 False:
35 %call2 = tail call i32 @subfun_2()
36 ret i32 %call2
37 }
38
39 ;; llvm.objectsize is another tricky case which gets folded to -1 very
40 ;; late in the game. We'd like to ensure that llvm.is.constant of
41 ;; llvm.objectsize is true.
42 define i1 @test_objectsize(i8* %obj) nounwind {
43 ;; CHECK-LABEL: test_objectsize
44 ;; CHECK-NOT: llvm.objectsize
45 ;; CHECK-NOT: llvm.is.constant
46 ;; CHECK: ret i1 true
47 %os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false)
48 %os1 = add i64 %os, 1
49 %v = call i1 @llvm.is.constant.i64(i64 %os1)
50 ret i1 %v
51 }
52
53 @test_phi_a = dso_local global i32 0, align 4
54 declare dso_local i32 @test_phi_b(...)
55
56 ; Function Attrs: nounwind uwtable
57 define dso_local i32 @test_phi() {
58 entry:
59 %0 = load i32, i32* @test_phi_a, align 4
60 %1 = tail call i1 @llvm.is.constant.i32(i32 %0)
61 br i1 %1, label %cond.end, label %cond.false
62
63 cond.false: ; preds = %entry
64 %call = tail call i32 bitcast (i32 (...)* @test_phi_b to i32 ()*)() #3
65 %.pre = load i32, i32* @test_phi_a, align 4
66 br label %cond.end
67
68 cond.end: ; preds = %entry, %cond.false
69 %2 = phi i32 [ %.pre, %cond.false ], [ %0, %entry ]
70 %cond = phi i32 [ %call, %cond.false ], [ 1, %entry ]
71 %cmp = icmp eq i32 %cond, %2
72 br i1 %cmp, label %cond.true1, label %cond.end4
73
74 cond.true1: ; preds = %cond.end
75 %call2 = tail call i32 bitcast (i32 (...)* @test_phi_b to i32 ()*)() #3
76 br label %cond.end4
77
78 cond.end4: ; preds = %cond.end, %cond.true1
79 ret i32 undef
80 }
81
82 define i1 @test_various_types(i256 %int, float %float, <2 x i64> %vec, {i32, i32} %struct, [2 x i64] %arr, i64* %ptr) #0 {
83 ; CHECK-LABEL: @test_various_types(
84 ; CHECK-NOT: llvm.is.constant
85 %v1 = call i1 @llvm.is.constant.i256(i256 %int)
86 %v2 = call i1 @llvm.is.constant.f32(float %float)
87 %v3 = call i1 @llvm.is.constant.v2i64(<2 x i64> %vec)
88 %v4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} %struct)
89 %v5 = call i1 @llvm.is.constant.a2i64([2 x i64] %arr)
90 %v6 = call i1 @llvm.is.constant.p0i64(i64* %ptr)
91
92 %c1 = call i1 @llvm.is.constant.i256(i256 -1)
93 %c2 = call i1 @llvm.is.constant.f32(float 17.0)
94 %c3 = call i1 @llvm.is.constant.v2i64(<2 x i64> )
95 %c4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} {i32 -1, i32 32})
96 %c5 = call i1 @llvm.is.constant.a2i64([2 x i64] [i64 -1, i64 32])
97 %c6 = call i1 @llvm.is.constant.p0i64(i64* inttoptr (i32 42 to i64*))
98
99 %x1 = add i1 %v1, %c1
100 %x2 = add i1 %v2, %c2
101 %x3 = add i1 %v3, %c3
102 %x4 = add i1 %v4, %c4
103 %x5 = add i1 %v5, %c5
104 %x6 = add i1 %v6, %c6
105
106 %res2 = add i1 %x1, %x2
107 %res3 = add i1 %res2, %x3
108 %res4 = add i1 %res3, %x4
109 %res5 = add i1 %res4, %x5
110 %res6 = add i1 %res5, %x6
111
112 ret i1 %res6
113 }
0 ; RUN: opt -S -lower-constant-intrinsics %s -o - | FileCheck %s
1 ;
2 ; Ensure that we don't {crash,return a bad value} when given an alloca larger
3 ; than what a pointer can represent.
4
5 target datalayout = "p:16:16"
6
7 ; CHECK-LABEL: @alloca_overflow_is_unknown(
8 define i16 @alloca_overflow_is_unknown() {
9 %i = alloca i8, i32 65537
10 %j = call i16 @llvm.objectsize.i16.p0i8(i8* %i, i1 false, i1 false, i1 false)
11 ; CHECK: ret i16 -1
12 ret i16 %j
13 }
14
15 declare i16 @llvm.objectsize.i16.p0i8(i8*, i1, i1, i1)
0 ; RUN: opt -lower-constant-intrinsics -S < %s | FileCheck %s
1
2 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"
3 target triple = "x86_64-apple-darwin10.0.0"
4
5 declare i64 @llvm.objectsize.i64(i8*, i1, i1, i1) nounwind readonly
6 declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
7 declare void @llvm.trap() nounwind
8
9 ; CHECK-LABEL: @test1(
10 ; objectsize should fold to a constant, which causes the branch to fold to an
11 ; uncond branch.
12 define i32 @test1(i8* %ptr) nounwind ssp noredzone align 2 {
13 entry:
14 %0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false, i1 false, i1 false)
15 %1 = icmp ugt i64 %0, 3
16 br i1 %1, label %T, label %trap
17
18 ; CHECK: entry:
19 ; CHECK-NOT: label %trap
20
21 trap: ; preds = %0, %entry
22 tail call void @llvm.trap() noreturn nounwind
23 unreachable
24
25 T:
26 ; CHECK: ret i32 4
27 ret i32 4
28 }
29
30 ; CHECK-LABEL: @test_objectsize_null_flag(
31 define i64 @test_objectsize_null_flag(i8* %ptr) {
32 entry:
33 ; CHECK: ret i64 -1
34 %0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 false, i1 true, i1 false)
35 ret i64 %0
36 }
37
38 ; CHECK-LABEL: @test_objectsize_null_flag_min(
39 define i64 @test_objectsize_null_flag_min(i8* %ptr) {
40 entry:
41 ; CHECK: ret i64 0
42 %0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 true, i1 true, i1 false)
43 ret i64 %0
44 }
45
46 ; Test foldable null pointers because we evaluate them with non-exact modes in
47 ; CodeGenPrepare.
48 ; CHECK-LABEL: @test_objectsize_null_flag_noas0(
49 define i64 @test_objectsize_null_flag_noas0() {
50 entry:
51 ; CHECK: ret i64 -1
52 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false,
53 i1 true, i1 false)
54 ret i64 %0
55 }
56
57 ; CHECK-LABEL: @test_objectsize_null_flag_min_noas0(
58 define i64 @test_objectsize_null_flag_min_noas0() {
59 entry:
60 ; CHECK: ret i64 0
61 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true,
62 i1 true, i1 false)
63 ret i64 %0
64 }
65
66 ; CHECK-LABEL: @test_objectsize_null_known_flag_noas0
67 define i64 @test_objectsize_null_known_flag_noas0() {
68 entry:
69 ; CHECK: ret i64 -1
70 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false,
71 i1 false, i1 false)
72 ret i64 %0
73 }
74
75 ; CHECK-LABEL: @test_objectsize_null_known_flag_min_noas0
76 define i64 @test_objectsize_null_known_flag_min_noas0() {
77 entry:
78 ; CHECK: ret i64 0
79 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true,
80 i1 false, i1 false)
81 ret i64 %0
82 }
5656 "LowerAtomic.cpp",
5757 "LowerExpectIntrinsic.cpp",
5858 "LowerGuardIntrinsic.cpp",
59 "LowerConstantIntrinsics.cpp",
5960 "LowerWidenableCondition.cpp",
6061 "MakeGuardsExplicit.cpp",
6162 "MemCpyOptimizer.cpp",