-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[DAGCombiner] Teach SearchForAndLoads to handle an AND with 2 constant operands. #142062
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…t operands. If opaque constants are involved we can have an AND with 2 constant operands that hasn't been simplified. If this is the case, we need to modify at least one of the constants if it is out of range. Fixes llvm#142004
@llvm/pr-subscribers-llvm-selectiondag Author: Craig Topper (topperc) ChangesIf opaque constants are involved we can have an AND with 2 constant Fixes #142004 Full diff: https://github.com/llvm/llvm-project/pull/142062.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e05f85ea3bd8e..fe5310aff6c73 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6812,7 +6812,8 @@ bool DAGCombiner::SearchForAndLoads(SDNode *N,
// Some constants may need fixing up later if they are too large.
if (auto *C = dyn_cast<ConstantSDNode>(Op)) {
- if ((N->getOpcode() == ISD::OR || N->getOpcode() == ISD::XOR) &&
+ if ((N->getOpcode() == ISD::OR || N->getOpcode() == ISD::XOR ||
+ N->getOpcode() == ISD::AND) &&
(Mask->getAPIntValue() & C->getAPIntValue()) != C->getAPIntValue())
NodesWithConsts.insert(N);
continue;
@@ -6927,7 +6928,13 @@ bool DAGCombiner::BackwardsPropagateMask(SDNode *N) {
SDValue Op0 = LogicN->getOperand(0);
SDValue Op1 = LogicN->getOperand(1);
- if (isa<ConstantSDNode>(Op0))
+ // We only need to fix AND if both inputs are constants. And we only need
+ // to fix one of the constants.
+ if (LogicN->getOpcode() == ISD::AND &&
+ (!isa<ConstantSDNode>(Op0) || !isa<ConstantSDNode>(Op1)))
+ continue;
+
+ if (isa<ConstantSDNode>(Op0) && LogicN->getOpcode() != ISD::AND)
Op0 =
DAG.getNode(ISD::AND, SDLoc(Op0), Op0.getValueType(), Op0, MaskOp);
diff --git a/llvm/test/CodeGen/RISCV/pr142004.ll b/llvm/test/CodeGen/RISCV/pr142004.ll
new file mode 100644
index 0000000000000..709644e49e704
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/pr142004.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=riscv64 | FileCheck %s
+
+@f = global i64 0, align 8
+@d = global i64 0, align 8
+@e = global i32 0, align 8
+
+define i32 @foo(i32 %x) {
+; CHECK-LABEL: foo:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lui a1, %hi(f)
+; CHECK-NEXT: lui a2, %hi(d)
+; CHECK-NEXT: lbu a1, %lo(f)(a1)
+; CHECK-NEXT: lhu a2, %lo(d)(a2)
+; CHECK-NEXT: slli a0, a0, 48
+; CHECK-NEXT: srli a3, a0, 48
+; CHECK-NEXT: xori a0, a1, 255
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: lui a1, %hi(e)
+; CHECK-NEXT: sw a3, %lo(e)(a1)
+; CHECK-NEXT: ret
+entry:
+ %1 = load i64, ptr @f, align 8
+ %conv1 = and i64 %1, 255
+ %conv2 = xor i64 %conv1, 255
+ %2 = load i64, ptr @d, align 8
+ %or = or i64 %conv2, %2
+ %conv3 = trunc i64 %or to i32
+ %conv4 = and i32 %conv3, 65535
+ %and = and i32 %x, 65535
+ store i32 %and, ptr @e
+ ret i32 %conv4
+}
|
@@ -6812,7 +6812,8 @@ bool DAGCombiner::SearchForAndLoads(SDNode *N, | |||
|
|||
// Some constants may need fixing up later if they are too large. | |||
if (auto *C = dyn_cast<ConstantSDNode>(Op)) { | |||
if ((N->getOpcode() == ISD::OR || N->getOpcode() == ISD::XOR) && | |||
if ((N->getOpcode() == ISD::OR || N->getOpcode() == ISD::XOR || | |||
N->getOpcode() == ISD::AND) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ISD::isBitwiseLogicOp(N->getOpcode())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
N is always a bitwise op. We can insert an assertion instead.
https://github.com/llvm/llvm-project/blob/2a3afa2feb90844ad0f8b0bc57663e2aec06cd0a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp#L6858-L6864
https://github.com/llvm/llvm-project/blob/2a3afa2feb90844ad0f8b0bc57663e2aec06cd0a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp#L6891-L6906
https://github.com/llvm/llvm-project/blob/2a3afa2feb90844ad0f8b0bc57663e2aec06cd0a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp#L7494-L7501
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG w/ comment fixed.
@@ -6812,7 +6812,8 @@ bool DAGCombiner::SearchForAndLoads(SDNode *N, | |||
|
|||
// Some constants may need fixing up later if they are too large. | |||
if (auto *C = dyn_cast<ConstantSDNode>(Op)) { | |||
if ((N->getOpcode() == ISD::OR || N->getOpcode() == ISD::XOR) && | |||
if ((N->getOpcode() == ISD::OR || N->getOpcode() == ISD::XOR || | |||
N->getOpcode() == ISD::AND) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
N is always a bitwise op. We can insert an assertion instead.
https://github.com/llvm/llvm-project/blob/2a3afa2feb90844ad0f8b0bc57663e2aec06cd0a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp#L6858-L6864
https://github.com/llvm/llvm-project/blob/2a3afa2feb90844ad0f8b0bc57663e2aec06cd0a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp#L6891-L6906
https://github.com/llvm/llvm-project/blob/2a3afa2feb90844ad0f8b0bc57663e2aec06cd0a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp#L7494-L7501
If opaque constants are involved we can have an AND with 2 constant
operands that hasn't been simplified. If this is the case, we need
to modify at least one of the constants if it is out of range.
Fixes #142004