summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2020-01-03 12:50:00 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2020-01-03 13:58:36 +0300
commit8dab0a4a7d691f2704f1079538e0ef29548db159 (patch)
tree488b5bceb5eefb1a8076da5cba84de6c7e7595a9 /llvm/lib/CodeGen
parentc0cbe3fbb7d6b3f197b05a47a2cc25ccb7977629 (diff)
downloadbcm5719-llvm-8dab0a4a7d691f2704f1079538e0ef29548db159.tar.gz
bcm5719-llvm-8dab0a4a7d691f2704f1079538e0ef29548db159.zip
[DAGCombine][X86][AArch64] 'A - (A & (B - 1))' -> 'A & (0 - B)' fold (PR44448)
While we do manage to fold integer-typed IR in middle-end, we can't do that for the main motivational case of pointers. There is @llvm.ptrmask() intrinsic which may or may not be helpful, but i'm not sure it is fully considered canonical yet, not everything is fully aware of it likely. https://rise4fun.com/Alive/ZVdp Name: ptr - (ptr & (alignment-1)) -> ptr & (0 - alignment) %mask = add i64 %alignment, -1 %bias = and i64 %ptr, %mask %r = sub i64 %ptr, %bias => %highbitmask = sub i64 0, %alignment %r = and i64 %ptr, %highbitmask See https://bugs.llvm.org/show_bug.cgi?id=44448 https://reviews.llvm.org/D71499
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp15
1 files changed, 15 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 1415b1e37d1..5dbe29f5fbd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -3104,6 +3104,21 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(1),
N1.getOperand(0)));
+ // A - (A & (B - 1)) -> A & (0 - B)
+ if (N1.getOpcode() == ISD::AND && N1.hasOneUse()) {
+ SDValue A = N1.getOperand(0);
+ SDValue BDec = N1.getOperand(1);
+ if (A != N0)
+ std::swap(A, BDec);
+ if (A == N0 && BDec.getOpcode() == ISD::ADD &&
+ isAllOnesOrAllOnesSplat(BDec->getOperand(1))) {
+ SDValue B = BDec.getOperand(0);
+ SDValue NegB =
+ DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), B);
+ return DAG.getNode(ISD::AND, DL, VT, A, NegB);
+ }
+ }
+
// fold (X - (-Y * Z)) -> (X + (Y * Z))
if (N1.getOpcode() == ISD::MUL && N1.hasOneUse()) {
if (N1.getOperand(0).getOpcode() == ISD::SUB &&
OpenPOWER on IntegriCloud