Skip to content

Commit 6c57130

Browse files
Merge pull request swiftlang#19716 from aschwaighofer/assume
Add the Swift equivalent of the llvm.assume intrinsic
2 parents ae55481 + d2f5278 commit 6c57130

File tree

8 files changed

+57
-2
lines changed

8 files changed

+57
-2
lines changed

include/swift/AST/Builtins.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ BUILTIN_UNARY_OPERATION(FNeg, "fneg", "n", FloatOrVector)
114114
// It has only an effect if the argument is a load or call.
115115
// TODO: consider printing a warning if it is not used on a load or call.
116116
BUILTIN_UNARY_OPERATION(AssumeNonNegative, "assumeNonNegative", "n", Integer)
117+
// It only works on i1.
118+
BUILTIN_UNARY_OPERATION(AssumeTrue, "assume", "", Integer)
117119

118120
#undef BUILTIN_UNARY_OPERATION
119121

lib/IRGen/GenBuiltin.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,13 @@ if (Builtin.ID == BuiltinValueKind::id) { \
393393
llvm::Value *v = IGF.Builder.CreateFSub(lhs, rhs);
394394
return out.add(v);
395395
}
396-
396+
if (Builtin.ID == BuiltinValueKind::AssumeTrue) {
397+
llvm::Value *v = args.claimNext();
398+
if (v->getType() == IGF.IGM.Int1Ty) {
399+
IGF.Builder.CreateIntrinsicCall(llvm::Intrinsic::ID::assume, v);
400+
}
401+
return;
402+
}
397403
if (Builtin.ID == BuiltinValueKind::AssumeNonNegative) {
398404
llvm::Value *v = args.claimNext();
399405
// Set a value range on the load instruction, which must be the argument of

lib/SIL/SILOwnershipVerifier.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AssignCopyArrayFrontToBack)
11571157
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AssignCopyArrayBackToFront)
11581158
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AssignTakeArray)
11591159
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AssumeNonNegative)
1160+
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AssumeTrue)
11601161
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AtomicLoad)
11611162
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AtomicRMW)
11621163
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AtomicStore)

lib/SIL/ValueOwnershipKindClassifier.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, AShr)
401401
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Add)
402402
CONSTANT_OWNERSHIP_BUILTIN(Trivial, And)
403403
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AssumeNonNegative)
404+
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AssumeTrue)
404405
CONSTANT_OWNERSHIP_BUILTIN(Trivial, BitCast)
405406
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ExactSDiv)
406407
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ExactUDiv)

stdlib/public/core/Builtin.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,13 @@ public func _onFastPath() {
290290
Builtin.onFastPath()
291291
}
292292

293+
// Optimizer hint that the condition is true. The condition is unchecked.
294+
// The builtin acts as an opaque instruction with side-effects.
295+
@usableFromInline @_transparent
296+
func _uncheckedUnsafeAssume(_ condition: Bool) {
297+
_ = Builtin.assume_Int1(condition._value)
298+
}
299+
293300
//===--- Runtime shim wrappers --------------------------------------------===//
294301

295302
/// Returns `true` iff the class indicated by `theClass` uses native

test/IRGen/assume.sil

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -O -emit-ir %s | %FileCheck %s
2+
sil_stage canonical
3+
4+
import Swift
5+
import Builtin
6+
7+
// CHECK-LABEL: define{{.*}} swiftcc i64 @test_assume(i64)
8+
// CHECK: [[COND:%.*]] = icmp sgt i64 %0, -1
9+
// CHECK: tail call void @llvm.assume(i1 [[COND]])
10+
// CHECK: [[RES:%.*]] = lshr i64 %0, 6
11+
// CHECK: ret i64 [[RES]]
12+
// CHECK: }
13+
14+
sil @test_assume : $@convention(thin) (Int64) -> Int64 {
15+
bb0(%0 : $Int64):
16+
%2 = integer_literal $Builtin.Int64, 0
17+
%3 = struct_extract %0 : $Int64, #Int64._value
18+
%4 = builtin "cmp_slt_Int64"(%3 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int1
19+
%5 = integer_literal $Builtin.Int1, -1
20+
%6 = builtin "xor_Int1"(%4 : $Builtin.Int1, %5 : $Builtin.Int1) : $Builtin.Int1
21+
%7 = builtin "assume_Int1"(%6 : $Builtin.Int1) : $Builtin.Int1
22+
%8 = integer_literal $Builtin.Int64, 64
23+
%9 = builtin "sdiv_Int64"(%3 : $Builtin.Int64, %8 : $Builtin.Int64) : $Builtin.Int64
24+
%10 = struct $Int64 (%9 : $Builtin.Int64)
25+
return %10 : $Int64
26+
}

test/IRGen/builtins.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,12 @@ func isUnique(_ ref: inout Builtin.BridgeObject) -> Bool {
652652
return Builtin.isUnique(&ref)
653653
}
654654

655+
// CHECK-LABEL: define hidden{{.*}} @"$s8builtins10assumeTrueyyBi1_F"
656+
// CHECK: call void @llvm.assume(i1 %0)
657+
// CHECK: ret
658+
func assumeTrue(_ x: Builtin.Int1) {
659+
Builtin.assume_Int1(x)
660+
}
655661
// BridgeObject nonNull
656662
// CHECK-LABEL: define hidden {{.*}}i1 @"$s8builtins15isUnique_nativeyBi1_BbzF"(%swift.bridge** nocapture dereferenceable({{.*}})) {{.*}} {
657663
// CHECK-NEXT: entry:

test/SILGen/builtins.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,4 +812,10 @@ func once(control: Builtin.RawPointer) {
812812
func valueToBridgeObject(_ x: UInt) -> Builtin.BridgeObject {
813813
return Builtin.valueToBridgeObject(x)
814814
}
815-
815+
816+
// CHECK-LABEL: sil hidden @$s8builtins10assumeTrueyyBi1_F
817+
// CHECK: builtin "assume_Int1"({{.*}} : $Builtin.Int1)
818+
// CHECK: return
819+
func assumeTrue(_ x: Builtin.Int1) {
820+
Builtin.assume_Int1(x)
821+
}

0 commit comments

Comments
 (0)