From 5b7752afa5aec5299e986ab9bca26007fbaea810 Mon Sep 17 00:00:00 2001 From: c8ef Date: Sat, 24 Aug 2024 09:47:29 +0800 Subject: [PATCH 1/3] fold select (trunc nuw X to i1), X, Y --- .../InstCombine/InstCombineSelect.cpp | 10 ++++++ .../InstCombine/fold-select-trunc-if-nuw.ll | 35 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 18ffc209f259e..49582004d9a4f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -4201,5 +4201,15 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { } } + // select (trunc nuw X to i1), X, Y --> select (trunc nuw X to i1), 1, Y + if (auto *TI = dyn_cast(CondVal)) { + Value *Trunc; + if (TI->hasNoUnsignedWrap() && match(CondVal, m_Trunc(m_Value(Trunc))) && + match(TrueVal, m_Specific(Trunc))) { + return SelectInst::Create( + CondVal, ConstantInt::get(TrueVal->getType(), 1), FalseVal); + } + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll b/llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll new file mode 100644 index 0000000000000..09fb2d77f9ef5 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i8 @fold_select_trunc_if_nuw(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_select_trunc_if_nuw( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 1, i8 [[Y:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %trunc = trunc nuw i8 %x to i1 + %ret = select i1 %trunc, i8 %x, i8 %y + ret i8 %ret +} + +define i8 @fold_select_trunc_if_nuw_negative(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_select_trunc_if_nuw_negative( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i8 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[X]], i8 [[Y:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %trunc = trunc nsw i8 %x to i1 + %ret = select i1 %trunc, i8 %x, i8 %y + ret i8 %ret +} + +define <2 x i8> @fold_select_trunc_if_nuw_vector(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @fold_select_trunc_if_nuw_vector( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw <2 x i8> [[X:%.*]] to <2 x i1> +; CHECK-NEXT: [[RET:%.*]] = select <2 x i1> [[TRUNC]], <2 x i8> , <2 x i8> [[Y:%.*]] +; CHECK-NEXT: ret <2 x i8> [[RET]] +; + %trunc = trunc nuw <2 x i8> %x to <2 x i1> + %ret = select <2 x i1> %trunc, <2 x i8> %x, <2 x i8> %y + ret <2 x i8> %ret +} From 5b9e6c717ebf53c5ea5e13cbf900d5c257aa9e53 Mon Sep 17 00:00:00 2001 From: c8ef Date: Sat, 24 Aug 2024 15:48:43 +0800 Subject: [PATCH 2/3] add more fold; use replaceOperand; rewrite test --- .../InstCombine/InstCombineSelect.cpp | 22 ++++-- .../InstCombine/fold-select-trunc-if-nuw.ll | 35 ---------- .../InstCombine/fold-select-trunc.ll | 68 +++++++++++++++++++ 3 files changed, 83 insertions(+), 42 deletions(-) delete mode 100644 llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll create mode 100644 llvm/test/Transforms/InstCombine/fold-select-trunc.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 49582004d9a4f..16903800d9daf 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -4202,13 +4202,21 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { } // select (trunc nuw X to i1), X, Y --> select (trunc nuw X to i1), 1, Y - if (auto *TI = dyn_cast(CondVal)) { - Value *Trunc; - if (TI->hasNoUnsignedWrap() && match(CondVal, m_Trunc(m_Value(Trunc))) && - match(TrueVal, m_Specific(Trunc))) { - return SelectInst::Create( - CondVal, ConstantInt::get(TrueVal->getType(), 1), FalseVal); - } + // select (trunc nuw X to i1), Y, X --> select (trunc nuw X to i1), Y, 0 + // select (trunc nsw X to i1), X, Y --> select (trunc nsw X to i1), -1, Y + // select (trunc nsw X to i1), Y, X --> select (trunc nsw X to i1), Y, 0 + Value *Trunc; + if (match(CondVal, m_NUWTrunc(m_Value(Trunc)))) { + if (match(TrueVal, m_Specific(Trunc))) + return replaceOperand(SI, 1, ConstantInt::get(TrueVal->getType(), 1)); + if (match(FalseVal, m_Specific(Trunc))) + return replaceOperand(SI, 2, ConstantInt::get(TrueVal->getType(), 0)); + } + if (match(CondVal, m_NSWTrunc(m_Value(Trunc)))) { + if (match(TrueVal, m_Specific(Trunc))) + return replaceOperand(SI, 1, ConstantInt::get(TrueVal->getType(), -1)); + if (match(FalseVal, m_Specific(Trunc))) + return replaceOperand(SI, 2, ConstantInt::get(TrueVal->getType(), 0)); } return nullptr; diff --git a/llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll b/llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll deleted file mode 100644 index 09fb2d77f9ef5..0000000000000 --- a/llvm/test/Transforms/InstCombine/fold-select-trunc-if-nuw.ll +++ /dev/null @@ -1,35 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes=instcombine -S | FileCheck %s - -define i8 @fold_select_trunc_if_nuw(i8 %x, i8 %y) { -; CHECK-LABEL: @fold_select_trunc_if_nuw( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1 -; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 1, i8 [[Y:%.*]] -; CHECK-NEXT: ret i8 [[RET]] -; - %trunc = trunc nuw i8 %x to i1 - %ret = select i1 %trunc, i8 %x, i8 %y - ret i8 %ret -} - -define i8 @fold_select_trunc_if_nuw_negative(i8 %x, i8 %y) { -; CHECK-LABEL: @fold_select_trunc_if_nuw_negative( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i8 [[X:%.*]] to i1 -; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[X]], i8 [[Y:%.*]] -; CHECK-NEXT: ret i8 [[RET]] -; - %trunc = trunc nsw i8 %x to i1 - %ret = select i1 %trunc, i8 %x, i8 %y - ret i8 %ret -} - -define <2 x i8> @fold_select_trunc_if_nuw_vector(<2 x i8> %x, <2 x i8> %y) { -; CHECK-LABEL: @fold_select_trunc_if_nuw_vector( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw <2 x i8> [[X:%.*]] to <2 x i1> -; CHECK-NEXT: [[RET:%.*]] = select <2 x i1> [[TRUNC]], <2 x i8> , <2 x i8> [[Y:%.*]] -; CHECK-NEXT: ret <2 x i8> [[RET]] -; - %trunc = trunc nuw <2 x i8> %x to <2 x i1> - %ret = select <2 x i1> %trunc, <2 x i8> %x, <2 x i8> %y - ret <2 x i8> %ret -} diff --git a/llvm/test/Transforms/InstCombine/fold-select-trunc.ll b/llvm/test/Transforms/InstCombine/fold-select-trunc.ll new file mode 100644 index 0000000000000..9bc0a5a2bd8fc --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fold-select-trunc.ll @@ -0,0 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i8 @fold_select_trunc_nuw_true(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_select_trunc_nuw_true( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 1, i8 [[Y:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %trunc = trunc nuw i8 %x to i1 + %ret = select i1 %trunc, i8 %x, i8 %y + ret i8 %ret +} + +define i8 @fold_select_trunc_nuw_false(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_select_trunc_nuw_false( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[Y:%.*]], i8 0 +; CHECK-NEXT: ret i8 [[RET]] +; + %trunc = trunc nuw i8 %x to i1 + %ret = select i1 %trunc, i8 %y, i8 %x + ret i8 %ret +} + +define i8 @fold_select_trunc_nsw_true(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_select_trunc_nsw_true( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i8 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 -1, i8 [[Y:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %trunc = trunc nsw i8 %x to i1 + %ret = select i1 %trunc, i8 %x, i8 %y + ret i8 %ret +} + +define i8 @fold_select_trunc_nsw_false(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_select_trunc_nsw_false( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i8 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[Y:%.*]], i8 0 +; CHECK-NEXT: ret i8 [[RET]] +; + %trunc = trunc nsw i8 %x to i1 + %ret = select i1 %trunc, i8 %y, i8 %x + ret i8 %ret +} + +define i8 @fold_select_trunc_negative(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_select_trunc_negative( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[X]], i8 [[Y:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %trunc = trunc i8 %x to i1 + %ret = select i1 %trunc, i8 %x, i8 %y + ret i8 %ret +} + +define <2 x i8> @fold_select_trunc_vector(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @fold_select_trunc_vector( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw <2 x i8> [[X:%.*]] to <2 x i1> +; CHECK-NEXT: [[RET:%.*]] = select <2 x i1> [[TRUNC]], <2 x i8> , <2 x i8> [[Y:%.*]] +; CHECK-NEXT: ret <2 x i8> [[RET]] +; + %trunc = trunc nuw <2 x i8> %x to <2 x i1> + %ret = select <2 x i1> %trunc, <2 x i8> %x, <2 x i8> %y + ret <2 x i8> %ret +} From def908da230baeda971b4b1e36eb65b9160d1e2e Mon Sep 17 00:00:00 2001 From: c8ef Date: Sat, 24 Aug 2024 16:01:47 +0800 Subject: [PATCH 3/3] add i128 test --- .../Transforms/InstCombine/InstCombineSelect.cpp | 15 ++++++++------- .../Transforms/InstCombine/fold-select-trunc.ll | 14 +++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 16903800d9daf..fcd11126073bf 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -4207,16 +4207,17 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { // select (trunc nsw X to i1), Y, X --> select (trunc nsw X to i1), Y, 0 Value *Trunc; if (match(CondVal, m_NUWTrunc(m_Value(Trunc)))) { - if (match(TrueVal, m_Specific(Trunc))) + if (TrueVal == Trunc) return replaceOperand(SI, 1, ConstantInt::get(TrueVal->getType(), 1)); - if (match(FalseVal, m_Specific(Trunc))) - return replaceOperand(SI, 2, ConstantInt::get(TrueVal->getType(), 0)); + if (FalseVal == Trunc) + return replaceOperand(SI, 2, ConstantInt::get(FalseVal->getType(), 0)); } if (match(CondVal, m_NSWTrunc(m_Value(Trunc)))) { - if (match(TrueVal, m_Specific(Trunc))) - return replaceOperand(SI, 1, ConstantInt::get(TrueVal->getType(), -1)); - if (match(FalseVal, m_Specific(Trunc))) - return replaceOperand(SI, 2, ConstantInt::get(TrueVal->getType(), 0)); + if (TrueVal == Trunc) + return replaceOperand(SI, 1, + Constant::getAllOnesValue(TrueVal->getType())); + if (FalseVal == Trunc) + return replaceOperand(SI, 2, ConstantInt::get(FalseVal->getType(), 0)); } return nullptr; diff --git a/llvm/test/Transforms/InstCombine/fold-select-trunc.ll b/llvm/test/Transforms/InstCombine/fold-select-trunc.ll index 9bc0a5a2bd8fc..5567d7d5e1fca 100644 --- a/llvm/test/Transforms/InstCombine/fold-select-trunc.ll +++ b/llvm/test/Transforms/InstCombine/fold-select-trunc.ll @@ -23,15 +23,15 @@ define i8 @fold_select_trunc_nuw_false(i8 %x, i8 %y) { ret i8 %ret } -define i8 @fold_select_trunc_nsw_true(i8 %x, i8 %y) { +define i128 @fold_select_trunc_nsw_true(i128 %x, i128 %y) { ; CHECK-LABEL: @fold_select_trunc_nsw_true( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i8 [[X:%.*]] to i1 -; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 -1, i8 [[Y:%.*]] -; CHECK-NEXT: ret i8 [[RET]] +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i128 [[X:%.*]] to i1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i128 -1, i128 [[Y:%.*]] +; CHECK-NEXT: ret i128 [[RET]] ; - %trunc = trunc nsw i8 %x to i1 - %ret = select i1 %trunc, i8 %x, i8 %y - ret i8 %ret + %trunc = trunc nsw i128 %x to i1 + %ret = select i1 %trunc, i128 %x, i128 %y + ret i128 %ret } define i8 @fold_select_trunc_nsw_false(i8 %x, i8 %y) {