diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go index dd96bec282..6c56b8d8e5 100644 --- a/src/cmd/compile/internal/gc/asm_test.go +++ b/src/cmd/compile/internal/gc/asm_test.go @@ -1327,6 +1327,22 @@ var linuxARM64Tests = []*asmTest{ `, []string{"\tCLZ\t"}, }, + { + ` + func f34(a uint64) uint64 { + return a & ((1<<63)-1) + } + `, + []string{"\tAND\t"}, + }, + { + ` + func f35(a uint64) uint64 { + return a & (1<<63) + } + `, + []string{"\tAND\t"}, + }, } var linuxMIPSTests = []*asmTest{ diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 8f7680a347..189e739434 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1148,8 +1148,11 @@ ( ORshiftRL [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 -> (RORWconst [ c] x) (XORshiftRL [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 -> (RORWconst [ c] x) -// Replace SRL-of-SLL with ROR-of-SLL to avoid hardware bug. -(SRLconst [c] y:(SLLconst [c] _)) && c <= 8 -> (RORconst [c] y) +// Generic rules rewrite certain AND to a pair of shifts. +// However, on ARM64 the bitmask can fit into an instruction. +// Rewrite it back to AND. +(SRLconst [c] (SLLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [1< (ANDconst [^(1<> uint64(c)) return true } - // match: (SRLconst [c] y:(SLLconst [c] _)) - // cond: c <= 8 - // result: (RORconst [c] y) + // match: (SRLconst [c] (SLLconst [c] x)) + // cond: 0 < c && c < 64 + // result: (ANDconst [1<