[llvm] r245350 - DAGCombiner: Improve DAGCombiner select normalization
Arnaud A. de Grandmaison via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 01:16:43 PDT 2015
Thanks Matthias !
> -----Original Message-----
> From: llvm-commits [mailto:llvm-commits-bounces at lists.llvm.org] On Behalf
> Of Matthias Braun via llvm-commits
> Sent: 18 August 2015 22:49
> To: llvm-commits at lists.llvm.org
> Subject: [llvm] r245350 - DAGCombiner: Improve DAGCombiner select
> normalization
>
> Author: matze
> Date: Tue Aug 18 15:48:36 2015
> New Revision: 245350
>
> URL: http://llvm.org/viewvc/llvm-project?rev=245350&view=rev
> Log:
> DAGCombiner: Improve DAGCombiner select normalization
>
> The current code normalizes select(C0, x, select(C1, x, y)) towards
> select(C0|C1, x, y) if the targets prefers that form. This patch adds an
> additional rule that if the select(C1, x, y) part already exists in the function
> then we want to normalize into the other direction because the effects of
> reusing the existing value are bigger than transforming into the target
> preferred form.
>
> This addresses regressions following r238793, see also:
> http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-
> 20150727/290272.html
>
> Differential Revision: http://reviews.llvm.org/D11616
>
> Modified:
> llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
> llvm/trunk/test/CodeGen/AArch64/dag-combine-select.ll
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=245
> 350&r1=245349&r2=245350&view=diff
> ==========================================================
> ====================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Aug 18
> +++ 15:48:36 2015
> @@ -4956,36 +4956,46 @@ SDValue DAGCombiner::visitSELECT(SDNode
> return SDValue(N, 0); // Don't revisit N.
>
> if (VT0 == MVT::i1) {
> - if (TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT)) {
> - // select (and Cond0, Cond1), X, Y
> - // -> select Cond0, (select Cond1, X, Y), Y
> - if (N0->getOpcode() == ISD::AND && N0->hasOneUse()) {
> - SDValue Cond0 = N0->getOperand(0);
> - SDValue Cond1 = N0->getOperand(1);
> - SDValue InnerSelect = DAG.getNode(ISD::SELECT, SDLoc(N),
> - N1.getValueType(), Cond1, N1, N2);
> + // The code in this block deals with the following 2 equivalences:
> + // select(C0|C1, x, y) <=> select(C0, x, select(C1, x, y))
> + // select(C0&C1, x, y) <=> select(C0, select(C1, x, y), y)
> + // The target can specify its prefered form with the
> + // shouldNormalizeToSelectSequence() callback. However we always
> transform
> + // to the right anyway if we find the inner select exists in the DAG anyway
> + // and we always transform to the left side if we know that we can
> further
> + // optimize the combination of the conditions.
> + bool normalizeToSequence
> + = TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT);
> + // select (and Cond0, Cond1), X, Y
> + // -> select Cond0, (select Cond1, X, Y), Y
> + if (N0->getOpcode() == ISD::AND && N0->hasOneUse()) {
> + SDValue Cond0 = N0->getOperand(0);
> + SDValue Cond1 = N0->getOperand(1);
> + SDValue InnerSelect = DAG.getNode(ISD::SELECT, SDLoc(N),
> + N1.getValueType(), Cond1, N1, N2);
> + if (normalizeToSequence || !InnerSelect.use_empty())
> return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(), Cond0,
> InnerSelect, N2);
> - }
> - // select (or Cond0, Cond1), X, Y -> select Cond0, X, (select Cond1, X, Y)
> - if (N0->getOpcode() == ISD::OR && N0->hasOneUse()) {
> - SDValue Cond0 = N0->getOperand(0);
> - SDValue Cond1 = N0->getOperand(1);
> - SDValue InnerSelect = DAG.getNode(ISD::SELECT, SDLoc(N),
> - N1.getValueType(), Cond1, N1, N2);
> + }
> + // select (or Cond0, Cond1), X, Y -> select Cond0, X, (select Cond1, X, Y)
> + if (N0->getOpcode() == ISD::OR && N0->hasOneUse()) {
> + SDValue Cond0 = N0->getOperand(0);
> + SDValue Cond1 = N0->getOperand(1);
> + SDValue InnerSelect = DAG.getNode(ISD::SELECT, SDLoc(N),
> + N1.getValueType(), Cond1, N1, N2);
> + if (normalizeToSequence || !InnerSelect.use_empty())
> return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(), Cond0,
> N1,
> InnerSelect);
> - }
> }
>
> // select Cond0, (select Cond1, X, Y), Y -> select (and Cond0, Cond1), X, Y
> - if (N1->getOpcode() == ISD::SELECT) {
> + if (N1->getOpcode() == ISD::SELECT && N1->hasOneUse()) {
> SDValue N1_0 = N1->getOperand(0);
> SDValue N1_1 = N1->getOperand(1);
> SDValue N1_2 = N1->getOperand(2);
> if (N1_2 == N2 && N0.getValueType() == N1_0.getValueType()) {
> // Create the actual and node if we can generate good code for it.
> - if (!TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT)) {
> + if (!normalizeToSequence) {
> SDValue And = DAG.getNode(ISD::AND, SDLoc(N), N0.getValueType(),
> N0, N1_0);
> return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(), And,
> @@ -4998,13 +5008,13 @@ SDValue DAGCombiner::visitSELECT(SDNode
> }
> }
> // select Cond0, X, (select Cond1, X, Y) -> select (or Cond0, Cond1), X, Y
> - if (N2->getOpcode() == ISD::SELECT) {
> + if (N2->getOpcode() == ISD::SELECT && N2->hasOneUse()) {
> SDValue N2_0 = N2->getOperand(0);
> SDValue N2_1 = N2->getOperand(1);
> SDValue N2_2 = N2->getOperand(2);
> if (N2_1 == N1 && N0.getValueType() == N2_0.getValueType()) {
> // Create the actual or node if we can generate good code for it.
> - if (!TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT)) {
> + if (!normalizeToSequence) {
> SDValue Or = DAG.getNode(ISD::OR, SDLoc(N), N0.getValueType(),
> N0, N2_0);
> return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(), Or,
>
> Modified: llvm/trunk/test/CodeGen/AArch64/dag-combine-select.ll
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/test/CodeGen/AArch64/dag-combine-
> select.ll?rev=245350&r1=245349&r2=245350&view=diff
> ==========================================================
> ====================
> --- llvm/trunk/test/CodeGen/AArch64/dag-combine-select.ll (original)
> +++ llvm/trunk/test/CodeGen/AArch64/dag-combine-select.ll Tue Aug 18
> +++ 15:48:36 2015
> @@ -1,6 +1,8 @@
> ; RUN: llc -o - %s | FileCheck %s
> target triple = "arm64--"
>
> + at out = internal global i32 0, align 4
> +
> ; Ensure that we transform select(C0, x, select(C1, x, y)) towards ; select(C0
> | C1, x, y) so we can use CMP;CCMP for the implementation.
> ; CHECK-LABEL: test0:
> @@ -15,3 +17,31 @@ define i32 @test0(i32 %v0, i32 %v1, i32
> %sel1 = select i1 %cmp2, i32 %v1, i32 %sel0
> ret i32 %sel1
> }
> +
> +; Usually we keep select(C0 | C1, x, y) as is on aarch64 to create
> +CMP;CCMP ; sequences. This case should be transformed to select(C0,
> +select(C1, x, y), y) ; anyway to get CSE effects.
> +; CHECK-LABEL: test1:
> +; CHECK-NOT: ccmp
> +; CHECK: cmp w0, #7
> +; CHECK: adrp x[[OUTNUM:[0-9]+]], out
> +; CHECK: csel w[[SEL0NUM:[0-9]+]], w1, w2, eq ; CHECK: cmp
> +w[[SEL0NUM]], #13 ; CHECK: csel w[[SEL1NUM:[0-9]+]], w1, w2, lo ;
> +CHECK: cmp w0, #42 ; CHECK: csel w[[SEL2NUM:[0-9]+]], w1,
> w[[SEL1NUM]],
> +eq ; CHECK: str w[[SEL1NUM]], [x[[OUTNUM]], :lo12:out] ; CHECK: str
> +w[[SEL2NUM]], [x[[OUTNUM]], :lo12:out] ; CHECK: ret define void
> + at test1(i32 %bitset, i32 %val0, i32 %val1) {
> + %cmp1 = icmp eq i32 %bitset, 7
> + %cond = select i1 %cmp1, i32 %val0, i32 %val1
> + %cmp5 = icmp ult i32 %cond, 13
> + %cond11 = select i1 %cmp5, i32 %val0, i32 %val1
> + %cmp3 = icmp eq i32 %bitset, 42
> + %or.cond = or i1 %cmp3, %cmp5
> + %cond17 = select i1 %or.cond, i32 %val0, i32 %val1
> + store volatile i32 %cond11, i32* @out, align 4
> + store volatile i32 %cond17, i32* @out, align 4
> + ret void
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list