1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare { <2 x i32>, <2 x i1> } @llvm.sadd.with.overflow.v2i32(<2 x i32>, <2 x i32>) 5 6declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) 7 8declare { i8, i1 } @llvm.sadd.with.overflow.i8(i8, i8) 9 10define { i32, i1 } @simple_fold(i32 %x) { 11; CHECK-LABEL: @simple_fold( 12; CHECK-NEXT: [[B:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 20) 13; CHECK-NEXT: ret { i32, i1 } [[B]] 14; 15 %a = add nsw i32 %x, 7 16 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 13) 17 ret { i32, i1 } %b 18} 19 20define { i32, i1 } @fold_mixed_signs(i32 %x) { 21; CHECK-LABEL: @fold_mixed_signs( 22; CHECK-NEXT: [[B:%.*]] = add nsw i32 [[X:%.*]], 6 23; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[B]], 0 24; CHECK-NEXT: ret { i32, i1 } [[TMP1]] 25; 26 %a = add nsw i32 %x, 13 27 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 -7) 28 ret { i32, i1 } %b 29} 30 31define { i8, i1 } @fold_on_constant_add_no_overflow(i8 %x) { 32; CHECK-LABEL: @fold_on_constant_add_no_overflow( 33; CHECK-NEXT: [[B:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 127) 34; CHECK-NEXT: ret { i8, i1 } [[B]] 35; 36 %a = add nsw i8 %x, 100 37 %b = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 27) 38 ret { i8, i1 } %b 39} 40 41define { i8, i1 } @no_fold_on_constant_add_overflow(i8 %x) { 42; CHECK-LABEL: @no_fold_on_constant_add_overflow( 43; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 100 44; CHECK-NEXT: [[B:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A]], i8 28) 45; CHECK-NEXT: ret { i8, i1 } [[B]] 46; 47 %a = add nsw i8 %x, 100 48 %b = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 28) 49 ret { i8, i1 } %b 50} 51 52define { <2 x i32>, <2 x i1> } @fold_simple_splat_constant(<2 x i32> %x) { 53; CHECK-LABEL: @fold_simple_splat_constant( 54; CHECK-NEXT: [[B:%.*]] = call { <2 x i32>, <2 x i1> } @llvm.sadd.with.overflow.v2i32(<2 x i32> [[X:%.*]], <2 x i32> splat (i32 42)) 55; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[B]] 56; 57 %a = add nsw <2 x i32> %x, <i32 12, i32 12> 58 %b = tail call { <2 x i32>, <2 x i1> } @llvm.sadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 30, i32 30>) 59 ret { <2 x i32>, <2 x i1> } %b 60} 61 62define { <2 x i32>, <2 x i1> } @no_fold_splat_undef_constant(<2 x i32> %x) { 63; CHECK-LABEL: @no_fold_splat_undef_constant( 64; CHECK-NEXT: [[A:%.*]] = add nsw <2 x i32> [[X:%.*]], <i32 12, i32 undef> 65; CHECK-NEXT: [[B:%.*]] = tail call { <2 x i32>, <2 x i1> } @llvm.sadd.with.overflow.v2i32(<2 x i32> [[A]], <2 x i32> splat (i32 30)) 66; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[B]] 67; 68 %a = add nsw <2 x i32> %x, <i32 12, i32 undef> 69 %b = tail call { <2 x i32>, <2 x i1> } @llvm.sadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 30, i32 30>) 70 ret { <2 x i32>, <2 x i1> } %b 71} 72 73define { <2 x i32>, <2 x i1> } @no_fold_splat_not_constant(<2 x i32> %x, <2 x i32> %y) { 74; CHECK-LABEL: @no_fold_splat_not_constant( 75; CHECK-NEXT: [[A:%.*]] = add nsw <2 x i32> [[X:%.*]], [[Y:%.*]] 76; CHECK-NEXT: [[B:%.*]] = tail call { <2 x i32>, <2 x i1> } @llvm.sadd.with.overflow.v2i32(<2 x i32> [[A]], <2 x i32> splat (i32 30)) 77; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[B]] 78; 79 %a = add nsw <2 x i32> %x, %y 80 %b = tail call { <2 x i32>, <2 x i1> } @llvm.sadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 30, i32 30>) 81 ret { <2 x i32>, <2 x i1> } %b 82} 83 84define { i32, i1 } @fold_nuwnsw(i32 %x) { 85; CHECK-LABEL: @fold_nuwnsw( 86; CHECK-NEXT: [[B:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 42) 87; CHECK-NEXT: ret { i32, i1 } [[B]] 88; 89 %a = add nuw nsw i32 %x, 12 90 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 30) 91 ret { i32, i1 } %b 92} 93 94define { i32, i1 } @no_fold_nuw(i32 %x) { 95; CHECK-LABEL: @no_fold_nuw( 96; CHECK-NEXT: [[A:%.*]] = add nuw i32 [[X:%.*]], 12 97; CHECK-NEXT: [[B:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A]], i32 30) 98; CHECK-NEXT: ret { i32, i1 } [[B]] 99; 100 %a = add nuw i32 %x, 12 101 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 30) 102 ret { i32, i1 } %b 103} 104 105define { i32, i1 } @no_fold_wrapped_add(i32 %x) { 106; CHECK-LABEL: @no_fold_wrapped_add( 107; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 12 108; CHECK-NEXT: [[B:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A]], i32 30) 109; CHECK-NEXT: ret { i32, i1 } [[B]] 110; 111 %a = add i32 %x, 12 112 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 30, i32 %a) 113 ret { i32, i1 } %b 114} 115 116define { i32, i1 } @fold_sub_simple(i32 %x) { 117; CHECK-LABEL: @fold_sub_simple( 118; CHECK-NEXT: [[B:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 42) 119; CHECK-NEXT: ret { i32, i1 } [[B]] 120; 121 %a = sub nsw i32 %x, -12 122 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 30) 123 ret { i32, i1 } %b 124} 125 126define { i32, i1 } @fold_with_distjoin_or(i32 %x) { 127; CHECK-LABEL: @fold_with_distjoin_or( 128; CHECK-NEXT: [[B:%.*]] = add nsw i32 [[X:%.*]], 6 129; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[B]], 0 130; CHECK-NEXT: ret { i32, i1 } [[TMP1]] 131; 132 %a = or disjoint i32 %x, 13 133 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 -7) 134 ret { i32, i1 } %b 135} 136 137define { i32, i1 } @fold_with_disjoint_or2(i32 %x) { 138; CHECK-LABEL: @fold_with_disjoint_or2( 139; CHECK-NEXT: [[B:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 127) 140; CHECK-NEXT: ret { i32, i1 } [[B]] 141; 142 %a = or disjoint i32 %x, 100 143 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 27) 144 ret { i32, i1 } %b 145} 146 147define { i32, i1 } @fold_with_or_fail(i32 %x) { 148; CHECK-LABEL: @fold_with_or_fail( 149; CHECK-NEXT: [[A:%.*]] = or i32 [[X:%.*]], 100 150; CHECK-NEXT: [[B:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A]], i32 27) 151; CHECK-NEXT: ret { i32, i1 } [[B]] 152; 153 %a = or i32 %x, 100 154 %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 27) 155 ret { i32, i1 } %b 156} 157