From 2d8829d7f4daeaa46ca4286ba7a81f483e2c2c28 Mon Sep 17 00:00:00 2001 From: Qiuweihong <953950914@qq.com> Date: Tue, 19 May 2026 13:50:07 +0800 Subject: [PATCH] cmd/compile/internal: add intrinsic for sync atomic and/or 32/64 on riscv --- src/cmd/compile/internal/riscv64/ssa.go | 9 +++ .../compile/internal/ssa/_gen/RISCV64.rules | 5 ++ .../compile/internal/ssa/_gen/RISCV64Ops.go | 6 ++ src/cmd/compile/internal/ssa/opGen.go | 72 +++++++++++++++++++ .../compile/internal/ssa/rewriteRISCV64.go | 12 ++++ src/cmd/compile/internal/ssagen/intrinsics.go | 28 ++++---- .../internal/ssagen/intrinsics_test.go | 14 ++++ test/codegen/atomics.go | 9 +++ 8 files changed, 141 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index b34256c1766230..4ce97b847eec33 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -750,6 +750,15 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Args[0].Reg() p.RegTo2 = riscv.REG_ZERO + case ssa.OpRISCV64LoweredAtomicAnd32value, ssa.OpRISCV64LoweredAtomicAnd64value, + ssa.OpRISCV64LoweredAtomicOr32value, ssa.OpRISCV64LoweredAtomicOr64value: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = v.Args[1].Reg() + p.To.Type = obj.TYPE_MEM + p.To.Reg = v.Args[0].Reg() + p.RegTo2 = v.Reg0() + case ssa.OpRISCV64LoweredZero: ptr := v.Args[0].Reg() sc := v.AuxValAndOff() diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules index ed7e142d0881bb..de90b5791ab38c 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules @@ -495,6 +495,11 @@ (AtomicAnd32 ...) => (LoweredAtomicAnd32 ...) +(AtomicAnd32value ...) => (LoweredAtomicAnd32value ...) +(AtomicAnd64value ...) => (LoweredAtomicAnd64value ...) +(AtomicOr32value ...) => (LoweredAtomicOr32value ...) +(AtomicOr64value ...) => (LoweredAtomicOr64value ...) + (AtomicCompareAndSwap32 ptr old new mem) => (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) (AtomicCompareAndSwap64 ...) => (LoweredAtomicCas64 ...) diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go index 08ed0703788fc3..15108afcafcfec 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go @@ -420,6 +420,12 @@ func init() { {name: "LoweredAtomicAnd32", argLength: 3, reg: gpatomic, asm: "AMOANDW", faultOnNilArg0: true, hasSideEffects: true}, {name: "LoweredAtomicOr32", argLength: 3, reg: gpatomic, asm: "AMOORW", faultOnNilArg0: true, hasSideEffects: true}, + // Atomic 32/64 bit AND/OR that return the old value. + {name: "LoweredAtomicAnd32value", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AMOANDW", faultOnNilArg0: true, hasSideEffects: true}, + {name: "LoweredAtomicAnd64value", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AMOANDD", faultOnNilArg0: true, hasSideEffects: true}, + {name: "LoweredAtomicOr32value", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AMOORW", faultOnNilArg0: true, hasSideEffects: true}, + {name: "LoweredAtomicOr64value", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AMOORD", faultOnNilArg0: true, hasSideEffects: true}, + // Lowering pass-throughs {name: "LoweredNilCheck", argLength: 2, faultOnNilArg0: true, nilCheck: true, reg: regInfo{inputs: []regMask{gpspMask}}}, // arg0=ptr,arg1=mem, returns void. Faults if ptr is nil. {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{regCtxt}}}, // scheduler ensures only at beginning of entry block diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 40574e2a2df18e..eded8bf49ef782 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -5317,6 +5317,10 @@ const ( OpRISCV64LoweredAtomicCas64 OpRISCV64LoweredAtomicAnd32 OpRISCV64LoweredAtomicOr32 + OpRISCV64LoweredAtomicAnd32value + OpRISCV64LoweredAtomicAnd64value + OpRISCV64LoweredAtomicOr32value + OpRISCV64LoweredAtomicOr64value OpRISCV64LoweredNilCheck OpRISCV64LoweredGetClosurePtr OpRISCV64LoweredGetCallerSP @@ -80979,6 +80983,74 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "LoweredAtomicAnd32value", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + asm: riscv.AAMOANDW, + reg: regInfo{ + inputs: []inputInfo{ + {1, regMask{v1: 1073741808, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, regMask{v1: 9223372037928517618, v2: 0}}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + }, + outputs: []outputInfo{ + {0, regMask{v1: 1006632944, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, + { + name: "LoweredAtomicAnd64value", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + asm: riscv.AAMOANDD, + reg: regInfo{ + inputs: []inputInfo{ + {1, regMask{v1: 1073741808, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, regMask{v1: 9223372037928517618, v2: 0}}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + }, + outputs: []outputInfo{ + {0, regMask{v1: 1006632944, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, + { + name: "LoweredAtomicOr32value", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + asm: riscv.AAMOORW, + reg: regInfo{ + inputs: []inputInfo{ + {1, regMask{v1: 1073741808, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, regMask{v1: 9223372037928517618, v2: 0}}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + }, + outputs: []outputInfo{ + {0, regMask{v1: 1006632944, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, + { + name: "LoweredAtomicOr64value", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + asm: riscv.AAMOORD, + reg: regInfo{ + inputs: []inputInfo{ + {1, regMask{v1: 1073741808, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, regMask{v1: 9223372037928517618, v2: 0}}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + }, + outputs: []outputInfo{ + {0, regMask{v1: 1006632944, v2: 0}}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, { name: "LoweredNilCheck", argLen: 2, diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 43df9db6bc8445..b42c694a30d338 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -59,6 +59,12 @@ func rewriteValueRISCV64(v *Value) bool { case OpAtomicAnd32: v.Op = OpRISCV64LoweredAtomicAnd32 return true + case OpAtomicAnd32value: + v.Op = OpRISCV64LoweredAtomicAnd32value + return true + case OpAtomicAnd64value: + v.Op = OpRISCV64LoweredAtomicAnd64value + return true case OpAtomicAnd8: return rewriteValueRISCV64_OpAtomicAnd8(v) case OpAtomicCompareAndSwap32: @@ -87,6 +93,12 @@ func rewriteValueRISCV64(v *Value) bool { case OpAtomicOr32: v.Op = OpRISCV64LoweredAtomicOr32 return true + case OpAtomicOr32value: + v.Op = OpRISCV64LoweredAtomicOr32value + return true + case OpAtomicOr64value: + v.Op = OpRISCV64LoweredAtomicOr64value + return true case OpAtomicOr8: return rewriteValueRISCV64_OpAtomicOr8(v) case OpAtomicStore32: diff --git a/src/cmd/compile/internal/ssagen/intrinsics.go b/src/cmd/compile/internal/ssagen/intrinsics.go index d708bcac18a711..23cee2fcb27804 100644 --- a/src/cmd/compile/internal/ssagen/intrinsics.go +++ b/src/cmd/compile/internal/ssagen/intrinsics.go @@ -662,7 +662,7 @@ func initIntrinsics(cfg *intrinsicBuildConfig) { s.vars[memVar] = p1 return p0 }, - sys.AMD64, sys.Loong64) + sys.AMD64, sys.Loong64, sys.RISCV64) addF("internal/runtime/atomic", "And32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { v := s.newValue3(ssa.OpAtomicAnd32value, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], args[1], s.mem()) @@ -670,7 +670,7 @@ func initIntrinsics(cfg *intrinsicBuildConfig) { s.vars[memVar] = p1 return p0 }, - sys.AMD64, sys.Loong64) + sys.AMD64, sys.Loong64, sys.RISCV64) addF("internal/runtime/atomic", "Or64", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { v := s.newValue3(ssa.OpAtomicOr64value, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], args[1], s.mem()) @@ -678,7 +678,7 @@ func initIntrinsics(cfg *intrinsicBuildConfig) { s.vars[memVar] = p1 return p0 }, - sys.AMD64, sys.Loong64) + sys.AMD64, sys.Loong64, sys.RISCV64) addF("internal/runtime/atomic", "Or32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { v := s.newValue3(ssa.OpAtomicOr32value, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], args[1], s.mem()) @@ -686,7 +686,7 @@ func initIntrinsics(cfg *intrinsicBuildConfig) { s.vars[memVar] = p1 return p0 }, - sys.AMD64, sys.Loong64) + sys.AMD64, sys.Loong64, sys.RISCV64) // Aliases for atomic load operations alias("internal/runtime/atomic", "Loadint32", "internal/runtime/atomic", "Load", all...) @@ -1333,16 +1333,16 @@ func initIntrinsics(cfg *intrinsicBuildConfig) { alias("sync/atomic", "AddUintptr", "internal/runtime/atomic", "Xadd", p4...) alias("sync/atomic", "AddUintptr", "internal/runtime/atomic", "Xadd64", p8...) - alias("sync/atomic", "AndInt32", "internal/runtime/atomic", "And32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "AndUint32", "internal/runtime/atomic", "And32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "AndInt64", "internal/runtime/atomic", "And64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "AndUint64", "internal/runtime/atomic", "And64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "AndUintptr", "internal/runtime/atomic", "And64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "OrInt32", "internal/runtime/atomic", "Or32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "OrUint32", "internal/runtime/atomic", "Or32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "OrInt64", "internal/runtime/atomic", "Or64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "OrUint64", "internal/runtime/atomic", "Or64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) - alias("sync/atomic", "OrUintptr", "internal/runtime/atomic", "Or64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64) + alias("sync/atomic", "AndInt32", "internal/runtime/atomic", "And32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "AndUint32", "internal/runtime/atomic", "And32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "AndInt64", "internal/runtime/atomic", "And64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "AndUint64", "internal/runtime/atomic", "And64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "AndUintptr", "internal/runtime/atomic", "And64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "OrInt32", "internal/runtime/atomic", "Or32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "OrUint32", "internal/runtime/atomic", "Or32", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "OrInt64", "internal/runtime/atomic", "Or64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "OrUint64", "internal/runtime/atomic", "Or64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) + alias("sync/atomic", "OrUintptr", "internal/runtime/atomic", "Or64", sys.ArchARM64, sys.ArchAMD64, sys.ArchLoong64, sys.ArchRISCV64) /******** math/big ********/ alias("math/big", "mulWW", "math/bits", "Mul64", p8...) diff --git a/src/cmd/compile/internal/ssagen/intrinsics_test.go b/src/cmd/compile/internal/ssagen/intrinsics_test.go index 0fe0525ce1a3fc..3de8b07a6e65cb 100644 --- a/src/cmd/compile/internal/ssagen/intrinsics_test.go +++ b/src/cmd/compile/internal/ssagen/intrinsics_test.go @@ -1072,6 +1072,8 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"ppc64le", "crypto/internal/constanttime", "Select"}: struct{}{}, {"ppc64le", "crypto/internal/constanttime", "boolToUint8"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "And"}: struct{}{}, + {"riscv64", "internal/runtime/atomic", "And32"}: struct{}{}, + {"riscv64", "internal/runtime/atomic", "And64"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "And8"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "Cas"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "Cas64"}: struct{}{}, @@ -1092,6 +1094,8 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"riscv64", "internal/runtime/atomic", "Loaduint"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "Loaduintptr"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "Or"}: struct{}{}, + {"riscv64", "internal/runtime/atomic", "Or32"}: struct{}{}, + {"riscv64", "internal/runtime/atomic", "Or64"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "Or8"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "Store"}: struct{}{}, {"riscv64", "internal/runtime/atomic", "Store64"}: struct{}{}, @@ -1167,6 +1171,11 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"riscv64", "sync/atomic", "AddUint32"}: struct{}{}, {"riscv64", "sync/atomic", "AddUint64"}: struct{}{}, {"riscv64", "sync/atomic", "AddUintptr"}: struct{}{}, + {"riscv64", "sync/atomic", "AndInt32"}: struct{}{}, + {"riscv64", "sync/atomic", "AndInt64"}: struct{}{}, + {"riscv64", "sync/atomic", "AndUint32"}: struct{}{}, + {"riscv64", "sync/atomic", "AndUint64"}: struct{}{}, + {"riscv64", "sync/atomic", "AndUintptr"}: struct{}{}, {"riscv64", "sync/atomic", "CompareAndSwapInt32"}: struct{}{}, {"riscv64", "sync/atomic", "CompareAndSwapInt64"}: struct{}{}, {"riscv64", "sync/atomic", "CompareAndSwapUint32"}: struct{}{}, @@ -1178,6 +1187,11 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"riscv64", "sync/atomic", "LoadUint32"}: struct{}{}, {"riscv64", "sync/atomic", "LoadUint64"}: struct{}{}, {"riscv64", "sync/atomic", "LoadUintptr"}: struct{}{}, + {"riscv64", "sync/atomic", "OrInt32"}: struct{}{}, + {"riscv64", "sync/atomic", "OrInt64"}: struct{}{}, + {"riscv64", "sync/atomic", "OrUint32"}: struct{}{}, + {"riscv64", "sync/atomic", "OrUint64"}: struct{}{}, + {"riscv64", "sync/atomic", "OrUintptr"}: struct{}{}, {"riscv64", "sync/atomic", "StoreInt32"}: struct{}{}, {"riscv64", "sync/atomic", "StoreInt64"}: struct{}{}, {"riscv64", "sync/atomic", "StoreUint32"}: struct{}{}, diff --git a/test/codegen/atomics.go b/test/codegen/atomics.go index 7ae5a9aff71995..ccd69bf40139df 100644 --- a/test/codegen/atomics.go +++ b/test/codegen/atomics.go @@ -23,6 +23,7 @@ func (c *Counter) Increment() { // arm64/v8.0:".*arm64HasATOMICS" // arm64/v8.1:-".*arm64HasATOMICS" // amd64:"LOCK" -"CMPXCHG" + // riscv64:"AMOADDW" -"JAL" atomic.AddInt32(&c.count, 1) } @@ -35,12 +36,14 @@ func atomicLogical64(x *atomic.Uint64) uint64 { // arm64/v8.1:-".*arm64HasATOMICS" // On amd64, make sure we use LOCK+AND instead of CMPXCHG when we don't use the result. // amd64:"LOCK" -"CMPXCHGQ" + // riscv64:"AMOANDD" -"JAL" x.And(11) // arm64/v8.0:"LDCLRALD" // arm64/v8.1:"LDCLRALD" // arm64/v8.0:".*arm64HasATOMICS" // arm64/v8.1:-".*arm64HasATOMICS" // amd64:"LOCK" "CMPXCHGQ" + // riscv64:"AMOANDD" -"JAL" r += x.And(22) // arm64/v8.0:"LDORALD" @@ -49,12 +52,14 @@ func atomicLogical64(x *atomic.Uint64) uint64 { // arm64/v8.1:-".*arm64HasATOMICS" // On amd64, make sure we use LOCK+OR instead of CMPXCHG when we don't use the result. // amd64:"LOCK" -"CMPXCHGQ" + // riscv64:"AMOORD" -"JAL" x.Or(33) // arm64/v8.0:"LDORALD" // arm64/v8.1:"LDORALD" // arm64/v8.0:".*arm64HasATOMICS" // arm64/v8.1:-".*arm64HasATOMICS" // amd64:"LOCK" "CMPXCHGQ" + // riscv64:"AMOORD" -"JAL" r += x.Or(44) return r @@ -69,12 +74,14 @@ func atomicLogical32(x *atomic.Uint32) uint32 { // arm64/v8.1:-".*arm64HasATOMICS" // On amd64, make sure we use LOCK+AND instead of CMPXCHG when we don't use the result. // amd64:"LOCK" -"CMPXCHGL" + // riscv64:"AMOANDW" -"JAL" x.And(11) // arm64/v8.0:"LDCLRALW" // arm64/v8.1:"LDCLRALW" // arm64/v8.0:".*arm64HasATOMICS" // arm64/v8.1:-".*arm64HasATOMICS" // amd64:"LOCK" "CMPXCHGL" + // riscv64:"AMOANDW" -"JAL" r += x.And(22) // arm64/v8.0:"LDORALW" @@ -83,12 +90,14 @@ func atomicLogical32(x *atomic.Uint32) uint32 { // arm64/v8.1:-".*arm64HasATOMICS" // On amd64, make sure we use LOCK+OR instead of CMPXCHG when we don't use the result. // amd64:"LOCK" -"CMPXCHGL" + // riscv64:"AMOORW" -"JAL" x.Or(33) // arm64/v8.0:"LDORALW" // arm64/v8.1:"LDORALW" // arm64/v8.0:".*arm64HasATOMICS" // arm64/v8.1:-".*arm64HasATOMICS" // amd64:"LOCK" "CMPXCHGL" + // riscv64:"AMOORW" -"JAL" r += x.Or(44) return r