Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Test/LLVM/global_invalid_alignment.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
}) : () -> ()
}) : () -> ()

// CHECK: llvm.mlir.global: 'alignment' must be a 64-bit signless integer attribute
// CHECK: llvm.mlir.global: 'alignment' must be a 64-bit integer attribute
2 changes: 1 addition & 1 deletion Test/LLVM/invalid_alloca.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"func.func"() <{function_type = (i32) -> (), sym_name = "main"}> ({
^bb0(%0 : i32):
%1 = "llvm.alloca"(%0) <{"alignment" = 4 : i32, "elem_type" = i32, inalloca}> : (i32) -> !llvm.ptr
// CHECK: 'llvm.alloca' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute
// CHECK: 'llvm.alloca' op attribute 'alignment' failed to satisfy constraint: 64-bit integer attribute
"func.return"() : () -> ()
}) : () -> ()
}) : () -> ()
Expand Down
9 changes: 7 additions & 2 deletions Test/Passes/InstructionSelection/RISCV64/alloca_invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@
%layout = "llvm.alloca"(%one) <{elem_type = !llvm.struct<(i32, i64)>}> : (i64) -> !llvm.ptr
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = 0 : i64, "elem_type" = !llvm.struct<(i32, i64)>}>

// The byte size must fit 64 bits without wrapping, even for a wide count.
// The byte size must fit a signed 64-bit value without wrapping, even for a
// wide count: `riscv_stack.alloca` stores it as a nonnegative `BitVec 64`.
%overflow = "llvm.alloca"(%large) <{elem_type = i64}> : (i64) -> !llvm.ptr
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = 0 : i64, "elem_type" = i64}>
%signed_overflow = "llvm.alloca"(%large) <{elem_type = i32}> : (i64) -> !llvm.ptr
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = 0 : i64, "elem_type" = i32}>
%wide_count = "llvm.alloca"(%wide) <{elem_type = i8}> : (i128) -> !llvm.ptr
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = 0 : i64, "elem_type" = i8}>

Expand All @@ -41,9 +44,11 @@
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = -8 : i64, "elem_type" = i8}>
%wide_align = "llvm.alloca"(%one) <{elem_type = i8, alignment = 18446744073709551616 : i64}> : (i64) -> !llvm.ptr
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = 18446744073709551616 : i64, "elem_type" = i8}>
%signed_align = "llvm.alloca"(%one) <{elem_type = i8, alignment = 9223372036854775808 : i64}> : (i64) -> !llvm.ptr
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = 9223372036854775808 : i64, "elem_type" = i8}>
%not_pointer = "llvm.alloca"(%one) <{elem_type = i8}> : (i64) -> i64
// CHECK: "llvm.alloca"({{.*}}) <{"alignment" = 0 : i64, "elem_type" = i8}> : (i64) -> i64
"test.test"(%dynamic, %special, %layout, %overflow, %wide_count, %bad_align, %negative_align, %wide_align, %not_pointer) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, i64) -> ()
"test.test"(%dynamic, %special, %layout, %overflow, %signed_overflow, %wide_count, %bad_align, %negative_align, %wide_align, %signed_align, %not_pointer) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, i64) -> ()
"llvm.br"()[^later] : () -> ()
^later:
// A constant-count alloca outside the entry block is still dynamic.
Expand Down
14 changes: 7 additions & 7 deletions Test/Passes/InstructionSelection/RISCV64/const.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,30 @@
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i64
%c2 = "llvm.mlir.constant"() <{"value" = -1 : i32 }> : () -> i32
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i32}> : () -> !riscv.reg
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i32
%c3 = "llvm.mlir.constant"() <{"value" = -1 : i8 }> : () -> i8
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i8}> : () -> !riscv.reg
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i8
%c4 = "llvm.mlir.constant"() <{"value" = -1 : i1 }> : () -> i1
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i1}> : () -> !riscv.reg
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i1
// An attribute wider than the result carries bits that are not part of the
// value: `300 : i32` in an i8 result is 44.
%c5 = "llvm.mlir.constant"() <{"value" = 300 : i32 }> : () -> i8
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = 44 : i32}> : () -> !riscv.reg
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = 44 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i8
// An i1 attribute is zero-extended, so `-1 : i1` in an i64 result is 1.
%c6 = "llvm.mlir.constant"() <{"value" = -1 : i1 }> : () -> i64
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = 1 : i1}> : () -> !riscv.reg
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = 1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i64
// A non-i1 attribute is sign-extended, so `255 : i8` in an i64 result is -1.
%c7 = "llvm.mlir.constant"() <{"value" = 255 : i8 }> : () -> i64
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i8}> : () -> !riscv.reg
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i64
// Likewise `4294967295 : i32` in an i64 result is -1.
%c8 = "llvm.mlir.constant"() <{"value" = 4294967295 : i32 }> : () -> i64
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i32}> : () -> !riscv.reg
// CHECK: %[[A:.*]] = "riscv.li"() <{"value" = -1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: {{.*}} = "builtin.unrealized_conversion_cast"(%[[A]]) : (!riscv.reg) -> i64
"test.test"(%c1) : (i64) -> ()
"test.test"(%c2) : (i32) -> ()
Expand Down
2 changes: 1 addition & 1 deletion Test/Passes/InstructionSelection/RISCV64/li.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

"func.func"() <{function_type = () -> (), sym_name = "bar"}> ({
%one = "llvm.mlir.constant"() <{ "value" = 1 : i32 }> : () -> i32
// CHECK: [[C:%.*]] = "riscv.li"() <{"value" = 1 : i32}> : () -> !riscv.reg
// CHECK: [[C:%.*]] = "riscv.li"() <{"value" = 1 : i64}> : () -> !riscv.reg
// CHECK-NEXT: %{{.*}} = "builtin.unrealized_conversion_cast"([[C]]) : (!riscv.reg) -> i32
"test.test"(%one) : (i32) -> ()
"func.return"() : () -> ()
Expand Down
8 changes: 4 additions & 4 deletions Test/Passes/InstructionSelection/RISCV64/sext.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
// CHECK-NEXT: %[[M:.*]] = "riscv.sextw"(%[[L]]) : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[N:.*]] = "builtin.unrealized_conversion_cast"(%[[M]]) : (!riscv.reg) -> i64
// CHECK-NEXT: %[[O:.*]] = "builtin.unrealized_conversion_cast"([[A]]) : (i1) -> !riscv.reg
// CHECK-NEXT: %[[P:.*]] = "riscv.slli"(%[[O]]) <{"value" = 63 : i6}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[Q:.*]] = "riscv.srai"(%[[P]]) <{"value" = 63 : i6}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[P:.*]] = "riscv.slli"(%[[O]]) <{"value" = 63 : i64}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[Q:.*]] = "riscv.srai"(%[[P]]) <{"value" = 63 : i64}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[R:.*]] = "builtin.unrealized_conversion_cast"(%[[Q]]) : (!riscv.reg) -> i64
// CHECK-NEXT: %[[S:.*]] = "builtin.unrealized_conversion_cast"([[A]]) : (i1) -> !riscv.reg
// CHECK-NEXT: %[[T:.*]] = "riscv.slli"(%[[S]]) <{"value" = 63 : i6}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[U:.*]] = "riscv.srai"(%[[T]]) <{"value" = 63 : i6}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[T:.*]] = "riscv.slli"(%[[S]]) <{"value" = 63 : i64}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[U:.*]] = "riscv.srai"(%[[T]]) <{"value" = 63 : i64}> : (!riscv.reg) -> !riscv.reg
// CHECK-NEXT: %[[V:.*]] = "builtin.unrealized_conversion_cast"(%[[U]]) : (!riscv.reg) -> i32
// CHECK-NEXT: %[[W:.*]] = "builtin.unrealized_conversion_cast"([[E]]) : (i8) -> !riscv.reg
// CHECK-NEXT: %[[X:.*]] = "riscv.sextb"(%[[W]]) : (!riscv.reg) -> !riscv.reg
Expand Down
11 changes: 11 additions & 0 deletions Test/RISCV/mem-imm-width-not-i64.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: not veir-opt %s 2>&1 | filecheck %s

"builtin.module"() ({
"func.func"() <{sym_name = "main", function_type = () -> !riscv.reg}> ({
%a = "riscv.li"() <{ "value" = 0 : i64 }> : () -> !riscv.reg
%y = "riscv.ld"(%a) <{ "value" = 8 : i12 }> : (!riscv.reg) -> !riscv.reg
"func.return"(%y) : (!riscv.reg) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: error: RISC-V memory operation: expected 'value' to be a 64-bit integer attribute, but got i12
12 changes: 12 additions & 0 deletions Test/Verifier/riscv_stack_alloca_alignment_width_not_i64.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// RUN: not veir-opt %s 2>&1 | filecheck %s

// As `riscv_stack_alloca_size_width_not_i64.mlir`, for `alignment`.

"builtin.module"() ({
"func.func"() <{function_type = () -> (), sym_name = "main"}> ({
%slot = "riscv_stack.alloca"() <{size = 8 : i64, alignment = 8 : i16}> : () -> !riscv.reg
"func.return"() : () -> ()
}) : () -> ()
}) : () -> ()

// CHECK: error: alloca: expected 'alignment' to be a 64-bit integer attribute, but got i16
10 changes: 10 additions & 0 deletions Test/Verifier/riscv_stack_alloca_size_width_not_i64.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: not veir-opt %s 2>&1 | filecheck %s

"builtin.module"() ({
"func.func"() <{function_type = () -> (), sym_name = "main"}> ({
%slot = "riscv_stack.alloca"() <{size = 8 : i32, alignment = 8 : i64}> : () -> !riscv.reg
"func.return"() : () -> ()
}) : () -> ()
}) : () -> ()

// CHECK: error: alloca: expected 'size' to be a 64-bit integer attribute, but got i32
2 changes: 1 addition & 1 deletion UnitTest/FoldDecision.lean
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private def testRiscvConstantMaterialization : String := Id.run do
let value : RuntimeValue := .reg ⟨BitVec.ofInt 64 (-77)⟩
match (.riscv .add : OpCode).materializeConstant value regType with
| some ⟨.riscv .li, props⟩ =>
if props.value ≠ IntegerAttr.mk (-77) (IntegerType.mk 64) then
if props.value ≠ -77#64 then
return "RISC-V materialized the wrong immediate"
return "ok"
| _ => return "RISC-V did not materialize riscv.li"
Expand Down
20 changes: 20 additions & 0 deletions Veir/Dialects/Builtin/Properties.lean
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,26 @@ def UnregisteredProperties.fromAttrDict (attrDict : Std.HashMap ByteArray Attrib
Except String UnregisteredProperties :=
.ok { opName := .empty, properties := DictionaryAttr.fromArray attrDict.toArray }

/--
Read a required integer attribute that must be declared `i64`, returning the
value it denotes as a `BitVec 64`.
-/
def getI64Attr (errorCtx key : String) (attrDict : Std.HashMap ByteArray Attribute) :
Except String (BitVec 64) := do
let some attr := attrDict[key.toUTF8]?
| throw s!"{errorCtx}: missing '{key}' property"
let .integerAttr intAttr := attr
| throw s!"{errorCtx}: expected '{key}' to be an integer attribute, but got {attr}"
if intAttr.type.bitwidth ≠ 64 then
throw s!"{errorCtx}: expected '{key}' to be a 64-bit integer attribute, but got i{intAttr.type.bitwidth}"
if intAttr.value < -(2 ^ 63) ∨ 2 ^ 64 ≤ intAttr.value then
throw s!"{errorCtx}: '{key}' value {intAttr.value} does not fit in i64"
return BitVec.ofInt 64 intAttr.value

/-- Re-encode a `getI64Attr` value as the `i64` attribute it is printed as. -/
def i64Attr (value : BitVec 64) : Attribute :=
.integerAttr (IntegerAttr.mk value.toInt (IntegerType.mk 64))

def getUnitAttr (key : String) (attrDict : Std.HashMap ByteArray Attribute) :
Except String Bool := do
match attrDict[key.toUTF8]? with
Expand Down
8 changes: 4 additions & 4 deletions Veir/Dialects/LLVM/OpInfo.lean
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ def Llvm.verifyLocalInvariants {OpInfo : Type} [IsOpCode OpInfo]
let properties := op.getProperties! ctx.raw Llvm.mlir__global
if let some alignment := properties.alignment then
if alignment.type.bitwidth ≠ 64 then
throw "'alignment' must be a 64-bit signless integer attribute"
throw "'alignment' must be a 64-bit integer attribute"
if !isValidLLVMAlignment alignment.value then
throw "alignment attribute is not a power of 2"
if properties.addr_space.type.bitwidth ≠ 32 then
Expand Down Expand Up @@ -995,21 +995,21 @@ def Llvm.verifyLocalInvariants {OpInfo : Type} [IsOpCode OpInfo]
op.verifyPlainOpCounts ctx opIn 1 1
let properties := op.getProperties! ctx.raw Llvm.alloca
if properties.alignment.type.bitwidth ≠ 64 then
throw "'llvm.alloca' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute"
throw "'llvm.alloca' op attribute 'alignment' failed to satisfy constraint: 64-bit integer attribute"
pure ()
| .load => do
op.checkIsNonNullIntegerType ctx opIn
op.verifyPlainOpCounts ctx opIn 1 1
let properties := op.getProperties! ctx.raw Llvm.load
if properties.alignment.type.bitwidth ≠ 64 then
throw "'llvm.load' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute"
throw "'llvm.load' op attribute 'alignment' failed to satisfy constraint: 64-bit integer attribute"
pure ()
| .store => do
op.checkIsNonNullIntegerType ctx opIn
op.verifyPlainOpCounts ctx opIn 2 0
let properties := op.getProperties! ctx.raw Llvm.store
if properties.alignment.type.bitwidth ≠ 64 then
throw "'llvm.store' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute"
throw "'llvm.store' op attribute 'alignment' failed to satisfy constraint: 64-bit integer attribute"
pure ()
| .insertelement => do
op.checkIsNonNullIntegerType ctx opIn
Expand Down
Loading
Loading