1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Fold 5; (-1 u/ %x) u< %y 6; to 7; @llvm.umul.with.overflow(%x, %y) + extractvalue 8 9define i1 @t0_basic(i8 %x, i8 %y) { 10; CHECK-LABEL: @t0_basic( 11; CHECK-NEXT: [[MUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 12; CHECK-NEXT: [[MUL_OV:%.*]] = extractvalue { i8, i1 } [[MUL]], 1 13; CHECK-NEXT: ret i1 [[MUL_OV]] 14; 15 %t0 = udiv i8 -1, %x 16 %r = icmp ult i8 %t0, %y 17 ret i1 %r 18} 19 20define <2 x i1> @t1_vec(<2 x i8> %x, <2 x i8> %y) { 21; CHECK-LABEL: @t1_vec( 22; CHECK-NEXT: [[MUL:%.*]] = call { <2 x i8>, <2 x i1> } @llvm.umul.with.overflow.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) 23; CHECK-NEXT: [[MUL_OV:%.*]] = extractvalue { <2 x i8>, <2 x i1> } [[MUL]], 1 24; CHECK-NEXT: ret <2 x i1> [[MUL_OV]] 25; 26 %t0 = udiv <2 x i8> <i8 -1, i8 -1>, %x 27 %r = icmp ult <2 x i8> %t0, %y 28 ret <2 x i1> %r 29} 30 31define <3 x i1> @t2_vec_poison(<3 x i8> %x, <3 x i8> %y) { 32; CHECK-LABEL: @t2_vec_poison( 33; CHECK-NEXT: [[MUL:%.*]] = call { <3 x i8>, <3 x i1> } @llvm.umul.with.overflow.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 34; CHECK-NEXT: [[MUL_OV:%.*]] = extractvalue { <3 x i8>, <3 x i1> } [[MUL]], 1 35; CHECK-NEXT: ret <3 x i1> [[MUL_OV]] 36; 37 %t0 = udiv <3 x i8> <i8 -1, i8 poison, i8 -1>, %x 38 %r = icmp ult <3 x i8> %t0, %y 39 ret <3 x i1> %r 40} 41 42declare i8 @gen8() 43 44define i1 @t3_commutative(i8 %x) { 45; CHECK-LABEL: @t3_commutative( 46; CHECK-NEXT: [[Y:%.*]] = call i8 @gen8() 47; CHECK-NEXT: [[MUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y]]) 48; CHECK-NEXT: [[MUL_OV:%.*]] = extractvalue { i8, i1 } [[MUL]], 1 49; CHECK-NEXT: ret i1 [[MUL_OV]] 50; 51 %t0 = udiv i8 -1, %x 52 %y = call i8 @gen8() 53 %r = icmp ugt i8 %y, %t0 ; swapped 54 ret i1 %r 55} 56 57; Negative tests 58 59declare void @use8(i8) 60 61define i1 @n4_extrause(i8 %x, i8 %y) { 62; CHECK-LABEL: @n4_extrause( 63; CHECK-NEXT: [[T0:%.*]] = udiv i8 -1, [[X:%.*]] 64; CHECK-NEXT: call void @use8(i8 [[T0]]) 65; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y:%.*]] 66; CHECK-NEXT: ret i1 [[R]] 67; 68 %t0 = udiv i8 -1, %x 69 call void @use8(i8 %t0) 70 %r = icmp ult i8 %t0, %y 71 ret i1 %r 72} 73 74define i1 @n5_not_negone(i8 %x, i8 %y) { 75; CHECK-LABEL: @n5_not_negone( 76; CHECK-NEXT: [[T0:%.*]] = udiv i8 -2, [[X:%.*]] 77; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y:%.*]] 78; CHECK-NEXT: ret i1 [[R]] 79; 80 %t0 = udiv i8 -2, %x ; not -1 81 %r = icmp ult i8 %t0, %y 82 ret i1 %r 83} 84 85define i1 @n6_wrong_pred0(i8 %x, i8 %y) { 86; CHECK-LABEL: @n6_wrong_pred0( 87; CHECK-NEXT: [[T0:%.*]] = udiv i8 -1, [[X:%.*]] 88; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[T0]], [[Y:%.*]] 89; CHECK-NEXT: ret i1 [[R]] 90; 91 %t0 = udiv i8 -1, %x 92 %r = icmp ule i8 %t0, %y ; not ult 93 ret i1 %r 94} 95 96define i1 @n6_wrong_pred1(i8 %x, i8 %y) { 97; CHECK-LABEL: @n6_wrong_pred1( 98; CHECK-NEXT: [[T0:%.*]] = udiv i8 -1, [[X:%.*]] 99; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T0]], [[Y:%.*]] 100; CHECK-NEXT: ret i1 [[R]] 101; 102 %t0 = udiv i8 -1, %x 103 %r = icmp ugt i8 %t0, %y ; not ult 104 ret i1 %r 105} 106