1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s 3 4declare void @use64(i64) 5 6define void @test1(i32 %n) { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[FOR_COND:%.*]] 10; CHECK: for.cond: 11; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[EXT:%.*]], [[FOR_BODY:%.*]] ] 12; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -1 13; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 14; CHECK: for.body: 15; CHECK-NEXT: [[EXT_WIDE:%.*]] = zext nneg i32 [[A]] to i64 16; CHECK-NEXT: call void @use64(i64 [[EXT_WIDE]]) 17; CHECK-NEXT: [[EXT]] = trunc i64 [[EXT_WIDE]] to i32 18; CHECK-NEXT: br label [[FOR_COND]] 19; CHECK: for.end: 20; CHECK-NEXT: ret void 21; 22entry: 23 br label %for.cond 24 25for.cond: ; preds = %for.body, %entry 26 %a = phi i32 [ %n, %entry ], [ %ext, %for.body ] 27 %cmp = icmp sgt i32 %a, -1 28 br i1 %cmp, label %for.body, label %for.end 29 30for.body: ; preds = %for.cond 31 %ext.wide = zext i32 %a to i64 32 call void @use64(i64 %ext.wide) 33 %ext = trunc i64 %ext.wide to i32 34 br label %for.cond 35 36for.end: ; preds = %for.cond 37 ret void 38} 39 40;; Negative test to show transform doesn't happen unless n >= 0. 41define void @test2(i32 %n) { 42; CHECK-LABEL: @test2( 43; CHECK-NEXT: entry: 44; CHECK-NEXT: br label [[FOR_COND:%.*]] 45; CHECK: for.cond: 46; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[EXT:%.*]], [[FOR_BODY:%.*]] ] 47; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -2 48; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 49; CHECK: for.body: 50; CHECK-NEXT: [[EXT_WIDE:%.*]] = zext i32 [[A]] to i64 51; CHECK-NEXT: call void @use64(i64 [[EXT_WIDE]]) 52; CHECK-NEXT: [[EXT]] = trunc i64 [[EXT_WIDE]] to i32 53; CHECK-NEXT: br label [[FOR_COND]] 54; CHECK: for.end: 55; CHECK-NEXT: ret void 56; 57entry: 58 br label %for.cond 59 60for.cond: ; preds = %for.body, %entry 61 %a = phi i32 [ %n, %entry ], [ %ext, %for.body ] 62 %cmp = icmp sgt i32 %a, -2 63 br i1 %cmp, label %for.body, label %for.end 64 65for.body: ; preds = %for.cond 66 %ext.wide = zext i32 %a to i64 67 call void @use64(i64 %ext.wide) 68 %ext = trunc i64 %ext.wide to i32 69 br label %for.cond 70 71for.end: ; preds = %for.cond 72 ret void 73} 74 75;; Non looping test case. 76define void @test3(i32 %n) { 77; CHECK-LABEL: @test3( 78; CHECK-NEXT: entry: 79; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1 80; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] 81; CHECK: bb: 82; CHECK-NEXT: [[EXT_WIDE:%.*]] = zext nneg i32 [[N]] to i64 83; CHECK-NEXT: call void @use64(i64 [[EXT_WIDE]]) 84; CHECK-NEXT: [[EXT:%.*]] = trunc i64 [[EXT_WIDE]] to i32 85; CHECK-NEXT: br label [[EXIT]] 86; CHECK: exit: 87; CHECK-NEXT: ret void 88; 89entry: 90 %cmp = icmp sgt i32 %n, -1 91 br i1 %cmp, label %bb, label %exit 92 93bb: 94 %ext.wide = zext i32 %n to i64 95 call void @use64(i64 %ext.wide) 96 %ext = trunc i64 %ext.wide to i32 97 br label %exit 98 99exit: 100 ret void 101} 102 103;; Non looping negative test case. 104define void @test4(i32 %n) { 105; CHECK-LABEL: @test4( 106; CHECK-NEXT: entry: 107; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -2 108; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] 109; CHECK: bb: 110; CHECK-NEXT: [[EXT_WIDE:%.*]] = zext i32 [[N]] to i64 111; CHECK-NEXT: call void @use64(i64 [[EXT_WIDE]]) 112; CHECK-NEXT: [[EXT:%.*]] = trunc i64 [[EXT_WIDE]] to i32 113; CHECK-NEXT: br label [[EXIT]] 114; CHECK: exit: 115; CHECK-NEXT: ret void 116; 117entry: 118 %cmp = icmp sgt i32 %n, -2 119 br i1 %cmp, label %bb, label %exit 120 121bb: 122 %ext.wide = zext i32 %n to i64 123 call void @use64(i64 %ext.wide) 124 %ext = trunc i64 %ext.wide to i32 125 br label %exit 126 127exit: 128 ret void 129} 130 131define i64 @may_including_undef(i1 %c.1, i1 %c.2) { 132; CHECK-LABEL: @may_including_undef( 133; CHECK-NEXT: br i1 [[C_1:%.*]], label [[TRUE_1:%.*]], label [[FALSE:%.*]] 134; CHECK: true.1: 135; CHECK-NEXT: br i1 [[C_2:%.*]], label [[TRUE_2:%.*]], label [[EXIT:%.*]] 136; CHECK: true.2: 137; CHECK-NEXT: br label [[EXIT]] 138; CHECK: false: 139; CHECK-NEXT: br label [[EXIT]] 140; CHECK: exit: 141; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[TRUE_1]] ], [ 1, [[TRUE_2]] ], [ undef, [[FALSE]] ] 142; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[P]] to i64 143; CHECK-NEXT: ret i64 [[EXT]] 144; 145 br i1 %c.1, label %true.1, label %false 146 147true.1: 148 br i1 %c.2, label %true.2, label %exit 149 150true.2: 151 br label %exit 152 153false: 154 br label %exit 155 156exit: 157 %p = phi i32 [ 0, %true.1 ], [ 1, %true.2], [ undef, %false ] 158 %ext = zext i32 %p to i64 159 ret i64 %ext 160} 161 162define i64 @test_infer_at_use(i32 noundef %n) { 163; CHECK-LABEL: @test_infer_at_use( 164; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1 165; CHECK-NEXT: [[EXT:%.*]] = zext nneg i32 [[N]] to i64 166; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i64 [[EXT]], i64 0 167; CHECK-NEXT: ret i64 [[SELECT]] 168; 169 %cmp = icmp sgt i32 %n, -1 170 %ext = zext i32 %n to i64 171 %select = select i1 %cmp, i64 %ext, i64 0 172 ret i64 %select 173} 174