From: Craig Topper Date: Wed, 1 Sep 2021 19:11:37 +0000 (-0700) Subject: [RISCV] Fold (RISCVISD::SELECT_CC X, Y, CC, Z, Z) -> Z. X-Git-Tag: upstream/15.0.7~32508 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ccbb4c8b4ffd00588f0c21c7e5208bf210b26a53;p=platform%2Fupstream%2Fllvm.git [RISCV] Fold (RISCVISD::SELECT_CC X, Y, CC, Z, Z) -> Z. If the true and false values are the same, we don't need a SELECT_CC. This would normally be folded before a select is legalized to select_cc. The test case exploits the late legalization of vscale to trigger a case where they become identical after legalization. This works around an issue found on a test case in D107957. In that case the true/false values were both eventually 0 and the select was used by a vector AVL operand. The select_cc got expanded to control flow and a phi, but the phi inputs were both copies from X0. MachineIR optimizations simplified this to a single copy from X0 going into the vector instruction. This became the input of a vsetvli after vsetvli insertion. Then register coalescing folded the copy into the vsetvli. X0 as the source of a vsetvli is a special encoding and should not be created by coalesing. We need to fix our vsetvli handling to make sure this can never happen any other way, but removing the unneeded select is still a worthwhile optimization. --- diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 3711e52..e23844d 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -6206,6 +6206,13 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, // Transform SDValue LHS = N->getOperand(0); SDValue RHS = N->getOperand(1); + SDValue TrueV = N->getOperand(3); + SDValue FalseV = N->getOperand(4); + + // If the True and False values are the same, we don't need a select_cc. + if (TrueV == FalseV) + return TrueV; + ISD::CondCode CCVal = cast(N->getOperand(2))->get(); if (!ISD::isIntEqualitySetCC(CCVal)) break; @@ -6228,9 +6235,8 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG); SDValue TargetCC = DAG.getCondCode(CCVal); - return DAG.getNode( - RISCVISD::SELECT_CC, DL, N->getValueType(0), - {LHS, RHS, TargetCC, N->getOperand(3), N->getOperand(4)}); + return DAG.getNode(RISCVISD::SELECT_CC, DL, N->getValueType(0), + {LHS, RHS, TargetCC, TrueV, FalseV}); } // Fold (select_cc (xor X, Y), 0, eq/ne, trueV, falseV) -> @@ -6238,8 +6244,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, if (LHS.getOpcode() == ISD::XOR && isNullConstant(RHS)) return DAG.getNode(RISCVISD::SELECT_CC, SDLoc(N), N->getValueType(0), {LHS.getOperand(0), LHS.getOperand(1), - N->getOperand(2), N->getOperand(3), - N->getOperand(4)}); + N->getOperand(2), TrueV, FalseV}); // (select_cc X, 1, setne, trueV, falseV) -> // (select_cc X, 0, seteq, trueV, falseV) if we can prove X is 0/1. // This can occur when legalizing some floating point comparisons. @@ -6249,9 +6254,8 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, CCVal = ISD::getSetCCInverse(CCVal, LHS.getValueType()); SDValue TargetCC = DAG.getCondCode(CCVal); RHS = DAG.getConstant(0, DL, LHS.getValueType()); - return DAG.getNode( - RISCVISD::SELECT_CC, DL, N->getValueType(0), - {LHS, RHS, TargetCC, N->getOperand(3), N->getOperand(4)}); + return DAG.getNode(RISCVISD::SELECT_CC, DL, N->getValueType(0), + {LHS, RHS, TargetCC, TrueV, FalseV}); } break; diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i64.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i64.ll index 9384b4a..8ff72b3 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i64.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i64.ll @@ -81,4 +81,29 @@ entry: ret i64 %1 } +; vscale will always be a positive number, but we don't know that until after op +; legalization. The and will be considered a NOP and replaced with its input, +; but not until after the select becomes RISCVISD::SELECT_CC. Make sure we +; simplify this and don't leave behind any code for calculating the select +; condition. +define i64 @vscale_select(i32 %x, i32 %y) { +; RV64-LABEL: vscale_select: +; RV64: # %bb.0: +; RV64-NEXT: csrr a0, vlenb +; RV64-NEXT: srli a0, a0, 3 +; RV64-NEXT: ret +; +; RV32-LABEL: vscale_select: +; RV32: # %bb.0: +; RV32-NEXT: csrr a0, vlenb +; RV32-NEXT: srli a0, a0, 3 +; RV32-NEXT: mv a1, zero +; RV32-NEXT: ret + %a = call i64 @llvm.vscale.i64() + %b = and i64 %a, 4294967295 + %c = icmp eq i32 %x, %y + %d = select i1 %c, i64 %a, i64 %b + ret i64 %d +} + declare i64 @llvm.vscale.i64()