llvm.org GIT mirror llvm / 3125e35
Add support for llvm.is.constant intrinsic (PR4898) This adds the llvm-side support for post-inlining evaluation of the __builtin_constant_p GCC intrinsic. Also fixed SCCPSolver::visitCallSite to not blow up when seeing a call to a function where canConstantFoldTo returns true, and one of the arguments is a struct. Updated from patch initially by Janusz Sobczak. Differential Revision: https://reviews.llvm.org/D4276 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346322 91177308-0d34-0410-b5e6-96231b3b80d8 James Y Knight 11 months ago
12 changed file(s) with 301 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
1541615416 This intrinsic actually does nothing, but optimizers must assume that it
1541715417 has externally observable side effects.
1541815418
15419 '``llvm.is.constant.*``' Intrinsic
15420 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15421
15422 Syntax:
15423 """""""
15424
15425 This is an overloaded intrinsic. You can use llvm.is.constant with any argument type.
15426
15427 ::
15428
15429 declare i1 @llvm.is.constant.i32(i32 %operand) nounwind readnone
15430 declare i1 @llvm.is.constant.f32(float %operand) nounwind readnone
15431 declare i1 @llvm.is.constant.TYPENAME(TYPE %operand) nounwind readnone
15432
15433 Overview:
15434 """""""""
15435
15436 The '``llvm.is.constant``' intrinsic will return true if the argument
15437 is known to be a manifest compile-time constant. It is guaranteed to
15438 fold to either true or false before generating machine code.
15439
15440 Semantics:
15441 """"""""""
15442
15443 This intrinsic generates no code. If its argument is known to be a
15444 manifest compile-time constant value, then the intrinsic will be
15445 converted to a constant true value. Otherwise, it will be converted to
15446 a constant false value.
15447
15448 In particular, note that if the argument is a constant expression
15449 which refers to a global (the address of which _is_ a constant, but
15450 not manifest during the compile), then the intrinsic evaluates to
15451 false.
15452
15453 The result also intentionally depends on the result of optimization
15454 passes -- e.g., the result can change depending on whether a
15455 function gets inlined or not. A function's parameters are
15456 obviously not constant. However, a call like
15457 ``llvm.is.constant.i32(i32 %param)`` *can* return true after the
15458 function is inlined, if the value passed to the function parameter was
15459 a constant.
15460
15461 On the other hand, if constant folding is not run, it will never
15462 evaluate to true, even in simple cases.
15463
1541915464 Stack Map Intrinsics
1542015465 --------------------
1542115466
159159 case Intrinsic::invariant_end:
160160 case Intrinsic::launder_invariant_group:
161161 case Intrinsic::strip_invariant_group:
162 case Intrinsic::is_constant:
162163 case Intrinsic::lifetime_start:
163164 case Intrinsic::lifetime_end:
164165 case Intrinsic::objectsize:
898898 // maps to void __clear_cache() on supporting platforms
899899 def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
900900 [], "llvm.clear_cache">;
901
902 // Intrinsic to detect whether its argument is a constant.
903 def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem], "llvm.is.constant">;
904
901905
902906 //===-------------------------- Masked Intrinsics -------------------------===//
903907 //
14251425 case Intrinsic::x86_avx512_vcvtsd2usi64:
14261426 case Intrinsic::x86_avx512_cvttsd2usi:
14271427 case Intrinsic::x86_avx512_cvttsd2usi64:
1428 case Intrinsic::is_constant:
14281429 return true;
14291430 default:
14301431 return false;
15991600 return APF.convertToDouble();
16001601 }
16011602
1603 static bool isManifestConstant(const Constant *c) {
1604 if (isa(c)) {
1605 return true;
1606 } else if (isa(c) || isa(c)) {
1607 for (const Value *subc : c->operand_values()) {
1608 if (!isManifestConstant(cast(subc)))
1609 return false;
1610 }
1611 return true;
1612 }
1613 return false;
1614 }
1615
16021616 Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
16031617 ArrayRef Operands,
16041618 const TargetLibraryInfo *TLI,
16051619 ImmutableCallSite CS) {
16061620 if (Operands.size() == 1) {
1621 if (IntrinsicID == Intrinsic::is_constant) {
1622 // We know we have a "Constant" argument. But we want to only
1623 // return true for manifest constants, not those that depend on
1624 // constants with unknowable values, e.g. GlobalValue or BlockAddress.
1625 if (isManifestConstant(Operands[0]))
1626 return ConstantInt::getTrue(Ty->getContext());
1627 return nullptr;
1628 }
16071629 if (isa(Operands[0])) {
16081630 // cosine(arg) is between -1 and 1. cosine(invalid arg) is NaN
16091631 if (IntrinsicID == Intrinsic::cos)
320320 }
321321
322322 private:
323 template
324 void resetIteratorIfInvalidatedWhileCalling(BasicBlock *BB, F f) {
325 // Substituting can cause recursive simplifications, which can invalidate
326 // our iterator. Use a WeakTrackingVH to hold onto it in case this
327 // happens.
328 Value *CurValue = &*CurInstIterator;
329 WeakTrackingVH IterHandle(CurValue);
330
331 f();
332
333 // If the iterator instruction was recursively deleted, start over at the
334 // start of the block.
335 if (IterHandle != CurValue) {
336 CurInstIterator = BB->begin();
337 SunkAddrs.clear();
338 }
339 }
340
323341 bool eliminateFallThrough(Function &F);
324342 bool eliminateMostlyEmptyBlocks(Function &F);
325343 BasicBlock *findDestBlockOfMergeableEmptyBlock(BasicBlock *BB);
16891707 // Lower all uses of llvm.objectsize.*
16901708 ConstantInt *RetVal =
16911709 lowerObjectSizeCall(II, *DL, TLInfo, /*MustSucceed=*/true);
1692 // Substituting this can cause recursive simplifications, which can
1693 // invalidate our iterator. Use a WeakTrackingVH to hold onto it in case
1694 // this
1695 // happens.
1696 Value *CurValue = &*CurInstIterator;
1697 WeakTrackingVH IterHandle(CurValue);
1698
1699 replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1700
1701 // If the iterator instruction was recursively deleted, start over at the
1702 // start of the block.
1703 if (IterHandle != CurValue) {
1704 CurInstIterator = BB->begin();
1705 SunkAddrs.clear();
1706 }
1710
1711 resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
1712 replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1713 });
1714 return true;
1715 }
1716 case Intrinsic::is_constant: {
1717 // If is_constant hasn't folded away yet, lower it to false now.
1718 Constant *RetVal = ConstantInt::get(II->getType(), 0);
1719 resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
1720 replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1721 });
17071722 return true;
17081723 }
17091724 case Intrinsic::aarch64_stlxr:
946946 MIRBuilder.buildConstant(getOrCreateVReg(CI), Min->isZero() ? -1ULL : 0);
947947 return true;
948948 }
949 case Intrinsic::is_constant:
950 // If this wasn't constant-folded away by now, then it's not a
951 // constant.
952 MIRBuilder.buildConstant(getOrCreateVReg(CI), 0);
953 return true;
949954 case Intrinsic::stackguard:
950955 getStackGuard(getOrCreateVReg(CI), MIRBuilder);
951956 return true;
14491449 updateValueMap(II, ResultReg);
14501450 return true;
14511451 }
1452 case Intrinsic::is_constant: {
1453 Constant *ResCI = ConstantInt::get(II->getType(), 0);
1454 unsigned ResultReg = getRegForValue(ResCI);
1455 if (!ResultReg)
1456 return false;
1457 updateValueMap(II, ResultReg);
1458 return true;
1459 }
14521460 case Intrinsic::launder_invariant_group:
14531461 case Intrinsic::strip_invariant_group:
14541462 case Intrinsic::expect: {
58965896 setValue(&I, Res);
58975897 return nullptr;
58985898 }
5899
5900 case Intrinsic::is_constant:
5901 // If this wasn't constant-folded away by now, then it's not a
5902 // constant.
5903 setValue(&I, DAG.getConstant(0, sdl, MVT::i1));
5904 return nullptr;
5905
58995906 case Intrinsic::annotation:
59005907 case Intrinsic::ptr_annotation:
59015908 case Intrinsic::launder_invariant_group:
12291229 SmallVector Operands;
12301230 for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
12311231 AI != E; ++AI) {
1232 if (AI->get()->getType()->isStructTy())
1233 return markOverdefined(I); // Can't handle struct args.
12321234 LatticeVal State = getValueState(*AI);
12331235
12341236 if (State.isUnknown())
0 ; 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.a2i32([2 x i32] %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 i32] %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.a2i32([2 x i32] %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.a2i32([2 x i32] [i32 -1, i32 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 i32] [i32 -1, i32 55],
109 i64* inttoptr (i64 42 to i64*))
110 ret i1 %r
111 }
112
113 attributes #0 = { nounwind uwtable }
0 ; 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) 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)
47 %v = call i1 @llvm.is.constant.i64(i64 %os)
48 ret i1 %v
49 }
257257 }
258258
259259 declare i64 @llvm.ctpop.i64(i64)
260
261 ;;======================== test12
262 ;; Ensure that a struct as an arg to a potentially constant-foldable
263 ;; function does not crash SCCP (for now it'll just ignores it)
264
265 define i1 @test12() {
266 %c = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} {i32 -1, i32 32})
267 ret i1 %c
268 ; CHECK-LABEL: define i1 @test12
269 ; CHECK: ret i1 %c
270 }
271
272 declare i1 @llvm.is.constant.sl_i32i32s({i32, i32} %a)