]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add zero store operations for riscv64
authorJoel Sing <joel@sing.id.au>
Sun, 1 Mar 2020 17:26:54 +0000 (04:26 +1100)
committerJoel Sing <joel@sing.id.au>
Thu, 5 Mar 2020 11:56:33 +0000 (11:56 +0000)
This allows for zero stores to be performed using the zero register, rather
than loading a separate register with zero.

Change-Id: Ic81d8dbcdacbb2ca2c3f77682ff5ad7cdc33d18d
Reviewed-on: https://go-review.googlesource.com/c/go/+/221684
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/riscv64/ssa.go
src/cmd/compile/internal/ssa/gen/RISCV64.rules
src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteRISCV64.go

index 91f31643360f5b8344e696445073568af8eefb6f..3fece75b1b273b307dc0e6b8d232b29d7bda5cec 100644 (file)
@@ -314,6 +314,13 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p.To.Type = obj.TYPE_MEM
                p.To.Reg = v.Args[0].Reg()
                gc.AddAux(&p.To, v)
+       case ssa.OpRISCV64MOVBstorezero, ssa.OpRISCV64MOVHstorezero, ssa.OpRISCV64MOVWstorezero, ssa.OpRISCV64MOVDstorezero:
+               p := s.Prog(v.Op.Asm())
+               p.From.Type = obj.TYPE_REG
+               p.From.Reg = riscv.REG_ZERO
+               p.To.Type = obj.TYPE_MEM
+               p.To.Reg = v.Args[0].Reg()
+               gc.AddAux(&p.To, v)
        case ssa.OpRISCV64SEQZ, ssa.OpRISCV64SNEZ:
                p := s.Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_REG
index a19f8aa55bb3bc95eec196bbe55ca47bf439ebad..9b88b568718068b73b5e60deea9c126f70ed1f5b 100644 (file)
        (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
 (MOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
        (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVBstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
+       (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
+       (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
+       (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
+       (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 
 (MOVBUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
        (MOVBUload [off1+off2] {sym} base mem)
        (MOVWstore [off1+off2] {sym} base val mem)
 (MOVDstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
        (MOVDstore [off1+off2] {sym} base val mem)
+(MOVBstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBstorezero [off1+off2] {sym} ptr mem)
+(MOVHstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVHstorezero [off1+off2] {sym} ptr mem)
+(MOVWstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWstorezero [off1+off2] {sym} ptr mem)
+(MOVDstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVDstorezero [off1+off2] {sym} ptr mem)
 
 // Similarly, fold ADDI into MOVaddr to avoid confusing live variable analysis
 // with OffPtr -> ADDI.
 // Absorb SNEZ into branch.
 (BNE (SNEZ x) yes no) -> (BNE x yes no)
 
+// Store zero
+(MOVBstore [off] {sym} ptr (MOVBconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVHconst [0]) mem) -> (MOVHstorezero [off] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVWconst [0]) mem) -> (MOVWstorezero [off] {sym} ptr mem)
+(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVDstorezero [off] {sym} ptr mem)
+
 // Fold ADD+MOVDconst into ADDI where possible.
 (ADD (MOVDconst [off]) ptr) && is32Bit(off) -> (ADDI [off] ptr)
 
index 7829f9a07c5dfeb6c19187620e7169d66e144e96..28a91d559f0ae1c8d64b1e8d528898aa9609b117 100644 (file)
@@ -106,12 +106,13 @@ func init() {
        callerSave := gpMask | fpMask | regNamed["g"]
 
        var (
-               gpstore = regInfo{inputs: []regMask{gpspsbMask, gpspMask, 0}} // SB in first input so we can load from a global, but not in second to avoid using SB as a temporary register
-               gp01    = regInfo{outputs: []regMask{gpMask}}
-               gp11    = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}}
-               gp21    = regInfo{inputs: []regMask{gpMask, gpMask}, outputs: []regMask{gpMask}}
-               gpload  = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{gpMask}}
-               gp11sb  = regInfo{inputs: []regMask{gpspsbMask}, outputs: []regMask{gpMask}}
+               gpstore  = regInfo{inputs: []regMask{gpspsbMask, gpspMask, 0}} // SB in first input so we can load from a global, but not in second to avoid using SB as a temporary register
+               gpstore0 = regInfo{inputs: []regMask{gpspsbMask}}
+               gp01     = regInfo{outputs: []regMask{gpMask}}
+               gp11     = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}}
+               gp21     = regInfo{inputs: []regMask{gpMask, gpMask}, outputs: []regMask{gpMask}}
+               gpload   = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{gpMask}}
+               gp11sb   = regInfo{inputs: []regMask{gpspsbMask}, outputs: []regMask{gpMask}}
 
                fp11    = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{fpMask}}
                fp21    = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{fpMask}}
@@ -171,6 +172,12 @@ func init() {
                {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 32 bits
                {name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOV", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},  // 64 bits
 
+               // Stores: store <size> of zero in arg0+auxint+aux; arg1=mem
+               {name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, //  8 bits
+               {name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 16 bits
+               {name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 32 bits
+               {name: "MOVDstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},  // 64 bits
+
                // Shift ops
                {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"},                 // arg0 << aux1
                {name: "SRA", argLength: 2, reg: gp21, asm: "SRA"},                 // arg0 >> aux1, signed
index fb887017cf1eca7e77212b832b01ecf2f22413d0..9da7376a8ac12780ec0645a08659e8596c5aca42 100644 (file)
@@ -1917,6 +1917,10 @@ const (
        OpRISCV64MOVHstore
        OpRISCV64MOVWstore
        OpRISCV64MOVDstore
+       OpRISCV64MOVBstorezero
+       OpRISCV64MOVHstorezero
+       OpRISCV64MOVWstorezero
+       OpRISCV64MOVDstorezero
        OpRISCV64SLL
        OpRISCV64SRA
        OpRISCV64SRL
@@ -25483,6 +25487,58 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:           "MOVBstorezero",
+               auxType:        auxSymOff,
+               argLen:         2,
+               faultOnNilArg0: true,
+               symEffect:      SymWrite,
+               asm:            riscv.AMOVB,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB
+                       },
+               },
+       },
+       {
+               name:           "MOVHstorezero",
+               auxType:        auxSymOff,
+               argLen:         2,
+               faultOnNilArg0: true,
+               symEffect:      SymWrite,
+               asm:            riscv.AMOVH,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB
+                       },
+               },
+       },
+       {
+               name:           "MOVWstorezero",
+               auxType:        auxSymOff,
+               argLen:         2,
+               faultOnNilArg0: true,
+               symEffect:      SymWrite,
+               asm:            riscv.AMOVW,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB
+                       },
+               },
+       },
+       {
+               name:           "MOVDstorezero",
+               auxType:        auxSymOff,
+               argLen:         2,
+               faultOnNilArg0: true,
+               symEffect:      SymWrite,
+               asm:            riscv.AMOV,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB
+                       },
+               },
+       },
        {
                name:   "SLL",
                argLen: 2,
index 6b3f4f70b50454e66468631c91094574891de0d1..676ca52e8ede96effb7ca33fca7ca7d936164a95 100644 (file)
@@ -386,24 +386,32 @@ func rewriteValueRISCV64(v *Value) bool {
                return rewriteValueRISCV64_OpRISCV64MOVBload(v)
        case OpRISCV64MOVBstore:
                return rewriteValueRISCV64_OpRISCV64MOVBstore(v)
+       case OpRISCV64MOVBstorezero:
+               return rewriteValueRISCV64_OpRISCV64MOVBstorezero(v)
        case OpRISCV64MOVDconst:
                return rewriteValueRISCV64_OpRISCV64MOVDconst(v)
        case OpRISCV64MOVDload:
                return rewriteValueRISCV64_OpRISCV64MOVDload(v)
        case OpRISCV64MOVDstore:
                return rewriteValueRISCV64_OpRISCV64MOVDstore(v)
+       case OpRISCV64MOVDstorezero:
+               return rewriteValueRISCV64_OpRISCV64MOVDstorezero(v)
        case OpRISCV64MOVHUload:
                return rewriteValueRISCV64_OpRISCV64MOVHUload(v)
        case OpRISCV64MOVHload:
                return rewriteValueRISCV64_OpRISCV64MOVHload(v)
        case OpRISCV64MOVHstore:
                return rewriteValueRISCV64_OpRISCV64MOVHstore(v)
+       case OpRISCV64MOVHstorezero:
+               return rewriteValueRISCV64_OpRISCV64MOVHstorezero(v)
        case OpRISCV64MOVWUload:
                return rewriteValueRISCV64_OpRISCV64MOVWUload(v)
        case OpRISCV64MOVWload:
                return rewriteValueRISCV64_OpRISCV64MOVWload(v)
        case OpRISCV64MOVWstore:
                return rewriteValueRISCV64_OpRISCV64MOVWstore(v)
+       case OpRISCV64MOVWstorezero:
+               return rewriteValueRISCV64_OpRISCV64MOVWstorezero(v)
        case OpRISCV64SUB:
                return rewriteValueRISCV64_OpRISCV64SUB(v)
        case OpRISCV64SUBW:
@@ -2441,6 +2449,70 @@ func rewriteValueRISCV64_OpRISCV64MOVBstore(v *Value) bool {
                v.AddArg3(base, val, mem)
                return true
        }
+       // match: (MOVBstore [off] {sym} ptr (MOVBconst [0]) mem)
+       // result: (MOVBstorezero [off] {sym} ptr mem)
+       for {
+               off := v.AuxInt
+               sym := v.Aux
+               ptr := v_0
+               if v_1.Op != OpRISCV64MOVBconst || v_1.AuxInt != 0 {
+                       break
+               }
+               mem := v_2
+               v.reset(OpRISCV64MOVBstorezero)
+               v.AuxInt = off
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool {
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (MOVBstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+       // cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
+       // result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym1 := v.Aux
+               if v_0.Op != OpRISCV64MOVaddr {
+                       break
+               }
+               off2 := v_0.AuxInt
+               sym2 := v_0.Aux
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVBstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = mergeSym(sym1, sym2)
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       // match: (MOVBstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+       // cond: is32Bit(off1+off2)
+       // result: (MOVBstorezero [off1+off2] {sym} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym := v.Aux
+               if v_0.Op != OpRISCV64ADDI {
+                       break
+               }
+               off2 := v_0.AuxInt
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(is32Bit(off1 + off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVBstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
        return false
 }
 func rewriteValueRISCV64_OpRISCV64MOVDconst(v *Value) bool {
@@ -2585,6 +2657,70 @@ func rewriteValueRISCV64_OpRISCV64MOVDstore(v *Value) bool {
                v.AddArg3(base, val, mem)
                return true
        }
+       // match: (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem)
+       // result: (MOVDstorezero [off] {sym} ptr mem)
+       for {
+               off := v.AuxInt
+               sym := v.Aux
+               ptr := v_0
+               if v_1.Op != OpRISCV64MOVDconst || v_1.AuxInt != 0 {
+                       break
+               }
+               mem := v_2
+               v.reset(OpRISCV64MOVDstorezero)
+               v.AuxInt = off
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVDstorezero(v *Value) bool {
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (MOVDstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+       // cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
+       // result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym1 := v.Aux
+               if v_0.Op != OpRISCV64MOVaddr {
+                       break
+               }
+               off2 := v_0.AuxInt
+               sym2 := v_0.Aux
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVDstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = mergeSym(sym1, sym2)
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       // match: (MOVDstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+       // cond: is32Bit(off1+off2)
+       // result: (MOVDstorezero [off1+off2] {sym} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym := v.Aux
+               if v_0.Op != OpRISCV64ADDI {
+                       break
+               }
+               off2 := v_0.AuxInt
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(is32Bit(off1 + off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVDstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
        return false
 }
 func rewriteValueRISCV64_OpRISCV64MOVHUload(v *Value) bool {
@@ -2732,6 +2868,70 @@ func rewriteValueRISCV64_OpRISCV64MOVHstore(v *Value) bool {
                v.AddArg3(base, val, mem)
                return true
        }
+       // match: (MOVHstore [off] {sym} ptr (MOVHconst [0]) mem)
+       // result: (MOVHstorezero [off] {sym} ptr mem)
+       for {
+               off := v.AuxInt
+               sym := v.Aux
+               ptr := v_0
+               if v_1.Op != OpRISCV64MOVHconst || v_1.AuxInt != 0 {
+                       break
+               }
+               mem := v_2
+               v.reset(OpRISCV64MOVHstorezero)
+               v.AuxInt = off
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVHstorezero(v *Value) bool {
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (MOVHstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+       // cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
+       // result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym1 := v.Aux
+               if v_0.Op != OpRISCV64MOVaddr {
+                       break
+               }
+               off2 := v_0.AuxInt
+               sym2 := v_0.Aux
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVHstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = mergeSym(sym1, sym2)
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       // match: (MOVHstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+       // cond: is32Bit(off1+off2)
+       // result: (MOVHstorezero [off1+off2] {sym} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym := v.Aux
+               if v_0.Op != OpRISCV64ADDI {
+                       break
+               }
+               off2 := v_0.AuxInt
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(is32Bit(off1 + off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVHstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
        return false
 }
 func rewriteValueRISCV64_OpRISCV64MOVWUload(v *Value) bool {
@@ -2879,6 +3079,70 @@ func rewriteValueRISCV64_OpRISCV64MOVWstore(v *Value) bool {
                v.AddArg3(base, val, mem)
                return true
        }
+       // match: (MOVWstore [off] {sym} ptr (MOVWconst [0]) mem)
+       // result: (MOVWstorezero [off] {sym} ptr mem)
+       for {
+               off := v.AuxInt
+               sym := v.Aux
+               ptr := v_0
+               if v_1.Op != OpRISCV64MOVWconst || v_1.AuxInt != 0 {
+                       break
+               }
+               mem := v_2
+               v.reset(OpRISCV64MOVWstorezero)
+               v.AuxInt = off
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVWstorezero(v *Value) bool {
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (MOVWstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+       // cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
+       // result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym1 := v.Aux
+               if v_0.Op != OpRISCV64MOVaddr {
+                       break
+               }
+               off2 := v_0.AuxInt
+               sym2 := v_0.Aux
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVWstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = mergeSym(sym1, sym2)
+               v.AddArg2(ptr, mem)
+               return true
+       }
+       // match: (MOVWstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+       // cond: is32Bit(off1+off2)
+       // result: (MOVWstorezero [off1+off2] {sym} ptr mem)
+       for {
+               off1 := v.AuxInt
+               sym := v.Aux
+               if v_0.Op != OpRISCV64ADDI {
+                       break
+               }
+               off2 := v_0.AuxInt
+               ptr := v_0.Args[0]
+               mem := v_1
+               if !(is32Bit(off1 + off2)) {
+                       break
+               }
+               v.reset(OpRISCV64MOVWstorezero)
+               v.AuxInt = off1 + off2
+               v.Aux = sym
+               v.AddArg2(ptr, mem)
+               return true
+       }
        return false
 }
 func rewriteValueRISCV64_OpRISCV64SUB(v *Value) bool {