@@ -3083,9 +3083,7 @@ func walkcompare(n *Node, init *Nodes) *Node {
3083
3083
// Handle != similarly.
3084
3084
// This avoids the allocation that would be required
3085
3085
// to convert r to l for comparison.
3086
- var l * Node
3087
-
3088
- var r * Node
3086
+ var l , r * Node
3089
3087
if n .Left .Type .IsInterface () && ! n .Right .Type .IsInterface () {
3090
3088
l = n .Left
3091
3089
r = n .Right
@@ -3129,14 +3127,17 @@ func walkcompare(n *Node, init *Nodes) *Node {
3129
3127
3130
3128
// Must be comparison of array or struct.
3131
3129
// Otherwise back end handles it.
3130
+ // While we're here, decide whether to
3131
+ // inline or call an eq alg.
3132
3132
t := n .Left .Type
3133
-
3133
+ var inline bool
3134
3134
switch t .Etype {
3135
3135
default :
3136
3136
return n
3137
-
3138
- case TARRAY , TSTRUCT :
3139
- break
3137
+ case TARRAY :
3138
+ inline = t .NumElem () <= 1 || (t .NumElem () <= 4 && issimple [t .Elem ().Etype ])
3139
+ case TSTRUCT :
3140
+ inline = t .NumFields () <= 4
3140
3141
}
3141
3142
3142
3143
cmpl := n .Left
@@ -3152,103 +3153,68 @@ func walkcompare(n *Node, init *Nodes) *Node {
3152
3153
Fatalf ("arguments of comparison must be lvalues - %v %v" , cmpl , cmpr )
3153
3154
}
3154
3155
3155
- l = temp (Ptrto (t ))
3156
- a := Nod (OAS , l , Nod (OADDR , cmpl , nil ))
3157
- a .Right .Etype = 1 // addr does not escape
3158
- a = typecheck (a , Etop )
3159
- init .Append (a )
3160
-
3161
- r = temp (Ptrto (t ))
3162
- a = Nod (OAS , r , Nod (OADDR , cmpr , nil ))
3163
- a .Right .Etype = 1 // addr does not escape
3164
- a = typecheck (a , Etop )
3165
- init .Append (a )
3156
+ // Chose not to inline. Call equality function directly.
3157
+ if ! inline {
3158
+ // eq algs take pointers
3159
+ pl := temp (Ptrto (t ))
3160
+ al := Nod (OAS , pl , Nod (OADDR , cmpl , nil ))
3161
+ al .Right .Etype = 1 // addr does not escape
3162
+ al = typecheck (al , Etop )
3163
+ init .Append (al )
3164
+
3165
+ pr := temp (Ptrto (t ))
3166
+ ar := Nod (OAS , pr , Nod (OADDR , cmpr , nil ))
3167
+ ar .Right .Etype = 1 // addr does not escape
3168
+ ar = typecheck (ar , Etop )
3169
+ init .Append (ar )
3170
+
3171
+ var needsize int
3172
+ call := Nod (OCALL , eqfor (t , & needsize ), nil )
3173
+ call .List .Append (pl )
3174
+ call .List .Append (pr )
3175
+ if needsize != 0 {
3176
+ call .List .Append (Nodintconst (t .Width ))
3177
+ }
3178
+ res := call
3179
+ if n .Op != OEQ {
3180
+ res = Nod (ONOT , res , nil )
3181
+ }
3182
+ n = finishcompare (n , res , init )
3183
+ return n
3184
+ }
3166
3185
3167
- var andor Op = OANDAND
3186
+ // inline: build boolean expression comparing element by element
3187
+ andor := OANDAND
3168
3188
if n .Op == ONE {
3169
3189
andor = OOROR
3170
3190
}
3171
-
3172
3191
var expr * Node
3173
- if t .Etype == TARRAY && t .NumElem () <= 4 && issimple [t .Elem ().Etype ] {
3174
- // Four or fewer elements of a basic type.
3175
- // Unroll comparisons.
3176
- var li * Node
3177
- var ri * Node
3178
- for i := 0 ; int64 (i ) < t .NumElem (); i ++ {
3179
- li = Nod (OINDEX , l , Nodintconst (int64 (i )))
3180
- ri = Nod (OINDEX , r , Nodintconst (int64 (i )))
3181
- a = Nod (n .Op , li , ri )
3182
- if expr == nil {
3183
- expr = a
3184
- } else {
3185
- expr = Nod (andor , expr , a )
3186
- }
3187
- }
3188
-
3192
+ compare := func (el , er * Node ) {
3193
+ a := Nod (n .Op , el , er )
3189
3194
if expr == nil {
3190
- expr = Nodbool (n .Op == OEQ )
3191
- }
3192
- n = finishcompare (n , expr , init )
3193
- return n
3194
- }
3195
-
3196
- if t .Etype == TARRAY {
3197
- // Zero- or single-element array, of any type.
3198
- switch t .NumElem () {
3199
- case 0 :
3200
- n = finishcompare (n , Nodbool (n .Op == OEQ ), init )
3201
- return n
3202
- case 1 :
3203
- l0 := Nod (OINDEX , l , Nodintconst (0 ))
3204
- r0 := Nod (OINDEX , r , Nodintconst (0 ))
3205
- a := Nod (n .Op , l0 , r0 )
3206
- n = finishcompare (n , a , init )
3207
- return n
3195
+ expr = a
3196
+ } else {
3197
+ expr = Nod (andor , expr , a )
3208
3198
}
3209
3199
}
3210
-
3211
- if t .IsStruct () && t .NumFields () <= 4 {
3212
- // Struct of four or fewer fields.
3213
- // Inline comparisons.
3214
- var li * Node
3215
- var ri * Node
3200
+ if t .IsStruct () {
3216
3201
for _ , t1 := range t .Fields ().Slice () {
3217
- if isblanksym (t1 .Sym ) {
3202
+ sym := t1 .Sym
3203
+ if isblanksym (sym ) {
3218
3204
continue
3219
3205
}
3220
- li = NodSym (OXDOT , l , t1 .Sym )
3221
- ri = NodSym (OXDOT , r , t1 .Sym )
3222
- a = Nod (n .Op , li , ri )
3223
- if expr == nil {
3224
- expr = a
3225
- } else {
3226
- expr = Nod (andor , expr , a )
3227
- }
3206
+ compare (NodSym (OXDOT , cmpl , sym ), NodSym (OXDOT , cmpr , sym ))
3228
3207
}
3229
-
3230
- if expr == nil {
3231
- expr = Nodbool (n .Op == OEQ )
3208
+ } else {
3209
+ for i := 0 ; int64 (i ) < t .NumElem (); i ++ {
3210
+ idx := Nodintconst (int64 (i ))
3211
+ compare (Nod (OINDEX , cmpl , idx ), Nod (OINDEX , cmpr , idx ))
3232
3212
}
3233
- n = finishcompare (n , expr , init )
3234
- return n
3235
3213
}
3236
-
3237
- // Chose not to inline. Call equality function directly.
3238
- var needsize int
3239
- call := Nod (OCALL , eqfor (t , & needsize ), nil )
3240
-
3241
- call .List .Append (l )
3242
- call .List .Append (r )
3243
- if needsize != 0 {
3244
- call .List .Append (Nodintconst (t .Width ))
3214
+ if expr == nil {
3215
+ expr = Nodbool (n .Op == OEQ )
3245
3216
}
3246
- r = call
3247
- if n .Op != OEQ {
3248
- r = Nod (ONOT , r , nil )
3249
- }
3250
-
3251
- n = finishcompare (n , r , init )
3217
+ n = finishcompare (n , expr , init )
3252
3218
return n
3253
3219
}
3254
3220
0 commit comments