1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -inline -instcombine %s | FileCheck %s --check-prefixes=CHECK,CHECK-INLINE 3; RUN: opt -S -instcombine %s | FileCheck %s --check-prefixes=CHECK,CHECK-NOINLINE 4 5define i8* @widen_align_from_allocalign_callsite() { 6; CHECK-LABEL: @widen_align_from_allocalign_callsite( 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[CALL:%.*]] = tail call align 64 i8* @my_aligned_alloc_2(i32 noundef 320, i32 allocalign noundef 64) 9; CHECK-NEXT: ret i8* [[CALL]] 10; 11entry: 12 13 %call = tail call align 16 i8* @my_aligned_alloc_2(i32 noundef 320, i32 allocalign noundef 64) 14 ret i8* %call 15} 16 17define i8* @widen_align_from_allocalign() { 18; CHECK-LABEL: @widen_align_from_allocalign( 19; CHECK-NEXT: entry: 20; CHECK-NEXT: [[CALL:%.*]] = tail call align 64 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef 64) 21; CHECK-NEXT: ret i8* [[CALL]] 22; 23entry: 24 25 %call = tail call align 16 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef 64) 26 ret i8* %call 27} 28 29define i8* @dont_narrow_align_from_allocalign() { 30; CHECK-LABEL: @dont_narrow_align_from_allocalign( 31; CHECK-NEXT: entry: 32; CHECK-NEXT: [[CALL:%.*]] = tail call align 16 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef 8) 33; CHECK-NEXT: ret i8* [[CALL]] 34; 35entry: 36 %call = tail call align 16 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef 8) 37 ret i8* %call 38} 39 40define i8* @my_aligned_alloc_3(i32 noundef %foo, i32 allocalign %alignment) { 41; CHECK-LABEL: @my_aligned_alloc_3( 42; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @my_aligned_alloc_2(i32 noundef [[FOO:%.*]], i32 noundef [[ALIGNMENT:%.*]]) 43; CHECK-NEXT: ret i8* [[CALL]] 44; 45 %call = tail call i8* @my_aligned_alloc_2(i32 noundef %foo, i32 noundef %alignment) 46 ret i8* %call 47} 48 49; -inline is able to make my_aligned_alloc_3's arguments disappear and directly 50; call my_aligned_alloc_2, but the latter has no allocalign so the alignment just 51; disappears. This is conservatively correct but undesirable because we can't 52; figure out the `align 128` on the return value once the call is directly on 53; my_aligned_alloc_2. Note that this is a simplified version of what happens 54; with _mm_malloc which calls posix_memalign. 55define i8* @allocalign_disappears() { 56; CHECK-INLINE-LABEL: @allocalign_disappears( 57; CHECK-INLINE-NEXT: [[CALL_I:%.*]] = tail call i8* @my_aligned_alloc_2(i32 noundef 42, i32 noundef 128) 58; CHECK-INLINE-NEXT: ret i8* [[CALL_I]] 59; 60; CHECK-NOINLINE-LABEL: @allocalign_disappears( 61; CHECK-NOINLINE-NEXT: [[CALL:%.*]] = tail call align 128 i8* @my_aligned_alloc_3(i32 42, i32 128) 62; CHECK-NOINLINE-NEXT: ret i8* [[CALL]] 63; 64 %call = tail call i8* @my_aligned_alloc_3(i32 42, i32 128) 65 ret i8* %call 66} 67 68declare i8* @my_aligned_alloc(i32 noundef, i32 allocalign noundef) 69declare i8* @my_aligned_alloc_2(i32 noundef, i32 noundef) 70