1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine %s -S -o - | FileCheck %s 3 4; ((X - Y) - Z) --> X - (Y + Z) because we prefer add's. 5 6declare void @use8(i8) 7 8; Basic test 9define i8 @t0(i8 %x, i8 %y, i8 %z) { 10; CHECK-LABEL: @t0( 11; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]] 12; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]] 13; CHECK-NEXT: ret i8 [[R]] 14; 15 %i0 = sub i8 %x, %y 16 %r = sub i8 %i0, %z 17 ret i8 %r 18} 19 20; NSW/NUW flags are propagated 21define i8 @t1_flags(i8 %x, i8 %y, i8 %z) { 22; CHECK-LABEL: @t1_flags( 23; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[Y:%.*]], [[Z:%.*]] 24; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 [[X:%.*]], [[TMP1]] 25; CHECK-NEXT: ret i8 [[R]] 26; 27 %o0 = sub nuw nsw i8 %x, %y 28 %r = sub nuw nsw i8 %o0, %z 29 ret i8 %r 30} 31 32; NUW flags are propagated 33define i8 @t1_flags_nuw_only(i8 %x, i8 %y, i8 %z) { 34; CHECK-LABEL: @t1_flags_nuw_only( 35; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[Y:%.*]], [[Z:%.*]] 36; CHECK-NEXT: [[R:%.*]] = sub nuw i8 [[X:%.*]], [[TMP1]] 37; CHECK-NEXT: ret i8 [[R]] 38; 39 %o0 = sub nuw i8 %x, %y 40 %r = sub nuw i8 %o0, %z 41 ret i8 %r 42} 43 44; Negative tests 45define i8 @t1_flags_sub_nsw_sub(i8 %x, i8 %y, i8 %z) { 46; CHECK-LABEL: @t1_flags_sub_nsw_sub( 47; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]] 48; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]] 49; CHECK-NEXT: ret i8 [[R]] 50; 51 %o0 = sub nsw i8 %x, %y 52 %r = sub i8 %o0, %z 53 ret i8 %r 54} 55 56define i8 @t1_flags_nuw_first(i8 %x, i8 %y, i8 %z) { 57; CHECK-LABEL: @t1_flags_nuw_first( 58; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]] 59; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]] 60; CHECK-NEXT: ret i8 [[R]] 61; 62 %o0 = sub nuw i8 %x, %y 63 %r = sub i8 %o0, %z 64 ret i8 %r 65} 66 67define i8 @t1_flags_nuw_second(i8 %x, i8 %y, i8 %z) { 68; CHECK-LABEL: @t1_flags_nuw_second( 69; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]] 70; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]] 71; CHECK-NEXT: ret i8 [[R]] 72; 73 %o0 = sub i8 %x, %y 74 %r = sub nuw i8 %o0, %z 75 ret i8 %r 76} 77 78define i8 @t1_flags_nuw_nsw_first(i8 %x, i8 %y, i8 %z) { 79; CHECK-LABEL: @t1_flags_nuw_nsw_first( 80; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]] 81; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]] 82; CHECK-NEXT: ret i8 [[R]] 83; 84 %o0 = sub nuw nsw i8 %x, %y 85 %r = sub i8 %o0, %z 86 ret i8 %r 87} 88 89define i8 @t1_flags_nuw_nsw_second(i8 %x, i8 %y, i8 %z) { 90; CHECK-LABEL: @t1_flags_nuw_nsw_second( 91; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]] 92; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]] 93; CHECK-NEXT: ret i8 [[R]] 94; 95 %o0 = sub i8 %x, %y 96 %r = sub nuw nsw i8 %o0, %z 97 ret i8 %r 98} 99 100; The inner sub must have single use. 101define i8 @n2(i8 %x, i8 %y, i8 %z) { 102; CHECK-LABEL: @n2( 103; CHECK-NEXT: [[I0:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]] 104; CHECK-NEXT: call void @use8(i8 [[I0]]) 105; CHECK-NEXT: [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]] 106; CHECK-NEXT: ret i8 [[R]] 107; 108 %i0 = sub i8 %x, %y ; extra use 109 call void @use8(i8 %i0) 110 %r = sub i8 %i0, %z 111 ret i8 %r 112} 113 114; What if some operand is constant? 115 116define i8 @t3_c0(i8 %y, i8 %z) { 117; CHECK-LABEL: @t3_c0( 118; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]] 119; CHECK-NEXT: [[R:%.*]] = sub i8 42, [[TMP1]] 120; CHECK-NEXT: ret i8 [[R]] 121; 122 %i0 = sub i8 42, %y 123 %r = sub i8 %i0, %z 124 ret i8 %r 125} 126 127define i8 @t4_c1(i8 %x, i8 %z) { 128; CHECK-LABEL: @t4_c1( 129; CHECK-NEXT: [[I0:%.*]] = add i8 [[X:%.*]], -42 130; CHECK-NEXT: [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]] 131; CHECK-NEXT: ret i8 [[R]] 132; 133 %i0 = sub i8 %x, 42 134 %r = sub i8 %i0, %z 135 ret i8 %r 136} 137 138define i8 @t5_c2(i8 %x, i8 %y) { 139; CHECK-LABEL: @t5_c2( 140; CHECK-NEXT: [[I0:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]] 141; CHECK-NEXT: [[R:%.*]] = add i8 [[I0]], -42 142; CHECK-NEXT: ret i8 [[R]] 143; 144 %i0 = sub i8 %x, %y 145 %r = sub i8 %i0, 42 146 ret i8 %r 147} 148 149; What if some operand is constant and there was extra use? 150 151define i8 @t6_c0_extrause(i8 %y, i8 %z) { 152; CHECK-LABEL: @t6_c0_extrause( 153; CHECK-NEXT: [[I0:%.*]] = sub i8 42, [[Y:%.*]] 154; CHECK-NEXT: call void @use8(i8 [[I0]]) 155; CHECK-NEXT: [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]] 156; CHECK-NEXT: ret i8 [[R]] 157; 158 %i0 = sub i8 42, %y 159 call void @use8(i8 %i0) 160 %r = sub i8 %i0, %z 161 ret i8 %r 162} 163 164define i8 @t7_c1_extrause(i8 %x, i8 %z) { 165; CHECK-LABEL: @t7_c1_extrause( 166; CHECK-NEXT: [[I0:%.*]] = add i8 [[X:%.*]], -42 167; CHECK-NEXT: call void @use8(i8 [[I0]]) 168; CHECK-NEXT: [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]] 169; CHECK-NEXT: ret i8 [[R]] 170; 171 %i0 = sub i8 %x, 42 172 call void @use8(i8 %i0) 173 %r = sub i8 %i0, %z 174 ret i8 %r 175} 176 177define i8 @t8_c2_extrause(i8 %x, i8 %y) { 178; CHECK-LABEL: @t8_c2_extrause( 179; CHECK-NEXT: [[I0:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]] 180; CHECK-NEXT: call void @use8(i8 [[I0]]) 181; CHECK-NEXT: [[R:%.*]] = add i8 [[I0]], -42 182; CHECK-NEXT: ret i8 [[R]] 183; 184 %i0 = sub i8 %x, %y 185 call void @use8(i8 %i0) 186 %r = sub i8 %i0, 42 187 ret i8 %r 188} 189 190; What if two operands are constants? 191 192define i8 @t9_c0_c2(i8 %y, i8 %z) { 193; CHECK-LABEL: @t9_c0_c2( 194; CHECK-NEXT: [[R:%.*]] = sub i8 18, [[Y:%.*]] 195; CHECK-NEXT: ret i8 [[R]] 196; 197 %i0 = sub i8 42, %y 198 %r = sub i8 %i0, 24 199 ret i8 %r 200} 201 202define i8 @t10_c1_c2(i8 %x, i8 %z) { 203; CHECK-LABEL: @t10_c1_c2( 204; CHECK-NEXT: [[R:%.*]] = add i8 [[X:%.*]], -66 205; CHECK-NEXT: ret i8 [[R]] 206; 207 %i0 = sub i8 %x, 42 208 %r = sub i8 %i0, 24 209 ret i8 %r 210} 211 212; What if two operands are constants and there was extra use? 213 214define i8 @t11_c0_c2_extrause(i8 %y, i8 %z) { 215; CHECK-LABEL: @t11_c0_c2_extrause( 216; CHECK-NEXT: [[I0:%.*]] = sub i8 42, [[Y:%.*]] 217; CHECK-NEXT: call void @use8(i8 [[I0]]) 218; CHECK-NEXT: [[R:%.*]] = sub i8 18, [[Y]] 219; CHECK-NEXT: ret i8 [[R]] 220; 221 %i0 = sub i8 42, %y 222 call void @use8(i8 %i0) 223 %r = sub i8 %i0, 24 224 ret i8 %r 225} 226 227define i8 @t12_c1_c2_exrause(i8 %x, i8 %z) { 228; CHECK-LABEL: @t12_c1_c2_exrause( 229; CHECK-NEXT: [[I0:%.*]] = add i8 [[X:%.*]], -42 230; CHECK-NEXT: call void @use8(i8 [[I0]]) 231; CHECK-NEXT: [[R:%.*]] = add i8 [[X]], -66 232; CHECK-NEXT: ret i8 [[R]] 233; 234 %i0 = sub i8 %x, 42 235 call void @use8(i8 %i0) 236 %r = sub i8 %i0, 24 237 ret i8 %r 238} 239 240; PR49870 241@g0 = external global i8, align 1 242@g1 = external global i8, align 1 243define i32 @constantexpr0(i32 %x, ptr %y) unnamed_addr { 244; CHECK-LABEL: @constantexpr0( 245; CHECK-NEXT: [[I0:%.*]] = add i32 [[X:%.*]], ptrtoint (ptr @g0 to i32) 246; CHECK-NEXT: [[R:%.*]] = sub i32 0, [[I0]] 247; CHECK-NEXT: ret i32 [[R]] 248; 249 %i0 = add i32 %x, ptrtoint (ptr @g0 to i32) 250 %r = sub i32 0, %i0 251 ret i32 %r 252} 253define i32 @constantexpr1(i32 %x, ptr %y) unnamed_addr { 254; CHECK-LABEL: @constantexpr1( 255; CHECK-NEXT: [[I0:%.*]] = add i32 [[X:%.*]], 42 256; CHECK-NEXT: [[R:%.*]] = sub i32 ptrtoint (ptr @g1 to i32), [[I0]] 257; CHECK-NEXT: ret i32 [[R]] 258; 259 %i0 = add i32 %x, 42 260 %r = sub i32 ptrtoint (ptr @g1 to i32), %i0 261 ret i32 %r 262} 263define i32 @constantexpr2(i32 %x, ptr %y) unnamed_addr { 264; CHECK-LABEL: @constantexpr2( 265; CHECK-NEXT: [[I0:%.*]] = add i32 [[X:%.*]], ptrtoint (ptr @g0 to i32) 266; CHECK-NEXT: [[R:%.*]] = sub i32 ptrtoint (ptr @g1 to i32), [[I0]] 267; CHECK-NEXT: ret i32 [[R]] 268; 269 %i0 = add i32 %x, ptrtoint (ptr @g0 to i32) 270 %r = sub i32 ptrtoint (ptr @g1 to i32), %i0 271 ret i32 %r 272} 273 274define i64 @pr49870(i64 %x) { 275; CHECK-LABEL: @pr49870( 276; CHECK-NEXT: [[I0:%.*]] = xor i64 [[X:%.*]], -1 277; CHECK-NEXT: [[R:%.*]] = add i64 [[I0]], ptrtoint (ptr @g0 to i64) 278; CHECK-NEXT: ret i64 [[R]] 279; 280 %i0 = xor i64 %x, -1 281 %r = add i64 %i0, ptrtoint (ptr @g0 to i64) 282 ret i64 %r 283} 284