| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt < %s -passes=infer-alignment -S | FileCheck %s |
| %struct.S1 = type { %struct.float3, %struct.float3, i32, i32 } |
| %struct.float3 = type { float, float, float } |
| |
| |
| ; ------------------------------------------------------------------------------ |
| ; Test that we can propagate the align 16 to the load and store that are set to align 4 |
| ; ------------------------------------------------------------------------------ |
| |
| define void @prop_align(ptr %v, ptr %vout) { |
| ; CHECK-LABEL: define void @prop_align( |
| ; CHECK-SAME: ptr [[V:%.*]], ptr [[VOUT:%.*]]) { |
| ; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load float, ptr [[V]], align 16 |
| ; CHECK-NEXT: [[DOTUNPACK_ELT7:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 4 |
| ; CHECK-NEXT: [[DOTUNPACK_UNPACK8:%.*]] = load float, ptr [[DOTUNPACK_ELT7]], align 4 |
| ; CHECK-NEXT: [[DOTUNPACK_ELT9:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8 |
| ; CHECK-NEXT: [[DOTUNPACK_UNPACK10:%.*]] = load float, ptr [[DOTUNPACK_ELT9]], align 8 |
| ; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 12 |
| ; CHECK-NEXT: [[DOTUNPACK2_UNPACK:%.*]] = load float, ptr [[DOTELT1]], align 4 |
| ; CHECK-NEXT: [[DOTUNPACK2_ELT12:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 16 |
| ; CHECK-NEXT: [[DOTUNPACK2_UNPACK13:%.*]] = load float, ptr [[DOTUNPACK2_ELT12]], align 16 |
| ; CHECK-NEXT: [[DOTUNPACK2_ELT14:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 20 |
| ; CHECK-NEXT: [[DOTUNPACK2_UNPACK15:%.*]] = load float, ptr [[DOTUNPACK2_ELT14]], align 4 |
| ; CHECK-NEXT: [[DOTELT3:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 24 |
| ; CHECK-NEXT: [[DOTUNPACK4:%.*]] = load i32, ptr [[DOTELT3]], align 8 |
| ; CHECK-NEXT: [[DOTELT5:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 28 |
| ; CHECK-NEXT: [[DOTUNPACK6:%.*]] = load i32, ptr [[DOTELT5]], align 4 |
| ; CHECK-NEXT: store float [[DOTUNPACK_UNPACK]], ptr [[VOUT]], align 16 |
| ; CHECK-NEXT: [[VOUT_REPACK23:%.*]] = getelementptr inbounds nuw i8, ptr [[VOUT]], i64 4 |
| ; CHECK-NEXT: store float [[DOTUNPACK_UNPACK8]], ptr [[VOUT_REPACK23]], align 4 |
| ; CHECK-NEXT: [[VOUT_REPACK25:%.*]] = getelementptr inbounds nuw i8, ptr [[VOUT]], i64 8 |
| ; CHECK-NEXT: store float [[DOTUNPACK_UNPACK10]], ptr [[VOUT_REPACK25]], align 8 |
| ; CHECK-NEXT: [[VOUT_REPACK17:%.*]] = getelementptr inbounds nuw i8, ptr [[VOUT]], i64 12 |
| ; CHECK-NEXT: store float [[DOTUNPACK2_UNPACK]], ptr [[VOUT_REPACK17]], align 4 |
| ; CHECK-NEXT: [[VOUT_REPACK17_REPACK27:%.*]] = getelementptr inbounds nuw i8, ptr [[VOUT]], i64 16 |
| ; CHECK-NEXT: store float [[DOTUNPACK2_UNPACK13]], ptr [[VOUT_REPACK17_REPACK27]], align 16 |
| ; CHECK-NEXT: [[VOUT_REPACK17_REPACK29:%.*]] = getelementptr inbounds nuw i8, ptr [[VOUT]], i64 20 |
| ; CHECK-NEXT: store float [[DOTUNPACK2_UNPACK15]], ptr [[VOUT_REPACK17_REPACK29]], align 4 |
| ; CHECK-NEXT: [[VOUT_REPACK19:%.*]] = getelementptr inbounds nuw i8, ptr [[VOUT]], i64 24 |
| ; CHECK-NEXT: store i32 [[DOTUNPACK4]], ptr [[VOUT_REPACK19]], align 8 |
| ; CHECK-NEXT: [[VOUT_REPACK21:%.*]] = getelementptr inbounds nuw i8, ptr [[VOUT]], i64 28 |
| ; CHECK-NEXT: store i32 [[DOTUNPACK6]], ptr [[VOUT_REPACK21]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| %.unpack.unpack = load float, ptr %v, align 16 |
| %.unpack.elt7 = getelementptr inbounds nuw i8, ptr %v, i64 4 |
| %.unpack.unpack8 = load float, ptr %.unpack.elt7, align 4 |
| %.unpack.elt9 = getelementptr inbounds nuw i8, ptr %v, i64 8 |
| %.unpack.unpack10 = load float, ptr %.unpack.elt9, align 8 |
| %.elt1 = getelementptr inbounds nuw i8, ptr %v, i64 12 |
| %.unpack2.unpack = load float, ptr %.elt1, align 4 |
| %.unpack2.elt12 = getelementptr inbounds nuw i8, ptr %v, i64 16 |
| %.unpack2.unpack13 = load float, ptr %.unpack2.elt12, align 4 |
| %.unpack2.elt14 = getelementptr inbounds nuw i8, ptr %v, i64 20 |
| %.unpack2.unpack15 = load float, ptr %.unpack2.elt14, align 4 |
| %.elt3 = getelementptr inbounds nuw i8, ptr %v, i64 24 |
| %.unpack4 = load i32, ptr %.elt3, align 8 |
| %.elt5 = getelementptr inbounds nuw i8, ptr %v, i64 28 |
| %.unpack6 = load i32, ptr %.elt5, align 4 |
| store float %.unpack.unpack, ptr %vout, align 16 |
| %vout.repack23 = getelementptr inbounds nuw i8, ptr %vout, i64 4 |
| store float %.unpack.unpack8, ptr %vout.repack23, align 4 |
| %vout.repack25 = getelementptr inbounds nuw i8, ptr %vout, i64 8 |
| store float %.unpack.unpack10, ptr %vout.repack25, align 8 |
| %vout.repack17 = getelementptr inbounds nuw i8, ptr %vout, i64 12 |
| store float %.unpack2.unpack, ptr %vout.repack17, align 4 |
| %vout.repack17.repack27 = getelementptr inbounds nuw i8, ptr %vout, i64 16 |
| store float %.unpack2.unpack13, ptr %vout.repack17.repack27, align 4 |
| %vout.repack17.repack29 = getelementptr inbounds nuw i8, ptr %vout, i64 20 |
| store float %.unpack2.unpack15, ptr %vout.repack17.repack29, align 4 |
| %vout.repack19 = getelementptr inbounds nuw i8, ptr %vout, i64 24 |
| store i32 %.unpack4, ptr %vout.repack19, align 8 |
| %vout.repack21 = getelementptr inbounds nuw i8, ptr %vout, i64 28 |
| store i32 %.unpack6, ptr %vout.repack21, align 4 |
| ret void |
| } |
| |
| ; ------------------------------------------------------------------------------ |
| ; Test that alignment is not propagated from a source that does not dominate the destination |
| ; ------------------------------------------------------------------------------ |
| |
| define void @no_prop_align(ptr %v, ptr %vout, i1 %cond) { |
| ; CHECK-LABEL: define void @no_prop_align( |
| ; CHECK-SAME: ptr [[V:%.*]], ptr [[VOUT:%.*]], i1 [[COND:%.*]]) { |
| ; CHECK-NEXT: br i1 [[COND]], label %[[BRANCH1:.*]], label %[[BRANCH2:.*]] |
| ; CHECK: [[BRANCH1]]: |
| ; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load float, ptr [[V]], align 16 |
| ; CHECK-NEXT: [[DOTUNPACK_ELT7:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 4 |
| ; CHECK-NEXT: [[DOTUNPACK_UNPACK8:%.*]] = load float, ptr [[DOTUNPACK_ELT7]], align 4 |
| ; CHECK-NEXT: [[DOTUNPACK_ELT9:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8 |
| ; CHECK-NEXT: [[DOTUNPACK_UNPACK10:%.*]] = load float, ptr [[DOTUNPACK_ELT9]], align 8 |
| ; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 12 |
| ; CHECK-NEXT: [[DOTUNPACK2_UNPACK:%.*]] = load float, ptr [[DOTELT1]], align 4 |
| ; CHECK-NEXT: br label %[[END:.*]] |
| ; CHECK: [[BRANCH2]]: |
| ; CHECK-NEXT: [[DOTUNPACK2_ELT12:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 16 |
| ; CHECK-NEXT: [[DOTUNPACK2_UNPACK13:%.*]] = load float, ptr [[DOTUNPACK2_ELT12]], align 4 |
| ; CHECK-NEXT: [[DOTUNPACK2_ELT14:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 20 |
| ; CHECK-NEXT: [[DOTUNPACK2_UNPACK15:%.*]] = load float, ptr [[DOTUNPACK2_ELT14]], align 4 |
| ; CHECK-NEXT: [[DOTELT3:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 24 |
| ; CHECK-NEXT: [[DOTUNPACK4:%.*]] = load i32, ptr [[DOTELT3]], align 8 |
| ; CHECK-NEXT: [[DOTELT5:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 28 |
| ; CHECK-NEXT: [[DOTUNPACK6:%.*]] = load i32, ptr [[DOTELT5]], align 4 |
| ; CHECK-NEXT: br label %[[END]] |
| ; CHECK: [[END]]: |
| ; CHECK-NEXT: ret void |
| ; |
| br i1 %cond, label %branch1, label %branch2 |
| |
| branch1: |
| %.unpack.unpack = load float, ptr %v, align 16 |
| %.unpack.elt7 = getelementptr inbounds nuw i8, ptr %v, i64 4 |
| %.unpack.unpack8 = load float, ptr %.unpack.elt7, align 4 |
| %.unpack.elt9 = getelementptr inbounds nuw i8, ptr %v, i64 8 |
| %.unpack.unpack10 = load float, ptr %.unpack.elt9, align 8 |
| %.elt1 = getelementptr inbounds nuw i8, ptr %v, i64 12 |
| %.unpack2.unpack = load float, ptr %.elt1, align 4 |
| br label %end |
| |
| branch2: |
| %.unpack2.elt12 = getelementptr inbounds nuw i8, ptr %v, i64 16 |
| %.unpack2.unpack13 = load float, ptr %.unpack2.elt12, align 4 |
| %.unpack2.elt14 = getelementptr inbounds nuw i8, ptr %v, i64 20 |
| %.unpack2.unpack15 = load float, ptr %.unpack2.elt14, align 4 |
| %.elt3 = getelementptr inbounds nuw i8, ptr %v, i64 24 |
| %.unpack4 = load i32, ptr %.elt3, align 8 |
| %.elt5 = getelementptr inbounds nuw i8, ptr %v, i64 28 |
| %.unpack6 = load i32, ptr %.elt5, align 4 |
| br label %end |
| |
| end: |
| ret void |
| } |
| |
| ; ------------------------------------------------------------------------------ |
| ; Test that we can propagate to/from negative offset GEPs |
| ; ------------------------------------------------------------------------------ |
| |
| define void @prop_align_negative_offset(ptr %v) { |
| ; CHECK-LABEL: define void @prop_align_negative_offset( |
| ; CHECK-SAME: ptr [[V:%.*]]) { |
| ; CHECK-NEXT: [[LOADALIGNED:%.*]] = load float, ptr [[V]], align 16 |
| ; CHECK-NEXT: [[GEPNEGATIVE:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 -16 |
| ; CHECK-NEXT: [[LOADUNALIGNED:%.*]] = load float, ptr [[GEPNEGATIVE]], align 16 |
| ; CHECK-NEXT: ret void |
| ; |
| %loadAligned= load float, ptr %v, align 16 |
| %gepNegative = getelementptr inbounds nuw i8, ptr %v, i64 -16 |
| %loadUnaligned = load float, ptr %gepNegative, align 4 |
| ret void |
| } |
| |
| define void @prop_align_negative_offset_2(ptr %v) { |
| ; CHECK-LABEL: define void @prop_align_negative_offset_2( |
| ; CHECK-SAME: ptr [[V:%.*]]) { |
| ; CHECK-NEXT: [[GEPNEGATIVE:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 -16 |
| ; CHECK-NEXT: [[LOADALIGNED:%.*]] = load float, ptr [[GEPNEGATIVE]], align 16 |
| ; CHECK-NEXT: [[LOADUNALIGNED:%.*]] = load float, ptr [[V]], align 16 |
| ; CHECK-NEXT: ret void |
| ; |
| %gepNegative = getelementptr inbounds nuw i8, ptr %v, i64 -16 |
| %loadAligned = load float, ptr %gepNegative, align 16 |
| %loadUnaligned= load float, ptr %v, align 4 |
| ret void |
| } |
| |
| define void @prop_align_negative_offset_3(ptr %v) { |
| ; CHECK-LABEL: define void @prop_align_negative_offset_3( |
| ; CHECK-SAME: ptr [[V:%.*]]) { |
| ; CHECK-NEXT: [[LOADALIGNED:%.*]] = load float, ptr [[V]], align 16 |
| ; CHECK-NEXT: [[GEPNEGATIVE:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 -8 |
| ; CHECK-NEXT: [[LOADUNALIGNED:%.*]] = load float, ptr [[GEPNEGATIVE]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| %loadAligned= load float, ptr %v, align 16 |
| %gepNegative = getelementptr inbounds nuw i8, ptr %v, i64 -8 |
| %loadUnaligned = load float, ptr %gepNegative, align 4 |
| ret void |
| } |
| |
| define void @prop_align_negative_offset_4(ptr %v) { |
| ; CHECK-LABEL: define void @prop_align_negative_offset_4( |
| ; CHECK-SAME: ptr [[V:%.*]]) { |
| ; CHECK-NEXT: [[LOADALIGNED:%.*]] = load float, ptr [[V]], align 16 |
| ; CHECK-NEXT: [[GEPNEGATIVE:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 -20 |
| ; CHECK-NEXT: [[LOADUNALIGNED:%.*]] = load float, ptr [[GEPNEGATIVE]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| %loadAligned= load float, ptr %v, align 16 |
| %gepNegative = getelementptr inbounds nuw i8, ptr %v, i64 -20 |
| %loadUnaligned = load float, ptr %gepNegative, align 4 |
| ret void |
| } |