|
9 | 9 | "go/constant"
|
10 | 10 | "go/token"
|
11 | 11 | "os"
|
| 12 | + "strings" |
12 | 13 |
|
13 | 14 | "cmd/compile/internal/base"
|
14 | 15 | "cmd/compile/internal/ir"
|
@@ -866,14 +867,22 @@ func subst(n ir.Node, m map[*ir.Name]ir.Node) (ir.Node, bool) {
|
866 | 867 | }
|
867 | 868 | x = ir.Copy(x)
|
868 | 869 | ir.EditChildrenWithHidden(x, edit)
|
869 |
| - if x, ok := x.(*ir.ConvExpr); ok && x.X.Op() == ir.OLITERAL { |
870 |
| - if x, ok := truncate(x.X, x.Type()); ok { |
| 870 | + |
| 871 | + // TODO: handle more operations, see details discussion in go.dev/cl/466277. |
| 872 | + switch x.Op() { |
| 873 | + case ir.OCONV: |
| 874 | + x := x.(*ir.ConvExpr) |
| 875 | + if x.X.Op() == ir.OLITERAL { |
| 876 | + if x, ok := truncate(x.X, x.Type()); ok { |
| 877 | + return x |
| 878 | + } |
| 879 | + valid = false |
871 | 880 | return x
|
872 | 881 | }
|
873 |
| - valid = false |
874 |
| - return x |
| 882 | + case ir.OADDSTR: |
| 883 | + return addStr(x.(*ir.AddStringExpr)) |
875 | 884 | }
|
876 |
| - return typecheck.EvalConst(x) |
| 885 | + return x |
877 | 886 | }
|
878 | 887 | n = edit(n)
|
879 | 888 | return n, valid
|
@@ -909,6 +918,51 @@ func truncate(c ir.Node, t *types.Type) (ir.Node, bool) {
|
909 | 918 | return c, true
|
910 | 919 | }
|
911 | 920 |
|
| 921 | +func addStr(n *ir.AddStringExpr) ir.Node { |
| 922 | + // Merge adjacent constants in the argument list. |
| 923 | + s := n.List |
| 924 | + need := 0 |
| 925 | + for i := 0; i < len(s); i++ { |
| 926 | + if i == 0 || !ir.IsConst(s[i-1], constant.String) || !ir.IsConst(s[i], constant.String) { |
| 927 | + // Can't merge s[i] into s[i-1]; need a slot in the list. |
| 928 | + need++ |
| 929 | + } |
| 930 | + } |
| 931 | + if need == len(s) { |
| 932 | + return n |
| 933 | + } |
| 934 | + if need == 1 { |
| 935 | + var strs []string |
| 936 | + for _, c := range s { |
| 937 | + strs = append(strs, ir.StringVal(c)) |
| 938 | + } |
| 939 | + return typecheck.OrigConst(n, constant.MakeString(strings.Join(strs, ""))) |
| 940 | + } |
| 941 | + newList := make([]ir.Node, 0, need) |
| 942 | + for i := 0; i < len(s); i++ { |
| 943 | + if ir.IsConst(s[i], constant.String) && i+1 < len(s) && ir.IsConst(s[i+1], constant.String) { |
| 944 | + // merge from i up to but not including i2 |
| 945 | + var strs []string |
| 946 | + i2 := i |
| 947 | + for i2 < len(s) && ir.IsConst(s[i2], constant.String) { |
| 948 | + strs = append(strs, ir.StringVal(s[i2])) |
| 949 | + i2++ |
| 950 | + } |
| 951 | + |
| 952 | + nl := ir.Copy(n).(*ir.AddStringExpr) |
| 953 | + nl.List = s[i:i2] |
| 954 | + newList = append(newList, typecheck.OrigConst(nl, constant.MakeString(strings.Join(strs, "")))) |
| 955 | + i = i2 - 1 |
| 956 | + } else { |
| 957 | + newList = append(newList, s[i]) |
| 958 | + } |
| 959 | + } |
| 960 | + |
| 961 | + nn := ir.Copy(n).(*ir.AddStringExpr) |
| 962 | + nn.List = newList |
| 963 | + return nn |
| 964 | +} |
| 965 | + |
912 | 966 | const wrapGlobalMapInitSizeThreshold = 20
|
913 | 967 |
|
914 | 968 | // tryWrapGlobalMapInit examines the node 'n' to see if it is a map
|
|
0 commit comments