Skip to content

Commit 65a88fa

Browse files
artagnonregehr
andcommitted
[InstComb] Fold shr ([x]or x, y), x -> shr y, x
Proof: https://alive2.llvm.org/ce/z/yWCmMd Co-authored-by: John Regehr <regehr@cs.utah.edu>
1 parent abb1953 commit 65a88fa

File tree

2 files changed

+28
-24
lines changed

2 files changed

+28
-24
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -512,19 +512,27 @@ Instruction *InstCombinerImpl::commonShiftTransforms(BinaryOperator &I) {
512512
if (match(Op1, m_Or(m_Value(), m_SpecificInt(BitWidth - 1))))
513513
return replaceOperand(I, 1, ConstantInt::get(Ty, BitWidth - 1));
514514

515-
Instruction *CmpIntr;
516-
if ((I.getOpcode() == Instruction::LShr ||
517-
I.getOpcode() == Instruction::AShr) &&
518-
match(Op0, m_OneUse(m_Instruction(CmpIntr))) &&
519-
isa<CmpIntrinsic>(CmpIntr) &&
520-
match(Op1, m_SpecificInt(Ty->getScalarSizeInBits() - 1))) {
521-
Value *Cmp =
522-
Builder.CreateICmp(cast<CmpIntrinsic>(CmpIntr)->getLTPredicate(),
523-
CmpIntr->getOperand(0), CmpIntr->getOperand(1));
524-
return CastInst::Create(I.getOpcode() == Instruction::LShr
525-
? Instruction::ZExt
526-
: Instruction::SExt,
527-
Cmp, Ty);
515+
if (I.getOpcode() == Instruction::LShr ||
516+
I.getOpcode() == Instruction::AShr) {
517+
// (l|a)shr ([x]or x, y), x --> (l|a)shr y, x
518+
Value *X;
519+
if (match(Op0, m_CombineOr(m_Xor(m_Value(X), m_Value(Y)),
520+
m_Or(m_Value(X), m_Value(Y)))) &&
521+
Op1 == X)
522+
return BinaryOperator::Create(I.getOpcode(), Y, X);
523+
524+
Instruction *CmpIntr;
525+
if (match(Op0, m_OneUse(m_Instruction(CmpIntr))) &&
526+
isa<CmpIntrinsic>(CmpIntr) &&
527+
match(Op1, m_SpecificInt(Ty->getScalarSizeInBits() - 1))) {
528+
Value *Cmp =
529+
Builder.CreateICmp(cast<CmpIntrinsic>(CmpIntr)->getLTPredicate(),
530+
CmpIntr->getOperand(0), CmpIntr->getOperand(1));
531+
return CastInst::Create(I.getOpcode() == Instruction::LShr
532+
? Instruction::ZExt
533+
: Instruction::SExt,
534+
Cmp, Ty);
535+
}
528536
}
529537

530538
return nullptr;

llvm/test/Transforms/InstCombine/shift-logic.ll

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,7 @@ define <2 x i64> @lshr_sub_poison(<2 x i64> %x, <2 x i64> %py) {
550550

551551
define i32 @ashr_xor_operand_match(i32 %x, i32 %y) {
552552
; CHECK-LABEL: @ashr_xor_operand_match(
553-
; CHECK-NEXT: [[R:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
554-
; CHECK-NEXT: [[RET:%.*]] = ashr i32 [[R]], [[X]]
553+
; CHECK-NEXT: [[RET:%.*]] = ashr i32 [[R:%.*]], [[X:%.*]]
555554
; CHECK-NEXT: ret i32 [[RET]]
556555
;
557556
%r = xor i32 %x, %y
@@ -572,8 +571,7 @@ define i32 @ashr_xor_operand_mismtach(i32 %x, i32 %y) {
572571

573572
define i32 @lshr_xor_operand_match(i32 %x, i32 %y) {
574573
; CHECK-LABEL: @lshr_xor_operand_match(
575-
; CHECK-NEXT: [[R:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
576-
; CHECK-NEXT: [[RET:%.*]] = lshr i32 [[R]], [[X]]
574+
; CHECK-NEXT: [[RET:%.*]] = lshr i32 [[R:%.*]], [[X:%.*]]
577575
; CHECK-NEXT: ret i32 [[RET]]
578576
;
579577
%r = xor i32 %x, %y
@@ -594,8 +592,7 @@ define i32 @lshr_xor_operand_mismtach(i32 %x, i32 %y) {
594592

595593
define i32 @ashr_or_operand_match(i32 %x, i32 %y) {
596594
; CHECK-LABEL: @ashr_or_operand_match(
597-
; CHECK-NEXT: [[R:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
598-
; CHECK-NEXT: [[RET:%.*]] = ashr i32 [[R]], [[X]]
595+
; CHECK-NEXT: [[RET:%.*]] = ashr i32 [[R:%.*]], [[X:%.*]]
599596
; CHECK-NEXT: ret i32 [[RET]]
600597
;
601598
%r = or i32 %x, %y
@@ -616,8 +613,7 @@ define i32 @ashr_or_operand_mismtach(i32 %x, i32 %y) {
616613

617614
define i32 @lshr_or_operand_match(i32 %x, i32 %y) {
618615
; CHECK-LABEL: @lshr_or_operand_match(
619-
; CHECK-NEXT: [[R:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
620-
; CHECK-NEXT: [[RET:%.*]] = lshr i32 [[R]], [[X]]
616+
; CHECK-NEXT: [[RET:%.*]] = lshr i32 [[R:%.*]], [[X:%.*]]
621617
; CHECK-NEXT: ret i32 [[RET]]
622618
;
623619
%r = or i32 %x, %y
@@ -638,10 +634,10 @@ define i32 @lshr_or_operand_mismtach(i32 %x, i32 %y) {
638634

639635
define i32 @ashr_xor_operand_match_multiuse(i32 %x, i32 %y) {
640636
; CHECK-LABEL: @ashr_xor_operand_match_multiuse(
641-
; CHECK-NEXT: [[R:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
642-
; CHECK-NEXT: [[Q:%.*]] = ashr i32 [[R]], [[X]]
637+
; CHECK-NEXT: [[Q:%.*]] = ashr i32 [[R:%.*]], [[X:%.*]]
643638
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[R]], [[Q]]
644-
; CHECK-NEXT: ret i32 [[RET]]
639+
; CHECK-NEXT: [[RET1:%.*]] = xor i32 [[RET]], [[X]]
640+
; CHECK-NEXT: ret i32 [[RET1]]
645641
;
646642
%r = xor i32 %x, %y
647643
%q = ashr i32 %r, %x

0 commit comments

Comments
 (0)