| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -S -passes=instcombine < %s | FileCheck %s |
| |
| define i32 @uadd(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @uadd( |
| ; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i32 [[S]] |
| ; |
| %ao = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y) |
| %o = extractvalue { i32, i1 } %ao, 1 |
| %a = extractvalue { i32, i1 } %ao, 0 |
| %s = select i1 %o, i32 -1, i32 %a |
| ret i32 %s |
| } |
| |
| define i32 @usub(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @usub( |
| ; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i32 [[S]] |
| ; |
| %ao = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y) |
| %o = extractvalue { i32, i1 } %ao, 1 |
| %a = extractvalue { i32, i1 } %ao, 0 |
| %s = select i1 %o, i32 0, i32 %a |
| ret i32 %s |
| } |
| |
| |
| define i8 @sadd_x_lt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_lt_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_x_lt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_lt_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_x_le_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_le_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_x_le_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_le_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_x_gt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_gt_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_x_gt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_gt_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_x_ge_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_ge_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_x_ge_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_x_ge_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], -1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| |
| define i8 @sadd_y_lt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_lt_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_y_lt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_lt_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_y_le_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_le_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_y_le_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_le_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_y_gt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_gt_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_y_gt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_gt_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_y_ge_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_ge_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @sadd_y_ge_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sadd_y_ge_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], -1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| |
| |
| |
| define i8 @ssub_x_lt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_lt_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_lt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_lt_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_le_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_le_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_le_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_le_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_lt2_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_lt2_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], -1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %x, -1 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_lt2_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_lt2_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %x, -1 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_gt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_gt_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_gt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_gt_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_ge_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_ge_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %x, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_ge_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_ge_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], -1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %x, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_gt2_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_gt2_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %x, -2 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_x_gt2_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_x_gt2_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], -2 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %x, -2 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| |
| define i8 @ssub_y_lt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_lt_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_y_lt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_lt_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp slt i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_y_le_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_le_min( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_y_le_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_le_max( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sle i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_y_gt_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_gt_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_y_gt_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_gt_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sgt i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_y_ge_min(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_ge_min( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], -1 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %y, 0 |
| %s = select i1 %c, i8 127, i8 -128 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| define i8 @ssub_y_ge_max(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @ssub_y_ge_max( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) |
| %o = extractvalue { i8, i1 } %ao, 1 |
| %a = extractvalue { i8, i1 } %ao, 0 |
| %c = icmp sge i8 %y, 0 |
| %s = select i1 %c, i8 -128, i8 127 |
| %r = select i1 %o, i8 %s, i8 %a |
| ret i8 %r |
| } |
| |
| |
| define i32 @sadd_i32(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @sadd_i32( |
| ; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i32 [[R]] |
| ; |
| %ao = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y) |
| %o = extractvalue { i32, i1 } %ao, 1 |
| %a = extractvalue { i32, i1 } %ao, 0 |
| %c = icmp slt i32 %x, 0 |
| %s = select i1 %c, i32 -2147483648, i32 2147483647 |
| %r = select i1 %o, i32 %s, i32 %a |
| ret i32 %r |
| } |
| |
| define i32 @ssub_i32(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @ssub_i32( |
| ; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) |
| ; CHECK-NEXT: ret i32 [[R]] |
| ; |
| %ao = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y) |
| %o = extractvalue { i32, i1 } %ao, 1 |
| %a = extractvalue { i32, i1 } %ao, 0 |
| %c = icmp slt i32 %x, 0 |
| %s = select i1 %c, i32 -2147483648, i32 2147483647 |
| %r = select i1 %o, i32 %s, i32 %a |
| ret i32 %r |
| } |
| |
| define i32 @sadd_bounds(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @sadd_bounds( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -128, i32 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]] |
| ; CHECK-NEXT: ret i32 [[R]] |
| ; |
| %ao = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y) |
| %o = extractvalue { i32, i1 } %ao, 1 |
| %a = extractvalue { i32, i1 } %ao, 0 |
| %c = icmp slt i32 %x, 0 |
| %s = select i1 %c, i32 -128, i32 127 |
| %r = select i1 %o, i32 %s, i32 %a |
| ret i32 %r |
| } |
| |
| define i32 @ssub_bounds(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @ssub_bounds( |
| ; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) |
| ; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 |
| ; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0 |
| ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -128, i32 127 |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]] |
| ; CHECK-NEXT: ret i32 [[R]] |
| ; |
| %ao = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y) |
| %o = extractvalue { i32, i1 } %ao, 1 |
| %a = extractvalue { i32, i1 } %ao, 0 |
| %c = icmp slt i32 %x, 0 |
| %s = select i1 %c, i32 -128, i32 127 |
| %r = select i1 %o, i32 %s, i32 %a |
| ret i32 %r |
| } |
| |
| declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %0, i32 %1) |
| declare { i32, i1 } @llvm.usub.with.overflow.i32(i32 %0, i32 %1) |
| declare { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %0, i8 %1) |
| declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %0, i8 %1) |
| declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %0, i32 %1) |
| declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %0, i32 %1) |