[InstCombine] Convert xor (ashr X, BW-1), C -> select(X >=s 0, C, ~C)

The sequence of instructions `xor (ashr X, BW-1), C` (or with a truncation
`xor (trunc (ashr X, BW-1)), C)` takes a value, produces all zeros or all
ones and with it optionally inverts a constant depending on whether the
original input was positive or negative. This is the same as checking if
the value is positive, and selecting between the constant and ~constant.
https://alive2.llvm.org/ce/z/NJ85qY

This is a fairly general version of a fold that helps pull saturating
arithmetic into a canonical form.

Differential Revision: https://reviews.llvm.org/D109151
This commit is contained in:
David Green 2021-10-29 11:19:20 +01:00
parent a394231819
commit 9020e22a87
3 changed files with 60 additions and 64 deletions

View File

@ -3569,10 +3569,10 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
if (Instruction *Xor = visitMaskedMerge(I, Builder))
return Xor;
// Use DeMorgan and reassociation to eliminate a 'not' op.
Value *X, *Y;
Constant *C1;
if (match(Op1, m_Constant(C1))) {
// Use DeMorgan and reassociation to eliminate a 'not' op.
Constant *C2;
if (match(Op0, m_OneUse(m_Or(m_Not(m_Value(X)), m_Constant(C2))))) {
// (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
@ -3584,6 +3584,21 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
Value *Or = Builder.CreateOr(X, ConstantExpr::getNot(C2));
return BinaryOperator::CreateXor(Or, ConstantExpr::getNot(C1));
}
// Convert xor ([trunc] (ashr X, BW-1)), C =>
// select(X >s -1, C, ~C)
// The ashr creates "AllZeroOrAllOne's", which then optionally inverses the
// constant depending on whether this input is less than 0.
const APInt *CA;
if (match(Op0, m_OneUse(m_TruncOrSelf(
m_AShr(m_Value(X), m_APIntAllowUndef(CA))))) &&
*CA == X->getType()->getScalarSizeInBits() - 1 &&
!C1->isAllOnesValue()) {
assert(!C1->isZeroValue() && "Unexpected xor with 0");
Value *ICmp =
Builder.CreateICmpSGT(X, Constant::getAllOnesValue(X->getType()));
return SelectInst::Create(ICmp, Op1, Builder.CreateNot(Op1));
}
}
Type *Ty = I.getType();

View File

@ -13,9 +13,8 @@ define i8 @testi16i8(i16 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
; CHECK-NEXT: [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
; CHECK-NEXT: ret i8 [[COND_I]]
;
@ -38,9 +37,8 @@ define i32 @testi64i32(i64 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
; CHECK-NEXT: ret i32 [[COND_I]]
;
@ -155,9 +153,8 @@ define i32 @testi64i32addsat(i32 %a, i32 %b) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
; CHECK-NEXT: ret i32 [[COND_I]]
;
@ -183,9 +180,8 @@ define <4 x i8> @testv4i16i8(<4 x i16> %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc <4 x i16> [[ADD]] to <4 x i8>
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr <4 x i8> [[CONV1_I]], <i8 7, i8 7, i8 7, i8 7>
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq <4 x i8> [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr <4 x i16> [[ADD]], <i16 15, i16 15, i16 15, i16 15>
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc <4 x i16> [[SHR4_I]] to <4 x i8>
; CHECK-NEXT: [[XOR_I:%.*]] = xor <4 x i8> [[CONV5_I]], <i8 127, i8 127, i8 127, i8 127>
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD]], <i16 -1, i16 -1, i16 -1, i16 -1>
; CHECK-NEXT: [[XOR_I:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 -128, i8 -128, i8 -128, i8 -128>
; CHECK-NEXT: [[COND_I:%.*]] = select <4 x i1> [[CMP_NOT_I]], <4 x i8> [[CONV1_I]], <4 x i8> [[XOR_I]]
; CHECK-NEXT: ret <4 x i8> [[COND_I]]
;
@ -211,9 +207,8 @@ define <4 x i8> @testv4i16i8add(<4 x i8> %a, <4 x i8> %b) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc <4 x i16> [[ADD]] to <4 x i8>
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr <4 x i8> [[CONV1_I]], <i8 7, i8 7, i8 7, i8 7>
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq <4 x i8> [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr <4 x i16> [[ADD]], <i16 15, i16 15, i16 15, i16 15>
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc <4 x i16> [[SHR4_I]] to <4 x i8>
; CHECK-NEXT: [[XOR_I:%.*]] = xor <4 x i8> [[CONV5_I]], <i8 127, i8 127, i8 127, i8 127>
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD]], <i16 -1, i16 -1, i16 -1, i16 -1>
; CHECK-NEXT: [[XOR_I:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 -128, i8 -128, i8 -128, i8 -128>
; CHECK-NEXT: [[COND_I:%.*]] = select <4 x i1> [[CMP_NOT_I]], <4 x i8> [[CONV1_I]], <4 x i8> [[XOR_I]]
; CHECK-NEXT: ret <4 x i8> [[COND_I]]
;
@ -239,9 +234,8 @@ define i8 @testi16i8_revcmp(i16 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
; CHECK-NEXT: [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
; CHECK-NEXT: ret i8 [[COND_I]]
;
@ -264,9 +258,8 @@ define i8 @testi16i8_revselect(i16 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I_NOT:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
; CHECK-NEXT: [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I_NOT]], i8 [[CONV1_I]], i8 [[XOR_I]]
; CHECK-NEXT: ret i8 [[COND_I]]
;
@ -332,9 +325,8 @@ define i8 @badimm1(i16 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
; CHECK-NEXT: [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
; CHECK-NEXT: ret i8 [[COND_I]]
;
@ -357,9 +349,8 @@ define i8 @badimm2(i16 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 6
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
; CHECK-NEXT: [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
; CHECK-NEXT: ret i8 [[COND_I]]
;
@ -407,9 +398,8 @@ define i8 @badimm4(i16 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
; CHECK-NEXT: [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 126
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i8 126, i8 -127
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
; CHECK-NEXT: ret i8 [[COND_I]]
;
@ -434,9 +424,8 @@ define i32 @oneusexor(i64 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
; CHECK-NEXT: call void @use(i32 [[XOR_I]])
; CHECK-NEXT: ret i32 [[COND_I]]
@ -461,9 +450,8 @@ define i32 @oneuseconv(i64 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
; CHECK-NEXT: call void @use(i32 [[CONV1_I]])
; CHECK-NEXT: ret i32 [[COND_I]]
@ -488,9 +476,8 @@ define i32 @oneusecmp(i64 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
; CHECK-NEXT: call void @use1(i1 [[CMP_NOT_I]])
; CHECK-NEXT: ret i32 [[COND_I]]
@ -515,9 +502,8 @@ define i32 @oneuseboth(i64 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
; CHECK-NEXT: call void @use(i32 [[XOR_I]])
; CHECK-NEXT: call void @use(i32 [[CONV1_I]])
@ -544,9 +530,8 @@ define i32 @oneusethree(i64 %add) {
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
; CHECK-NEXT: [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
; CHECK-NEXT: [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
; CHECK-NEXT: [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
; CHECK-NEXT: call void @use(i32 [[XOR_I]])
; CHECK-NEXT: call void @use(i32 [[CONV1_I]])

View File

@ -7,8 +7,8 @@ declare void @use32(i32)
define i8 @testi8i8(i8 %add) {
; CHECK-LABEL: @testi8i8(
; CHECK-NEXT: [[SH:%.*]] = ashr i8 [[ADD:%.*]], 7
; CHECK-NEXT: [[X:%.*]] = xor i8 [[SH]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[ADD:%.*]], -1
; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
; CHECK-NEXT: ret i8 [[X]]
;
%sh = ashr i8 %add, 7
@ -18,9 +18,8 @@ define i8 @testi8i8(i8 %add) {
define i8 @testi16i8(i16 %add) {
; CHECK-LABEL: @testi16i8(
; CHECK-NEXT: [[SH:%.*]] = ashr i16 [[ADD:%.*]], 15
; CHECK-NEXT: [[T:%.*]] = trunc i16 [[SH]] to i8
; CHECK-NEXT: [[X:%.*]] = xor i8 [[T]], 27
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[ADD:%.*]], -1
; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP1]], i8 27, i8 -28
; CHECK-NEXT: ret i8 [[X]]
;
%sh = ashr i16 %add, 15
@ -31,9 +30,8 @@ define i8 @testi16i8(i16 %add) {
define i32 @testi64i32(i64 %add) {
; CHECK-LABEL: @testi64i32(
; CHECK-NEXT: [[SH:%.*]] = ashr i64 [[ADD:%.*]], 63
; CHECK-NEXT: [[T:%.*]] = trunc i64 [[SH]] to i32
; CHECK-NEXT: [[X:%.*]] = xor i32 [[T]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[ADD:%.*]], -1
; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP1]], i32 127, i32 -128
; CHECK-NEXT: ret i32 [[X]]
;
%sh = ashr i64 %add, 63
@ -44,8 +42,8 @@ define i32 @testi64i32(i64 %add) {
define i128 @testi128i128(i128 %add) {
; CHECK-LABEL: @testi128i128(
; CHECK-NEXT: [[SH:%.*]] = ashr i128 [[ADD:%.*]], 127
; CHECK-NEXT: [[X:%.*]] = xor i128 [[SH]], 27
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i128 [[ADD:%.*]], -1
; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP1]], i128 27, i128 -28
; CHECK-NEXT: ret i128 [[X]]
;
%sh = ashr i128 %add, 127
@ -55,9 +53,8 @@ define i128 @testi128i128(i128 %add) {
define <4 x i8> @testv4i16i8(<4 x i16> %add) {
; CHECK-LABEL: @testv4i16i8(
; CHECK-NEXT: [[SH:%.*]] = ashr <4 x i16> [[ADD:%.*]], <i16 15, i16 15, i16 15, i16 15>
; CHECK-NEXT: [[T:%.*]] = trunc <4 x i16> [[SH]] to <4 x i8>
; CHECK-NEXT: [[X:%.*]] = xor <4 x i8> [[T]], <i8 27, i8 27, i8 27, i8 27>
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD:%.*]], <i16 -1, i16 -1, i16 -1, i16 -1>
; CHECK-NEXT: [[X:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 27, i8 27, i8 27, i8 27>, <4 x i8> <i8 -28, i8 -28, i8 -28, i8 -28>
; CHECK-NEXT: ret <4 x i8> [[X]]
;
%sh = ashr <4 x i16> %add, <i16 15, i16 15, i16 15, i16 15>
@ -68,9 +65,8 @@ define <4 x i8> @testv4i16i8(<4 x i16> %add) {
define <4 x i8> @testv4i16i8_undef(<4 x i16> %add) {
; CHECK-LABEL: @testv4i16i8_undef(
; CHECK-NEXT: [[SH:%.*]] = ashr <4 x i16> [[ADD:%.*]], <i16 15, i16 undef, i16 15, i16 15>
; CHECK-NEXT: [[T:%.*]] = trunc <4 x i16> [[SH]] to <4 x i8>
; CHECK-NEXT: [[X:%.*]] = xor <4 x i8> [[T]], <i8 27, i8 27, i8 undef, i8 27>
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD:%.*]], <i16 -1, i16 -1, i16 -1, i16 -1>
; CHECK-NEXT: [[X:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 27, i8 27, i8 undef, i8 27>, <4 x i8> <i8 -28, i8 -28, i8 undef, i8 -28>
; CHECK-NEXT: ret <4 x i8> [[X]]
;
%sh = ashr <4 x i16> %add, <i16 15, i16 undef, i16 15, i16 15>
@ -112,9 +108,9 @@ define i16 @extrause(i16 %add) {
define i16 @extrause_trunc1(i32 %add) {
; CHECK-LABEL: @extrause_trunc1(
; CHECK-NEXT: [[SH:%.*]] = ashr i32 [[ADD:%.*]], 31
; CHECK-NEXT: [[T:%.*]] = trunc i32 [[SH]] to i16
; CHECK-NEXT: call void @use32(i32 [[SH]])
; CHECK-NEXT: [[X:%.*]] = xor i16 [[T]], 127
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[ADD]], -1
; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP1]], i16 127, i16 -128
; CHECK-NEXT: ret i16 [[X]]
;
%sh = ashr i32 %add, 31