Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/include/llvm/CodeGen/TargetLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -5800,6 +5800,8 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
private:
SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
const SDLoc &DL, DAGCombinerInfo &DCI) const;
SDValue foldSetCCWithOr(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
const SDLoc &DL, DAGCombinerInfo &DCI) const;
SDValue foldSetCCWithBinOp(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
const SDLoc &DL, DAGCombinerInfo &DCI) const;

Expand Down
41 changes: 41 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SDPatternMatch.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/DataLayout.h"
Expand All @@ -37,6 +38,7 @@
#include <cctype>
#include <deque>
using namespace llvm;
using namespace llvm::SDPatternMatch;

/// NOTE: The TargetMachine owns TLOF.
TargetLowering::TargetLowering(const TargetMachine &tm)
Expand Down Expand Up @@ -4212,6 +4214,42 @@ SDValue TargetLowering::foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1,
return SDValue();
}

/// This helper function of SimplifySetCC tries to optimize the comparison when
/// either operand of the SetCC node is a bitwise-or instruction.
/// For now, this just transforms (X | Y) ==/!= Y into X & ~Y ==/!= 0.
SDValue TargetLowering::foldSetCCWithOr(EVT VT, SDValue N0, SDValue N1,
ISD::CondCode Cond, const SDLoc &DL,
DAGCombinerInfo &DCI) const {
if (N1.getOpcode() == ISD::OR && N0.getOpcode() != ISD::OR)
std::swap(N0, N1);

SelectionDAG &DAG = DCI.DAG;
EVT OpVT = N0.getValueType();
if (!N0.hasOneUse() || !OpVT.isInteger() ||
(Cond != ISD::SETEQ && Cond != ISD::SETNE))
return SDValue();

// (X | Y) == Y
// (X | Y) != Y
SDValue X;
if (sd_match(N0, m_Or(m_Value(X), m_Specific(N1))) && hasAndNotCompare(N1)) {
// If the target supports an 'and-not' or 'and-complement' logic operation,
// try to use that to make a comparison operation more efficient.

// Bail out if the compare operand that we want to turn into a zero is
// already a zero (otherwise, infinite loop).
if (isNullConstant(N1))
return SDValue();

// Transform this into: X & ~Y ==/!= 0.
SDValue NotY = DAG.getNOT(SDLoc(N1), N1, OpVT);
SDValue NewAnd = DAG.getNode(ISD::AND, SDLoc(N0), OpVT, X, NotY);
return DAG.getSetCC(DL, VT, NewAnd, DAG.getConstant(0, DL, OpVT), Cond);
}

return SDValue();
}

/// There are multiple IR patterns that could be checking whether certain
/// truncation of a signed number would be lossy or not. The pattern which is
/// best at IR level, may not lower optimally. Thus, we want to unfold it.
Expand Down Expand Up @@ -5507,6 +5545,9 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,

if (SDValue V = foldSetCCWithAnd(VT, N0, N1, Cond, dl, DCI))
return V;

if (SDValue V = foldSetCCWithOr(VT, N0, N1, Cond, dl, DCI))
return V;
}

// Fold remainder of division by a constant.
Expand Down
24 changes: 24 additions & 0 deletions llvm/test/CodeGen/AArch64/aarch64-bitwisenot-fold.ll
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,27 @@ define i64 @andnot_sub_with_neg_i64(i64 %a0, i64 %a1) {
%and = and i64 %diff, %a0
ret i64 %and
}

define i32 @and_not_select_eq(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: and_not_select_eq:
; CHECK: // %bb.0:
; CHECK-NEXT: bics wzr, w1, w0
; CHECK-NEXT: csel w0, w0, w2, eq
; CHECK-NEXT: ret
%or = or i32 %b, %a
%cmp = icmp eq i32 %or, %a
%a.c = select i1 %cmp, i32 %a, i32 %c
ret i32 %a.c
}

define i32 @and_not_select_ne(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: and_not_select_ne:
; CHECK: // %bb.0:
; CHECK-NEXT: bics wzr, w1, w0
; CHECK-NEXT: csel w0, w0, w2, ne
; CHECK-NEXT: ret
%or = or i32 %b, %a
%cmp = icmp ne i32 %or, %a
%a.c = select i1 %cmp, i32 %a, i32 %c
ret i32 %a.c
}
3 changes: 1 addition & 2 deletions llvm/test/CodeGen/AArch64/switch-cases-to-branch-and.ll
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,7 @@ define void @test_successor_with_loop_phi(ptr %A, ptr %B) {
; CHECK-NEXT: ldr w8, [x0]
; CHECK-NEXT: str wzr, [x0]
; CHECK-NEXT: mov x0, x1
; CHECK-NEXT: orr w8, w8, #0x4
; CHECK-NEXT: cmp w8, #4
; CHECK-NEXT: tst w8, #0xfffffffb
; CHECK-NEXT: b.eq LBB7_1
; CHECK-NEXT: ; %bb.2: ; %exit
; CHECK-NEXT: ret
Expand Down