1; RUN: opt < %s -instsimplify -S | FileCheck %s 2 3; Division-by-zero is undef. UB in any vector lane means the whole op is undef. 4 5define <2 x i8> @sdiv_zero_elt_vec_constfold(<2 x i8> %x) { 6; CHECK-LABEL: @sdiv_zero_elt_vec_constfold( 7; CHECK-NEXT: ret <2 x i8> undef 8; 9 %div = sdiv <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42> 10 ret <2 x i8> %div 11} 12 13define <2 x i8> @udiv_zero_elt_vec_constfold(<2 x i8> %x) { 14; CHECK-LABEL: @udiv_zero_elt_vec_constfold( 15; CHECK-NEXT: ret <2 x i8> undef 16; 17 %div = udiv <2 x i8> <i8 1, i8 2>, <i8 42, i8 0> 18 ret <2 x i8> %div 19} 20 21define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) { 22; CHECK-LABEL: @sdiv_zero_elt_vec( 23; CHECK-NEXT: ret <2 x i8> undef 24; 25 %div = sdiv <2 x i8> %x, <i8 -42, i8 0> 26 ret <2 x i8> %div 27} 28 29define <2 x i8> @udiv_zero_elt_vec(<2 x i8> %x) { 30; CHECK-LABEL: @udiv_zero_elt_vec( 31; CHECK-NEXT: ret <2 x i8> undef 32; 33 %div = udiv <2 x i8> %x, <i8 0, i8 42> 34 ret <2 x i8> %div 35} 36 37; Division-by-zero is undef. UB in any vector lane means the whole op is undef. 38; Thus, we can simplify this: if any element of 'y' is 0, we can do anything. 39; Therefore, assume that all elements of 'y' must be 1. 40 41define <2 x i1> @sdiv_bool_vec(<2 x i1> %x, <2 x i1> %y) { 42; CHECK-LABEL: @sdiv_bool_vec( 43; CHECK-NEXT: ret <2 x i1> %x 44; 45 %div = sdiv <2 x i1> %x, %y 46 ret <2 x i1> %div 47} 48 49define <2 x i1> @udiv_bool_vec(<2 x i1> %x, <2 x i1> %y) { 50; CHECK-LABEL: @udiv_bool_vec( 51; CHECK-NEXT: ret <2 x i1> %x 52; 53 %div = udiv <2 x i1> %x, %y 54 ret <2 x i1> %div 55} 56 57define i32 @udiv_dividend_known_smaller_than_constant_divisor(i32 %x) { 58; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor( 59; CHECK-NEXT: ret i32 0 60; 61 %and = and i32 %x, 250 62 %div = udiv i32 %and, 251 63 ret i32 %div 64} 65 66define i32 @not_udiv_dividend_known_smaller_than_constant_divisor(i32 %x) { 67; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor( 68; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 251 69; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], 251 70; CHECK-NEXT: ret i32 [[DIV]] 71; 72 %and = and i32 %x, 251 73 %div = udiv i32 %and, 251 74 ret i32 %div 75} 76 77define i32 @udiv_constant_dividend_known_smaller_than_divisor(i32 %x) { 78; CHECK-LABEL: @udiv_constant_dividend_known_smaller_than_divisor( 79; CHECK-NEXT: ret i32 0 80; 81 %or = or i32 %x, 251 82 %div = udiv i32 250, %or 83 ret i32 %div 84} 85 86define i32 @not_udiv_constant_dividend_known_smaller_than_divisor(i32 %x) { 87; CHECK-LABEL: @not_udiv_constant_dividend_known_smaller_than_divisor( 88; CHECK-NEXT: [[OR:%.*]] = or i32 %x, 251 89; CHECK-NEXT: [[DIV:%.*]] = udiv i32 251, [[OR]] 90; CHECK-NEXT: ret i32 [[DIV]] 91; 92 %or = or i32 %x, 251 93 %div = udiv i32 251, %or 94 ret i32 %div 95} 96 97; This would require computing known bits on both x and y. Is it worth doing? 98 99define i32 @udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) { 100; CHECK-LABEL: @udiv_dividend_known_smaller_than_divisor( 101; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 250 102; CHECK-NEXT: [[OR:%.*]] = or i32 %y, 251 103; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], [[OR]] 104; CHECK-NEXT: ret i32 [[DIV]] 105; 106 %and = and i32 %x, 250 107 %or = or i32 %y, 251 108 %div = udiv i32 %and, %or 109 ret i32 %div 110} 111 112define i32 @not_udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) { 113; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_divisor( 114; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 251 115; CHECK-NEXT: [[OR:%.*]] = or i32 %y, 251 116; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], [[OR]] 117; CHECK-NEXT: ret i32 [[DIV]] 118; 119 %and = and i32 %x, 251 120 %or = or i32 %y, 251 121 %div = udiv i32 %and, %or 122 ret i32 %div 123} 124 125declare i32 @external() 126 127define i32 @div1() { 128; CHECK-LABEL: @div1( 129; CHECK-NEXT: [[CALL:%.*]] = call i32 @external(), !range !0 130; CHECK-NEXT: ret i32 0 131; 132 %call = call i32 @external(), !range !0 133 %urem = udiv i32 %call, 3 134 ret i32 %urem 135} 136 137!0 = !{i32 0, i32 3} 138