@@ -174,29 +174,48 @@ x mod m + y = r + y
174174We want K to understand what a bit-shift is.
175175
176176``` k
177+ // According to domains.md, shifting by negative amounts is #False, so
178+ // all simplification rules must take that into account.
179+
177180 rule (_X <<Int N) modInt M => 0
178- requires (2 ^Int N) modInt M ==Int 0
181+ requires 0 <=Int N andBool (2 ^Int N) modInt M ==Int 0
179182 [simplification]
180183
181184 rule #wrap(M, _X <<Int N) => 0
182- requires (M *Int 8) <=Int N
185+ requires 0 <=Int N andBool (M *Int 8) <=Int N
183186 [simplification]
184187
185- rule (X >>Int N) => 0 requires X <Int 2 ^Int N [simplification]
186- rule (_X <<Int N) modInt M => 0 requires M <Int 2 ^Int N [simplification]
188+ rule (X >>Int N) => 0
189+ requires 0 <=Int N
190+ andBool X <Int 2 ^Int N
191+ [simplification]
192+ rule (_X <<Int N) modInt M => 0
193+ requires 0 <=Int N
194+ andBool M <Int 2 ^Int N
195+ [simplification]
187196
188- rule (X >>Int N) >>Int M => X >>Int (N +Int M) [simplification]
189- rule (X <<Int N) <<Int M => X <<Int (N +Int M) [simplification]
197+ rule (X >>Int N) >>Int M => X >>Int (N +Int M)
198+ requires 0 <=Int N andBool 0 <=Int M
199+ [simplification]
200+ rule (X <<Int N) <<Int M => X <<Int (N +Int M)
201+ requires 0 <=Int N andBool 0 <=Int M
202+ [simplification]
190203
191- // The Haskell backend accepts negative shifts (the LLVM backend does not).
192- // So removing the side conditions and keeping one of each rule here could give faster symbolic execution.
193- rule (X <<Int N) >>Int M => X <<Int (N -Int M) requires N >=Int M [simplification]
194- rule (X <<Int N) >>Int M => X >>Int (M -Int N) requires notBool (N >=Int M) [simplification]
204+ rule (X <<Int N) >>Int M => X <<Int (N -Int M)
205+ requires 0 <=Int M andBool M <=Int N
206+ [simplification]
207+ rule (X <<Int N) >>Int M => X >>Int (M -Int N)
208+ requires 0 <=Int N andBool notBool (N >=Int M)
209+ [simplification]
195210```
196211
197212``` k
198- rule ((X <<Int M) +Int Y) >>Int N => (X <<Int (M -Int N)) +Int (Y >>Int N) requires M >=Int N [simplification]
199- rule (Y +Int (X <<Int M)) >>Int N => (X <<Int (M -Int N)) +Int (Y >>Int N) requires M >=Int N [simplification]
213+ rule ((X <<Int M) +Int Y) >>Int N => (X <<Int (M -Int N)) +Int (Y >>Int N)
214+ requires M >=Int N andBool N >=Int 0
215+ [simplification]
216+ rule (Y +Int (X <<Int M)) >>Int N => (X <<Int (M -Int N)) +Int (Y >>Int N)
217+ requires M >=Int N andBool N >=Int 0
218+ [simplification]
200219```
201220
202221Proof:
@@ -291,10 +310,13 @@ Bounds on `#getRange`:
291310 rule 0 <=Int VAL1 +Int VAL2 => true requires 0 <=Int VAL1 andBool 0 <=Int VAL2 [simplification]
292311
293312 rule #getRange(_, _, WIDTH) <Int MAX => true requires 2 ^Int (8 *Int WIDTH) <=Int MAX [simplification]
294- rule #getRange(_, _, WIDTH) <<Int SHIFT <Int MAX => true requires 2 ^Int ((8 *Int WIDTH) +Int SHIFT) <=Int MAX [simplification]
313+ rule #getRange(_, _, WIDTH) <<Int SHIFT <Int MAX => true requires 2 ^Int ((8 *Int WIDTH) +Int SHIFT) <=Int MAX
314+ requires 0 <=Int SHIFT
315+ [simplification]
295316 rule (#getRange(_, _, WIDTH1) #as VAL1) +Int ((#getRange(_, _, WIDTH2) <<Int SHIFT) #as VAL2) <Int MAX => true
296317 requires VAL1 <Int MAX
297318 andBool VAL2 <Int MAX
319+ andBool 0 <=Int SHIFT
298320 andBool WIDTH1 *Int 8 <=Int SHIFT
299321 andBool 2 ^Int ((8 *Int WIDTH2) +Int SHIFT) <=Int MAX
300322 [simplification]
@@ -344,6 +366,7 @@ Arithmetic over `#getRange`:
344366 rule #setRange(BM, ADDR, (#getRange(_, _, WIDTH1) #as VAL1) +Int (VAL2 <<Int SHIFT), WIDTH)
345367 => #setRange(#setRange(BM, ADDR, VAL1, minInt(WIDTH1, WIDTH)), ADDR +Int WIDTH1, VAL2, WIDTH -Int WIDTH1)
346368 requires 0 <=Int ADDR
369+ andBool 0 <=Int SHIFT
347370 andBool 0 <Int WIDTH
348371 andBool WIDTH1 *Int 8 ==Int SHIFT
349372 [simplification]
0 commit comments