@@ -90,6 +90,9 @@ EVMTargetLowering::EVMTargetLowering(const TargetMachine &TM,
9090 setOperationAction (ISD::INTRINSIC_VOID, MVT::Other, Custom);
9191 setOperationAction (ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
9292
93+ // Custom DAGCombine patterns.
94+ setTargetDAGCombine (ISD::SELECT);
95+
9396 setJumpIsExpensive (true );
9497 setMaximumJumpTableSize (0 );
9598}
@@ -766,3 +769,127 @@ MachineBasicBlock *EVMTargetLowering::emitSelect(MachineInstr &MI,
766769 MI.eraseFromParent (); // The pseudo instruction is gone now.
767770 return BB;
768771}
772+
773+ // Fold
774+ // (select C, (op Y, X), Y) -> (op Y, (select C, X, NEUTRAL))
775+ // and
776+ // (select C, Y, (op Y, X)) -> (op Y, (select not C, X, NEUTRAL))
777+ // when 0 is the neutral element for op.
778+ //
779+ // That lets a later combine turn (select C, X, 0) into (C * X).
780+ //
781+ // Examples:
782+ // (select C, (sub Y, X), Y) -> (sub Y, (select C, X, 0))
783+ // (select C, (or Y, X), Y) -> (or Y, (select C, X, 0))
784+ // (select C, (or X, Y), Y) -> (or Y, (select C, X, 0)) ; commutativity
785+ // handled.
786+ static SDValue tryFoldSelectIntoOp (SDNode *N, SelectionDAG &DAG, SDValue TrueV,
787+ SDValue FalseV, bool Swapped) {
788+
789+ if (!TrueV.hasOneUse () || isa<ConstantSDNode>(FalseV))
790+ return SDValue ();
791+
792+ bool Commutative = true ;
793+ switch (TrueV.getOpcode ()) {
794+ default :
795+ return SDValue ();
796+ case ISD::SHL:
797+ case ISD::SRA:
798+ case ISD::SRL:
799+ case ISD::SUB:
800+ Commutative = false ;
801+ break ;
802+ case ISD::ADD:
803+ case ISD::OR:
804+ case ISD::XOR:
805+ break ;
806+ }
807+
808+ if (FalseV != TrueV.getOperand (0 ) &&
809+ (!Commutative || FalseV != TrueV.getOperand (1 )))
810+ return SDValue ();
811+
812+ EVT VT = N->getValueType (0 );
813+ SDLoc DL (N);
814+ SDValue OtherOp =
815+ FalseV == TrueV.getOperand (0 ) ? TrueV.getOperand (1 ) : TrueV.getOperand (0 );
816+ EVT OtherOpVT = OtherOp.getValueType ();
817+ SDValue IdentityOperand = DAG.getConstant (0 , DL, OtherOpVT);
818+
819+ if (Swapped)
820+ std::swap (OtherOp, IdentityOperand);
821+ SDValue NewSel =
822+ DAG.getSelect (DL, OtherOpVT, N->getOperand (0 ), OtherOp, IdentityOperand);
823+ return DAG.getNode (TrueV.getOpcode (), DL, VT, FalseV, NewSel);
824+ }
825+
826+ SDValue EVMTargetLowering::combineSELECT (SDNode *N,
827+ DAGCombinerInfo &DCI) const {
828+ // Perform combines only after DAG legalisation.
829+ if (!DCI.isAfterLegalizeDAG ())
830+ return SDValue ();
831+
832+ SelectionDAG &DAG = DCI.DAG ;
833+ SDValue CondV = N->getOperand (0 );
834+ SDValue TrueV = N->getOperand (1 );
835+ SDValue FalseV = N->getOperand (2 );
836+ SDLoc DL (N);
837+ MVT VT = N->getSimpleValueType (0 );
838+
839+ const auto freeze = [&DAG](const SDValue V) { return DAG.getFreeze (V); };
840+ const auto iszero = [&DAG, DL, VT](const SDValue V) {
841+ return SDValue (DAG.getMachineNode (EVM::ISZERO, DL, VT, V), 0 );
842+ };
843+
844+ // X* means freeze(X)
845+ // fold (Cond ? X : 0) -> (X* * Cond)
846+ if (isNullConstant (FalseV))
847+ return DAG.getNode (ISD::MUL, DL, VT, freeze (TrueV), CondV);
848+
849+ // fold (Cond ? 0 : Y) -> (~Cond * Y*)
850+ if (isNullConstant (TrueV))
851+ return DAG.getNode (ISD::MUL, DL, VT, iszero (CondV), freeze (FalseV));
852+
853+ // fold (Cond ? X : 1) -> ((X* * Cond*) + ~Cond*)
854+ if (isOneConstant (FalseV))
855+ return DAG.getNode (
856+ ISD::ADD, DL, VT, iszero (freeze (CondV)),
857+ DAG.getNode (ISD::MUL, DL, VT, freeze (TrueV), freeze (CondV)));
858+
859+ // fold (Cond ? 1 : Y) -> (Cond* + ~Cond* * Y*)
860+ if (isOneConstant (TrueV))
861+ return DAG.getNode (
862+ ISD::ADD, DL, VT, freeze (CondV),
863+ DAG.getNode (ISD::MUL, DL, VT, freeze (FalseV), iszero (freeze (CondV))));
864+
865+ // fold (Cond ? X : -1) -> (Cond - 1) | X*)
866+ if (isAllOnesConstant (FalseV)) {
867+ const SDValue Const1 = DAG.getConstant (1 , DL, VT);
868+ return DAG.getNode (ISD::OR, DL, VT,
869+ DAG.getNode (ISD::SUB, DL, VT, CondV, Const1),
870+ freeze (TrueV));
871+ }
872+
873+ // fold (Cond ? -1 : Y) -> (-Cond | Y*)
874+ if (isAllOnesConstant (TrueV)) {
875+ SDValue Neg = DAG.getNegative (CondV, DL, VT);
876+ return DAG.getNode (ISD::OR, DL, VT, Neg, DAG.getFreeze (FalseV));
877+ }
878+
879+ if (SDValue V = tryFoldSelectIntoOp (N, DAG, TrueV, FalseV, /* Swapped=*/ false ))
880+ return V;
881+ // NOLINTNEXTLINE(readability-suspicious-call-argument)
882+ return tryFoldSelectIntoOp (N, DAG, FalseV, TrueV, /* Swapped=*/ true );
883+ }
884+
885+ SDValue EVMTargetLowering::PerformDAGCombine (SDNode *N,
886+ DAGCombinerInfo &DCI) const {
887+ switch (N->getOpcode ()) {
888+ default :
889+ break ;
890+ case ISD::SELECT:
891+ return combineSELECT (N, DCI);
892+ }
893+
894+ return SDValue ();
895+ }
0 commit comments