@@ -826,13 +826,12 @@ let Predicates = [BPFNoALU32] in {
826826}
827827
828828// Atomic Fetch-and-<add, and, or, xor> operations
829- class XFALU64<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
830- string OpcStr, PatFrag OpNode>
829+ class XFALU64<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr, string OpcStr>
831830 : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
832831 (outs GPR:$dst),
833832 (ins MEMri:$addr, GPR:$val),
834833 "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)",
835- [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val)) ]> {
834+ []> {
836835 bits<4> dst;
837836 bits<20> addr;
838837
@@ -844,13 +843,12 @@ class XFALU64<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
844843 let BPFClass = BPF_STX;
845844}
846845
847- class XFALU32<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
848- string OpcStr, PatFrag OpNode>
846+ class XFALU32<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr, string OpcStr>
849847 : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
850848 (outs GPR32:$dst),
851849 (ins MEMri:$addr, GPR32:$val),
852850 "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)",
853- [(set GPR32:$dst, (OpNode ADDRri:$addr, GPR32:$val)) ]> {
851+ []> {
854852 bits<4> dst;
855853 bits<20> addr;
856854
@@ -864,26 +862,122 @@ class XFALU32<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
864862
865863let Constraints = "$dst = $val" in {
866864 let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
867- def XFADDW32 : XFALU32<BPF_W, BPF_ADD, "u32", "add", atomic_load_add_i32 >;
868- def XFANDW32 : XFALU32<BPF_W, BPF_AND, "u32", "and", atomic_load_and_i32 >;
869- def XFORW32 : XFALU32<BPF_W, BPF_OR, "u32", "or", atomic_load_or_i32 >;
870- def XFXORW32 : XFALU32<BPF_W, BPF_XOR, "u32", "xor", atomic_load_xor_i32 >;
865+ def XFADDW32 : XFALU32<BPF_W, BPF_ADD, "u32", "add">;
866+ def XFANDW32 : XFALU32<BPF_W, BPF_AND, "u32", "and">;
867+ def XFORW32 : XFALU32<BPF_W, BPF_OR, "u32", "or">;
868+ def XFXORW32 : XFALU32<BPF_W, BPF_XOR, "u32", "xor">;
871869 }
872870
873871 let Predicates = [BPFHasALU32] in {
874- def XFADDD : XFALU64<BPF_DW, BPF_ADD, "u64", "add", atomic_load_add_i64 >;
872+ def XFADDD : XFALU64<BPF_DW, BPF_ADD, "u64", "add">;
875873 }
876- def XFANDD : XFALU64<BPF_DW, BPF_AND, "u64", "and", atomic_load_and_i64 >;
877- def XFORD : XFALU64<BPF_DW, BPF_OR, "u64", "or", atomic_load_or_i64 >;
878- def XFXORD : XFALU64<BPF_DW, BPF_XOR, "u64", "xor", atomic_load_xor_i64 >;
874+ def XFANDD : XFALU64<BPF_DW, BPF_AND, "u64", "and">;
875+ def XFORD : XFALU64<BPF_DW, BPF_OR, "u64", "or">;
876+ def XFXORD : XFALU64<BPF_DW, BPF_XOR, "u64", "xor">;
879877}
880878
881- // atomic_load_sub can be represented as a neg followed
882- // by an atomic_load_add.
883- def : Pat<(atomic_load_sub_i32 ADDRri:$addr, GPR32:$val),
884- (XFADDW32 ADDRri:$addr, (NEG_32 GPR32:$val))>;
885- def : Pat<(atomic_load_sub_i64 ADDRri:$addr, GPR:$val),
886- (XFADDD ADDRri:$addr, (NEG_64 GPR:$val))>;
879+ let Predicates = [BPFHasALU32] in {
880+ foreach P = [// add
881+ [atomic_load_add_i32_monotonic, XADDW32],
882+ [atomic_load_add_i32_acquire, XFADDW32],
883+ [atomic_load_add_i32_release, XFADDW32],
884+ [atomic_load_add_i32_acq_rel, XFADDW32],
885+ [atomic_load_add_i32_seq_cst, XFADDW32],
886+ // and
887+ [atomic_load_and_i32_monotonic, XANDW32],
888+ [atomic_load_and_i32_acquire, XFANDW32],
889+ [atomic_load_and_i32_release, XFANDW32],
890+ [atomic_load_and_i32_acq_rel, XFANDW32],
891+ [atomic_load_and_i32_seq_cst, XFANDW32],
892+ // or
893+ [atomic_load_or_i32_monotonic, XORW32],
894+ [atomic_load_or_i32_acquire, XFORW32],
895+ [atomic_load_or_i32_release, XFORW32],
896+ [atomic_load_or_i32_acq_rel, XFORW32],
897+ [atomic_load_or_i32_seq_cst, XFORW32],
898+ // xor
899+ [atomic_load_xor_i32_monotonic, XXORW32],
900+ [atomic_load_xor_i32_acquire, XFXORW32],
901+ [atomic_load_xor_i32_release, XFXORW32],
902+ [atomic_load_xor_i32_acq_rel, XFXORW32],
903+ [atomic_load_xor_i32_seq_cst, XFXORW32],
904+ ] in {
905+ def : Pat<(P[0] ADDRri:$addr, GPR32:$val), (P[1] ADDRri:$addr, GPR32:$val)>;
906+ }
907+
908+ // atomic_load_sub can be represented as a neg followed
909+ // by an atomic_load_add.
910+ foreach P = [[atomic_load_sub_i32_monotonic, XADDW32],
911+ [atomic_load_sub_i32_acquire, XFADDW32],
912+ [atomic_load_sub_i32_release, XFADDW32],
913+ [atomic_load_sub_i32_acq_rel, XFADDW32],
914+ [atomic_load_sub_i32_seq_cst, XFADDW32],
915+ ] in {
916+ def : Pat<(P[0] ADDRri:$addr, GPR32:$val), (P[1] ADDRri:$addr, (NEG_32 GPR32:$val))>;
917+ }
918+
919+ foreach P = [// add
920+ [atomic_load_add_i64_monotonic, XADDD],
921+ [atomic_load_add_i64_acquire, XFADDD],
922+ [atomic_load_add_i64_release, XFADDD],
923+ [atomic_load_add_i64_acq_rel, XFADDD],
924+ [atomic_load_add_i64_seq_cst, XFADDD],
925+ ] in {
926+ def : Pat<(P[0] ADDRri:$addr, GPR:$val), (P[1] ADDRri:$addr, GPR:$val)>;
927+ }
928+ }
929+
930+ foreach P = [[atomic_load_sub_i64_monotonic, XADDD],
931+ [atomic_load_sub_i64_acquire, XFADDD],
932+ [atomic_load_sub_i64_release, XFADDD],
933+ [atomic_load_sub_i64_acq_rel, XFADDD],
934+ [atomic_load_sub_i64_seq_cst, XFADDD],
935+ ] in {
936+ def : Pat<(P[0] ADDRri:$addr, GPR:$val), (P[1] ADDRri:$addr, (NEG_64 GPR:$val))>;
937+ }
938+
939+ // Borrow the idea from X86InstrFragments.td
940+ class binop_no_use<SDPatternOperator operator>
941+ : PatFrag<(ops node:$A, node:$B),
942+ (operator node:$A, node:$B),
943+ [{ return SDValue(N, 0).use_empty(); }]>;
944+
945+ class binop_has_use<SDPatternOperator operator>
946+ : PatFrag<(ops node:$A, node:$B),
947+ (operator node:$A, node:$B),
948+ [{ return !SDValue(N, 0).use_empty(); }]>;
949+
950+ foreach op = [add, and, or, xor] in {
951+ def atomic_load_ # op # _i64_monotonic_nu:
952+ binop_no_use <!cast<SDPatternOperator>("atomic_load_"#op# _i64_monotonic)>;
953+ def atomic_load_ # op # _i64_monotonic_hu:
954+ binop_has_use<!cast<SDPatternOperator>("atomic_load_"#op# _i64_monotonic)>;
955+ }
956+
957+ foreach P = [// and
958+ [atomic_load_and_i64_monotonic_nu, XANDD],
959+ [atomic_load_and_i64_monotonic_hu, XFANDD],
960+ [atomic_load_and_i64_acquire, XFANDD],
961+ [atomic_load_and_i64_release, XFANDD],
962+ [atomic_load_and_i64_acq_rel, XFANDD],
963+ [atomic_load_and_i64_seq_cst, XFANDD],
964+ // or
965+ [atomic_load_or_i64_monotonic_nu, XORD],
966+ [atomic_load_or_i64_monotonic_hu, XFORD],
967+ [atomic_load_or_i64_acquire, XFORD],
968+ [atomic_load_or_i64_release, XFORD],
969+ [atomic_load_or_i64_acq_rel, XFORD],
970+ [atomic_load_or_i64_seq_cst, XFORD],
971+ // xor
972+ [atomic_load_xor_i64_monotonic_nu, XXORD],
973+ [atomic_load_xor_i64_monotonic_hu, XFXORD],
974+ [atomic_load_xor_i64_acquire, XFXORD],
975+ [atomic_load_xor_i64_release, XFXORD],
976+ [atomic_load_xor_i64_acq_rel, XFXORD],
977+ [atomic_load_xor_i64_seq_cst, XFXORD],
978+ ] in {
979+ def : Pat<(P[0] ADDRri:$addr, GPR:$val), (P[1] ADDRri:$addr, GPR:$val)>;
980+ }
887981
888982// Atomic Exchange
889983class XCHG<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
0 commit comments