1; NOTE: Assertions have been autogenerated by update_test_checks.py 2; RUN: opt < %s -instsimplify -S | FileCheck %s 3 4; Division-by-zero is undef. UB in any vector lane means the whole op is undef. 5 6define <2 x i8> @srem_zero_elt_vec_constfold(<2 x i8> %x) { 7; CHECK-LABEL: @srem_zero_elt_vec_constfold( 8; CHECK-NEXT: ret <2 x i8> undef 9; 10 %rem = srem <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42> 11 ret <2 x i8> %rem 12} 13 14define <2 x i8> @urem_zero_elt_vec_constfold(<2 x i8> %x) { 15; CHECK-LABEL: @urem_zero_elt_vec_constfold( 16; CHECK-NEXT: ret <2 x i8> undef 17; 18 %rem = urem <2 x i8> <i8 1, i8 2>, <i8 42, i8 0> 19 ret <2 x i8> %rem 20} 21 22define <2 x i8> @srem_zero_elt_vec(<2 x i8> %x) { 23; CHECK-LABEL: @srem_zero_elt_vec( 24; CHECK-NEXT: ret <2 x i8> undef 25; 26 %rem = srem <2 x i8> %x, <i8 -42, i8 0> 27 ret <2 x i8> %rem 28} 29 30define <2 x i8> @urem_zero_elt_vec(<2 x i8> %x) { 31; CHECK-LABEL: @urem_zero_elt_vec( 32; CHECK-NEXT: ret <2 x i8> undef 33; 34 %rem = urem <2 x i8> %x, <i8 0, i8 42> 35 ret <2 x i8> %rem 36} 37 38; Division-by-zero is undef. UB in any vector lane means the whole op is undef. 39; Thus, we can simplify this: if any element of 'y' is 0, we can do anything. 40; Therefore, assume that all elements of 'y' must be 1. 41 42define <2 x i1> @srem_bool_vec(<2 x i1> %x, <2 x i1> %y) { 43; CHECK-LABEL: @srem_bool_vec( 44; CHECK-NEXT: ret <2 x i1> zeroinitializer 45; 46 %rem = srem <2 x i1> %x, %y 47 ret <2 x i1> %rem 48} 49 50define <2 x i1> @urem_bool_vec(<2 x i1> %x, <2 x i1> %y) { 51; CHECK-LABEL: @urem_bool_vec( 52; CHECK-NEXT: ret <2 x i1> zeroinitializer 53; 54 %rem = urem <2 x i1> %x, %y 55 ret <2 x i1> %rem 56} 57 58define i32 @select1(i32 %x, i1 %b) { 59; CHECK-LABEL: @select1( 60; CHECK-NEXT: ret i32 0 61; 62 %rhs = select i1 %b, i32 %x, i32 1 63 %rem = srem i32 %x, %rhs 64 ret i32 %rem 65} 66 67define i32 @select2(i32 %x, i1 %b) { 68; CHECK-LABEL: @select2( 69; CHECK-NEXT: ret i32 0 70; 71 %rhs = select i1 %b, i32 %x, i32 1 72 %rem = urem i32 %x, %rhs 73 ret i32 %rem 74} 75 76define i32 @rem1(i32 %x, i32 %n) { 77; CHECK-LABEL: @rem1( 78; CHECK-NEXT: [[MOD:%.*]] = srem i32 %x, %n 79; CHECK-NEXT: ret i32 [[MOD]] 80; 81 %mod = srem i32 %x, %n 82 %mod1 = srem i32 %mod, %n 83 ret i32 %mod1 84} 85 86define i32 @rem2(i32 %x, i32 %n) { 87; CHECK-LABEL: @rem2( 88; CHECK-NEXT: [[MOD:%.*]] = urem i32 %x, %n 89; CHECK-NEXT: ret i32 [[MOD]] 90; 91 %mod = urem i32 %x, %n 92 %mod1 = urem i32 %mod, %n 93 ret i32 %mod1 94} 95 96define i32 @rem3(i32 %x, i32 %n) { 97; CHECK-LABEL: @rem3( 98; CHECK-NEXT: [[MOD:%.*]] = srem i32 %x, %n 99; CHECK-NEXT: [[MOD1:%.*]] = urem i32 [[MOD]], %n 100; CHECK-NEXT: ret i32 [[MOD1]] 101; 102 %mod = srem i32 %x, %n 103 %mod1 = urem i32 %mod, %n 104 ret i32 %mod1 105} 106 107define i32 @urem_dividend_known_smaller_than_constant_divisor(i32 %x) { 108; CHECK-LABEL: @urem_dividend_known_smaller_than_constant_divisor( 109; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 250 110; CHECK-NEXT: ret i32 [[AND]] 111; 112 %and = and i32 %x, 250 113 %r = urem i32 %and, 251 114 ret i32 %r 115} 116 117define i32 @not_urem_dividend_known_smaller_than_constant_divisor(i32 %x) { 118; CHECK-LABEL: @not_urem_dividend_known_smaller_than_constant_divisor( 119; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 251 120; CHECK-NEXT: [[R:%.*]] = urem i32 [[AND]], 251 121; CHECK-NEXT: ret i32 [[R]] 122; 123 %and = and i32 %x, 251 124 %r = urem i32 %and, 251 125 ret i32 %r 126} 127 128define i32 @urem_constant_dividend_known_smaller_than_divisor(i32 %x) { 129; CHECK-LABEL: @urem_constant_dividend_known_smaller_than_divisor( 130; CHECK-NEXT: ret i32 250 131; 132 %or = or i32 %x, 251 133 %r = urem i32 250, %or 134 ret i32 %r 135} 136 137define i32 @not_urem_constant_dividend_known_smaller_than_divisor(i32 %x) { 138; CHECK-LABEL: @not_urem_constant_dividend_known_smaller_than_divisor( 139; CHECK-NEXT: [[OR:%.*]] = or i32 %x, 251 140; CHECK-NEXT: [[R:%.*]] = urem i32 251, [[OR]] 141; CHECK-NEXT: ret i32 [[R]] 142; 143 %or = or i32 %x, 251 144 %r = urem i32 251, %or 145 ret i32 %r 146} 147 148; This would require computing known bits on both x and y. Is it worth doing? 149 150define i32 @urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) { 151; CHECK-LABEL: @urem_dividend_known_smaller_than_divisor( 152; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 250 153; CHECK-NEXT: [[OR:%.*]] = or i32 %y, 251 154; CHECK-NEXT: [[R:%.*]] = urem i32 [[AND]], [[OR]] 155; CHECK-NEXT: ret i32 [[R]] 156; 157 %and = and i32 %x, 250 158 %or = or i32 %y, 251 159 %r = urem i32 %and, %or 160 ret i32 %r 161} 162 163define i32 @not_urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) { 164; CHECK-LABEL: @not_urem_dividend_known_smaller_than_divisor( 165; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 251 166; CHECK-NEXT: [[OR:%.*]] = or i32 %y, 251 167; CHECK-NEXT: [[R:%.*]] = urem i32 [[AND]], [[OR]] 168; CHECK-NEXT: ret i32 [[R]] 169; 170 %and = and i32 %x, 251 171 %or = or i32 %y, 251 172 %r = urem i32 %and, %or 173 ret i32 %r 174} 175 176declare i32 @external() 177 178define i32 @rem4() { 179; CHECK-LABEL: @rem4( 180; CHECK-NEXT: [[CALL:%.*]] = call i32 @external(), !range !0 181; CHECK-NEXT: ret i32 [[CALL]] 182; 183 %call = call i32 @external(), !range !0 184 %urem = urem i32 %call, 3 185 ret i32 %urem 186} 187 188!0 = !{i32 0, i32 3} 189