1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; Fold 5; ((%x * %y) u/ %x) != %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: [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 12; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1 13; CHECK-NEXT: ret i1 [[UMUL_OV]] 14; 15 %t0 = mul i8 %x, %y 16 %t1 = udiv i8 %t0, %x 17 %r = icmp ne i8 %t1, %y 18 ret i1 %r 19} 20 21define <2 x i1> @t1_vec(<2 x i8> %x, <2 x i8> %y) { 22; CHECK-LABEL: @t1_vec( 23; CHECK-NEXT: [[UMUL:%.*]] = call { <2 x i8>, <2 x i1> } @llvm.umul.with.overflow.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) 24; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { <2 x i8>, <2 x i1> } [[UMUL]], 1 25; CHECK-NEXT: ret <2 x i1> [[UMUL_OV]] 26; 27 %t0 = mul <2 x i8> %x, %y 28 %t1 = udiv <2 x i8> %t0, %x 29 %r = icmp ne <2 x i8> %t1, %y 30 ret <2 x i1> %r 31} 32 33declare i8 @gen8() 34 35define i1 @t2_commutative(i8 %x) { 36; CHECK-LABEL: @t2_commutative( 37; CHECK-NEXT: [[Y:%.*]] = call i8 @gen8() 38; CHECK-NEXT: [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y]]) 39; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1 40; CHECK-NEXT: ret i1 [[UMUL_OV]] 41; 42 %y = call i8 @gen8() 43 %t0 = mul i8 %y, %x ; swapped 44 %t1 = udiv i8 %t0, %x 45 %r = icmp ne i8 %t1, %y 46 ret i1 %r 47} 48 49define i1 @t3_commutative(i8 %x) { 50; CHECK-LABEL: @t3_commutative( 51; CHECK-NEXT: [[Y:%.*]] = call i8 @gen8() 52; CHECK-NEXT: [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y]]) 53; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1 54; CHECK-NEXT: ret i1 [[UMUL_OV]] 55; 56 %y = call i8 @gen8() 57 %t0 = mul i8 %y, %x ; swapped 58 %t1 = udiv i8 %t0, %x 59 %r = icmp ne i8 %t1, %y 60 ret i1 %r 61} 62 63define i1 @t4_commutative(i8 %x) { 64; CHECK-LABEL: @t4_commutative( 65; CHECK-NEXT: [[Y:%.*]] = call i8 @gen8() 66; CHECK-NEXT: [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y]]) 67; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1 68; CHECK-NEXT: ret i1 [[UMUL_OV]] 69; 70 %y = call i8 @gen8() 71 %t0 = mul i8 %y, %x ; swapped 72 %t1 = udiv i8 %t0, %x 73 %r = icmp ne i8 %y, %t1 ; swapped 74 ret i1 %r 75} 76 77; Extra-use tests 78 79declare void @use8(i8) 80 81define i1 @t5_extrause0(i8 %x, i8 %y) { 82; CHECK-LABEL: @t5_extrause0( 83; CHECK-NEXT: [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 84; CHECK-NEXT: [[UMUL_VAL:%.*]] = extractvalue { i8, i1 } [[UMUL]], 0 85; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1 86; CHECK-NEXT: call void @use8(i8 [[UMUL_VAL]]) 87; CHECK-NEXT: ret i1 [[UMUL_OV]] 88; 89 %t0 = mul i8 %x, %y 90 call void @use8(i8 %t0) 91 %t1 = udiv i8 %t0, %x 92 %r = icmp ne i8 %t1, %y 93 ret i1 %r 94} 95 96define i1 @t6_extrause1(i8 %x, i8 %y) { 97; CHECK-LABEL: @t6_extrause1( 98; CHECK-NEXT: [[T0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]] 99; CHECK-NEXT: [[T1:%.*]] = udiv i8 [[T0]], [[X]] 100; CHECK-NEXT: call void @use8(i8 [[T1]]) 101; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[T1]], [[Y]] 102; CHECK-NEXT: ret i1 [[R]] 103; 104 %t0 = mul i8 %x, %y 105 %t1 = udiv i8 %t0, %x 106 call void @use8(i8 %t1) 107 %r = icmp ne i8 %t1, %y 108 ret i1 %r 109} 110 111define i1 @t7_extrause2(i8 %x, i8 %y) { 112; CHECK-LABEL: @t7_extrause2( 113; CHECK-NEXT: [[T0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]] 114; CHECK-NEXT: call void @use8(i8 [[T0]]) 115; CHECK-NEXT: [[T1:%.*]] = udiv i8 [[T0]], [[X]] 116; CHECK-NEXT: call void @use8(i8 [[T1]]) 117; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[T1]], [[Y]] 118; CHECK-NEXT: ret i1 [[R]] 119; 120 %t0 = mul i8 %x, %y 121 call void @use8(i8 %t0) 122 %t1 = udiv i8 %t0, %x 123 call void @use8(i8 %t1) 124 %r = icmp ne i8 %t1, %y 125 ret i1 %r 126} 127 128; Negative tests 129 130define i1 @n8_different_x(i8 %x0, i8 %x1, i8 %y) { 131; CHECK-LABEL: @n8_different_x( 132; CHECK-NEXT: [[T0:%.*]] = mul i8 [[X0:%.*]], [[Y:%.*]] 133; CHECK-NEXT: [[T1:%.*]] = udiv i8 [[T0]], [[X1:%.*]] 134; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[T1]], [[Y]] 135; CHECK-NEXT: ret i1 [[R]] 136; 137 %t0 = mul i8 %x0, %y 138 %t1 = udiv i8 %t0, %x1 139 %r = icmp ne i8 %t1, %y 140 ret i1 %r 141} 142 143define i1 @n9_different_y(i8 %x, i8 %y0, i8 %y1) { 144; CHECK-LABEL: @n9_different_y( 145; CHECK-NEXT: [[T0:%.*]] = mul i8 [[X:%.*]], [[Y0:%.*]] 146; CHECK-NEXT: [[T1:%.*]] = udiv i8 [[T0]], [[X]] 147; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[T1]], [[Y1:%.*]] 148; CHECK-NEXT: ret i1 [[R]] 149; 150 %t0 = mul i8 %x, %y0 151 %t1 = udiv i8 %t0, %x 152 %r = icmp ne i8 %t1, %y1 153 ret i1 %r 154} 155 156define i1 @n10_wrong_pred(i8 %x, i8 %y) { 157; CHECK-LABEL: @n10_wrong_pred( 158; CHECK-NEXT: [[T0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]] 159; CHECK-NEXT: [[T1:%.*]] = udiv i8 [[T0]], [[X]] 160; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T1]], [[Y]] 161; CHECK-NEXT: ret i1 [[R]] 162; 163 %t0 = mul i8 %x, %y 164 %t1 = udiv i8 %t0, %x 165 %r = icmp ugt i8 %t1, %y 166 ret i1 %r 167} 168