| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals |
| ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT |
| ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC |
| |
| %struct.T = type { i32, [10 x [20 x i8]] } |
| |
| declare noalias ptr @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" |
| |
| define i8 @select_offsets_simplifiable_1(i1 %cnd1, i1 %cnd2) { |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_1 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1) |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: store i8 23, ptr [[GEP23]], align 4 |
| ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29 |
| ; CHECK-NEXT: store i8 29, ptr [[GEP29]], align 4 |
| ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7 |
| ; CHECK-NEXT: store i8 7, ptr [[GEP7]], align 4 |
| ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31 |
| ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]] |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_SEL]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = call ptr @calloc(i64 1024, i64 1) |
| |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| store i8 23, ptr %gep23, align 4 |
| %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29 |
| store i8 29, ptr %gep29, align 4 |
| %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7 |
| store i8 7, ptr %gep7, align 4 |
| |
| ;; This store is redundant, hence removed. |
| %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31 |
| store i8 42, ptr %gep31, align 4 |
| |
| %sel0 = select i1 %cnd1, i64 23, i64 29 |
| %sel1 = select i1 %cnd2, i64 %sel0, i64 7 |
| %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1 |
| %i = load i8, ptr %gep.sel, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_offsets_simplifiable_2(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_2 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: store i8 23, ptr [[GEP23]], align 4 |
| ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29 |
| ; CHECK-NEXT: store i8 29, ptr [[GEP29]], align 4 |
| ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7 |
| ; CHECK-NEXT: store i8 7, ptr [[GEP7]], align 4 |
| ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31 |
| ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 20, i64 26 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 4 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]] |
| ; CHECK-NEXT: [[GEP_PLUS:%.*]] = getelementptr inbounds i8, ptr [[GEP_SEL]], i64 3 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_PLUS]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| store i8 23, ptr %gep23, align 4 |
| %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29 |
| store i8 29, ptr %gep29, align 4 |
| %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7 |
| store i8 7, ptr %gep7, align 4 |
| |
| ;; This store is redundant, hence removed. |
| %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31 |
| store i8 42, ptr %gep31, align 4 |
| |
| ;; Adjust the offsets so that they match the stores after adding 3 |
| %sel0 = select i1 %cnd1, i64 20, i64 26 |
| %sel1 = select i1 %cnd2, i64 %sel0, i64 4 |
| %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1 |
| %gep.plus = getelementptr inbounds i8, ptr %gep.sel, i64 3 |
| %i = load i8, ptr %gep.plus, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_offsets_simplifiable_3(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_3 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BUNDLE:%.*]] = alloca [[STRUCT_T:%.*]], align 64 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND1]], i64 1, i64 3 |
| ; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CND2]], i64 5, i64 11 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [[STRUCT_T]], ptr [[BUNDLE]], i64 0, i32 1, i64 [[SEL1]], i64 [[SEL2]] |
| ; CHECK-NEXT: ret i8 100 |
| ; |
| entry: |
| %bundle = alloca %struct.T, align 64 |
| %gep.fixed = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 1, i64 1 |
| store i8 100, ptr %gep.fixed, align 4 |
| %sel1 = select i1 %cnd1, i64 1, i64 3 |
| %sel2 = select i1 %cnd2, i64 5, i64 11 |
| %gep.sel = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 %sel1, i64 %sel2 |
| store i8 42, ptr %gep.sel, align 4 |
| %i = load i8, ptr %gep.fixed, align 4 |
| ret i8 %i |
| } |
| |
| ; Similar to select_offsets_not_simplifiable_3 but with uninitialized memory. |
| define i8 @select_offsets_simplifiable_4(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_4 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]] |
| ; CHECK-NEXT: ret i8 100 |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| %sel0 = select i1 %cnd1, i64 23, i64 29 |
| %sel1 = select i1 %cnd2, i64 %sel0, i64 7 |
| %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1 |
| store i8 100, ptr %gep.sel, align 4 |
| %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29 |
| %i = load i8, ptr %gep29, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_offsets_not_simplifiable_1(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_1 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7 |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: store i8 100, ptr [[GEP23]], align 4 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]] |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_SEL]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| %sel0 = select i1 %cnd1, i64 23, i64 29 |
| %sel1 = select i1 %cnd2, i64 %sel0, i64 7 |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| store i8 100, ptr %gep23, align 4 |
| %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1 |
| %i = load i8, ptr %gep.sel, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_offsets_not_simplifiable_2(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_2 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7 |
| ; CHECK-NEXT: [[GEP32:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 32 |
| ; CHECK-NEXT: store i8 100, ptr [[GEP32]], align 16 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]] |
| ; CHECK-NEXT: [[GEP_PLUS:%.*]] = getelementptr inbounds i8, ptr [[GEP_SEL]], i64 3 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_PLUS]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| %sel0 = select i1 %cnd1, i64 23, i64 29 |
| %sel1 = select i1 %cnd2, i64 %sel0, i64 7 |
| %gep32 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 32 |
| store i8 100, ptr %gep32, align 4 |
| %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1 |
| %gep.plus = getelementptr inbounds i8, ptr %gep.sel, i64 3 |
| %i = load i8, ptr %gep.plus, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_offsets_not_simplifiable_3(i1 %cnd1, i1 %cnd2) { |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_3 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1) |
| ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]] |
| ; CHECK-NEXT: store i8 100, ptr [[GEP_SEL]], align 4 |
| ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP29]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = call ptr @calloc(i64 1024, i64 1) |
| %sel0 = select i1 %cnd1, i64 23, i64 29 |
| %sel1 = select i1 %cnd2, i64 %sel0, i64 7 |
| %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1 |
| store i8 100, ptr %gep.sel, align 4 |
| %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29 |
| %i = load i8, ptr %gep29, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_offsets_not_simplifiable_4(i1 %cnd1, i1 %cnd2) { |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_4 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1) |
| ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]] |
| ; CHECK-NEXT: [[GEP_PLUS:%.*]] = getelementptr inbounds i8, ptr [[GEP_SEL]], i64 3 |
| ; CHECK-NEXT: store i8 100, ptr [[GEP_PLUS]], align 4 |
| ; CHECK-NEXT: [[GEP32:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 32 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP32]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = call ptr @calloc(i64 1024, i64 1) |
| %sel0 = select i1 %cnd1, i64 23, i64 29 |
| %sel1 = select i1 %cnd2, i64 %sel0, i64 7 |
| %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1 |
| %gep.plus = getelementptr inbounds i8, ptr %gep.sel, i64 3 |
| store i8 100, ptr %gep.plus, align 4 |
| %gep32 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 32 |
| %i = load i8, ptr %gep32, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_offsets_not_simplifiable_5(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) |
| ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_5 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BUNDLE:%.*]] = alloca [[STRUCT_T:%.*]], align 64 |
| ; CHECK-NEXT: [[GEP_FIXED:%.*]] = getelementptr inbounds [[STRUCT_T]], ptr [[BUNDLE]], i64 0, i32 1, i64 3, i64 5 |
| ; CHECK-NEXT: store i8 100, ptr [[GEP_FIXED]], align 4 |
| ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND1]], i64 1, i64 3 |
| ; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CND2]], i64 5, i64 11 |
| ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [[STRUCT_T]], ptr [[BUNDLE]], i64 0, i32 1, i64 [[SEL1]], i64 [[SEL2]] |
| ; CHECK-NEXT: store i8 42, ptr [[GEP_SEL]], align 4 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_FIXED]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %bundle = alloca %struct.T, align 64 |
| %gep.fixed = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 3, i64 5 |
| store i8 100, ptr %gep.fixed, align 4 |
| %sel1 = select i1 %cnd1, i64 1, i64 3 |
| %sel2 = select i1 %cnd2, i64 5, i64 11 |
| %gep.sel = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 %sel1, i64 %sel2 |
| |
| ;; This store prevents the constant 100 from being propagated to ret |
| store i8 42, ptr %gep.sel, align 4 |
| |
| %i = load i8, ptr %gep.fixed, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_gep_simplifiable_1(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) |
| ; CHECK-LABEL: define {{[^@]+}}@select_gep_simplifiable_1 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR2:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7 |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: [[SEL_PTR:%.*]] = select i1 [[CND1]], ptr [[GEP7]], ptr [[GEP23]] |
| ; CHECK-NEXT: store i8 42, ptr [[SEL_PTR]], align 4 |
| ; CHECK-NEXT: ret i8 21 |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| %gep3 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 3 |
| store i8 21, ptr %gep3, align 4 |
| %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7 |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| %sel.ptr = select i1 %cnd1, ptr %gep7, ptr %gep23 |
| store i8 42, ptr %sel.ptr, align 4 |
| %i = load i8, ptr %gep3, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @select_gep_not_simplifiable_1(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn |
| ; CHECK-LABEL: define {{[^@]+}}@select_gep_not_simplifiable_1 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR3:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7 |
| ; CHECK-NEXT: store i8 1, ptr [[GEP7]], align 4 |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: [[SEL_PTR:%.*]] = select i1 [[CND1]], ptr [[GEP7]], ptr [[GEP23]] |
| ; CHECK-NEXT: store i8 42, ptr [[SEL_PTR]], align 4 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP7]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7 |
| store i8 1, ptr %gep7, align 4 |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| %sel.ptr = select i1 %cnd1, ptr %gep7, ptr %gep23 |
| store i8 42, ptr %sel.ptr, align 4 |
| %i = load i8, ptr %gep7, align 4 |
| ret i8 %i |
| } |
| |
| ; FIXME: The whole function is just "ret i8 21". |
| |
| define i8 @phi_gep_simplifiable_1(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn |
| ; CHECK-LABEL: define {{[^@]+}}@phi_gep_simplifiable_1 |
| ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR3]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: store i8 21, ptr [[GEP23]], align 4 |
| ; CHECK-NEXT: br label [[JOIN:%.*]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31 |
| ; CHECK-NEXT: store i8 21, ptr [[GEP31]], align 4 |
| ; CHECK-NEXT: br label [[JOIN]] |
| ; CHECK: join: |
| ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ] |
| ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[PHI_PTR]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| br i1 %cnd1, label %then, label %else |
| |
| then: |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| store i8 21, ptr %gep23, align 4 |
| br label %join |
| |
| else: |
| %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31 |
| store i8 21, ptr %gep31, align 4 |
| br label %join |
| |
| join: |
| %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else] |
| ;; This store is eliminated |
| %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29 |
| store i8 42, ptr %gep29, align 4 |
| %i = load i8, ptr %phi.ptr, align 4 |
| ret i8 %i |
| } |
| |
| ; FIXME: The whole function is just "ret i8 42". |
| |
| define i8 @phi_gep_simplifiable_2(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) |
| ; CHECK-LABEL: define {{[^@]+}}@phi_gep_simplifiable_2 |
| ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: br label [[JOIN:%.*]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31 |
| ; CHECK-NEXT: br label [[JOIN]] |
| ; CHECK: join: |
| ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ] |
| ; CHECK-NEXT: store i8 21, ptr [[PHI_PTR]], align 4 |
| ; CHECK-NEXT: ret i8 42 |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29 |
| ;; This store is propagated to the load. |
| store i8 42, ptr %gep29, align 4 |
| br i1 %cnd1, label %then, label %else |
| |
| then: |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| br label %join |
| |
| else: |
| %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31 |
| br label %join |
| |
| join: |
| %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else] |
| store i8 21, ptr %phi.ptr, align 4 |
| ;; Replaced with the constant, and both store/load are eliminated. |
| %i = load i8, ptr %gep29, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @phi_gep_not_simplifiable_1(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn |
| ; CHECK-LABEL: define {{[^@]+}}@phi_gep_not_simplifiable_1 |
| ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR3]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: br label [[JOIN:%.*]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31 |
| ; CHECK-NEXT: br label [[JOIN]] |
| ; CHECK: join: |
| ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ] |
| ; CHECK-NEXT: store i8 42, ptr [[GEP23]], align 4 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[PHI_PTR]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| br i1 %cnd1, label %then, label %else |
| |
| then: |
| br label %join |
| |
| else: |
| %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31 |
| br label %join |
| |
| join: |
| %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else] |
| ;; This store cannot be eliminated |
| store i8 42, ptr %gep23, align 4 |
| %i = load i8, ptr %phi.ptr, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @phi_gep_not_simplifiable_2(i1 %cnd1, i1 %cnd2) { |
| ; CHECK-LABEL: define {{[^@]+}}@phi_gep_not_simplifiable_2 |
| ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1) |
| ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23 |
| ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: br label [[JOIN:%.*]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31 |
| ; CHECK-NEXT: br label [[JOIN]] |
| ; CHECK: join: |
| ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ] |
| ; CHECK-NEXT: store i8 21, ptr [[PHI_PTR]], align 4 |
| ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP23]], align 4 |
| ; CHECK-NEXT: ret i8 [[I]] |
| ; |
| entry: |
| %Bytes = call ptr @calloc(i64 1024, i64 1) |
| %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23 |
| br i1 %cnd1, label %then, label %else |
| |
| then: |
| br label %join |
| |
| else: |
| %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31 |
| br label %join |
| |
| join: |
| %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else] |
| store i8 21, ptr %phi.ptr, align 4 |
| %i = load i8, ptr %gep23, align 4 |
| ret i8 %i |
| } |
| |
| define i8 @phi_offsets(i1 %cnd1, i1 %cnd2) { |
| ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) |
| ; CHECK-LABEL: define {{[^@]+}}@phi_offsets |
| ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 |
| ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: br label [[JOIN:%.*]] |
| ; CHECK: else: |
| ; CHECK-NEXT: br label [[JOIN]] |
| ; CHECK: join: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 3, [[THEN]] ], [ 11, [[ELSE]] ] |
| ; CHECK-NEXT: [[GEP_PHI:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[PHI]] |
| ; CHECK-NEXT: ret i8 100 |
| ; |
| entry: |
| %Bytes = alloca [1024 x i8], align 16 |
| store i8 100, ptr %Bytes, align 4 |
| br i1 %cnd1, label %then, label %else |
| |
| then: |
| br label %join |
| |
| else: |
| br label %join |
| |
| join: |
| %phi = phi i64 [ 3, %then ], [ 11, %else ] |
| %gep.phi = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %phi |
| store i8 42, ptr %gep.phi, align 4 |
| %i = load i8, ptr %Bytes, align 4 |
| ret i8 %i |
| } |
| |
| ;. |
| ; CHECK: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" } |
| ; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } |
| ; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } |
| ; CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn } |
| ;. |
| ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: |
| ; CGSCC: {{.*}} |
| ; TUNIT: {{.*}} |