| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature |
| ; RUN: opt -passes='require<domtree>,require<assumptions>,assume-simplify,verify' --enable-knowledge-retention -S %s | FileCheck %s |
| |
| target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" |
| |
| declare void @may_throw() |
| |
| declare void @llvm.assume(i1 noundef) #0 |
| |
| define i32 @test1(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) { |
| ; CHECK-LABEL: define {{[^@]+}}@test1 |
| ; CHECK-SAME: (ptr nonnull dereferenceable(4) [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[I:%.*]] = icmp ne i32 [[ARG2]], 4 |
| ; CHECK-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[A:%.*]] |
| ; CHECK: bb4: |
| ; CHECK-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]] |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "align"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]) ] |
| ; CHECK-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4 |
| ; CHECK-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]] |
| ; CHECK-NEXT: store i32 0, ptr [[ARG]], align 4 |
| ; CHECK-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 |
| ; CHECK-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]] |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "ignore"(ptr undef) ] |
| ; CHECK-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4 |
| ; CHECK-NEXT: br label [[B:%.*]] |
| ; CHECK: A: |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "ignore"(ptr undef, i64 4), "ignore"(ptr undef) ] |
| ; CHECK-NEXT: br label [[B]] |
| ; CHECK: B: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| bb: |
| %i = icmp ne i32 %arg2, 4 |
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] |
| br i1 %i, label %bb4, label %A |
| |
| bb4: ; preds = %bb |
| %i5 = add nsw i32 %arg3, %arg2 |
| call void @may_throw() |
| %i6 = load i32, ptr %arg, align 4 |
| %i7 = add nsw i32 %i5, %i6 |
| store i32 0, ptr %arg, align 4 |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4) ] |
| %i8 = load i32, ptr %arg1, align 4 |
| %i9 = add nsw i32 %i7, %i8 |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] |
| call void @may_throw() |
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] |
| store i32 %i9, ptr %arg1, align 4 |
| br label %B |
| |
| A: ; preds = %bb |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] |
| br label %B |
| |
| B: ; preds = %A, %bb4 |
| ret i32 0 |
| } |
| |
| define i32 @test2(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) { |
| ; CHECK-LABEL: define {{[^@]+}}@test2 |
| ; CHECK-SAME: (ptr [[ARG:%.*]], ptr nonnull align 4 dereferenceable(4) [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[I4:%.*]] = load i32, ptr [[ARG1]], align 4 |
| ; CHECK-NEXT: [[I5:%.*]] = icmp ne i32 [[I4]], 0 |
| ; CHECK-NEXT: br i1 [[I5]], label [[BB7:%.*]], label [[BB17:%.*]] |
| ; CHECK: bb7: |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 |
| ; CHECK-NEXT: [[I9:%.*]] = getelementptr inbounds i32, ptr [[ARG1]], i64 2 |
| ; CHECK-NEXT: store i32 [[I8]], ptr [[I9]], align 4 |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: [[I10:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 1 |
| ; CHECK-NEXT: [[I11:%.*]] = load ptr, ptr [[I10]], align 8 |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 12), "align"(ptr [[I11]], i64 4), "dereferenceable"(ptr [[I11]], i64 4), "nonnull"(ptr [[I11]]) ] |
| ; CHECK-NEXT: [[I13:%.*]] = load i32, ptr [[I11]], align 4 |
| ; CHECK-NEXT: [[I14:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 1 |
| ; CHECK-NEXT: [[I15:%.*]] = load ptr, ptr [[I14]], align 8 |
| ; CHECK-NEXT: [[I16:%.*]] = getelementptr inbounds i32, ptr [[I15]], i64 2 |
| ; CHECK-NEXT: store i32 [[I13]], ptr [[I16]], align 4 |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ] |
| ; CHECK-NEXT: br label [[BB33:%.*]] |
| ; CHECK: bb17: |
| ; CHECK-NEXT: [[I18:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 7 |
| ; CHECK-NEXT: [[I19:%.*]] = load ptr, ptr [[I18]], align 8 |
| ; CHECK-NEXT: [[I21:%.*]] = load i32, ptr [[I19]], align 4 |
| ; CHECK-NEXT: [[I22:%.*]] = icmp ne i32 [[I21]], 0 |
| ; CHECK-NEXT: br i1 [[I22]], label [[BB23:%.*]], label [[BB31:%.*]] |
| ; CHECK: bb23: |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ] |
| ; CHECK-NEXT: [[I24:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 2 |
| ; CHECK-NEXT: [[I25:%.*]] = load ptr, ptr [[I24]], align 8 |
| ; CHECK-NEXT: [[I27:%.*]] = load i32, ptr [[I25]], align 4 |
| ; CHECK-NEXT: [[I28:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 2 |
| ; CHECK-NEXT: [[I29:%.*]] = load ptr, ptr [[I28]], align 8 |
| ; CHECK-NEXT: [[I30:%.*]] = getelementptr inbounds i32, ptr [[I29]], i64 2 |
| ; CHECK-NEXT: store i32 [[I27]], ptr [[I30]], align 4 |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: br label [[BB31]] |
| ; CHECK: bb31: |
| ; CHECK-NEXT: br label [[BB32:%.*]] |
| ; CHECK: bb32: |
| ; CHECK-NEXT: br label [[BB33]] |
| ; CHECK: bb33: |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ] |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| bb: |
| %i4 = load i32, ptr %arg1, align 4 |
| %i5 = icmp ne i32 %i4, 0 |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "dereferenceable"(ptr %arg1, i64 4) ] |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] |
| br i1 %i5, label %bb7, label %bb17 |
| |
| bb7: ; preds = %bb |
| call void @may_throw() |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "dereferenceable"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] |
| %i8 = load i32, ptr %arg1, align 4 |
| %i9 = getelementptr inbounds i32, ptr %arg1, i64 2 |
| store i32 %i8, ptr %i9, align 4 |
| call void @may_throw() |
| call void @may_throw() |
| call void @llvm.assume(i1 true) [ "align"(ptr %i9, i64 4), "dereferenceable"(ptr %i9, i64 4), "nonnull"(ptr %i9) ] |
| %i10 = getelementptr inbounds ptr, ptr %arg, i64 1 |
| %i11 = load ptr, ptr %i10, align 8 |
| %i13 = load i32, ptr %i11, align 4 |
| call void @llvm.assume(i1 true) [ "align"(ptr %i11, i64 4), "dereferenceable"(ptr %i11, i64 4), "nonnull"(ptr %i11) ] |
| %i14 = getelementptr inbounds ptr, ptr %arg, i64 1 |
| %i15 = load ptr, ptr %i14, align 8 |
| %i16 = getelementptr inbounds i32, ptr %i15, i64 2 |
| store i32 %i13, ptr %i16, align 4 |
| call void @may_throw() |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] |
| br label %bb33 |
| |
| bb17: ; preds = %bb |
| %i18 = getelementptr inbounds ptr, ptr %arg, i64 7 |
| %i19 = load ptr, ptr %i18, align 8 |
| %i21 = load i32, ptr %i19, align 4 |
| %i22 = icmp ne i32 %i21, 0 |
| br i1 %i22, label %bb23, label %bb31 |
| |
| bb23: ; preds = %bb17 |
| call void @may_throw() |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] |
| %i24 = getelementptr inbounds ptr, ptr %arg, i64 2 |
| %i25 = load ptr, ptr %i24, align 8 |
| %i27 = load i32, ptr %i25, align 4 |
| %i28 = getelementptr inbounds ptr, ptr %arg, i64 2 |
| %i29 = load ptr, ptr %i28, align 8 |
| %i30 = getelementptr inbounds i32, ptr %i29, i64 2 |
| store i32 %i27, ptr %i30, align 4 |
| call void @may_throw() |
| br label %bb31 |
| |
| bb31: ; preds = %bb23, %bb17 |
| br label %bb32 |
| |
| bb32: ; preds = %bb31 |
| br label %bb33 |
| |
| bb33: ; preds = %bb32, %bb7 |
| call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] |
| ret i32 0 |
| } |
| |
| define i32 @test3(ptr nonnull %p, i32 %i) { |
| ; CHECK-LABEL: define {{[^@]+}}@test3 |
| ; CHECK-SAME: (ptr nonnull [[P:%.*]], i32 [[I:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] |
| ; CHECK: A: |
| ; CHECK-NEXT: ret i32 0 |
| ; CHECK: B: |
| ; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 |
| ; CHECK-NEXT: ret i32 [[RET]] |
| ; |
| bb: |
| %cond = icmp ne i32 %i, 0 |
| call void @llvm.assume(i1 true) [ "nonnull"(ptr %p) ] |
| br i1 %cond, label %A, label %B |
| |
| A: ; preds = %bb |
| ret i32 0 |
| |
| B: ; preds = %bb |
| %ret = load i32, ptr %p, align 4 |
| ret i32 %ret |
| } |
| |
| define i32 @test4(ptr %p, i32 %i) { |
| ; CHECK-LABEL: define {{[^@]+}}@test4 |
| ; CHECK-SAME: (ptr nonnull dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] |
| ; CHECK: A: |
| ; CHECK-NEXT: ret i32 0 |
| ; CHECK: B: |
| ; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 |
| ; CHECK-NEXT: ret i32 [[RET]] |
| ; |
| bb: |
| %cond = icmp ne i32 %i, 0 |
| call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ] |
| br i1 %cond, label %A, label %B |
| |
| A: ; preds = %bb |
| ret i32 0 |
| |
| B: ; preds = %bb |
| %ret = load i32, ptr %p, align 4 |
| ret i32 %ret |
| } |
| |
| define i32 @test4A(ptr %p, i32 %i) { |
| ; CHECK-LABEL: define {{[^@]+}}@test4A |
| ; CHECK-SAME: (ptr [[P:%.*]], i32 [[I:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i32 32) ] |
| ; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] |
| ; CHECK: A: |
| ; CHECK-NEXT: ret i32 0 |
| ; CHECK: B: |
| ; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 |
| ; CHECK-NEXT: ret i32 [[RET]] |
| ; |
| bb: |
| call void @may_throw() |
| %cond = icmp ne i32 %i, 0 |
| call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ] |
| br i1 %cond, label %A, label %B |
| |
| A: ; preds = %bb |
| ret i32 0 |
| |
| B: ; preds = %bb |
| %ret = load i32, ptr %p, align 4 |
| ret i32 %ret |
| } |
| |
| define i32 @test5(ptr dereferenceable(64) %p, i32 %i) { |
| ; CHECK-LABEL: define {{[^@]+}}@test5 |
| ; CHECK-SAME: (ptr nonnull dereferenceable(64) [[P:%.*]], i32 [[I:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] |
| ; CHECK: A: |
| ; CHECK-NEXT: ret i32 0 |
| ; CHECK: B: |
| ; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 |
| ; CHECK-NEXT: ret i32 [[RET]] |
| ; |
| bb: |
| %cond = icmp ne i32 %i, 0 |
| call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ] |
| br i1 %cond, label %A, label %B |
| |
| A: ; preds = %bb |
| ret i32 0 |
| |
| B: ; preds = %bb |
| %ret = load i32, ptr %p, align 4 |
| ret i32 %ret |
| } |
| |
| define i32 @test5A(ptr dereferenceable(8) %p, i32 %i) { |
| ; CHECK-LABEL: define {{[^@]+}}@test5A |
| ; CHECK-SAME: (ptr dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "ignore"(ptr undef, i32 32) ] |
| ; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] |
| ; CHECK: A: |
| ; CHECK-NEXT: ret i32 0 |
| ; CHECK: B: |
| ; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 |
| ; CHECK-NEXT: ret i32 [[RET]] |
| ; |
| bb: |
| %cond = icmp ne i32 %i, 0 |
| call void @llvm.assume(i1 true) [ "cold"(), "dereferenceable"(ptr %p, i32 32) ] |
| br i1 %cond, label %A, label %B |
| |
| A: ; preds = %bb |
| ret i32 0 |
| |
| B: ; preds = %bb |
| %ret = load i32, ptr %p, align 4 |
| ret i32 %ret |
| } |
| |
| define i32 @test6() { |
| ; CHECK-LABEL: define {{[^@]+}}@test6() { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] |
| ; CHECK-NEXT: call void @may_throw() |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| bb: |
| call void @llvm.assume(i1 true) [ "cold"() ] |
| call void @llvm.assume(i1 true) [ "cold"() ] |
| call void @may_throw() |
| call void @llvm.assume(i1 true) [ "cold"() ] |
| ret i32 0 |
| } |
| |
| define i32 @test7(ptr %p) { |
| ; CHECK-LABEL: define {{[^@]+}}@test7 |
| ; CHECK-SAME: (ptr nonnull align 4 dereferenceable(4) [[P:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| bb: |
| call void @llvm.assume(i1 true) [ "cold"() ] |
| call void @llvm.assume(i1 true) [ "align"(ptr %p, i32 4) ] |
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i32 4) ] |
| call void @llvm.assume(i1 true) [ "align"(ptr %p, i32 4), "nonnull"(ptr %p) ] |
| ret i32 0 |
| } |
| |
| attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } |