| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=ipsccp -S | FileCheck %s |
| |
| define internal i32 @test1a(i32 %A, i32 %b) { |
| ; CHECK-LABEL: @test1a( |
| ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 1 |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X]], [[B:%.*]] |
| ; CHECK-NEXT: br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]] |
| ; CHECK: bb.true: |
| ; CHECK-NEXT: [[R:%.*]] = call i32 @test1a(i32 [[X]], i32 [[B]]) |
| ; CHECK-NEXT: ret i32 [[R]] |
| ; CHECK: bb.false: |
| ; CHECK-NEXT: ret i32 [[A]] |
| ; |
| %X = add i32 %A, 1 |
| %c = icmp eq i32 %X, %b |
| br i1 %c, label %bb.true, label %bb.false |
| |
| bb.true: |
| %r = call i32 @test1a(i32 %X, i32 %b) |
| ret i32 %r |
| |
| bb.false: |
| ret i32 %A |
| } |
| |
| define i32 @test1b(i32 %b) { |
| ; CHECK-LABEL: @test1b( |
| ; CHECK-NEXT: [[X:%.*]] = call i32 @test1a(i32 17, i32 [[B:%.*]]) |
| ; CHECK-NEXT: ret i32 [[X]] |
| ; |
| %X = call i32 @test1a( i32 17, i32 %b) |
| ret i32 %X |
| } |
| |
| @Getopt.optind = internal global i32 1, align 4 |
| |
| define i32 @test2(i32 %a) { |
| ; CHECK-LABEL: @test2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LV:%.*]] = load i32, i32* @Getopt.optind, align 4 |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LV]], 1 |
| ; CHECK-NEXT: store i32 [[ADD]], i32* @Getopt.optind, align 4 |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[ADD]], [[A:%.*]] |
| ; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i32 [[ADD]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %lv = load i32, i32* @Getopt.optind, align 4 |
| %add = add i32 %lv, 1 |
| store i32 %add, i32* @Getopt.optind |
| %c = icmp eq i32 %add, %a |
| br i1 %c, label %exit, label %loop |
| |
| exit: |
| ret i32 %add |
| } |
| |
| |
| define internal i32 @test3a(i32 %a) { |
| ; CHECK-LABEL: @test3a( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = add i32 [[A:%.*]], 1 |
| ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[RES]], 1000 |
| ; CHECK-NEXT: br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]] |
| ; CHECK: bb.true: |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; CHECK: bb.false: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| entry: |
| %res = add i32 %a, 1 |
| %c = icmp ult i32 %res, 1000 |
| br i1 %c, label %bb.true, label %bb.false |
| |
| bb.true: |
| ret i32 %res |
| |
| bb.false: |
| ret i32 0 |
| } |
| |
| define i32 @test3b(i32 %a) { |
| ; CHECK-LABEL: @test3b( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[V1:%.*]] = call i32 @test3a(i32 0) |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[V2:%.*]] = call i32 @test3a(i32 [[V1]]) |
| ; CHECK-NEXT: [[V3:%.*]] = add i32 [[V2]], 1 |
| ; CHECK-NEXT: [[V4:%.*]] = call i32 @test3a(i32 [[V3]]) |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[V4]], [[A:%.*]] |
| ; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i32 [[V4]] |
| ; |
| entry: |
| %v1 = call i32 @test3a(i32 0) |
| br label %loop |
| |
| loop: |
| %v2 = call i32 @test3a(i32 %v1) |
| %v3 = add i32 %v2, 1 |
| %v4 = call i32 @test3a(i32 %v3) |
| %c = icmp eq i32 %v4, %a |
| br i1 %c, label %exit, label %loop |
| |
| exit: |
| ret i32 %v4 |
| } |
| |
| %struct.S = type { i32, i32 } |
| |
| ; Check for a range extension cycle through a struct argument. |
| define internal i32 @test4a(%struct.S %s) { |
| ; CHECK-LABEL: @test4a( |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue [[STRUCT_S:%.*]] %s, 0 |
| ; CHECK-NEXT: [[B:%.*]] = extractvalue [[STRUCT_S]] %s, 1 |
| ; CHECK-NEXT: [[X:%.*]] = add i32 [[A]], 1 |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X]], [[B]] |
| ; CHECK-NEXT: br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]] |
| ; CHECK: bb.true: |
| ; CHECK-NEXT: [[S2:%.*]] = insertvalue [[STRUCT_S]] %s, i32 [[X]], 0 |
| ; CHECK-NEXT: [[R:%.*]] = call i32 @test4a(%struct.S [[S2]]) |
| ; CHECK-NEXT: ret i32 [[R]] |
| ; CHECK: bb.false: |
| ; CHECK-NEXT: ret i32 [[A]] |
| ; |
| %a = extractvalue %struct.S %s, 0 |
| %b = extractvalue %struct.S %s, 1 |
| |
| %x = add i32 %a, 1 |
| %c = icmp eq i32 %x, %b |
| br i1 %c, label %bb.true, label %bb.false |
| |
| bb.true: |
| %s2 = insertvalue %struct.S %s, i32 %x, 0 |
| %r = call i32 @test4a(%struct.S %s2) |
| ret i32 %r |
| |
| bb.false: |
| ret i32 %a |
| } |
| |
| define i32 @test4b(i32 %b) { |
| ; CHECK-LABEL: @test4b( |
| ; CHECK-NEXT: [[S2:%.*]] = insertvalue [[STRUCT_S:%.*]] { i32 17, i32 undef }, i32 [[B:%.*]], 1 |
| ; CHECK-NEXT: [[X:%.*]] = call i32 @test4a(%struct.S [[S2]]) |
| ; CHECK-NEXT: ret i32 [[X]] |
| ; |
| %s1 = insertvalue %struct.S undef, i32 17, 0 |
| %s2 = insertvalue %struct.S %s1, i32 %b, 1 |
| %X = call i32 @test4a(%struct.S %s2) |
| ret i32 %X |
| } |
| |
| ; Check for a range extension cycle through a returned value. |
| |
| define internal i32 @test5a(i8* %arg, i32 %arg1, i32 %arg2) { |
| ; CHECK-LABEL: @test5a( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[TMP:%.*]] = icmp eq i8* [[ARG:%.*]], null |
| ; CHECK-NEXT: br i1 [[TMP]], label [[BB6:%.*]], label [[BB3:%.*]] |
| ; CHECK: bb3: |
| ; CHECK-NEXT: [[TMP4:%.*]] = tail call i32 @test5a(i8* [[ARG]], i32 0, i32 -1) |
| ; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP4]], -1 |
| ; CHECK-NEXT: ret i32 [[TMP5]] |
| ; CHECK: bb6: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| bb: |
| %tmp = icmp eq i8* %arg, null |
| br i1 %tmp, label %bb6, label %bb3 |
| |
| bb3: ; preds = %bb |
| %tmp4 = tail call i32 @test5a(i8* %arg, i32 %arg1, i32 %arg2) |
| %tmp5 = add nsw i32 %tmp4, %arg2 |
| ret i32 %tmp5 |
| |
| bb6: ; preds = %bb |
| ret i32 %arg1 |
| } |
| |
| define void @test5b(i8* %ptr) { |
| ; CHECK-LABEL: @test5b( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[TMP:%.*]] = tail call i32 @test5a(i8* [[PTR:%.*]], i32 0, i32 -1) |
| ; CHECK-NEXT: ret void |
| ; |
| bb: |
| %tmp = tail call i32 @test5a(i8* %ptr, i32 0, i32 -1) |
| ret void |
| } |
| |
| %struct = type { i32, i32 } |
| |
| define internal %struct @test6a(i8* %arg, i32 %arg1, i32 %arg2) { |
| ; CHECK-LABEL: @test6a( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[TMP:%.*]] = icmp eq i8* [[ARG:%.*]], null |
| ; CHECK-NEXT: br i1 [[TMP]], label [[BB6:%.*]], label [[BB3:%.*]] |
| ; CHECK: bb3: |
| ; CHECK-NEXT: [[S1:%.*]] = tail call [[STRUCT:%.*]] @test6a(i8* [[ARG]], i32 0, i32 -1) |
| ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue [[STRUCT]] %s1, 0 |
| ; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP4]], -1 |
| ; CHECK-NEXT: [[S2:%.*]] = insertvalue [[STRUCT]] %s1, i32 [[TMP5]], 0 |
| ; CHECK-NEXT: ret [[STRUCT]] %s2 |
| ; CHECK: bb6: |
| ; CHECK-NEXT: ret [[STRUCT]] { i32 0, i32 undef } |
| ; |
| bb: |
| %tmp = icmp eq i8* %arg, null |
| br i1 %tmp, label %bb6, label %bb3 |
| |
| bb3: ; preds = %bb |
| %s1 = tail call %struct @test6a(i8* %arg, i32 %arg1, i32 %arg2) |
| %tmp4 = extractvalue %struct %s1, 0 |
| %tmp5 = add nsw i32 %tmp4, %arg2 |
| %s2 = insertvalue %struct %s1, i32 %tmp5, 0 |
| ret %struct %s2 |
| |
| bb6: ; preds = %bb |
| %s3 = insertvalue %struct undef, i32 %arg1, 0 |
| ret %struct %s3 |
| } |
| |
| define void @test6b(i8* %ptr) { |
| ; CHECK-LABEL: @test6b( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[TMP:%.*]] = tail call [[STRUCT:%.*]] @test6a(i8* [[PTR:%.*]], i32 0, i32 -1) |
| ; CHECK-NEXT: ret void |
| ; |
| bb: |
| %tmp = tail call %struct @test6a(i8* %ptr, i32 0, i32 -1) |
| ret void |
| } |