121e3a212SVolodymyr Vasylkun; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 221e3a212SVolodymyr Vasylkun; RUN: opt < %s -passes=instcombine -S | FileCheck %s 321e3a212SVolodymyr Vasylkun 421e3a212SVolodymyr Vasylkundeclare void @use(i8 %value); 521e3a212SVolodymyr Vasylkun 621e3a212SVolodymyr Vasylkun; Since we know that any comparison of ucmp/scmp with a constant will result in 721e3a212SVolodymyr Vasylkun; a comparison of ucmp/scmp's operands, we can propagate such a comparison 821e3a212SVolodymyr Vasylkun; through the phi node and let the next iteration of instcombine simplify it. 921e3a212SVolodymyr Vasylkundefine i1 @icmp_of_phi_of_scmp_with_constant(i1 %c, i16 %x, i16 %y) 1021e3a212SVolodymyr Vasylkun; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant( 1121e3a212SVolodymyr Vasylkun; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) { 1221e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[ENTRY:.*:]] 1321e3a212SVolodymyr Vasylkun; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 1421e3a212SVolodymyr Vasylkun; CHECK: [[TRUE]]: 1521e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]] 1621e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT:.*]] 1721e3a212SVolodymyr Vasylkun; CHECK: [[FALSE]]: 1821e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i16 [[Y]], [[X]] 1921e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT]] 2021e3a212SVolodymyr Vasylkun; CHECK: [[EXIT]]: 2121e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[R:%.*]] = phi i1 [ [[TMP0]], %[[TRUE]] ], [ [[TMP1]], %[[FALSE]] ] 2221e3a212SVolodymyr Vasylkun; CHECK-NEXT: ret i1 [[R]] 2321e3a212SVolodymyr Vasylkun; 2421e3a212SVolodymyr Vasylkun{ 2521e3a212SVolodymyr Vasylkunentry: 2621e3a212SVolodymyr Vasylkun br i1 %c, label %true, label %false 2721e3a212SVolodymyr Vasylkuntrue: 2821e3a212SVolodymyr Vasylkun %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 2921e3a212SVolodymyr Vasylkun br label %exit 3021e3a212SVolodymyr Vasylkunfalse: 3121e3a212SVolodymyr Vasylkun %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x) 3221e3a212SVolodymyr Vasylkun br label %exit 3321e3a212SVolodymyr Vasylkunexit: 3421e3a212SVolodymyr Vasylkun %phi = phi i8 [%cmp1, %true], [%cmp2, %false] 3521e3a212SVolodymyr Vasylkun %r = icmp slt i8 %phi, 0 3621e3a212SVolodymyr Vasylkun ret i1 %r 3721e3a212SVolodymyr Vasylkun} 3821e3a212SVolodymyr Vasylkun 3921e3a212SVolodymyr Vasylkun; When one of the incoming values is ucmp/scmp and the other is not we can still perform the transformation 4021e3a212SVolodymyr Vasylkundefine i1 @icmp_of_phi_of_one_scmp_with_constant(i1 %c, i16 %x, i16 %y, i8 %false_val) 4121e3a212SVolodymyr Vasylkun; CHECK-LABEL: define i1 @icmp_of_phi_of_one_scmp_with_constant( 4221e3a212SVolodymyr Vasylkun; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[FALSE_VAL:%.*]]) { 4321e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[ENTRY:.*:]] 4421e3a212SVolodymyr Vasylkun; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 4521e3a212SVolodymyr Vasylkun; CHECK: [[TRUE]]: 4621e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]] 4721e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT:.*]] 4821e3a212SVolodymyr Vasylkun; CHECK: [[FALSE]]: 4921e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[FALSE_VAL]], 0 5021e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT]] 5121e3a212SVolodymyr Vasylkun; CHECK: [[EXIT]]: 5221e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ [[TMP0]], %[[TRUE]] ], [ [[TMP1]], %[[FALSE]] ] 5321e3a212SVolodymyr Vasylkun; CHECK-NEXT: ret i1 [[PHI]] 5421e3a212SVolodymyr Vasylkun; 5521e3a212SVolodymyr Vasylkun{ 5621e3a212SVolodymyr Vasylkunentry: 5721e3a212SVolodymyr Vasylkun br i1 %c, label %true, label %false 5821e3a212SVolodymyr Vasylkuntrue: 5921e3a212SVolodymyr Vasylkun %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 6021e3a212SVolodymyr Vasylkun br label %exit 6121e3a212SVolodymyr Vasylkunfalse: 6221e3a212SVolodymyr Vasylkun br label %exit 6321e3a212SVolodymyr Vasylkunexit: 6421e3a212SVolodymyr Vasylkun %phi = phi i8 [%cmp1, %true], [%false_val, %false] 6521e3a212SVolodymyr Vasylkun %r = icmp slt i8 %phi, 0 6621e3a212SVolodymyr Vasylkun ret i1 %r 6721e3a212SVolodymyr Vasylkun} 6821e3a212SVolodymyr Vasylkun 6921e3a212SVolodymyr Vasylkun; Negative test: the RHS of comparison that uses the phi node is not constant 7021e3a212SVolodymyr Vasylkundefine i1 @icmp_of_phi_of_scmp_with_non_constant(i1 %c, i16 %x, i16 %y, i8 %cmp) 7121e3a212SVolodymyr Vasylkun; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_non_constant( 7221e3a212SVolodymyr Vasylkun; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[CMP:%.*]]) { 7321e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[ENTRY:.*:]] 7421e3a212SVolodymyr Vasylkun; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 7521e3a212SVolodymyr Vasylkun; CHECK: [[TRUE]]: 7621e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[CMP1:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[X]], i16 [[Y]]) 7721e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT:.*]] 7821e3a212SVolodymyr Vasylkun; CHECK: [[FALSE]]: 7921e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[CMP2:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[Y]], i16 [[X]]) 8021e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT]] 8121e3a212SVolodymyr Vasylkun; CHECK: [[EXIT]]: 8221e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ [[CMP1]], %[[TRUE]] ], [ [[CMP2]], %[[FALSE]] ] 8321e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[PHI]], [[CMP]] 8421e3a212SVolodymyr Vasylkun; CHECK-NEXT: ret i1 [[R]] 8521e3a212SVolodymyr Vasylkun; 8621e3a212SVolodymyr Vasylkun{ 8721e3a212SVolodymyr Vasylkunentry: 8821e3a212SVolodymyr Vasylkun br i1 %c, label %true, label %false 8921e3a212SVolodymyr Vasylkuntrue: 9021e3a212SVolodymyr Vasylkun %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 9121e3a212SVolodymyr Vasylkun br label %exit 9221e3a212SVolodymyr Vasylkunfalse: 9321e3a212SVolodymyr Vasylkun %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x) 9421e3a212SVolodymyr Vasylkun br label %exit 9521e3a212SVolodymyr Vasylkunexit: 9621e3a212SVolodymyr Vasylkun %phi = phi i8 [%cmp1, %true], [%cmp2, %false] 9721e3a212SVolodymyr Vasylkun %r = icmp slt i8 %phi, %cmp 9821e3a212SVolodymyr Vasylkun ret i1 %r 9921e3a212SVolodymyr Vasylkun} 10021e3a212SVolodymyr Vasylkun 10121e3a212SVolodymyr Vasylkun; Negative test: more than one incoming value of the phi node is not one-use 10221e3a212SVolodymyr Vasylkundefine i1 @icmp_of_phi_of_scmp_with_constant_not_one_use(i1 %c, i16 %x, i16 %y) 10321e3a212SVolodymyr Vasylkun; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant_not_one_use( 10421e3a212SVolodymyr Vasylkun; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) { 10521e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[ENTRY:.*:]] 10621e3a212SVolodymyr Vasylkun; CHECK-NEXT: br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]] 10721e3a212SVolodymyr Vasylkun; CHECK: [[TRUE]]: 10821e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[CMP1:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[X]], i16 [[Y]]) 10921e3a212SVolodymyr Vasylkun; CHECK-NEXT: call void @use(i8 [[CMP1]]) 11021e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT:.*]] 11121e3a212SVolodymyr Vasylkun; CHECK: [[FALSE]]: 11221e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[CMP2:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[Y]], i16 [[X]]) 11321e3a212SVolodymyr Vasylkun; CHECK-NEXT: call void @use(i8 [[CMP2]]) 11421e3a212SVolodymyr Vasylkun; CHECK-NEXT: br label %[[EXIT]] 11521e3a212SVolodymyr Vasylkun; CHECK: [[EXIT]]: 11621e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ [[CMP1]], %[[TRUE]] ], [ [[CMP2]], %[[FALSE]] ] 11721e3a212SVolodymyr Vasylkun; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[PHI]], 0 11821e3a212SVolodymyr Vasylkun; CHECK-NEXT: ret i1 [[R]] 11921e3a212SVolodymyr Vasylkun; 12021e3a212SVolodymyr Vasylkun{ 12121e3a212SVolodymyr Vasylkunentry: 12221e3a212SVolodymyr Vasylkun br i1 %c, label %true, label %false 12321e3a212SVolodymyr Vasylkuntrue: 12421e3a212SVolodymyr Vasylkun %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y) 12521e3a212SVolodymyr Vasylkun call void @use(i8 %cmp1) 12621e3a212SVolodymyr Vasylkun br label %exit 12721e3a212SVolodymyr Vasylkunfalse: 12821e3a212SVolodymyr Vasylkun %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x) 12921e3a212SVolodymyr Vasylkun call void @use(i8 %cmp2) 13021e3a212SVolodymyr Vasylkun br label %exit 13121e3a212SVolodymyr Vasylkunexit: 13221e3a212SVolodymyr Vasylkun %phi = phi i8 [%cmp1, %true], [%cmp2, %false] 13321e3a212SVolodymyr Vasylkun %r = icmp slt i8 %phi, 0 13421e3a212SVolodymyr Vasylkun ret i1 %r 13521e3a212SVolodymyr Vasylkun} 136*b189b89bSVolodymyr Vasylkun 137*b189b89bSVolodymyr Vasylkun; 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 138*b189b89bSVolodymyr Vasylkundefine i1 @icmp_of_phi_of_scmp_with_constant_one_user_two_uses(i8 %c, i16 %x, i16 %y, i8 %false_val) { 139*b189b89bSVolodymyr Vasylkun; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant_one_user_two_uses( 140*b189b89bSVolodymyr Vasylkun; CHECK-SAME: i8 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[FALSE_VAL:%.*]]) { 141*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: [[ENTRY:.*]]: 142*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]] 143*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: switch i8 [[C]], label %[[BB_2:.*]] [ 144*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: i8 0, label %[[BB:.*]] 145*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: i8 1, label %[[BB]] 146*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: ] 147*b189b89bSVolodymyr Vasylkun; CHECK: [[BB_2]]: 148*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: br label %[[BB]] 149*b189b89bSVolodymyr Vasylkun; CHECK: [[BB]]: 150*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: [[R:%.*]] = phi i1 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP0]], %[[ENTRY]] ], [ false, %[[BB_2]] ] 151*b189b89bSVolodymyr Vasylkun; CHECK-NEXT: ret i1 [[R]] 152*b189b89bSVolodymyr Vasylkun; 153*b189b89bSVolodymyr Vasylkunentry: 154*b189b89bSVolodymyr Vasylkun %cmp = call i8 @llvm.scmp(i16 %x, i16 %y) 155*b189b89bSVolodymyr Vasylkun switch i8 %c, label %bb_2 [ 156*b189b89bSVolodymyr Vasylkun i8 0, label %bb 157*b189b89bSVolodymyr Vasylkun i8 1, label %bb 158*b189b89bSVolodymyr Vasylkun ] 159*b189b89bSVolodymyr Vasylkun 160*b189b89bSVolodymyr Vasylkunbb_2: 161*b189b89bSVolodymyr Vasylkun br label %bb 162*b189b89bSVolodymyr Vasylkun 163*b189b89bSVolodymyr Vasylkunbb: 164*b189b89bSVolodymyr Vasylkun %phi = phi i8 [ %cmp, %entry ], [ %cmp, %entry ], [ 0, %bb_2 ] 165*b189b89bSVolodymyr Vasylkun %r = icmp slt i8 %phi, 0 166*b189b89bSVolodymyr Vasylkun ret i1 %r 167*b189b89bSVolodymyr Vasylkun} 168