mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[IRGen] Use at least Int8 for extra tag bits
rdar://149985633 Using at least Int8 here allows LLVM to apply more optimizations, reducing code size, avoiding stack allocations and as a result often eliminating complete stack frames.
This commit is contained in:
@@ -1430,10 +1430,7 @@ namespace {
|
||||
// types other than i1 or power-of-two-byte sizes like i8, i16, etc. inhibit
|
||||
// FastISel and expose backend bugs.
|
||||
static unsigned getIntegerBitSizeForTag(unsigned tagBits) {
|
||||
// i1 is used to represent bool in C so is fairly well supported.
|
||||
if (tagBits == 1)
|
||||
return 1;
|
||||
// Otherwise, round the physical size in bytes up to the next power of two.
|
||||
// Round the physical size in bytes up to the next power of two.
|
||||
unsigned tagBytes = (tagBits + 7U)/8U;
|
||||
if (!llvm::isPowerOf2_32(tagBytes))
|
||||
tagBytes = llvm::NextPowerOf2(tagBytes);
|
||||
@@ -2221,15 +2218,9 @@ namespace {
|
||||
// If any tag bits are present, they must match.
|
||||
llvm::Value *tagResult = nullptr;
|
||||
if (tagBits) {
|
||||
if (ExtraTagBitCount == 1) {
|
||||
if (extraTag == 1)
|
||||
tagResult = tagBits;
|
||||
else
|
||||
tagResult = IGF.Builder.CreateNot(tagBits);
|
||||
} else {
|
||||
tagResult = IGF.Builder.CreateICmpEQ(tagBits,
|
||||
llvm::ConstantInt::get(IGF.IGM.getLLVMContext(), extraTag));
|
||||
}
|
||||
tagResult = IGF.Builder.CreateICmpEQ(
|
||||
tagBits,
|
||||
llvm::ConstantInt::get(IGF.IGM.getLLVMContext(), extraTag));
|
||||
}
|
||||
|
||||
if (tagResult && payloadResult)
|
||||
@@ -2311,7 +2302,9 @@ namespace {
|
||||
oneDest = llvm::BasicBlock::Create(C);
|
||||
tagBitBlocks.push_back(oneDest);
|
||||
}
|
||||
IGF.Builder.CreateCondBr(tagBits, oneDest, zeroDest);
|
||||
auto isOne = IGF.Builder.CreateICmpEQ(
|
||||
tagBits, llvm::ConstantInt::get(tagBits->getType(), 1));
|
||||
IGF.Builder.CreateCondBr(isOne, oneDest, zeroDest);
|
||||
} else {
|
||||
auto swi = SwitchBuilder::create(IGF, tagBits,
|
||||
SwitchDefaultDest(unreachableBB, IsUnreachable),
|
||||
@@ -2587,14 +2580,9 @@ namespace {
|
||||
// If we have extra tag bits, they will be zero if we contain a payload.
|
||||
if (ExtraTagBitCount > 0) {
|
||||
assert(extraBits);
|
||||
llvm::Value *isNonzero;
|
||||
if (ExtraTagBitCount == 1) {
|
||||
isNonzero = extraBits;
|
||||
} else {
|
||||
llvm::Value *zero = llvm::ConstantInt::get(extraBits->getType(), 0);
|
||||
isNonzero = IGF.Builder.CreateICmp(llvm::CmpInst::ICMP_NE,
|
||||
extraBits, zero);
|
||||
}
|
||||
llvm::Value *zero = llvm::ConstantInt::get(extraBits->getType(), 0);
|
||||
llvm::Value *isNonzero =
|
||||
IGF.Builder.CreateICmp(llvm::CmpInst::ICMP_NE, extraBits, zero);
|
||||
|
||||
auto *zeroBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
||||
IGF.Builder.CreateCondBr(isNonzero, nonzeroBB, zeroBB);
|
||||
|
||||
@@ -57,10 +57,10 @@ entry:
|
||||
store %w to %d : $*NoPayload
|
||||
|
||||
// CHECK: load i32{{.*}}, align 16
|
||||
// CHECK: load i1{{.*}}, align 4
|
||||
// CHECK: load i8{{.*}}, align 4
|
||||
%v = load %e : $*SinglePayload
|
||||
// CHECK: store i32{{.*}}, align 16
|
||||
// CHECK: store i1{{.*}}, align 4
|
||||
// CHECK: store i8{{.*}}, align 4
|
||||
store %v to %e : $*SinglePayload
|
||||
|
||||
// CHECK: load i32{{.*}}, align 16
|
||||
|
||||
@@ -40,11 +40,9 @@ entry(%c : $C):
|
||||
|
||||
// CHECK-x86_64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @bitcast_trivial_optional(i64 %0, i8 %1) {{.*}} {
|
||||
// CHECK-x86_64-NEXT: entry:
|
||||
// CHECK-x86_64-NEXT: %2 = trunc i8 %1 to i1
|
||||
// CHECK-x86_64-NEXT: %3 = zext i1 %2 to i8
|
||||
// CHECK-x86_64-NEXT: %4 = insertvalue { i64, i8 } undef, i64 %0, 0
|
||||
// CHECK-x86_64-NEXT: %5 = insertvalue { i64, i8 } %4, i8 %3, 1
|
||||
// CHECK-x86_64-NEXT: ret { i64, i8 } %5
|
||||
// CHECK-x86_64-NEXT: %2 = insertvalue { i64, i8 } undef, i64 %0, 0
|
||||
// CHECK-x86_64-NEXT: %3 = insertvalue { i64, i8 } %2, i8 %1, 1
|
||||
// CHECK-x86_64-NEXT: ret { i64, i8 } %3
|
||||
|
||||
sil @bitcast_trivial_optional: $@convention(thin) (Optional<Int>) -> Optional<Int> {
|
||||
entry(%c : $Optional<Int>):
|
||||
|
||||
@@ -470,10 +470,10 @@ enum SinglePayloadNoXI2 {
|
||||
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @select_enum([[WORD:i32]] %0, i8 %1)
|
||||
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @select_enum([[WORD:i64]] %0, i8 %1)
|
||||
// CHECK: entry:
|
||||
// CHECK: [[TAG:%.*]] = trunc i8 %1 to i1
|
||||
// CHECK: [[PAYLOAD:%.*]] = icmp eq [[WORD]] %0, 1
|
||||
// CHECK: [[MATCHES:%.*]] = and i1 [[TAG]], [[PAYLOAD]]
|
||||
// CHECK: [[RES:%.*]] = select i1 [[MATCHES]], i1 false, i1 true
|
||||
// CHECK: [[TAG:%.*]] = icmp eq i8 %1, 1
|
||||
// CHECK: [[COMBINED:%.*]] = and i1 [[TAG]], [[PAYLOAD]]
|
||||
// CHECK: [[RES:%.*]] = select i1 [[COMBINED]], i1 false, i1 true
|
||||
// CHECK: ret i1 [[RES]]
|
||||
// CHECK: }
|
||||
|
||||
@@ -490,7 +490,7 @@ bb0(%0 : $SinglePayloadNoXI2):
|
||||
sil @single_payload_no_xi_switch : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
||||
// CHECK: entry:
|
||||
entry(%u : $SinglePayloadNoXI2):
|
||||
// CHECK: %2 = trunc i8
|
||||
// CHECK: %2 = icmp eq i8 %1, 1
|
||||
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_DEST:[0-9]+]]
|
||||
// CHECK: [[TAGS]]:
|
||||
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
||||
@@ -564,7 +564,7 @@ end:
|
||||
sil @single_payload_no_xi_switch_arg : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
||||
// CHECK: entry:
|
||||
entry(%u : $SinglePayloadNoXI2):
|
||||
// CHECK: %2 = trunc i8
|
||||
// CHECK: %2 = icmp eq i8 %1, 1
|
||||
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_PREDEST:[0-9]+]]
|
||||
// CHECK: [[TAGS]]:
|
||||
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
||||
@@ -633,7 +633,7 @@ entry(%0 : $Builtin.Word):
|
||||
// CHECK: entry:
|
||||
// CHECK: store [[WORD]] %0, ptr %1
|
||||
// CHECK: [[T0:%.*]] = getelementptr inbounds %T4enum18SinglePayloadNoXI2O, ptr %1, i32 0, i32 1
|
||||
// CHECK: store i1 false, ptr [[T0]]
|
||||
// CHECK: store i8 0, ptr [[T0]]
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
sil @single_payload_no_xi_inject_x_indirect : $(Builtin.Word, @inout SinglePayloadNoXI2) -> () {
|
||||
@@ -659,7 +659,7 @@ entry:
|
||||
// CHECK: entry:
|
||||
// CHECK: store [[WORD]] 0, ptr %0
|
||||
// CHECK: [[T0:%.*]] = getelementptr inbounds %T4enum18SinglePayloadNoXI2O, ptr %0, i32 0, i32 1
|
||||
// CHECK: store i1 true, ptr [[T0]]
|
||||
// CHECK: store i8 1, ptr [[T0]]
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
sil @single_payload_no_xi_inject_y_indirect : $(@inout SinglePayloadNoXI2) -> () {
|
||||
@@ -1593,12 +1593,10 @@ enum MultiPayloadOneSpareBit {
|
||||
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_switch(i64 %0, i8 %1) {{.*}} {
|
||||
sil @multi_payload_one_spare_bit_switch : $(MultiPayloadOneSpareBit) -> () {
|
||||
entry(%u : $MultiPayloadOneSpareBit):
|
||||
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i8 %1 to i1
|
||||
// CHECK-64: [[SPARE_TAG_LSHR:%.*]] = lshr i64 %0, 63
|
||||
// CHECK-64: [[SPARE_TAG_TRUNC:%.*]] = trunc i64 [[SPARE_TAG_LSHR]] to i8
|
||||
// CHECK-64: [[SPARE_TAG:%.*]] = and i8 [[SPARE_TAG_TRUNC]], 1
|
||||
// CHECK-64: [[EXTRA_TAG_ZEXT:%.*]] = zext i1 [[NATIVECC_TRUNC]] to i8
|
||||
// CHECK-64: [[EXTRA_TAG:%.*]] = shl i8 [[EXTRA_TAG_ZEXT]], 1
|
||||
// CHECK-64: [[EXTRA_TAG:%.*]] = shl i8 %1, 1
|
||||
// CHECK-64: [[TAG:%.*]] = or i8 [[SPARE_TAG]], [[EXTRA_TAG]]
|
||||
// CHECK-64: switch i8 [[TAG]], label %[[UNREACHABLE:[0-9]+]] [
|
||||
// CHECK-64: i8 0, label %[[X_PREDEST:[0-9]+]]
|
||||
@@ -1681,7 +1679,7 @@ sil @multi_payload_one_spare_bit_switch_indirect : $(@inout MultiPayloadOneSpare
|
||||
entry(%u : $*MultiPayloadOneSpareBit):
|
||||
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %0
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, ptr %0, i32 0, i32 1
|
||||
// CHECK-64: [[TAG:%.*]] = load i1, ptr [[T0]]
|
||||
// CHECK-64: [[TAG:%.*]] = load i8, ptr [[T0]]
|
||||
// CHECK-64: switch i8 {{%.*}}
|
||||
// CHECK-64: switch i64 [[PAYLOAD]]
|
||||
// CHECK-64: {{[0-9]+}}:
|
||||
@@ -1748,7 +1746,7 @@ entry(%0 : $Builtin.Int62):
|
||||
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
||||
// CHECK-64: store i64 [[PAYLOAD_MASKED]], ptr %1
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, ptr %1, i32 0, i32 1
|
||||
// CHECK-64: store i1 false, ptr [[T0]]
|
||||
// CHECK-64: store i8 0, ptr [[T0]]
|
||||
// CHECK-64: ret void
|
||||
// CHECK-64: }
|
||||
sil @multi_payload_one_spare_bit_inject_x_indirect : $(Builtin.Int62, @inout MultiPayloadOneSpareBit) -> () {
|
||||
@@ -1788,7 +1786,7 @@ entry(%0 : $Builtin.Int63):
|
||||
// CHECK-64: [[PAYLOAD_TAGGED:%.*]] = or i64 [[PAYLOAD_MASKED]], -9223372036854775808
|
||||
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], ptr %1
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, ptr %1, i32 0, i32 1
|
||||
// CHECK-64: store i1 false, ptr [[T0]]
|
||||
// CHECK-64: store i8 0, ptr [[T0]]
|
||||
// CHECK-64: ret void
|
||||
// CHECK-64: }
|
||||
|
||||
@@ -1831,7 +1829,7 @@ entry:
|
||||
// -- 0x8000_0000_0000_0000
|
||||
// CHECK-64: store i64 -9223372036854775808, ptr %0
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, ptr %0, i32 0, i32 1
|
||||
// CHECK-64: store i1 true, ptr [[T0]]
|
||||
// CHECK-64: store i8 1, ptr [[T0]]
|
||||
// CHECK-64: ret void
|
||||
// CHECK-64: }
|
||||
sil @multi_payload_one_spare_bit_inject_a_indirect : $(@inout MultiPayloadOneSpareBit) -> () {
|
||||
@@ -2227,8 +2225,9 @@ enum MultiPayloadNested {
|
||||
// CHECK: %3 = getelementptr
|
||||
// CHECK: %4 = load i8, ptr %3
|
||||
// CHECK: %5 = lshr i8 %4, 7
|
||||
// CHECK: %6 = trunc i8 %5 to i1
|
||||
// CHECK: br i1 %6
|
||||
// CHECK: %6 = and i8 %5, 1
|
||||
// CHECK: %7 = icmp ne i8 %6, 1
|
||||
// CHECK: br i1 %7
|
||||
sil @multi_payload_nested_switch : $(@in MultiPayloadNested) -> () {
|
||||
entry(%c : $*MultiPayloadNested):
|
||||
switch_enum_addr %c : $*MultiPayloadNested, case #MultiPayloadNested.A!enumelt: a_dest, case #MultiPayloadNested.B!enumelt: b_dest
|
||||
@@ -2259,8 +2258,10 @@ enum MultiPayloadNestedSpareBits {
|
||||
// CHECK-64: entry:
|
||||
// CHECK-64: %1 = load [[WORD]], ptr %0
|
||||
// CHECK-64: %2 = lshr [[WORD]] %1, 61
|
||||
// CHECK-64: %3 = trunc [[WORD]] %2 to i1
|
||||
// CHECK-64: br i1 %3
|
||||
// CHECK-64: %3 = trunc [[WORD]] %2 to i8
|
||||
// CHECK-64: %4 = and i8 %3, 1
|
||||
// CHECK-64: %5 = icmp ne i8 %4, 1
|
||||
// CHECK-64: br i1 %5
|
||||
sil @multi_payload_nested_spare_bits_switch : $(@in MultiPayloadNestedSpareBits) -> () {
|
||||
entry(%c : $*MultiPayloadNestedSpareBits):
|
||||
switch_enum_addr %c : $*MultiPayloadNestedSpareBits, case #MultiPayloadNestedSpareBits.A!enumelt: a_dest, case #MultiPayloadNestedSpareBits.B!enumelt: b_dest
|
||||
@@ -2459,7 +2460,7 @@ entry(%x : $Int32):
|
||||
// CHECK-64: [[INT_ZEXT:%.*]] = zext i32 %0 to i64
|
||||
// CHECK-64: [[INT_SHL:%.*]] = shl i64 [[INT_ZEXT]], 32
|
||||
%d = enum $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt, %c : $(Optional<()>, Int32)
|
||||
// CHECK-64: [[BIT:%.*]] = trunc i64 [[INT_SHL]] to i1
|
||||
// CHECK-64: [[BIT:%.*]] = trunc i64 [[INT_SHL]] to i8
|
||||
// CHECK-64: [[INT_SHR:%.*]] = lshr i64 [[INT_SHL]], 32
|
||||
// CHECK-64: [[INT:%.*]] = trunc i64 [[INT_SHR]] to i32
|
||||
%e = unchecked_enum_data %d : $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt
|
||||
|
||||
@@ -30,9 +30,9 @@ struct HasAnEnum {
|
||||
// CHECK: define {{.*}} swiftcc range(i64 -1, 5) i64 @"$s31enum_copy_init_with_take_memcpy9HasAnEnumV9readValueSiyF"(ptr {{.*}} %0)
|
||||
// CHECK: [[T0:%.*]] = getelementptr inbounds i8, ptr %0, i64 160
|
||||
// CHECK: [[T1:%.*]] = load i8, ptr [[T0]]
|
||||
// CHECK: [[T2:%.*]] = icmp eq i8 [[T1]], 2
|
||||
// CHECK: br i1 [[T2]], label
|
||||
// CHECK: [[R:%.*]] = phi i64 [ -1, {{.*}} ], [ 4, {{.*}} ]
|
||||
// CHECK: [[T2:%.*]] = and i8 [[T1]], -3
|
||||
// CHECK: [[T3:%.*]] = icmp eq i8 [[T2]], 0
|
||||
// CHECK: [[R:%.*]] = select i1 [[T3]], i64 -1, i64 4
|
||||
// CHECK: ret i64 [[R]]
|
||||
|
||||
}
|
||||
|
||||
@@ -40,21 +40,21 @@ entry(%e : $Either<(), ()>):
|
||||
fix_lifetime %e : $Either<(), ()>
|
||||
|
||||
// CHECK-NEXT: alloca
|
||||
// CHECK-NEXT: trunc i8 {{.*}} to i1
|
||||
// CHECK-NEXT: llvm.lifetime.start
|
||||
%s = alloc_stack $Either<(), ()>
|
||||
|
||||
%l = enum $Either<(), ()>, #Either.Left!enumelt, undef : $()
|
||||
// CHECK-NEXT: store i1 false
|
||||
// CHECK-NEXT: store i8 0
|
||||
store %l to %s : $*Either<(), ()>
|
||||
%r = enum $Either<(), ()>, #Either.Right!enumelt, undef : $()
|
||||
// CHECK-NEXT: store i1 true
|
||||
// CHECK-NEXT: store i8 1
|
||||
// CHECK-NEXT: [[COND:%.*]] = icmp ne i8 {{%.*}}, 1
|
||||
store %r to %s : $*Either<(), ()>
|
||||
|
||||
%a = unchecked_enum_data %l : $Either<(), ()>, #Either.Left!enumelt
|
||||
%b = unchecked_enum_data %r : $Either<(), ()>, #Either.Right!enumelt
|
||||
|
||||
// CHECK-NEXT: br i1 {{%.*}}, label %[[RIGHT_PRE:[0-9]+]], label %[[LEFT_PRE:[0-9]+]]
|
||||
// CHECK-NEXT: br i1 [[COND]], label %[[LEFT_PRE:[0-9]+]], label %[[RIGHT_PRE:[0-9]+]]
|
||||
// CHECK: [[LEFT_PRE]]:
|
||||
// CHECK: br label [[LEFT:%[0-9]+]]
|
||||
// CHECK: [[RIGHT_PRE]]:
|
||||
|
||||
@@ -474,8 +474,8 @@ enum SinglePayloadNoXI2 {
|
||||
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @select_enum([[WORD:i32]] %0, i8 %1)
|
||||
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @select_enum([[WORD:i64]] %0, i8 %1)
|
||||
// CHECK: entry:
|
||||
// CHECK: [[TAG:%.*]] = trunc i8 %1 to i1
|
||||
// CHECK: [[PAYLOAD:%.*]] = icmp eq [[WORD]] %0, 1
|
||||
// CHECK: [[TAG:%.*]] = icmp eq i8 %1, 1
|
||||
// CHECK: [[MATCHES:%.*]] = and i1 [[TAG]], [[PAYLOAD]]
|
||||
// CHECK: [[RES:%.*]] = select i1 [[MATCHES]], i1 false, i1 true
|
||||
// CHECK: ret i1 [[RES]]
|
||||
@@ -494,7 +494,7 @@ bb0(%0 : $SinglePayloadNoXI2):
|
||||
sil @single_payload_no_xi_switch : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
||||
// CHECK: entry:
|
||||
entry(%u : $SinglePayloadNoXI2):
|
||||
// CHECK: %2 = trunc i8
|
||||
// CHECK: %2 = icmp eq i8 %1, 1
|
||||
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_DEST:[0-9]+]]
|
||||
// CHECK: [[TAGS]]:
|
||||
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
||||
@@ -568,7 +568,7 @@ end:
|
||||
sil @single_payload_no_xi_switch_arg : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
||||
// CHECK: entry:
|
||||
entry(%u : $SinglePayloadNoXI2):
|
||||
// CHECK: %2 = trunc i8
|
||||
// CHECK: %2 = icmp eq i8 %1, 1
|
||||
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_PREDEST:[0-9]+]]
|
||||
// CHECK: [[TAGS]]:
|
||||
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
||||
@@ -637,7 +637,7 @@ entry(%0 : $Builtin.Word):
|
||||
// CHECK: entry:
|
||||
// CHECK: store [[WORD]] %0, ptr %1
|
||||
// CHECK: [[T0:%.*]] = getelementptr inbounds %T11enum_future18SinglePayloadNoXI2O, ptr %1, i32 0, i32 1
|
||||
// CHECK: store i1 false, ptr [[T0]]
|
||||
// CHECK: store i8 0, ptr [[T0]]
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
sil @single_payload_no_xi_inject_x_indirect : $(Builtin.Word, @inout SinglePayloadNoXI2) -> () {
|
||||
@@ -663,7 +663,7 @@ entry:
|
||||
// CHECK: entry:
|
||||
// CHECK: store [[WORD]] 0, ptr %0
|
||||
// CHECK: [[T0:%.*]] = getelementptr inbounds %T11enum_future18SinglePayloadNoXI2O, ptr %0, i32 0, i32 1
|
||||
// CHECK: store i1 true, ptr [[T0]]
|
||||
// CHECK: store i8 1, ptr [[T0]]
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
sil @single_payload_no_xi_inject_y_indirect : $(@inout SinglePayloadNoXI2) -> () {
|
||||
@@ -1597,12 +1597,10 @@ enum MultiPayloadOneSpareBit {
|
||||
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_switch(i64 %0, i8 %1) {{.*}} {
|
||||
sil @multi_payload_one_spare_bit_switch : $(MultiPayloadOneSpareBit) -> () {
|
||||
entry(%u : $MultiPayloadOneSpareBit):
|
||||
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i8 %1 to i1
|
||||
// CHECK-64: [[SPARE_TAG_LSHR:%.*]] = lshr i64 %0, 63
|
||||
// CHECK-64: [[SPARE_TAG_TRUNC:%.*]] = trunc i64 [[SPARE_TAG_LSHR]] to i8
|
||||
// CHECK-64: [[SPARE_TAG:%.*]] = and i8 [[SPARE_TAG_TRUNC]], 1
|
||||
// CHECK-64: [[EXTRA_TAG_ZEXT:%.*]] = zext i1 [[NATIVECC_TRUNC]] to i8
|
||||
// CHECK-64: [[EXTRA_TAG:%.*]] = shl i8 [[EXTRA_TAG_ZEXT]], 1
|
||||
// CHECK-64: [[EXTRA_TAG:%.*]] = shl i8 %1, 1
|
||||
// CHECK-64: [[TAG:%.*]] = or i8 [[SPARE_TAG]], [[EXTRA_TAG]]
|
||||
// CHECK-64: switch i8 [[TAG]], label %[[UNREACHABLE:[0-9]+]] [
|
||||
// CHECK-64: i8 0, label %[[X_PREDEST:[0-9]+]]
|
||||
@@ -1685,7 +1683,7 @@ sil @multi_payload_one_spare_bit_switch_indirect : $(@inout MultiPayloadOneSpare
|
||||
entry(%u : $*MultiPayloadOneSpareBit):
|
||||
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %0
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T11enum_future23MultiPayloadOneSpareBitO, ptr %0, i32 0, i32 1
|
||||
// CHECK-64: [[TAG:%.*]] = load i1, ptr [[T0]]
|
||||
// CHECK-64: [[TAG:%.*]] = load i8, ptr [[T0]]
|
||||
// CHECK-64: switch i8 {{%.*}}
|
||||
// CHECK-64: switch i64 [[PAYLOAD]]
|
||||
// CHECK-64: {{[0-9]+}}:
|
||||
@@ -1752,7 +1750,7 @@ entry(%0 : $Builtin.Int62):
|
||||
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
||||
// CHECK-64: store i64 [[PAYLOAD_MASKED]], ptr %1
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T11enum_future23MultiPayloadOneSpareBitO, ptr %1, i32 0, i32 1
|
||||
// CHECK-64: store i1 false, ptr [[T0]]
|
||||
// CHECK-64: store i8 0, ptr [[T0]]
|
||||
// CHECK-64: ret void
|
||||
// CHECK-64: }
|
||||
sil @multi_payload_one_spare_bit_inject_x_indirect : $(Builtin.Int62, @inout MultiPayloadOneSpareBit) -> () {
|
||||
@@ -1792,7 +1790,7 @@ entry(%0 : $Builtin.Int63):
|
||||
// CHECK-64: [[PAYLOAD_TAGGED:%.*]] = or i64 [[PAYLOAD_MASKED]], -9223372036854775808
|
||||
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], ptr %1
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T11enum_future23MultiPayloadOneSpareBitO, ptr %1, i32 0, i32 1
|
||||
// CHECK-64: store i1 false, ptr [[T0]]
|
||||
// CHECK-64: store i8 0, ptr [[T0]]
|
||||
// CHECK-64: ret void
|
||||
// CHECK-64: }
|
||||
|
||||
@@ -1835,7 +1833,7 @@ entry:
|
||||
// -- 0x8000_0000_0000_0000
|
||||
// CHECK-64: store i64 -9223372036854775808, ptr %0
|
||||
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T11enum_future23MultiPayloadOneSpareBitO, ptr %0, i32 0, i32 1
|
||||
// CHECK-64: store i1 true, ptr [[T0]]
|
||||
// CHECK-64: store i8 1, ptr [[T0]]
|
||||
// CHECK-64: ret void
|
||||
// CHECK-64: }
|
||||
sil @multi_payload_one_spare_bit_inject_a_indirect : $(@inout MultiPayloadOneSpareBit) -> () {
|
||||
@@ -2231,8 +2229,9 @@ enum MultiPayloadNested {
|
||||
// CHECK: %3 = getelementptr
|
||||
// CHECK: %4 = load i8, ptr %3
|
||||
// CHECK: %5 = lshr i8 %4, 7
|
||||
// CHECK: %6 = trunc i8 %5 to i1
|
||||
// CHECK: br i1 %6
|
||||
// CHECK: %6 = and i8 %5, 1
|
||||
// CHECK: %7 = icmp ne i8 %6, 1
|
||||
// CHECK: br i1 %7
|
||||
sil @multi_payload_nested_switch : $(@in MultiPayloadNested) -> () {
|
||||
entry(%c : $*MultiPayloadNested):
|
||||
switch_enum_addr %c : $*MultiPayloadNested, case #MultiPayloadNested.A!enumelt: a_dest, case #MultiPayloadNested.B!enumelt: b_dest
|
||||
@@ -2263,8 +2262,10 @@ enum MultiPayloadNestedSpareBits {
|
||||
// CHECK-64: entry:
|
||||
// CHECK-64: %1 = load [[WORD]], ptr %0
|
||||
// CHECK-64: %2 = lshr [[WORD]] %1, 61
|
||||
// CHECK-64: %3 = trunc [[WORD]] %2 to i1
|
||||
// CHECK-64: br i1 %3
|
||||
// CHECK-64: %3 = trunc [[WORD]] %2 to i8
|
||||
// CHECK-64: %4 = and i8 %3, 1
|
||||
// CHECK-64: %5 = icmp ne i8 %4, 1
|
||||
// CHECK-64: br i1 %5
|
||||
sil @multi_payload_nested_spare_bits_switch : $(@in MultiPayloadNestedSpareBits) -> () {
|
||||
entry(%c : $*MultiPayloadNestedSpareBits):
|
||||
switch_enum_addr %c : $*MultiPayloadNestedSpareBits, case #MultiPayloadNestedSpareBits.A!enumelt: a_dest, case #MultiPayloadNestedSpareBits.B!enumelt: b_dest
|
||||
@@ -2463,7 +2464,7 @@ entry(%x : $Int32):
|
||||
// CHECK-64: [[INT_ZEXT:%.*]] = zext i32 %0 to i64
|
||||
// CHECK-64: [[INT_SHL:%.*]] = shl i64 [[INT_ZEXT]], 32
|
||||
%d = enum $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt, %c : $(Optional<()>, Int32)
|
||||
// CHECK-64: [[BIT:%.*]] = trunc i64 [[INT_SHL]] to i1
|
||||
// CHECK-64: [[BIT:%.*]] = trunc i64 [[INT_SHL]] to i8
|
||||
// CHECK-64: [[INT_SHR:%.*]] = lshr i64 [[INT_SHL]], 32
|
||||
// CHECK-64: [[INT:%.*]] = trunc i64 [[INT_SHR]] to i32
|
||||
%e = unchecked_enum_data %d : $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt
|
||||
|
||||
@@ -357,8 +357,8 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
// -- The payload has no spare bits and there are no empty cases, so the tag
|
||||
// is entirely contained in the extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics24MultiPayloadNoEmptyCasesO, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i32
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32
|
||||
// CHECK-NEXT: ret i32 [[EXTRA_TAG]]
|
||||
|
||||
// -- MultiPayloadNoEmptyCases destructiveProjectEnumData
|
||||
@@ -368,11 +368,11 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
|
||||
// -- MultiPayloadNoEmptyCases destructiveInjectEnumTag
|
||||
// CHECK-LABEL: define internal void @"$s20enum_value_semantics24MultiPayloadNoEmptyCasesOwui"
|
||||
// CHECK: [[TAG:%.*]] = trunc i32 %tag to i1
|
||||
// CHECK: [[TAG:%.*]] = trunc i32 %tag to i8
|
||||
|
||||
// -- Store the tag in the extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics24MultiPayloadNoEmptyCasesO, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: store i1 [[TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: store i8 [[TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
|
||||
@@ -564,13 +564,12 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
|
||||
// -- Load the load bits of the tag from the extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
|
||||
// -- Load the high bits of the tag from the spare bits area
|
||||
// CHECK-NEXT: [[SPARE_BITS_TMP2:%.*]] = lshr i64 [[PAYLOAD]], 63
|
||||
// CHECK-NEXT: [[SPARE_BITS_TMP:%.*]] = trunc i64 [[SPARE_BITS_TMP2]] to i8
|
||||
// CHECK-NEXT: [[SPARE_BITS:%.*]] = and i8 [[SPARE_BITS_TMP]], 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i8
|
||||
|
||||
// -- Combine high bits and low bits to form tag
|
||||
// CHECK-NEXT: [[TAG_TMP:%.*]] = shl i8 [[EXTRA_TAG]], 1
|
||||
@@ -609,7 +608,7 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
|
||||
// -- Store high bits of tag in extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = lshr i32 %tag, 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = trunc i32 [[EXTRA_TAG_TMP]] to i1
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = trunc i32 [[EXTRA_TAG_TMP]] to i8
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: store i1 [[EXTRA_TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: store i8 [[EXTRA_TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
@@ -362,8 +362,8 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
// -- The payload has no spare bits and there are no empty cases, so the tag
|
||||
// is entirely contained in the extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T27enum_value_semantics_future24MultiPayloadNoEmptyCasesO, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i32
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32
|
||||
// CHECK-NEXT: ret i32 [[EXTRA_TAG]]
|
||||
|
||||
// -- MultiPayloadNoEmptyCases destructiveProjectEnumData
|
||||
@@ -373,11 +373,11 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
|
||||
// -- MultiPayloadNoEmptyCases destructiveInjectEnumTag
|
||||
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future24MultiPayloadNoEmptyCasesOwui"
|
||||
// CHECK: [[TAG:%.*]] = trunc i32 %tag to i1
|
||||
// CHECK: [[TAG:%.*]] = trunc i32 %tag to i8
|
||||
|
||||
// -- Store the tag in the extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T27enum_value_semantics_future24MultiPayloadNoEmptyCasesO, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: store i1 [[TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: store i8 [[TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
|
||||
@@ -569,13 +569,12 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
|
||||
// -- Load the load bits of the tag from the extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T27enum_value_semantics_future029MultiPayloadSpareBitsAndExtraH0O, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
|
||||
// -- Load the high bits of the tag from the spare bits area
|
||||
// CHECK-NEXT: [[SPARE_BITS_TMP2:%.*]] = lshr i64 [[PAYLOAD]], 63
|
||||
// CHECK-NEXT: [[SPARE_BITS_TMP:%.*]] = trunc i64 [[SPARE_BITS_TMP2]] to i8
|
||||
// CHECK-NEXT: [[SPARE_BITS:%.*]] = and i8 [[SPARE_BITS_TMP]], 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i8
|
||||
|
||||
// -- Combine high bits and low bits to form tag
|
||||
// CHECK-NEXT: [[TAG_TMP:%.*]] = shl i8 [[EXTRA_TAG]], 1
|
||||
@@ -614,7 +613,7 @@ bb0(%0 : $SinglePayloadNontrivial):
|
||||
|
||||
// -- Store high bits of tag in extra tag area
|
||||
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = lshr i32 %tag, 1
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = trunc i32 [[EXTRA_TAG_TMP]] to i1
|
||||
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = trunc i32 [[EXTRA_TAG_TMP]] to i8
|
||||
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T27enum_value_semantics_future029MultiPayloadSpareBitsAndExtraH0O, ptr %value, i32 0, i32 1
|
||||
// CHECK-NEXT: store i1 [[EXTRA_TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: store i8 [[EXTRA_TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
@@ -183,8 +183,6 @@ entry(%b : $*MOStruct):
|
||||
|
||||
// CHECK-LABEL: define{{.*}}@destroy_enum_value(
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: trunc
|
||||
// CHECK-NEXT: zext
|
||||
// CHECK-NEXT: call{{.*}}@destroy_enum(
|
||||
// CHECK-NEXT: ret void
|
||||
sil @destroy_enum_value : $@convention(thin) (@owned MOEnum) -> () {
|
||||
@@ -198,7 +196,6 @@ entry(%b : $MOEnum):
|
||||
// CHECK-NEXT: load
|
||||
// CHECK-NEXT: getelementptr
|
||||
// CHECK-NEXT: load
|
||||
// CHECK-NEXT: zext
|
||||
// CHECK-NEXT: call{{.*}}@destroy_enum(
|
||||
// CHECK-NEXT: ret void
|
||||
sil @destroy_enum_value_indirect : $@convention(thin) (@in MOEnum) -> () {
|
||||
|
||||
@@ -231,9 +231,8 @@ func consumeKlassEnumPairWithDeinit(_ x: __owned KlassEnumPairWithDeinit) { }
|
||||
// IR: [[BB1]]:
|
||||
// IR-NEXT: [[LHS:%.*]] = load i64, ptr [[ALLOCA]]
|
||||
// IR-NEXT: [[GEP:%.*]] = getelementptr inbounds [[TYPE]], ptr [[ALLOCA]], i32 0, i32 1
|
||||
// IR-NEXT: [[RHS:%.*]] = load i1, ptr [[GEP]]
|
||||
// IR-NEXT: [[RHS_ZEXT:%.*]] = zext i1 [[RHS]]
|
||||
// IR-NEXT: call swiftcc void @"$s16moveonly_deinits31consumeIntEnumPairWithoutDeinityyAA0defgH0OnF"(i64 [[LHS]], i8 [[RHS_ZEXT]])
|
||||
// IR-NEXT: [[RHS:%.*]] = load i8, ptr [[GEP]]
|
||||
// IR-NEXT: call swiftcc void @"$s16moveonly_deinits31consumeIntEnumPairWithoutDeinityyAA0defgH0OnF"(i64 [[LHS]], i8 [[RHS]])
|
||||
// IR-NEXT: br label %[[CONT:[0-9]+]]
|
||||
//
|
||||
// IR: [[BB2]]:
|
||||
@@ -257,17 +256,15 @@ public func testIntEnumPairWithoutDeinit() {
|
||||
// IR: [[BB1]]:
|
||||
// IR-NEXT: [[LHS:%.*]] = load i64, ptr [[ALLOCA]]
|
||||
// IR-NEXT: [[GEP:%.*]] = getelementptr inbounds [[TYPE]], ptr [[ALLOCA]], i32 0, i32 1
|
||||
// IR-NEXT: [[RHS:%.*]] = load i1, ptr [[GEP]]
|
||||
// IR-NEXT: [[RHS_ZEXT:%.*]] = zext i1 [[RHS]]
|
||||
// IR-NEXT: call swiftcc void @"$s16moveonly_deinits28consumeIntEnumPairWithDeinityyAA0defgH0OnF"(i64 [[LHS]], i8 [[RHS_ZEXT]])
|
||||
// IR-NEXT: [[RHS:%.*]] = load i8, ptr [[GEP]]
|
||||
// IR-NEXT: call swiftcc void @"$s16moveonly_deinits28consumeIntEnumPairWithDeinityyAA0defgH0OnF"(i64 [[LHS]], i8 [[RHS]])
|
||||
// IR-NEXT: br label %[[CONT:[0-9]+]]
|
||||
//
|
||||
// IR: [[BB2]]:
|
||||
// IR-NEXT: [[LHS:%.*]] = load i64, ptr [[ALLOCA]]
|
||||
// IR-NEXT: [[GEP:%.*]] = getelementptr inbounds [[TYPE]], ptr [[ALLOCA]], i32 0, i32 1
|
||||
// IR-NEXT: [[RHS:%.*]] = load i1, ptr [[GEP]]
|
||||
// IR-NEXT: [[RHS_ZEXT:%.*]] = zext i1 [[RHS]]
|
||||
// IR-NEXT: call swiftcc void @"$s16moveonly_deinits21IntEnumPairWithDeinitOfD"(i64 [[LHS]], i8 [[RHS_ZEXT]])
|
||||
// IR-NEXT: [[RHS:%.*]] = load i8, ptr [[GEP]]
|
||||
// IR-NEXT: call swiftcc void @"$s16moveonly_deinits21IntEnumPairWithDeinitOfD"(i64 [[LHS]], i8 [[RHS]])
|
||||
// IR-NEXT: br label %[[CONT]]
|
||||
//
|
||||
// IR: [[CONT]]
|
||||
@@ -404,7 +401,7 @@ func testSingleEnum() {
|
||||
|
||||
// IR-LABEL: define {{.*}}swiftcc void @"$s16moveonly_deinits13testMultiEnumyyF"()
|
||||
func testMultiEnum() {
|
||||
// IR: call void @"$s16moveonly_deinits6EMultiOWOe"(i1 true)
|
||||
// IR: call void @"$s16moveonly_deinits6EMultiOWOe"(i8 1)
|
||||
_ = EMulti.b(OtherEmptyMoveOnlyWithDeinit())
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ func create<T>(_ t: T) -> C<T> {
|
||||
// OPT-LABEL: define hidden swiftcc void @"$s16non_fixed_return1CVACyxGycfC"(ptr noalias sret(%swift.opaque) %0
|
||||
// OPT: store i32 0, ptr [[BASE:%[0-9]+]]
|
||||
// OPT: [[ADDR2:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 4
|
||||
// OPT: store i1 true, ptr [[ADDR2]]
|
||||
// OPT: store i8 1, ptr [[ADDR2]]
|
||||
// OPT: [[ADDR4:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 8
|
||||
// OPT: call void @llvm.memset.p0.i64(ptr {{.*}}[[ADDR4]], i8 0, i64 16, i1 false)
|
||||
// OPT: ret void
|
||||
|
||||
@@ -12,25 +12,29 @@ sil @select_enum_SinglePayloadSingleEmpty : $@convention(thin) (@in SinglePayloa
|
||||
bb0(%0 : $*SinglePayloadSingleEmpty):
|
||||
%1 = load %0 : $*SinglePayloadSingleEmpty
|
||||
// CHECK: [[PAYLOAD1:%[0-9]+]] = load [[WORD_TY:(i32|i64)]], ptr
|
||||
// CHECK: [[TAG1:%[0-9]+]] = load i1, ptr
|
||||
// CHECK: [[TAG1:%[0-9]+]] = load i8, ptr
|
||||
// CHECK: [[TAG1_TRUNC0:%.*]] = icmp eq i8 [[TAG1]], 1
|
||||
|
||||
%2 = integer_literal $Builtin.Int32, 2
|
||||
%3 = integer_literal $Builtin.Int32, 3
|
||||
|
||||
// CHECK: select i1 [[TAG1]], i32 2, i32 3
|
||||
// CHECK: select i1 [[TAG1_TRUNC0]], i32 2, i32 3
|
||||
%4 = select_enum %1 : $SinglePayloadSingleEmpty, case #SinglePayloadSingleEmpty.EmptyCase!enumelt: %2, case #SinglePayloadSingleEmpty.DataCase!enumelt: %3 : $Builtin.Int32
|
||||
|
||||
// CHECK: [[V3:%[0-9]+]] = xor i1 [[TAG1]], true
|
||||
// CHECK: [[TAG1_TRUNC1:%.*]] = icmp eq i8 [[TAG1]], 1
|
||||
// CHECK: [[V3:%[0-9]+]] = xor i1 [[TAG1_TRUNC1]], true
|
||||
// CHECK-NEXT: select i1 [[V3]], i32 3, i32 2
|
||||
%5 = select_enum %1 : $SinglePayloadSingleEmpty, case #SinglePayloadSingleEmpty.DataCase!enumelt: %3, case #SinglePayloadSingleEmpty.EmptyCase!enumelt: %2 : $Builtin.Int32
|
||||
|
||||
// CHECK: [[PAYLOAD0:%[0-9]+]] = load [[WORD_TY:(i32|i64)]], ptr
|
||||
// CHECK: [[TAG0:%[0-9]+]] = load i1, ptr
|
||||
// CHECK: [[TAG0:%[0-9]+]] = load i8, ptr
|
||||
// CHECK: [[TAG0_TRUNC0:%.*]] = icmp eq i8 [[TAG0]], 1
|
||||
|
||||
// CHECK: select i1 [[TAG0]], i32 2, i32 3
|
||||
// CHECK: select i1 [[TAG0_TRUNC0]], i32 2, i32 3
|
||||
%6 = select_enum_addr %0 : $*SinglePayloadSingleEmpty, case #SinglePayloadSingleEmpty.EmptyCase!enumelt: %2, case #SinglePayloadSingleEmpty.DataCase!enumelt: %3 : $Builtin.Int32
|
||||
|
||||
// CHECK-NEXT: select i1 [[TAG1]], i32 2, i32 3
|
||||
// CHECK: [[TAG1_TRUNC2:%.*]] = icmp eq i8 [[TAG1]], 1
|
||||
// CHECK-NEXT: select i1 [[TAG1_TRUNC2]], i32 2, i32 3
|
||||
%7 = select_enum %1 : $SinglePayloadSingleEmpty, case #SinglePayloadSingleEmpty.EmptyCase!enumelt: %2, default %3 : $Builtin.Int32
|
||||
|
||||
return undef : $()
|
||||
@@ -45,17 +49,17 @@ enum MyOptional<T> {
|
||||
|
||||
sil @select_enum_TwoCasesNoPayload :$ @convention(thin) (@in TwoCasesNoPayload, @in MyOptional<TwoCasesNoPayload>) -> () {
|
||||
bb0(%0 : $*TwoCasesNoPayload, %10 : $*MyOptional<TwoCasesNoPayload>):
|
||||
// CHECK: [[PAYLOAD1:%[0-9]+]] = load i1, ptr
|
||||
// CHECK: [[PAYLOAD1:%[0-9]+]] = load i8, ptr
|
||||
%1 = load %0 : $*TwoCasesNoPayload
|
||||
|
||||
%2 = integer_literal $Builtin.Int32, 2
|
||||
%3 = integer_literal $Builtin.Int32, 42
|
||||
|
||||
// CHECK-NEXT: [[V2:%[0-9]+]] = icmp eq i1 [[PAYLOAD1]], false
|
||||
// CHECK-NEXT: [[V2:%[0-9]+]] = icmp eq i8 [[PAYLOAD1]], 0
|
||||
// CHECK-NEXT: select i1 [[V2]], i32 2, i32 42
|
||||
%4 = select_enum %1 : $TwoCasesNoPayload, case #TwoCasesNoPayload.X!enumelt: %2, case #TwoCasesNoPayload.Y!enumelt: %3 : $Builtin.Int32
|
||||
|
||||
// CHECK-NEXT: [[V2:%[0-9]+]] = icmp eq i1 [[PAYLOAD1]], true
|
||||
// CHECK-NEXT: [[V2:%[0-9]+]] = icmp eq i8 [[PAYLOAD1]], 1
|
||||
// CHECK-NEXT: select i1 [[V2]], i32 42, i32 2
|
||||
%5 = select_enum %1 : $TwoCasesNoPayload, case #TwoCasesNoPayload.Y!enumelt: %3, default %2 : $Builtin.Int32
|
||||
|
||||
@@ -82,7 +86,7 @@ enum NoPayloadSingleton {
|
||||
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @testOptionalOfNoPayloadSingleton(i8 %0)
|
||||
sil @testOptionalOfNoPayloadSingleton : $@convention(thin) (MyOptional<NoPayloadSingleton>) -> Builtin.Int1 {
|
||||
bb0(%0 : $MyOptional<NoPayloadSingleton>):
|
||||
// CHECK: [[NATIVECCTRUNC:%.*]] = trunc i8 %0 to i1
|
||||
// CHECK: [[NATIVECCTRUNC:%.*]] = icmp eq i8 %0, 1
|
||||
// CHECK: [[NOT:%.*]] = xor i1 [[NATIVECCTRUNC]], true
|
||||
// CHECK: ret i1 [[NOT]]
|
||||
%4 = integer_literal $Builtin.Int1, -1 // users: %6, %7
|
||||
|
||||
@@ -13,9 +13,10 @@ enum ManyEmptyCases {
|
||||
|
||||
// CHECK-LABEL-64: define{{( protected)?}} swiftcc i1 @select_enum_A(i64)
|
||||
// CHECK-64: %2 = load i32, ptr %temp-coercion.coerced
|
||||
// CHECK-64: %4 = load i1, ptr %3
|
||||
// CHECK-64: %4 = load i8, ptr %3
|
||||
// CHECK-64: [[PAYLOAD:%.*]] = icmp eq i32 %2, 0
|
||||
// CHECK-64: [[EXTRA:%.*]] = and i1 %4, [[PAYLOAD]]
|
||||
// CHECK-64: [[TAG_TRUNC:%.*]] = icmp eq i8 %4, 1
|
||||
// CHECK-64: [[EXTRA:%.*]] = and i1 [[TAG_TRUNC]], [[PAYLOAD]]
|
||||
// CHECK-64: ret i1 [[EXTRA]]
|
||||
|
||||
// CHECK-LABEL-32: define{{( protected)?}} swiftcc i1 @select_enum_A(i32, i8) {{.*}}{
|
||||
@@ -34,9 +35,10 @@ entry(%0 : $ManyEmptyCases):
|
||||
|
||||
// CHECK-LABEL-64: define{{( protected)?}} swiftcc i1 @select_enum_B(i64)
|
||||
// CHECK-64: %2 = load i32, ptr %temp-coercion.coerced
|
||||
// CHECK-64: %4 = load i1, ptr %3
|
||||
// CHECK-64: %4 = load i8, ptr %3
|
||||
// CHECK-64: [[PAYLOAD:%.*]] = icmp eq i32 %2, 1
|
||||
// CHECK-64: [[EXTRA:%.*]] = and i1 %4, [[PAYLOAD]]
|
||||
// CHECK-64: [[TAG_TRUNC:%.*]] = icmp eq i8 %4, 1
|
||||
// CHECK-64: [[EXTRA:%.*]] = and i1 [[TAG_TRUNC]], [[PAYLOAD]]
|
||||
// CHECK-64: ret i1 [[EXTRA]]
|
||||
|
||||
// CHECK-LABEL-32: define{{( protected)?}} swiftcc i1 @select_enum_A(i32, i8) {{.*}}{
|
||||
|
||||
@@ -95,7 +95,7 @@ sil_global @static_optional_int_vector : $Optional<Int32> = {
|
||||
%8 = enum $Optional<Int32>, #Optional.some!enumelt, %5 : $Int32
|
||||
%initval = vector (%6 : $Optional<Int32>, %7 : $Optional<Int32>, %8 : $Optional<Int32>)
|
||||
}
|
||||
// CHECK: @static_optional_int_vector = {{(dllexport )?}}{{(protected )?}}global [3 x <{ i32, i1, i8, i8, i8 }>] [<{ i32, i1, i8, i8, i8 }> <{ i32 2, i1 false, i8 undef, i8 undef, i8 undef }>, <{ i32, i1, i8, i8, i8 }> <{ i32 10, i1 false, i8 undef, i8 undef, i8 undef }>, <{ i32, i1, i8, i8, i8 }> <{ i32 20, i1 false, i8 undef, i8 undef, i8 undef }>], align 4
|
||||
// CHECK: @static_optional_int_vector = {{(dllexport )?}}{{(protected )?}}global [3 x <{ i32, i8, i8, i8, i8 }>] [<{ i32, i8, i8, i8, i8 }> <{ i32 2, i8 0, i8 undef, i8 undef, i8 undef }>, <{ i32, i8, i8, i8, i8 }> <{ i32 10, i8 0, i8 undef, i8 undef, i8 undef }>, <{ i32, i8, i8, i8, i8 }> <{ i32 20, i8 0, i8 undef, i8 undef, i8 undef }>], align 4
|
||||
|
||||
sil_global @static_aligned_array : $TestArrayStorage = {
|
||||
%0 = integer_literal $Builtin.Int32, 2
|
||||
|
||||
49
validation-test/IRGen/rdar149985633.swift
Normal file
49
validation-test/IRGen/rdar149985633.swift
Normal file
@@ -0,0 +1,49 @@
|
||||
// RUN: %target-swift-frontend -O -emit-ir %s | %FileCheck %s
|
||||
|
||||
// REQUIRES: PTRSIZE=64
|
||||
|
||||
// CHECK: define {{.*}}swiftcc void @"$s13rdar1499856334DateV1a1b1c1d1e1fACSiSg_A5JtcfC"(ptr noalias nocapture writeonly sret(%T13rdar1499856334DateV) %0, i64 %1, i8 %2, i64 %3, i8 %4, i64 %5, i8 %6, i64 %7, i8 %8, i64 %9, i8 %10, i64 %11, i8 %12)
|
||||
// CHECK: entry:
|
||||
// CHECK: store i64 %1
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 8
|
||||
// CHECK: store i8 %2
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 16
|
||||
// CHECK: store i64 %3
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 24
|
||||
// CHECK: store i8 %4
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 32
|
||||
// CHECK: store i64 %5
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 40
|
||||
// CHECK: store i8 %6
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 48
|
||||
// CHECK: store i64 %7
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 56
|
||||
// CHECK: store i8 %8
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 64
|
||||
// CHECK: store i64 %9
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 72
|
||||
// CHECK: store i8 %10
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 80
|
||||
// CHECK: store i64 %11
|
||||
// CHECK: getelementptr inbounds i8, ptr %0, i64 88
|
||||
// CHECK: store i8 %12
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
|
||||
public struct Date {
|
||||
internal var a: Int?
|
||||
internal var b: Int?
|
||||
internal var c: Int?
|
||||
internal var d: Int?
|
||||
internal var e: Int?
|
||||
internal var f: Int?
|
||||
|
||||
public init(a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?) {
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.c = c
|
||||
self.d = d
|
||||
self.e = e
|
||||
self.f = f
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user