1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; 'Negate' is considered less complex than a normal binop, so the xor should have the binop as the first operand. 5 6define i8 @neg(i8 %x) { 7; CHECK-LABEL: @neg( 8; CHECK-NEXT: [[BO:%.*]] = udiv i8 [[X:%.*]], 42 9; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X]] 10; CHECK-NEXT: [[R:%.*]] = xor i8 [[BO]], [[NEGX]] 11; CHECK-NEXT: ret i8 [[R]] 12; 13 %bo = udiv i8 %x, 42 14 %negx = sub i8 0, %x 15 %r = xor i8 %negx, %bo 16 ret i8 %r 17} 18 19define <2 x i8> @neg_vec(<2 x i8> %x) { 20; CHECK-LABEL: @neg_vec( 21; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42> 22; CHECK-NEXT: [[NEGX:%.*]] = sub <2 x i8> zeroinitializer, [[X]] 23; CHECK-NEXT: [[R:%.*]] = xor <2 x i8> [[BO]], [[NEGX]] 24; CHECK-NEXT: ret <2 x i8> [[R]] 25; 26 %bo = udiv <2 x i8> %x, <i8 42, i8 -42> 27 %negx = sub <2 x i8> <i8 0, i8 0>, %x 28 %r = xor <2 x i8> %negx, %bo 29 ret <2 x i8> %r 30} 31 32define <2 x i8> @neg_vec_undef(<2 x i8> %x) { 33; CHECK-LABEL: @neg_vec_undef( 34; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42> 35; CHECK-NEXT: [[NEGX:%.*]] = sub <2 x i8> <i8 0, i8 undef>, [[X]] 36; CHECK-NEXT: [[R:%.*]] = xor <2 x i8> [[BO]], [[NEGX]] 37; CHECK-NEXT: ret <2 x i8> [[R]] 38; 39 %bo = udiv <2 x i8> %x, <i8 42, i8 -42> 40 %negx = sub <2 x i8> <i8 0, i8 undef>, %x 41 %r = xor <2 x i8> %negx, %bo 42 ret <2 x i8> %r 43} 44 45; 'Not' is considered less complex than a normal binop, so the mul should have the binop as the first operand. 46 47define i8 @not(i8 %x) { 48; CHECK-LABEL: @not( 49; CHECK-NEXT: [[BO:%.*]] = udiv i8 [[X:%.*]], 42 50; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X]], -1 51; CHECK-NEXT: [[R:%.*]] = mul i8 [[BO]], [[NOTX]] 52; CHECK-NEXT: ret i8 [[R]] 53; 54 %bo = udiv i8 %x, 42 55 %notx = xor i8 -1, %x 56 %r = mul i8 %notx, %bo 57 ret i8 %r 58} 59 60define <2 x i8> @not_vec(<2 x i8> %x) { 61; CHECK-LABEL: @not_vec( 62; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42> 63; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 -1> 64; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[BO]], [[NOTX]] 65; CHECK-NEXT: ret <2 x i8> [[R]] 66; 67 %bo = udiv <2 x i8> %x, <i8 42, i8 -42> 68 %notx = xor <2 x i8> <i8 -1, i8 -1>, %x 69 %r = mul <2 x i8> %notx, %bo 70 ret <2 x i8> %r 71} 72 73define <2 x i8> @not_vec_undef(<2 x i8> %x) { 74; CHECK-LABEL: @not_vec_undef( 75; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42> 76; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 undef> 77; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[BO]], [[NOTX]] 78; CHECK-NEXT: ret <2 x i8> [[R]] 79; 80 %bo = udiv <2 x i8> %x, <i8 42, i8 -42> 81 %notx = xor <2 x i8> <i8 -1, i8 undef>, %x 82 %r = mul <2 x i8> %notx, %bo 83 ret <2 x i8> %r 84} 85 86; 'Fneg' is considered less complex than a normal binop, so the fmul should have the binop as the first operand. 87; Extra uses are required to ensure that the fneg is not canonicalized after the fmul. 88 89declare void @use(float) 90declare void @use_vec(<2 x float>) 91 92define float @fneg(float %x) { 93; CHECK-LABEL: @fneg( 94; CHECK-NEXT: [[BO:%.*]] = fdiv float [[X:%.*]], 4.200000e+01 95; CHECK-NEXT: [[FNEGX:%.*]] = fneg float [[X]] 96; CHECK-NEXT: [[R:%.*]] = fmul float [[BO]], [[FNEGX]] 97; CHECK-NEXT: call void @use(float [[FNEGX]]) 98; CHECK-NEXT: ret float [[R]] 99; 100 %bo = fdiv float %x, 42.0 101 %fnegx = fsub float -0.0, %x 102 %r = fmul float %fnegx, %bo 103 call void @use(float %fnegx) 104 ret float %r 105} 106 107define float @unary_fneg(float %x) { 108; CHECK-LABEL: @unary_fneg( 109; CHECK-NEXT: [[BO:%.*]] = fdiv float [[X:%.*]], 4.200000e+01 110; CHECK-NEXT: [[FNEGX:%.*]] = fneg float [[X]] 111; CHECK-NEXT: [[R:%.*]] = fmul float [[BO]], [[FNEGX]] 112; CHECK-NEXT: call void @use(float [[FNEGX]]) 113; CHECK-NEXT: ret float [[R]] 114; 115 %bo = fdiv float %x, 42.0 116 %fnegx = fneg float %x 117 %r = fmul float %fnegx, %bo 118 call void @use(float %fnegx) 119 ret float %r 120} 121 122define <2 x float> @fneg_vec(<2 x float> %x) { 123; CHECK-LABEL: @fneg_vec( 124; CHECK-NEXT: [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01> 125; CHECK-NEXT: [[FNEGX:%.*]] = fneg <2 x float> [[X]] 126; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]] 127; CHECK-NEXT: call void @use_vec(<2 x float> [[FNEGX]]) 128; CHECK-NEXT: ret <2 x float> [[R]] 129; 130 %bo = fdiv <2 x float> %x, <float 42.0, float -42.0> 131 %fnegx = fsub <2 x float> <float -0.0, float -0.0>, %x 132 %r = fmul <2 x float> %fnegx, %bo 133 call void @use_vec(<2 x float> %fnegx) 134 ret <2 x float> %r 135} 136 137define <2 x float> @fneg_vec_undef(<2 x float> %x) { 138; CHECK-LABEL: @fneg_vec_undef( 139; CHECK-NEXT: [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01> 140; CHECK-NEXT: [[FNEGX:%.*]] = fneg <2 x float> [[X]] 141; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]] 142; CHECK-NEXT: call void @use_vec(<2 x float> [[FNEGX]]) 143; CHECK-NEXT: ret <2 x float> [[R]] 144; 145 %bo = fdiv <2 x float> %x, <float 42.0, float -42.0> 146 %fnegx = fsub <2 x float> <float -0.0, float undef>, %x 147 %r = fmul <2 x float> %fnegx, %bo 148 call void @use_vec(<2 x float> %fnegx) 149 ret <2 x float> %r 150} 151 152define <2 x float> @unary_fneg_vec(<2 x float> %x) { 153; CHECK-LABEL: @unary_fneg_vec( 154; CHECK-NEXT: [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01> 155; CHECK-NEXT: [[FNEGX:%.*]] = fneg <2 x float> [[X]] 156; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]] 157; CHECK-NEXT: call void @use_vec(<2 x float> [[FNEGX]]) 158; CHECK-NEXT: ret <2 x float> [[R]] 159; 160 %bo = fdiv <2 x float> %x, <float 42.0, float -42.0> 161 %fnegx = fneg <2 x float> %x 162 %r = fmul <2 x float> %fnegx, %bo 163 call void @use_vec(<2 x float> %fnegx) 164 ret <2 x float> %r 165} 166 167