From 62adb8958aa7cc54fdfe3779ad5ae9c18c262ccd Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Fri, 10 Jan 2025 17:47:12 -0600 Subject: [PATCH 1/3] [InstSimpify] Add tests for simplifying `(xor (sub C_Mask, X), C_Mask)`; NFC --- .../InstSimplify/subnuw-with-xor.ll | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll diff --git a/llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll b/llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll new file mode 100644 index 0000000000000..c6175cd8dd0ce --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll @@ -0,0 +1,122 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=instsimplify -S | FileCheck %s + +define i8 @xor_w_sub_fail_missing_nuw(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @xor_w_sub_fail_missing_nuw( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 15 +; CHECK-NEXT: [[R:%.*]] = sub nsw i8 15, [[XOR]] +; CHECK-NEXT: ret i8 [[R]] +; + %xor = xor i8 %x, 15 + %r = sub nsw i8 15, %xor + ret i8 %r +} + +define i8 @xor_w_sub_fail_diff_values(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @xor_w_sub_fail_diff_values( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 15 +; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 31, [[XOR]] +; CHECK-NEXT: ret i8 [[R]] +; + %xor = xor i8 %x, 15 + %r = sub nsw nuw i8 31, %xor + ret i8 %r +} + +define i8 @xor_w_sub_fail_diff_values2(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @xor_w_sub_fail_diff_values2( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 31 +; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 15, [[XOR]] +; CHECK-NEXT: ret i8 [[R]] +; + %xor = xor i8 %x, 31 + %r = sub nsw nuw i8 15, %xor + ret i8 %r +} + +define i8 @xor_w_sub_fail_not_mask(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @xor_w_sub_fail_not_mask( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 30 +; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 30, [[XOR]] +; CHECK-NEXT: ret i8 [[R]] +; + %xor = xor i8 %x, 30 + %r = sub nsw nuw i8 30, %xor + ret i8 %r +} + +define i8 @xor_w_sub_okay(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @xor_w_sub_okay( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 31 +; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 31, [[XOR]] +; CHECK-NEXT: ret i8 [[R]] +; + %xor = xor i8 %x, 31 + %r = sub nsw nuw i8 31, %xor + ret i8 %r +} + +define i8 @sub_w_xor_fail_missing_nuw(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @sub_w_xor_fail_missing_nuw( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 15, [[X]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[SUB]], 15 +; CHECK-NEXT: ret i8 [[R]] +; + %sub = sub nsw i8 15, %x + %r = xor i8 %sub, 15 + ret i8 %r +} + +define i8 @sub_w_xor_fail_diff_values(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @sub_w_xor_fail_diff_values( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i8 15, [[X]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[SUB]], 31 +; CHECK-NEXT: ret i8 [[R]] +; + %sub = sub nsw nuw i8 15, %x + %r = xor i8 %sub, 31 + ret i8 %r +} + +define i8 @sub_w_sub_fail_diff_values2(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @sub_w_sub_fail_diff_values2( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i8 31, [[X]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[SUB]], 15 +; CHECK-NEXT: ret i8 [[R]] +; + %sub = sub nsw nuw i8 31, %x + %r = xor i8 %sub, 15 + ret i8 %r +} + +define i8 @sub_w_sub_fail_not_mask(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @sub_w_sub_fail_not_mask( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i8 30, [[X]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[SUB]], 30 +; CHECK-NEXT: ret i8 [[R]] +; + %sub = sub nsw nuw i8 30, %x + %r = xor i8 %sub, 30 + ret i8 %r +} + +define i8 @sub_w_sub_okay(i8 range(i8 0, 16) %x) { +; CHECK-LABEL: define i8 @sub_w_sub_okay( +; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { +; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i8 31, [[X]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[SUB]], 31 +; CHECK-NEXT: ret i8 [[R]] +; + %sub = sub nsw nuw i8 31, %x + %r = xor i8 %sub, 31 + ret i8 %r +} From 59160414cef226cdb80eeb5080f9a7582f9ebee2 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Fri, 10 Jan 2025 17:47:14 -0600 Subject: [PATCH 2/3] [InstSimpify] Simplifying `(xor (sub C_Mask, X), C_Mask)` -> `X` Helps address regressions with folding `clz(Pow2)`. Proof: https://alive2.llvm.org/ce/z/zGwUBp --- llvm/lib/Analysis/InstructionSimplify.cpp | 16 ++++++++++++++++ .../Transforms/InstSimplify/subnuw-with-xor.ll | 8 ++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 999386c0a0491..ef9454fd9c9ab 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -871,6 +871,14 @@ static Value *simplifySubInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW, if (Value *V = simplifyByDomEq(Instruction::Sub, Op0, Op1, Q, MaxRecurse)) return V; + // (sub nuw C_Mask, (xor X, C_Mask)) -> X + if (IsNUW) { + Value *X; + if (match(Op1, m_Xor(m_Value(X), m_Specific(Op0))) && + match(Op0, m_CheckedInt([](const APInt &C) { return C.isMask(); }))) + return X; + } + return nullptr; } @@ -2540,6 +2548,14 @@ static Value *simplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, if (Value *V = simplifyByDomEq(Instruction::Xor, Op0, Op1, Q, MaxRecurse)) return V; + // (xor (sub nuw C_Mask, X), C_Mask) -> X + { + Value *X; + if (match(Op0, m_NUWSub(m_Specific(Op1), m_Value(X))) && + match(Op1, m_CheckedInt([](const APInt &C) { return C.isMask(); }))) + return X; + } + return nullptr; } diff --git a/llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll b/llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll index c6175cd8dd0ce..a990e2f2ae394 100644 --- a/llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll +++ b/llvm/test/Transforms/InstSimplify/subnuw-with-xor.ll @@ -52,9 +52,7 @@ define i8 @xor_w_sub_fail_not_mask(i8 range(i8 0, 16) %x) { define i8 @xor_w_sub_okay(i8 range(i8 0, 16) %x) { ; CHECK-LABEL: define i8 @xor_w_sub_okay( ; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 31 -; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 31, [[XOR]] -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 [[X]] ; %xor = xor i8 %x, 31 %r = sub nsw nuw i8 31, %xor @@ -112,9 +110,7 @@ define i8 @sub_w_sub_fail_not_mask(i8 range(i8 0, 16) %x) { define i8 @sub_w_sub_okay(i8 range(i8 0, 16) %x) { ; CHECK-LABEL: define i8 @sub_w_sub_okay( ; CHECK-SAME: i8 range(i8 0, 16) [[X:%.*]]) { -; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i8 31, [[X]] -; CHECK-NEXT: [[R:%.*]] = xor i8 [[SUB]], 31 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 [[X]] ; %sub = sub nsw nuw i8 31, %x %r = xor i8 %sub, 31 From eada4688a1237bd4a1dfebfacc6c0f4054ff645f Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sat, 11 Jan 2025 12:54:19 -0600 Subject: [PATCH 3/3] Apply Suggestion --- llvm/lib/Analysis/InstructionSimplify.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index ef9454fd9c9ab..d69747e30f884 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -875,7 +875,7 @@ static Value *simplifySubInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW, if (IsNUW) { Value *X; if (match(Op1, m_Xor(m_Value(X), m_Specific(Op0))) && - match(Op0, m_CheckedInt([](const APInt &C) { return C.isMask(); }))) + match(Op0, m_LowBitMask())) return X; } @@ -2552,7 +2552,7 @@ static Value *simplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, { Value *X; if (match(Op0, m_NUWSub(m_Specific(Op1), m_Value(X))) && - match(Op1, m_CheckedInt([](const APInt &C) { return C.isMask(); }))) + match(Op1, m_LowBitMask())) return X; }