1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(i8 %value); 5 6; Since we know that any comparison of ucmp/scmp with a constant will result in 7; a comparison of ucmp/scmp's operands, we can propagate such a comparison 8; through the phi node and let the next iteration of instcombine simplify it. 9define i1 @icmp_of_phi_of_scmp_with_constant(i1 %c, i16 %x, i16 %y) 10; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant( 11; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) { 12; CHECK-NEXT: [[ENTRY:.*:]] 13; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 14; CHECK: [[TRUE]]: 15; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]] 16; CHECK-NEXT: br label %[[EXIT:.*]] 17; CHECK: [[FALSE]]: 18; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i16 [[Y]], [[X]] 19; CHECK-NEXT: br label %[[EXIT]] 20; CHECK: [[EXIT]]: 21; CHECK-NEXT: [[R:%.*]] = phi i1 [ [[TMP0]], %[[TRUE]] ], [ [[TMP1]], %[[FALSE]] ] 22; CHECK-NEXT: ret i1 [[R]] 23; 24{ 25entry: 26 br i1 %c, label %true, label %false 27true: 28 %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 29 br label %exit 30false: 31 %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x) 32 br label %exit 33exit: 34 %phi = phi i8 [%cmp1, %true], [%cmp2, %false] 35 %r = icmp slt i8 %phi, 0 36 ret i1 %r 37} 38 39; When one of the incoming values is ucmp/scmp and the other is not we can still perform the transformation 40define i1 @icmp_of_phi_of_one_scmp_with_constant(i1 %c, i16 %x, i16 %y, i8 %false_val) 41; CHECK-LABEL: define i1 @icmp_of_phi_of_one_scmp_with_constant( 42; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[FALSE_VAL:%.*]]) { 43; CHECK-NEXT: [[ENTRY:.*:]] 44; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 45; CHECK: [[TRUE]]: 46; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]] 47; CHECK-NEXT: br label %[[EXIT:.*]] 48; CHECK: [[FALSE]]: 49; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[FALSE_VAL]], 0 50; CHECK-NEXT: br label %[[EXIT]] 51; CHECK: [[EXIT]]: 52; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ [[TMP0]], %[[TRUE]] ], [ [[TMP1]], %[[FALSE]] ] 53; CHECK-NEXT: ret i1 [[PHI]] 54; 55{ 56entry: 57 br i1 %c, label %true, label %false 58true: 59 %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 60 br label %exit 61false: 62 br label %exit 63exit: 64 %phi = phi i8 [%cmp1, %true], [%false_val, %false] 65 %r = icmp slt i8 %phi, 0 66 ret i1 %r 67} 68 69; Negative test: the RHS of comparison that uses the phi node is not constant 70define i1 @icmp_of_phi_of_scmp_with_non_constant(i1 %c, i16 %x, i16 %y, i8 %cmp) 71; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_non_constant( 72; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[CMP:%.*]]) { 73; CHECK-NEXT: [[ENTRY:.*:]] 74; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 75; CHECK: [[TRUE]]: 76; CHECK-NEXT: [[CMP1:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[X]], i16 [[Y]]) 77; CHECK-NEXT: br label %[[EXIT:.*]] 78; CHECK: [[FALSE]]: 79; CHECK-NEXT: [[CMP2:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[Y]], i16 [[X]]) 80; CHECK-NEXT: br label %[[EXIT]] 81; CHECK: [[EXIT]]: 82; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ [[CMP1]], %[[TRUE]] ], [ [[CMP2]], %[[FALSE]] ] 83; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[PHI]], [[CMP]] 84; CHECK-NEXT: ret i1 [[R]] 85; 86{ 87entry: 88 br i1 %c, label %true, label %false 89true: 90 %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 91 br label %exit 92false: 93 %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x) 94 br label %exit 95exit: 96 %phi = phi i8 [%cmp1, %true], [%cmp2, %false] 97 %r = icmp slt i8 %phi, %cmp 98 ret i1 %r 99} 100 101; Negative test: more than one incoming value of the phi node is not one-use 102define i1 @icmp_of_phi_of_scmp_with_constant_not_one_use(i1 %c, i16 %x, i16 %y) 103; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant_not_one_use( 104; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) { 105; CHECK-NEXT: [[ENTRY:.*:]] 106; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 107; CHECK: [[TRUE]]: 108; CHECK-NEXT: [[CMP1:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[X]], i16 [[Y]]) 109; CHECK-NEXT: call void @use(i8 [[CMP1]]) 110; CHECK-NEXT: br label %[[EXIT:.*]] 111; CHECK: [[FALSE]]: 112; CHECK-NEXT: [[CMP2:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[Y]], i16 [[X]]) 113; CHECK-NEXT: call void @use(i8 [[CMP2]]) 114; CHECK-NEXT: br label %[[EXIT]] 115; CHECK: [[EXIT]]: 116; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ [[CMP1]], %[[TRUE]] ], [ [[CMP2]], %[[FALSE]] ] 117; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[PHI]], 0 118; CHECK-NEXT: ret i1 [[R]] 119; 120{ 121entry: 122 br i1 %c, label %true, label %false 123true: 124 %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 125 call void @use(i8 %cmp1) 126 br label %exit 127false: 128 %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x) 129 call void @use(i8 %cmp2) 130 br label %exit 131exit: 132 %phi = phi i8 [%cmp1, %true], [%cmp2, %false] 133 %r = icmp slt i8 %phi, 0 134 ret i1 %r 135} 136 137; Same as the first transformation, but the phi node uses the result of scmp twice. This verifies that we don't clone values more than once per block 138define i1 @icmp_of_phi_of_scmp_with_constant_one_user_two_uses(i8 %c, i16 %x, i16 %y, i8 %false_val) { 139; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant_one_user_two_uses( 140; CHECK-SAME: i8 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[FALSE_VAL:%.*]]) { 141; CHECK-NEXT: [[ENTRY:.*]]: 142; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]] 143; CHECK-NEXT: switch i8 [[C]], label %[[BB_2:.*]] [ 144; CHECK-NEXT: i8 0, label %[[BB:.*]] 145; CHECK-NEXT: i8 1, label %[[BB]] 146; CHECK-NEXT: ] 147; CHECK: [[BB_2]]: 148; CHECK-NEXT: br label %[[BB]] 149; CHECK: [[BB]]: 150; CHECK-NEXT: [[R:%.*]] = phi i1 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP0]], %[[ENTRY]] ], [ false, %[[BB_2]] ] 151; CHECK-NEXT: ret i1 [[R]] 152; 153entry: 154 %cmp = call i8 @llvm.scmp(i16 %x, i16 %y) 155 switch i8 %c, label %bb_2 [ 156 i8 0, label %bb 157 i8 1, label %bb 158 ] 159 160bb_2: 161 br label %bb 162 163bb: 164 %phi = phi i8 [ %cmp, %entry ], [ %cmp, %entry ], [ 0, %bb_2 ] 165 %r = icmp slt i8 %phi, 0 166 ret i1 %r 167} 168