[llvm] [InstCombine] Fold xor-lshr sign-mask idiom to ashr (PR #213954)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 4 07:07:14 PDT 2026
https://github.com/GabrielKimm created https://github.com/llvm/llvm-project/pull/213954
Issue #204851 shows an unsigned arithmetic-right-shift idiom that InstCombine currently leaves as a sequence of XOR and shift instructions:
```llvm
((X ^ SignMask) lshr ShiftAmt) ^ SignMask
```
When `SignMask` is `X ashr (BitWidth - 1)`, this is equivalent to `X ashr ShiftAmt`. Teach `visitXor` to perform that fold.
The matcher accepts commuted XOR operands and scalar, fixed-vector, and scalable-vector integer types. The `lshr` must have one use so replacing the outer expression cannot increase the instruction count; the inner XOR may still have other users. The new `ashr` deliberately does not inherit the `exact` flag from either matched shift.
Tests cover commuted operands, exact shifts, unusual integer widths, vector poison, scalable vectors, and negative cases for the source, full-width shift, non-splat vectors, `undef`, and the one-use constraint.
Fixes #204851.
Tested with:
```text
ninja check-llvm-transforms-instcombine
```
>From 3a2cf41cd08b1302fe5fbfd6c8fdbb4cc03486fa Mon Sep 17 00:00:00 2001
From: GabrielKim <0xGabriel.kim at gmail.com>
Date: Sun, 2 Aug 2026 21:19:00 +0900
Subject: [PATCH 1/2] [InstCombine] Add tests for xor-lshr sign-mask idiom
Add pre-commit coverage for the missed optimization in #204851, including commuted operands, exact shifts, unusual integer widths, vector poison, scalable vectors, and negative one-use/source/shift cases.
Assisted-by: OpenAI Codex
---
.../InstCombine/binop-and-shifts.ll | 214 ++++++++++++++++++
1 file changed, 214 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/binop-and-shifts.ll b/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
index 40275fd29fde1..f8860a70b6fa5 100644
--- a/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
+++ b/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
@@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+declare void @use(i8)
+
define i8 @shl_and_and(i8 %x, i8 %y) {
; CHECK-LABEL: @shl_and_and(
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[Y:%.*]], [[X:%.*]]
@@ -951,6 +953,218 @@ define <4 x i8> @xor_ashr_not_vec_poison_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %s
ret <4 x i8> %xor
}
+define i8 @xor_lshr_signmask(i8 %x, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %signmask = ashr i8 %x, 7
+ %flipped = xor i8 %x, %signmask
+ %shifted = lshr i8 %flipped, %shamt
+ %r = xor i8 %shifted, %signmask
+ ret i8 %r
+}
+
+define i8 @xor_lshr_signmask_commuted(i8 %x, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_commuted(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[SIGNMASK]], [[X]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SIGNMASK]], [[SHIFTED]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %signmask = ashr i8 %x, 7
+ %flipped = xor i8 %signmask, %x
+ %shifted = lshr i8 %flipped, %shamt
+ %r = xor i8 %signmask, %shifted
+ ret i8 %r
+}
+
+define i8 @xor_lshr_signmask_exact(i8 %x, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_exact(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr exact i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %signmask = ashr i8 %x, 7
+ %flipped = xor i8 %x, %signmask
+ %shifted = lshr exact i8 %flipped, %shamt
+ %r = xor i8 %shifted, %signmask
+ ret i8 %r
+}
+
+define i1 @xor_lshr_signmask_i1(i1 %x, i1 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_i1(
+; CHECK-NEXT: ret i1 [[X:%.*]]
+;
+ %signmask = ashr i1 %x, 0
+ %flipped = xor i1 %x, %signmask
+ %shifted = lshr i1 %flipped, %shamt
+ %r = xor i1 %shifted, %signmask
+ ret i1 %r
+}
+
+define i13 @xor_lshr_signmask_i13(i13 %x, i13 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_i13(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i13 [[X:%.*]], 12
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i13 [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i13 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i13 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret i13 [[R]]
+;
+ %signmask = ashr i13 %x, 12
+ %flipped = xor i13 %x, %signmask
+ %shifted = lshr i13 %flipped, %shamt
+ %r = xor i13 %shifted, %signmask
+ ret i13 %r
+}
+
+define i8 @xor_lshr_signmask_signmask_exact(i8 %x, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_signmask_exact(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr exact i8 [[X:%.*]], 7
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %signmask = ashr exact i8 %x, 7
+ %flipped = xor i8 %x, %signmask
+ %shifted = lshr i8 %flipped, %shamt
+ %r = xor i8 %shifted, %signmask
+ ret i8 %r
+}
+
+define { i8, i8 } @xor_lshr_signmask_inner_multiuse(i8 %x, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_inner_multiuse(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R0:%.*]] = insertvalue { i8, i8 } poison, i8 [[R]], 0
+; CHECK-NEXT: [[R1:%.*]] = insertvalue { i8, i8 } [[R0]], i8 [[FLIPPED]], 1
+; CHECK-NEXT: ret { i8, i8 } [[R1]]
+;
+ %signmask = ashr i8 %x, 7
+ %flipped = xor i8 %x, %signmask
+ %shifted = lshr i8 %flipped, %shamt
+ %r = xor i8 %shifted, %signmask
+ %r0 = insertvalue { i8, i8 } poison, i8 %r, 0
+ %r1 = insertvalue { i8, i8 } %r0, i8 %flipped, 1
+ ret { i8, i8 } %r1
+}
+
+define <4 x i8> @xor_lshr_signmask_vec_poison(<4 x i8> %x, <4 x i8> %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_vec_poison(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr <4 x i8> [[X:%.*]], <i8 7, i8 poison, i8 7, i8 poison>
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor <4 x i8> [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr <4 x i8> [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor <4 x i8> [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret <4 x i8> [[R]]
+;
+ %signmask = ashr <4 x i8> %x, <i8 7, i8 poison, i8 7, i8 poison>
+ %flipped = xor <4 x i8> %x, %signmask
+ %shifted = lshr <4 x i8> %flipped, %shamt
+ %r = xor <4 x i8> %shifted, %signmask
+ ret <4 x i8> %r
+}
+
+define <4 x i8> @xor_lshr_signmask_vec_undef(<4 x i8> %x, <4 x i8> %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_vec_undef(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr <4 x i8> [[X:%.*]], <i8 7, i8 undef, i8 7, i8 undef>
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor <4 x i8> [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr <4 x i8> [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor <4 x i8> [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret <4 x i8> [[R]]
+;
+ %signmask = ashr <4 x i8> %x, <i8 7, i8 undef, i8 7, i8 undef>
+ %flipped = xor <4 x i8> %x, %signmask
+ %shifted = lshr <4 x i8> %flipped, %shamt
+ %r = xor <4 x i8> %shifted, %signmask
+ ret <4 x i8> %r
+}
+
+define <vscale x 4 x i8> @xor_lshr_signmask_scalable(<vscale x 4 x i8> %x, <vscale x 4 x i8> %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_scalable(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr <vscale x 4 x i8> [[X:%.*]], splat (i8 7)
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor <vscale x 4 x i8> [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr <vscale x 4 x i8> [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor <vscale x 4 x i8> [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret <vscale x 4 x i8> [[R]]
+;
+ %signmask = ashr <vscale x 4 x i8> %x, splat (i8 7)
+ %flipped = xor <vscale x 4 x i8> %x, %signmask
+ %shifted = lshr <vscale x 4 x i8> %flipped, %shamt
+ %r = xor <vscale x 4 x i8> %shifted, %signmask
+ ret <vscale x 4 x i8> %r
+}
+
+define i8 @xor_lshr_signmask_wrong_source(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_wrong_source(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[Y:%.*]], 7
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X:%.*]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %signmask = ashr i8 %y, 7
+ %flipped = xor i8 %x, %signmask
+ %shifted = lshr i8 %flipped, %shamt
+ %r = xor i8 %shifted, %signmask
+ ret i8 %r
+}
+
+define i8 @xor_lshr_signmask_wrong_full_shift(i8 %x, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_wrong_full_shift(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 6
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %signmask = ashr i8 %x, 6
+ %flipped = xor i8 %x, %signmask
+ %shifted = lshr i8 %flipped, %shamt
+ %r = xor i8 %shifted, %signmask
+ ret i8 %r
+}
+
+define i8 @xor_lshr_signmask_lshr_multiuse(i8 %x, i8 %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_lshr_multiuse(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: call void @use(i8 [[SHIFTED]])
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %signmask = ashr i8 %x, 7
+ %flipped = xor i8 %x, %signmask
+ %shifted = lshr i8 %flipped, %shamt
+ call void @use(i8 %shifted)
+ %r = xor i8 %shifted, %signmask
+ ret i8 %r
+}
+
+define <4 x i8> @xor_lshr_signmask_vec_nonsplat(<4 x i8> %x, <4 x i8> %shamt) {
+; CHECK-LABEL: @xor_lshr_signmask_vec_nonsplat(
+; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr <4 x i8> [[X:%.*]], <i8 7, i8 6, i8 7, i8 6>
+; CHECK-NEXT: [[FLIPPED:%.*]] = xor <4 x i8> [[X]], [[SIGNMASK]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr <4 x i8> [[FLIPPED]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor <4 x i8> [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: ret <4 x i8> [[R]]
+;
+ %signmask = ashr <4 x i8> %x, <i8 7, i8 6, i8 7, i8 6>
+ %flipped = xor <4 x i8> %x, %signmask
+ %shifted = lshr <4 x i8> %flipped, %shamt
+ %r = xor <4 x i8> %shifted, %signmask
+ ret <4 x i8> %r
+}
+
; Negative test: outer binop has multiple users
define i8 @shl_add_add_multiuse_binop(i8 %x, i8 %y0, i8 %y1) {
>From 2fe781d01d21c4707a94eba9abd43e26044fad5f Mon Sep 17 00:00:00 2001
From: GabrielKim <0xGabriel.kim at gmail.com>
Date: Sun, 2 Aug 2026 21:19:24 +0900
Subject: [PATCH 2/2] [InstCombine] Fold xor-lshr sign-mask idiom to ashr
Fold ((X ^ SignMask) lshr ShiftAmt) ^ SignMask to X ashr ShiftAmt when SignMask is X ashr (BitWidth - 1). Require the lshr to have one use so the fold does not increase instruction count, while still allowing the inner xor to remain live.
The replacement intentionally does not propagate exact flags. The matcher supports commuted xor operands and scalar, fixed-vector, and scalable-vector integer types.
Fixes #204851
Assisted-by: OpenAI Codex
---
.../InstCombine/InstCombineAndOrXor.cpp | 12 ++++++
.../InstCombine/binop-and-shifts.ll | 38 ++++---------------
2 files changed, 20 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b6f4a55c07e8a..05f0bdd8250b3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -5368,6 +5368,18 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
if (Instruction *R = foldBinOpShiftWithShift(I))
return R;
+ // ((X ^ SignMask) >>u ShiftAmt) ^ SignMask --> X >>s ShiftAmt
+ // where SignMask = X >>s (BitWidth - 1).
+ Value *Base, *SignMask, *ShiftAmt;
+ if (match(&I, m_c_Xor(m_Value(SignMask),
+ m_OneUse(
+ m_LShr(m_c_Xor(m_Deferred(SignMask), m_Value(Base)),
+ m_Value(ShiftAmt))))) &&
+ match(SignMask, m_AShr(m_Specific(Base),
+ m_SpecificIntAllowPoison(
+ I.getType()->getScalarSizeInBits() - 1))))
+ return BinaryOperator::CreateAShr(Base, ShiftAmt);
+
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
Value *X, *Y, *M;
diff --git a/llvm/test/Transforms/InstCombine/binop-and-shifts.ll b/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
index f8860a70b6fa5..3c8c0dd01e810 100644
--- a/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
+++ b/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
@@ -955,10 +955,7 @@ define <4 x i8> @xor_ashr_not_vec_poison_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %s
define i8 @xor_lshr_signmask(i8 %x, i8 %shamt) {
; CHECK-LABEL: @xor_lshr_signmask(
-; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
-; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%signmask = ashr i8 %x, 7
@@ -970,10 +967,7 @@ define i8 @xor_lshr_signmask(i8 %x, i8 %shamt) {
define i8 @xor_lshr_signmask_commuted(i8 %x, i8 %shamt) {
; CHECK-LABEL: @xor_lshr_signmask_commuted(
-; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
-; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[SIGNMASK]], [[X]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[SIGNMASK]], [[SHIFTED]]
+; CHECK-NEXT: [[R:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%signmask = ashr i8 %x, 7
@@ -985,10 +979,7 @@ define i8 @xor_lshr_signmask_commuted(i8 %x, i8 %shamt) {
define i8 @xor_lshr_signmask_exact(i8 %x, i8 %shamt) {
; CHECK-LABEL: @xor_lshr_signmask_exact(
-; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
-; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr exact i8 [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%signmask = ashr i8 %x, 7
@@ -1011,10 +1002,7 @@ define i1 @xor_lshr_signmask_i1(i1 %x, i1 %shamt) {
define i13 @xor_lshr_signmask_i13(i13 %x, i13 %shamt) {
; CHECK-LABEL: @xor_lshr_signmask_i13(
-; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i13 [[X:%.*]], 12
-; CHECK-NEXT: [[FLIPPED:%.*]] = xor i13 [[X]], [[SIGNMASK]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i13 [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i13 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R:%.*]] = ashr i13 [[X:%.*]], [[SHAMT:%.*]]
; CHECK-NEXT: ret i13 [[R]]
;
%signmask = ashr i13 %x, 12
@@ -1026,10 +1014,7 @@ define i13 @xor_lshr_signmask_i13(i13 %x, i13 %shamt) {
define i8 @xor_lshr_signmask_signmask_exact(i8 %x, i8 %shamt) {
; CHECK-LABEL: @xor_lshr_signmask_signmask_exact(
-; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr exact i8 [[X:%.*]], 7
-; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%signmask = ashr exact i8 %x, 7
@@ -1043,8 +1028,7 @@ define { i8, i8 } @xor_lshr_signmask_inner_multiuse(i8 %x, i8 %shamt) {
; CHECK-LABEL: @xor_lshr_signmask_inner_multiuse(
; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr i8 [[X:%.*]], 7
; CHECK-NEXT: [[FLIPPED:%.*]] = xor i8 [[X]], [[SIGNMASK]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i8 [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R:%.*]] = ashr i8 [[X]], [[SHAMT:%.*]]
; CHECK-NEXT: [[R0:%.*]] = insertvalue { i8, i8 } poison, i8 [[R]], 0
; CHECK-NEXT: [[R1:%.*]] = insertvalue { i8, i8 } [[R0]], i8 [[FLIPPED]], 1
; CHECK-NEXT: ret { i8, i8 } [[R1]]
@@ -1060,10 +1044,7 @@ define { i8, i8 } @xor_lshr_signmask_inner_multiuse(i8 %x, i8 %shamt) {
define <4 x i8> @xor_lshr_signmask_vec_poison(<4 x i8> %x, <4 x i8> %shamt) {
; CHECK-LABEL: @xor_lshr_signmask_vec_poison(
-; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr <4 x i8> [[X:%.*]], <i8 7, i8 poison, i8 7, i8 poison>
-; CHECK-NEXT: [[FLIPPED:%.*]] = xor <4 x i8> [[X]], [[SIGNMASK]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr <4 x i8> [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor <4 x i8> [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R:%.*]] = ashr <4 x i8> [[X:%.*]], [[SHAMT:%.*]]
; CHECK-NEXT: ret <4 x i8> [[R]]
;
%signmask = ashr <4 x i8> %x, <i8 7, i8 poison, i8 7, i8 poison>
@@ -1090,10 +1071,7 @@ define <4 x i8> @xor_lshr_signmask_vec_undef(<4 x i8> %x, <4 x i8> %shamt) {
define <vscale x 4 x i8> @xor_lshr_signmask_scalable(<vscale x 4 x i8> %x, <vscale x 4 x i8> %shamt) {
; CHECK-LABEL: @xor_lshr_signmask_scalable(
-; CHECK-NEXT: [[SIGNMASK:%.*]] = ashr <vscale x 4 x i8> [[X:%.*]], splat (i8 7)
-; CHECK-NEXT: [[FLIPPED:%.*]] = xor <vscale x 4 x i8> [[X]], [[SIGNMASK]]
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr <vscale x 4 x i8> [[FLIPPED]], [[SHAMT:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor <vscale x 4 x i8> [[SHIFTED]], [[SIGNMASK]]
+; CHECK-NEXT: [[R:%.*]] = ashr <vscale x 4 x i8> [[X:%.*]], [[SHAMT:%.*]]
; CHECK-NEXT: ret <vscale x 4 x i8> [[R]]
;
%signmask = ashr <vscale x 4 x i8> %x, splat (i8 7)
More information about the llvm-commits
mailing list