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