forked from OSchip/llvm-project
[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:
parent
a394231819
commit
9020e22a87
|
@ -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();
|
||||
|
|
|
@ -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]])
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue