From: Nikita Popov Date: Sat, 13 Apr 2019 11:40:16 +0000 (+0000) Subject: [CVP] Add tests for with.overflow used as condition; NFC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=644b6da1983021088408dd419b44ac2a2778a928;p=llvm [CVP] Add tests for with.overflow used as condition; NFC git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358330 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Transforms/CorrelatedValuePropagation/overflow_predicate.ll b/test/Transforms/CorrelatedValuePropagation/overflow_predicate.ll new file mode 100644 index 00000000000..070982fc8c5 --- /dev/null +++ b/test/Transforms/CorrelatedValuePropagation/overflow_predicate.ll @@ -0,0 +1,474 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -correlated-propagation < %s | FileCheck %s + +declare void @llvm.trap() +declare {i8, i1} @llvm.uadd.with.overflow(i8, i8) +declare {i8, i1} @llvm.sadd.with.overflow(i8, i8) +declare {i8, i1} @llvm.usub.with.overflow(i8, i8) +declare {i8, i1} @llvm.ssub.with.overflow(i8, i8) +declare {i8, i1} @llvm.umul.with.overflow(i8, i8) +declare {i8, i1} @llvm.smul.with.overflow(i8, i8) + +define i1 @uadd_ov_false(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @uadd_ov_false( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] +; CHECK: no_overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], -102 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp ugt i8 [[X]], -101 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %trap, label %no_overflow + +no_overflow: + %c1 = icmp ugt i8 %x, 154 + store i1 %c1, i1* %pc + %c2 = icmp ugt i8 %x, 155 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @uadd_ov_true(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @uadd_ov_true( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] +; CHECK: overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], -100 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp ugt i8 [[X]], -101 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %overflow, label %trap + +overflow: + %c1 = icmp ugt i8 %x, 156 + store i1 %c1, i1* %pc + %c2 = icmp ugt i8 %x, 155 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @sadd_ov_false(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @sadd_ov_false( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] +; CHECK: no_overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], 26 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp sgt i8 [[X]], 27 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %trap, label %no_overflow + +no_overflow: + %c1 = icmp sgt i8 %x, 26 + store i1 %c1, i1* %pc + %c2 = icmp sgt i8 %x, 27 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @sadd_ov_true(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @sadd_ov_true( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] +; CHECK: overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], 28 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp sgt i8 [[X]], 27 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %overflow, label %trap + +overflow: + %c1 = icmp sgt i8 %x, 28 + store i1 %c1, i1* %pc + %c2 = icmp sgt i8 %x, 27 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @usub_ov_false(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @usub_ov_false( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] +; CHECK: no_overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], 101 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp ult i8 [[X]], 100 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %trap, label %no_overflow + +no_overflow: + %c1 = icmp ult i8 %x, 101 + store i1 %c1, i1* %pc + %c2 = icmp ult i8 %x, 100 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @usub_ov_true(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @usub_ov_true( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] +; CHECK: overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], 99 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp ult i8 [[X]], 100 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %overflow, label %trap + +overflow: + %c1 = icmp ult i8 %x, 99 + store i1 %c1, i1* %pc + %c2 = icmp ult i8 %x, 100 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @ssub_ov_false(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @ssub_ov_false( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] +; CHECK: no_overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], -27 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp slt i8 [[X]], -28 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %trap, label %no_overflow + +no_overflow: + %c1 = icmp slt i8 %x, -27 + store i1 %c1, i1* %pc + %c2 = icmp slt i8 %x, -28 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @ssub_ov_true(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @ssub_ov_true( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] +; CHECK: overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], -29 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp slt i8 [[X]], -28 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %overflow, label %trap + +overflow: + %c1 = icmp slt i8 %x, -29 + store i1 %c1, i1* %pc + %c2 = icmp slt i8 %x, -28 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @umul_ov_false(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @umul_ov_false( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] +; CHECK: no_overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], 25 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp ult i8 [[X]], 26 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %trap, label %no_overflow + +no_overflow: + %c1 = icmp ult i8 %x, 25 + store i1 %c1, i1* %pc + %c2 = icmp ult i8 %x, 26 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @umul_ov_true(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @umul_ov_true( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] +; CHECK: overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], 27 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp ult i8 [[X]], 26 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %overflow, label %trap + +overflow: + %c1 = icmp ult i8 %x, 27 + store i1 %c1, i1* %pc + %c2 = icmp ult i8 %x, 26 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +; Signed mul is constrained from both sides. +define i1 @smul_ov_false_bound1(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @smul_ov_false_bound1( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] +; CHECK: no_overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], -11 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp slt i8 [[X]], -12 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %trap, label %no_overflow + +no_overflow: + %c1 = icmp slt i8 %x, -11 + store i1 %c1, i1* %pc + %c2 = icmp slt i8 %x, -12 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @smul_ov_false_bound2(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @smul_ov_false_bound2( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] +; CHECK: no_overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], 11 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp sgt i8 [[X]], 12 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %trap, label %no_overflow + +no_overflow: + %c1 = icmp sgt i8 %x, 11 + store i1 %c1, i1* %pc + %c2 = icmp sgt i8 %x, 12 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +; Can't use slt/sgt to test for a hole in the range, check equality instead. +define i1 @smul_ov_true_bound1(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @smul_ov_true_bound1( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] +; CHECK: overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], -13 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[X]], -12 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %overflow, label %trap + +overflow: + %c1 = icmp eq i8 %x, -13 + store i1 %c1, i1* %pc + %c2 = icmp eq i8 %x, -12 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +} + +define i1 @smul_ov_true_bound2(i8 %x, i8* %px, i1* %pc) { +; CHECK-LABEL: @smul_ov_true_bound2( +; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) +; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 +; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]] +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 +; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] +; CHECK: overflow: +; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], 13 +; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[X]], 12 +; CHECK-NEXT: ret i1 [[C2]] +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() +; CHECK-NEXT: unreachable +; + %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) + %val = extractvalue {i8, i1} %val_ov, 0 + store i8 %val, i8* %px + %ov = extractvalue {i8, i1} %val_ov, 1 + br i1 %ov, label %overflow, label %trap + +overflow: + %c1 = icmp eq i8 %x, 13 + store i1 %c1, i1* %pc + %c2 = icmp eq i8 %x, 12 + ret i1 %c2 + +trap: + call void @llvm.trap() + unreachable +}