@@ -90,6 +90,9 @@ EVMTargetLowering::EVMTargetLowering(const TargetMachine &TM,
90
90
setOperationAction (ISD::INTRINSIC_VOID, MVT::Other, Custom);
91
91
setOperationAction (ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
92
92
93
+ // Custom DAGCombine patterns.
94
+ setTargetDAGCombine (ISD::SELECT);
95
+
93
96
setJumpIsExpensive (true );
94
97
setMaximumJumpTableSize (0 );
95
98
}
@@ -766,3 +769,127 @@ MachineBasicBlock *EVMTargetLowering::emitSelect(MachineInstr &MI,
766
769
MI.eraseFromParent (); // The pseudo instruction is gone now.
767
770
return BB;
768
771
}
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