@@ -218,6 +218,95 @@ SILInstruction *SILCombiner::visitUpcastInst(UpcastInst *uci) {
218218 return nullptr ;
219219}
220220
221+ // Optimize Builtin.assumeAlignment -> pointer_to_address
222+ //
223+ // Case #1. Literal zero = natural alignment
224+ // %1 = integer_literal $Builtin.Int64, 0
225+ // %2 = builtin "assumeAlignment"
226+ // (%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
227+ // %3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*Int
228+ //
229+ // Erases the `pointer_to_address` `[align=]` attribute:
230+ //
231+ // Case #2. Literal nonzero = forced alignment.
232+ //
233+ // %1 = integer_literal $Builtin.Int64, 16
234+ // %2 = builtin "assumeAlignment"
235+ // (%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
236+ // %3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*Int
237+ //
238+ // Promotes the `pointer_to_address` `[align=]` attribute to a higher value.
239+ //
240+ // Case #3. Folded dynamic alignment
241+ //
242+ // %1 = builtin "alignof"<T>(%0 : $@thin T.Type) : $Builtin.Word
243+ // %2 = builtin "assumeAlignment"
244+ // (%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
245+ // %3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*T
246+ //
247+ // Erases the `pointer_to_address` `[align=]` attribute.
248+ SILInstruction *
249+ SILCombiner::optimizeAlignment (PointerToAddressInst *ptrAdrInst) {
250+ if (!ptrAdrInst->alignment ())
251+ return nullptr ;
252+
253+ llvm::Align oldAlign = ptrAdrInst->alignment ().valueOrOne ();
254+
255+ // TODO: stripCasts(ptrAdrInst->getOperand()) can be used to find the Builtin,
256+ // but then the Builtin could not be trivially removed. Ideally,
257+ // Builtin.assume will be the immediate operand so it can be removed in the
258+ // common case.
259+ BuiltinInst *assumeAlign = dyn_cast<BuiltinInst>(ptrAdrInst->getOperand ());
260+ if (!assumeAlign
261+ || assumeAlign->getBuiltinKind () != BuiltinValueKind::AssumeAlignment) {
262+ return nullptr ;
263+ }
264+ SILValue ptrSrc = assumeAlign->getArguments ()[0 ];
265+ SILValue alignOper = assumeAlign->getArguments ()[1 ];
266+
267+ if (auto *integerInst = dyn_cast<IntegerLiteralInst>(alignOper)) {
268+ llvm::MaybeAlign newAlign (integerInst->getValue ().getLimitedValue ());
269+ if (newAlign && newAlign.valueOrOne () <= oldAlign)
270+ return nullptr ;
271+
272+ // Case #1: the pointer is assumed naturally aligned
273+ //
274+ // Or Case #2: the pointer is assumed to have non-zero alignment greater
275+ // than it current alignment.
276+ //
277+ // In either case, rewrite the address alignment with the assumed alignment,
278+ // and bypass the Builtin.assumeAlign.
279+ return Builder.createPointerToAddress (
280+ ptrAdrInst->getLoc (), ptrSrc, ptrAdrInst->getType (),
281+ ptrAdrInst->isStrict (), ptrAdrInst->isInvariant (), newAlign);
282+ }
283+ // Handle possible 32-bit sign-extension.
284+ SILValue extendedAlignment;
285+ if (match (alignOper,
286+ m_ApplyInst (BuiltinValueKind::SExtOrBitCast,
287+ m_ApplyInst (BuiltinValueKind::TruncOrBitCast,
288+ m_SILValue (extendedAlignment))))) {
289+ alignOper = extendedAlignment;
290+ }
291+ MetatypeInst *metatype;
292+ if (match (alignOper,
293+ m_ApplyInst (BuiltinValueKind::Alignof, m_MetatypeInst (metatype)))) {
294+ SILType instanceType = ptrAdrInst->getFunction ()->getLoweredType (
295+ metatype->getType ().castTo <MetatypeType>().getInstanceType ());
296+
297+ if (instanceType.getAddressType () != ptrAdrInst->getType ())
298+ return nullptr ;
299+
300+ // Case #3: the alignOf type matches the address type. Convert to a
301+ // naturally aligned pointer by erasing alignment and bypassing the
302+ // Builtin.assumeAlign.
303+ return Builder.createPointerToAddress (
304+ ptrAdrInst->getLoc (), ptrSrc, ptrAdrInst->getType (),
305+ ptrAdrInst->isStrict (), ptrAdrInst->isInvariant ());
306+ }
307+ return nullptr ;
308+ }
309+
221310SILInstruction *
222311SILCombiner::
223312visitPointerToAddressInst (PointerToAddressInst *PTAI) {
@@ -374,7 +463,7 @@ visitPointerToAddressInst(PointerToAddressInst *PTAI) {
374463 }
375464 }
376465
377- return nullptr ;
466+ return optimizeAlignment (PTAI) ;
378467}
379468
380469SILInstruction *
0 commit comments