diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp index 15caf9a2c5331..350fdc69a164f 100644 --- a/lib/IRGen/LoadableByAddress.cpp +++ b/lib/IRGen/LoadableByAddress.cpp @@ -3504,6 +3504,8 @@ class LargeLoadableHeuristic { bool isLargeLoadableType(SILType ty); bool isPotentiallyCArray(SILType ty); + void propagate(PostOrderFunctionInfo &po); + private: bool isLargeLoadableTypeOld(SILType ty); @@ -3545,6 +3547,32 @@ class LargeLoadableHeuristic { }; } +void LargeLoadableHeuristic::propagate(PostOrderFunctionInfo &po) { + if (!UseAggressiveHeuristic) + return; + + for (auto *BB : po.getPostOrder()) { + for (auto &I : llvm::reverse(*BB)) { + switch (I.getKind()) { + case SILInstructionKind::TupleExtractInst: + case SILInstructionKind::StructExtractInst: { + auto &proj = cast(I); + if (isLargeLoadableType(proj.getType())) { + auto opdTy = proj.getOperand(0)->getType(); + auto entry = largeTypeProperties[opdTy]; + entry.setNumRegisters(65535); + largeTypeProperties[opdTy] = entry; + } + } + break; + + default: + continue; + } + } + } +} + void LargeLoadableHeuristic::visit(SILArgument *arg) { auto objType = arg->getType().getObjectType(); if (numRegisters(objType) < NumRegistersLargeType) @@ -4659,6 +4687,9 @@ static void runPeepholesAndReg2Mem(SILPassManager *pm, SILModule *silMod, // Delete replaced instructions. opts.deleteInstructions(); + PostOrderFunctionInfo postorderInfo(&currF); + heuristic.propagate(postorderInfo); + AddressAssignment assignment(heuristic, irgenModule, currF); // Assign addresses to basic block arguments. @@ -4729,7 +4760,6 @@ static void runPeepholesAndReg2Mem(SILPassManager *pm, SILModule *silMod, } // Asign addresses to non-address SSA values. - PostOrderFunctionInfo postorderInfo(&currF); for (auto *BB : postorderInfo.getReversePostOrder()) { SmallVector origInsts; for (SILInstruction &i : *BB) { diff --git a/test/IRGen/Inputs/large_c.h b/test/IRGen/Inputs/large_c.h index 9c1e690ddab8e..b8e2ff880b6d9 100644 --- a/test/IRGen/Inputs/large_c.h +++ b/test/IRGen/Inputs/large_c.h @@ -78,3 +78,19 @@ typedef union { unsigned char cnt; } out; } union_t; + + +typedef enum { + TYPE1, + TYPE2, + TYPE3 +} member_type_t; + +typedef unsigned char uuid_t[16]; +typedef struct { + member_type_t member_type; + union { + uuid_t uuid; + unsigned x; + } member_value; +} member_id_t; diff --git a/test/IRGen/loadable_by_address_reg2mem.sil b/test/IRGen/loadable_by_address_reg2mem.sil index 7dc645fc9d30a..66d20aa78b16a 100644 --- a/test/IRGen/loadable_by_address_reg2mem.sil +++ b/test/IRGen/loadable_by_address_reg2mem.sil @@ -1,5 +1,10 @@ // RUN: %target-swift-frontend %s -Xllvm -sil-print-types -Xllvm -sil-print-after=loadable-address -import-objc-header %S/Inputs/large_c.h -c -o %t/t.o 2>&1 | %FileCheck %s +// wasm currently disables aggressive reg2mem +// UNSUPPORTED: wasm +// UNSUPPORTED: OS=wasi +// UNSUPPORTED: CPU=wasm32 + sil_stage canonical import Builtin @@ -397,3 +402,25 @@ bb3(%4 : $X): %t = tuple () return %t : $() } + +sil @usei8 : $@convention(thin) (UInt8) -> () + +// CHECK: sil @test16 +// CHECK: bb0(%0 : $member_id_t): +// CHECK: [[T0:%.*]] = alloc_stack $member_id_t +// CHECK: store %0 to [[T0]] : $*member_id_t +// CHECK: struct_element_addr [[T0]] +// CHECK:} // end sil function 'test16' + +sil @test16 : $@convention(thin) (member_id_t) -> () { +bb0(%0 : $member_id_t): + %2 = alloc_stack $X + %44 = struct_extract %0 : $member_id_t, #member_id_t.member_value // user: %45 + %45 = unchecked_trivial_bit_cast %44 : $member_id_t.__Unnamed_union_member_value to $(UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) + %46 = tuple_extract %45 : $(UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8), 0 + %11 = function_ref @usei8 : $@convention(thin) (UInt8) -> () + %12 = apply %11(%46) : $@convention(thin) (UInt8) -> () + dealloc_stack %2 : $*X + %13 = tuple () + return %13 : $() +}