Skip to content

Commit e100f58

Browse files
committed
Add support for llvm.is.constant intrinsic (PR4898)
This adds llvm-side support for post-inline evaluation of the __builtin_constant_p GCC intrinsic. This patch is derived from jyknight's patch: https://reviews.llvm.org/D4276
1 parent b41c4e1 commit e100f58

File tree

9 files changed

+112
-14
lines changed

9 files changed

+112
-14
lines changed

docs/LangRef.rst

+45
Original file line numberDiff line numberDiff line change
@@ -15097,6 +15097,51 @@ Semantics:
1509715097
This intrinsic actually does nothing, but optimizers must assume that it
1509815098
has externally observable side effects.
1509915099

15100+
'``llvm.is.constant.*``' Intrinsic
15101+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15102+
15103+
Syntax:
15104+
"""""""
15105+
15106+
This is an overloaded intrinsic. You can use llvm.is.constant with any argument type.
15107+
15108+
::
15109+
15110+
declare i1 @llvm.is.constant.i32(i32 %operand) nounwind readnone
15111+
declare i1 @llvm.is.constant.f32(float %operand) nounwind readnone
15112+
declare i1 @llvm.is.constant.TYPENAME(TYPE %operand) nounwind readnone
15113+
15114+
Overview:
15115+
"""""""""
15116+
15117+
The '``llvm.is.constant``' intrinsic will return true if the argument
15118+
is known to be a manifest compile-time constant. It is guaranteed to
15119+
fold to either true or false before generating machine code.
15120+
15121+
Semantics:
15122+
""""""""""
15123+
15124+
This intrinsic generates no code. If its argument is known to be a
15125+
manifest compile-time constant value, then the intrinsic will be
15126+
converted to a constant true value. Otherwise, it will be converted to
15127+
a constant false value.
15128+
15129+
In particular, note that if the argument is a constant expression
15130+
which refers to a global (the address of which _is_ a constant, but
15131+
not manifest during the compile), then the intrinsic evaluates to
15132+
false.
15133+
15134+
The result also intentionally depends on the result of optimization
15135+
passes -- e.g., the result can change depending on whether a
15136+
function gets inlined or not. A function's parameters are
15137+
obviously not constant. However, a call like
15138+
``llvm.is.constant.i32(i32 %param)`` *can* return true after the
15139+
function is inlined, if the value passed to the function parameter was
15140+
a constant.
15141+
15142+
On the other hand, if constant folding is not run, it will never
15143+
evaluate to true, even in simple cases.
15144+
1510015145
Stack Map Intrinsics
1510115146
--------------------
1510215147

include/llvm/Analysis/TargetTransformInfoImpl.h

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class TargetTransformInfoImplBase {
176176
case Intrinsic::coro_suspend:
177177
case Intrinsic::coro_param:
178178
case Intrinsic::coro_subfn_addr:
179+
case Intrinsic::is_constant:
179180
// These intrinsics don't actually represent code after lowering.
180181
return TTI::TCC_Free;
181182
}

include/llvm/IR/Intrinsics.td

+5
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,11 @@ def int_convert_from_fp16 : Intrinsic<[llvm_anyfloat_ty], [llvm_i16_ty]>;
850850
def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
851851
[], "llvm.clear_cache">;
852852

853+
// Intrinsic to detect whether its argument is a constant.
854+
def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem],
855+
"llvm.is.constant">,
856+
GCCBuiltin<"__builtin_constant_p">;
857+
853858
//===-------------------------- Masked Intrinsics -------------------------===//
854859
//
855860
def int_masked_store : Intrinsic<[], [llvm_anyvector_ty,

lib/Analysis/ConstantFolding.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,7 @@ bool llvm::canConstantFoldCallTo(ImmutableCallSite CS, const Function *F) {
14241424
case Intrinsic::x86_avx512_vcvtsd2usi64:
14251425
case Intrinsic::x86_avx512_cvttsd2usi:
14261426
case Intrinsic::x86_avx512_cvttsd2usi64:
1427+
case Intrinsic::is_constant:
14271428
return true;
14281429
default:
14291430
return false;
@@ -1603,6 +1604,15 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
16031604
const TargetLibraryInfo *TLI,
16041605
ImmutableCallSite CS) {
16051606
if (Operands.size() == 1) {
1607+
if (IntrinsicID == Intrinsic::is_constant) {
1608+
// We know we have a "Constant" argument. But we want to only
1609+
// return true for manifest constants, not those that depend on
1610+
// constants with unknowable values, e.g. GlobalValue or BlockAddress.
1611+
if (isa<ConstantInt>(Operands[0]) || isa<ConstantFP>(Operands[0]))
1612+
return ConstantInt::getTrue(Ty->getContext());
1613+
return ConstantInt::getFalse(Ty->getContext());
1614+
}
1615+
16061616
if (isa<UndefValue>(Operands[0])) {
16071617
// cosine(arg) is between -1 and 1. cosine(invalid arg) is NaN
16081618
if (IntrinsicID == Intrinsic::cos)

lib/CodeGen/CodeGenPrepare.cpp

+29-14
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,24 @@ class TypePromotionTransaction;
321321
}
322322

323323
private:
324+
template <typename F>
325+
void resetIteratorIfInvalidatedWhileCalling(BasicBlock *BB, F f) {
326+
// Substituting can cause recursive simplifications, which can invalidate
327+
// our iterator. Use a WeakTrackingVH to hold onto it in case this
328+
// happens.
329+
Value *CurValue = &*CurInstIterator;
330+
WeakTrackingVH IterHandle(CurValue);
331+
332+
f();
333+
334+
// If the iterator instruction was recursively deleted, start over at the
335+
// start of the block.
336+
if (IterHandle != CurValue) {
337+
CurInstIterator = BB->begin();
338+
SunkAddrs.clear();
339+
}
340+
}
341+
324342
bool eliminateFallThrough(Function &F);
325343
bool eliminateMostlyEmptyBlocks(Function &F);
326344
BasicBlock *findDestBlockOfMergeableEmptyBlock(BasicBlock *BB);
@@ -1690,21 +1708,18 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool &ModifiedDT) {
16901708
// Lower all uses of llvm.objectsize.*
16911709
ConstantInt *RetVal =
16921710
lowerObjectSizeCall(II, *DL, TLInfo, /*MustSucceed=*/true);
1693-
// Substituting this can cause recursive simplifications, which can
1694-
// invalidate our iterator. Use a WeakTrackingVH to hold onto it in case
1695-
// this
1696-
// happens.
1697-
Value *CurValue = &*CurInstIterator;
1698-
WeakTrackingVH IterHandle(CurValue);
16991711

1700-
replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1701-
1702-
// If the iterator instruction was recursively deleted, start over at the
1703-
// start of the block.
1704-
if (IterHandle != CurValue) {
1705-
CurInstIterator = BB->begin();
1706-
SunkAddrs.clear();
1707-
}
1712+
resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
1713+
replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1714+
});
1715+
return true;
1716+
}
1717+
case Intrinsic::is_constant: {
1718+
// If is_constant hasn't folded away yet, lower it to false now.
1719+
Constant *RetVal = ConstantInt::getFalse(II->getContext());
1720+
resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
1721+
replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
1722+
});
17081723
return true;
17091724
}
17101725
case Intrinsic::aarch64_stlxr:

lib/CodeGen/GlobalISel/IRTranslator.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,11 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
917917
MIRBuilder.buildConstant(getOrCreateVReg(CI), Min->isZero() ? -1ULL : 0);
918918
return true;
919919
}
920+
case Intrinsic::is_constant:
921+
// If this wasn't constant-folded away by now, then it's not a
922+
// constant.
923+
MIRBuilder.buildConstant(getOrCreateVReg(CI), 0);
924+
return true;
920925
case Intrinsic::stackguard:
921926
getStackGuard(getOrCreateVReg(CI), MIRBuilder);
922927
return true;

lib/CodeGen/SelectionDAG/FastISel.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,14 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
14571457
updateValueMap(II, ResultReg);
14581458
return true;
14591459
}
1460+
case Intrinsic::is_constant: {
1461+
Constant *ResCI = ConstantInt::getFalse(II->getContext());
1462+
unsigned ResultReg = getRegForValue(ResCI);
1463+
if (!ResultReg)
1464+
return false;
1465+
updateValueMap(II, ResultReg);
1466+
return true;
1467+
}
14601468
case Intrinsic::experimental_stackmap:
14611469
return selectStackmap(II);
14621470
case Intrinsic::experimental_patchpoint_void:

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -5851,6 +5851,13 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
58515851
setValue(&I, Res);
58525852
return nullptr;
58535853
}
5854+
5855+
case Intrinsic::is_constant:
5856+
// If this wasn't constant-folded away by now, then it's not a
5857+
// constant.
5858+
setValue(&I, DAG.getConstant(0, sdl, MVT::i1));
5859+
return nullptr;
5860+
58545861
case Intrinsic::annotation:
58555862
case Intrinsic::ptr_annotation:
58565863
case Intrinsic::launder_invariant_group:

lib/Transforms/Scalar/SCCP.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,8 @@ void SCCPSolver::visitCallSite(CallSite CS) {
12281228
SmallVector<Constant*, 8> Operands;
12291229
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
12301230
AI != E; ++AI) {
1231+
if (AI->get()->getType()->isStructTy())
1232+
return markOverdefined(I); // Can't handle struct args.
12311233
LatticeVal State = getValueState(*AI);
12321234

12331235
if (State.isUnknown())

0 commit comments

Comments
 (0)