Skip to content

Commit eb50231

Browse files
committed
volatile flag for store/load
1 parent e4aa996 commit eb50231

4 files changed

Lines changed: 84 additions & 56 deletions

File tree

docs/source/user-guide/ir/ir-builder.rst

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,26 +459,44 @@ Memory
459459
*typ*. If *size* is not given, a stack slot for 1 value is
460460
allocated.
461461

462-
* .. method:: IRBuilder.load(ptr, name='', align=None)
462+
* .. method:: IRBuilder.load(ptr, name='', align=None, atomic_ordering=None, volatile=False)
463463

464464
Load value from pointer *ptr*. If *align* is passed, it should
465465
be a Python integer specifying the guaranteed pointer
466466
alignment.
467+
468+
If *volatile* is truthy, the load is marked as volatile.
467469

468-
* .. method:: IRBuilder.store(value, ptr, align=None)
470+
If *atomic_ordering* and *align* are specified, the load is marked as
471+
atomic.
472+
473+
* .. method:: IRBuilder.store(value, ptr, align=None, atomic_ordering=None, volatile=False)
469474

470475
Store *value* to pointer *ptr*. If *align* is passed, it should
471476
be a Python integer specifying the guaranteed pointer
472477
alignment.
478+
479+
If *volatile* is truthy, the load is marked as volatile.
480+
481+
If *atomic_ordering* and *align* are specified, the load is marked as
482+
atomic.
473483

474484
* .. method:: IRBuilder.load_atomic(ptr, ordering, align, name='')
475485

486+
.. deprecated:: 0.33.0
487+
488+
Use :func:`IRBuilder.load` with parameter `atomic_ordering` instead.
489+
476490
Load value from pointer *ptr* as an atomic operation with the given
477491
*ordering*. *align* must be a Python integer specifying the guaranteed
478492
pointer alignment.
479493

480494
* .. method:: IRBuilder.store_atomic(value, ptr, ordering, align)
481495

496+
.. deprecated:: 0.33.0
497+
498+
Use :func:`IRBuilder.store` with parameter `atomic_ordering` instead.
499+
482500
Store *value* to pointer *ptr* as an atomic operation with the given
483501
*ordering*. *align* must be a Python integer specifying the guaranteed
484502
pointer alignment.

llvmlite/ir/builder.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -724,19 +724,22 @@ def alloca(self, typ, size=None, name=''):
724724
self._insert(al)
725725
return al
726726

727-
def load(self, ptr, name='', align=None, atomic_ordering=None):
727+
def load(self, ptr, name='', align=None, atomic_ordering=None,
728+
volatile=False):
728729
"""
729730
Load value from pointer, with optional guaranteed alignment:
730731
name = *ptr
731732
"""
732733
if not isinstance(ptr.type, types.PointerType):
733734
msg = "cannot load from value of type %s (%r): not a pointer"
734735
raise TypeError(msg % (ptr.type, str(ptr)))
735-
ld = instructions.LoadInstr(self.block, ptr, name, align, atomic_ordering)
736+
ld = instructions.LoadInstr(self.block, ptr, name, align,
737+
atomic_ordering, volatile)
736738
self._insert(ld)
737739
return ld
738740

739-
def store(self, value, ptr, align=None, atomic_ordering=None):
741+
def store(self, value, ptr, align=None, atomic_ordering=None,
742+
volatile=False):
740743
"""
741744
Store value to pointer, with optional guaranteed alignment:
742745
*ptr = name
@@ -747,7 +750,8 @@ def store(self, value, ptr, align=None, atomic_ordering=None):
747750
if ptr.type.pointee != value.type:
748751
raise TypeError("cannot store %s to %s: mismatching types"
749752
% (value.type, ptr.type))
750-
st = instructions.StoreInstr(self.block, value, ptr, align, atomic_ordering)
753+
st = instructions.StoreInstr(self.block, value, ptr, align,
754+
atomic_ordering, volatile)
751755
self._insert(st)
752756
return st
753757

llvmlite/ir/instructions.py

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -390,75 +390,65 @@ def descr(self, buf):
390390

391391

392392
class LoadInstr(Instruction):
393-
def __init__(self, parent, ptr, name='', align=None, atomic_ordering=None):
393+
def __init__(self, parent, ptr, name='', align=None, atomic_ordering=None,
394+
volatile=False):
394395
if atomic_ordering is not None and align is None:
395396
msg = "atomic load requires the align paramter to be specified"
396397
raise ValueError(msg)
397398
super(LoadInstr, self).__init__(parent, ptr.type.pointee, "load",
398399
[ptr], name=name)
399400
self.align = align
400401
self.atomic_ordering = atomic_ordering
402+
self.volatile = volatile
401403

402404
def descr(self, buf):
403405
[val] = self.operands
404-
if self.atomic_ordering is None:
405-
if self.align is not None:
406-
align = ', align %d' % (self.align)
407-
else:
408-
align = ''
409-
buf.append("load {0}, {1} {2}{3}{4}\n".format(
410-
val.type.pointee,
411-
val.type,
412-
val.get_reference(),
413-
align,
414-
self._stringify_metadata(leading_comma=True),
415-
))
416-
else:
417-
buf.append("load atomic {0}, {1} {2} {3}, align {4}{5}\n".format(
418-
val.type.pointee,
419-
val.type,
420-
val.get_reference(),
421-
self.atomic_ordering,
422-
self.align,
423-
self._stringify_metadata(leading_comma=True),
424-
))
406+
407+
flags = []
408+
if self.atomic_ordering is not None:
409+
flags.append('atomic')
410+
if self.volatile:
411+
flags.append('volatile')
412+
413+
opname = ' '.join(['load'] + flags)
414+
ordering = ('' if self.atomic_ordering is None
415+
else f' {self.atomic_ordering}')
416+
align = '' if self.align is None else f', align {self.align}'
417+
metadata = self._stringify_metadata(leading_comma=True)
418+
419+
buf.append(f"{opname} {val.type.pointee}, {val.type} "
420+
f"{val.get_reference()}{ordering}{align}{metadata}\n")
425421

426422

427423
class StoreInstr(Instruction):
428-
def __init__(self, parent, val, ptr, align=None, atomic_ordering=None):
424+
def __init__(self, parent, val, ptr, align=None, atomic_ordering=None,
425+
volatile=False):
429426
if atomic_ordering is not None and align is None:
430427
msg = "atomic store requires the align paramter to be specified"
431428
raise ValueError(msg)
432429
super(StoreInstr, self).__init__(parent, types.VoidType(), "store",
433430
[val, ptr])
434431
self.align = align
435432
self.atomic_ordering = atomic_ordering
433+
self.volatile = volatile
436434

437435
def descr(self, buf):
438436
val, ptr = self.operands
439-
if self.atomic_ordering is None:
440-
if self.align is not None:
441-
align = ', align %d' % (self.align)
442-
else:
443-
align = ''
444-
buf.append("store {0} {1}, {2} {3}{4}{5}\n".format(
445-
val.type,
446-
val.get_reference(),
447-
ptr.type,
448-
ptr.get_reference(),
449-
align,
450-
self._stringify_metadata(leading_comma=True),
451-
))
452-
else:
453-
buf.append("store atomic {0} {1}, {2} {3} {4}, align {5}{6}\n".format(
454-
val.type,
455-
val.get_reference(),
456-
ptr.type,
457-
ptr.get_reference(),
458-
self.atomic_ordering,
459-
self.align,
460-
self._stringify_metadata(leading_comma=True),
461-
))
437+
438+
flags = []
439+
if self.atomic_ordering is not None:
440+
flags.append('atomic')
441+
if self.volatile:
442+
flags.append('volatile')
443+
444+
opname = ' '.join(['store'] + flags)
445+
ordering = ('' if self.atomic_ordering is None
446+
else f' {self.atomic_ordering}')
447+
align = '' if self.align is None else f', align {self.align}'
448+
metadata = self._stringify_metadata(leading_comma=True)
449+
450+
buf.append(f"{opname} {val.type} {val.get_reference()}, {ptr.type} "
451+
f"{ptr.get_reference()}{ordering}{align}{metadata}\n")
462452

463453

464454
class LoadAtomicInstr(LoadInstr):

llvmlite/tests/test_ir.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -805,11 +805,23 @@ def test_mem_ops(self):
805805
self.assertEqual(h.type, ir.VoidType())
806806
i = builder.load(c, 'i', align=1)
807807
self.assertEqual(i.type, int32)
808-
# Atomics
809-
j = builder.store_atomic(b, c, ordering="seq_cst", align=4)
808+
# Volatile
809+
j = builder.store(b, c, align=1, volatile=True)
810810
self.assertEqual(j.type, ir.VoidType())
811-
k = builder.load_atomic(c, ordering="seq_cst", align=4, name='k')
811+
k = builder.load(c, 'k', align=1, volatile=True)
812812
self.assertEqual(k.type, int32)
813+
# Atomics
814+
l = builder.store(b, c, atomic_ordering="seq_cst", align=4)
815+
self.assertEqual(l.type, ir.VoidType())
816+
m = builder.load(c, atomic_ordering="seq_cst", align=4, name='m')
817+
self.assertEqual(m.type, int32)
818+
# Atomics Volatile
819+
o = builder.store(b, c, atomic_ordering="seq_cst",
820+
align=4, volatile=True)
821+
self.assertEqual(o.type, ir.VoidType())
822+
p = builder.load(c, atomic_ordering="seq_cst",
823+
align=4, name='p', volatile=True)
824+
self.assertEqual(p.type, int32)
813825
# Not pointer types
814826
with self.assertRaises(TypeError):
815827
builder.store(b, a)
@@ -830,8 +842,12 @@ def test_mem_ops(self):
830842
%"g" = load i32, i32* %"c"
831843
store i32 %".2", i32* %"c", align 1
832844
%"i" = load i32, i32* %"c", align 1
845+
store volatile i32 %".2", i32* %"c", align 1
846+
%"k" = load volatile i32, i32* %"c", align 1
833847
store atomic i32 %".2", i32* %"c" seq_cst, align 4
834-
%"k" = load atomic i32, i32* %"c" seq_cst, align 4
848+
%"m" = load atomic i32, i32* %"c" seq_cst, align 4
849+
store atomic volatile i32 %".2", i32* %"c" seq_cst, align 4
850+
%"p" = load atomic volatile i32, i32* %"c" seq_cst, align 4
835851
""")
836852

837853
def test_gep(self):

0 commit comments

Comments
 (0)