Tobias Gysi 7b420a1ada [mlir][llvm] Add inbounds attriubte to the gep op.
The revision adds an inbounds attribute to the LLVM dialect
GEP operation. It extends the builders and the import and export
to support the optional inbounds attribute.

As all builders set inbounds to false by default, existing lowerings
from higher-level dialects to LLVM dialect are not affected by the
change. Canonicalization/folding remains untouched since it currently
does not implement any simplifications in case of undefined behavior
(the handling of undefined behavior is deferred to LLVM).

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D139821
2022-12-14 10:46:07 +01:00

496 lines
17 KiB
LLVM

; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
; CHECK-LABEL: @integer_arith
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]
define void @integer_arith(i32 %arg1, i32 %arg2, i64 %arg3, i64 %arg4) {
; CHECK: %[[C1:[0-9]+]] = llvm.mlir.constant(-7 : i32) : i32
; CHECK: %[[C2:[0-9]+]] = llvm.mlir.constant(42 : i32) : i32
; CHECK: llvm.add %[[ARG1]], %[[C1]] : i32
%1 = add i32 %arg1, -7
; CHECK: llvm.add %[[C2]], %[[ARG2]] : i32
%2 = add i32 42, %arg2
; CHECK: llvm.sub %[[ARG3]], %[[ARG4]] : i64
%3 = sub i64 %arg3, %arg4
; CHECK: llvm.mul %[[ARG1]], %[[ARG2]] : i32
%4 = mul i32 %arg1, %arg2
; CHECK: llvm.udiv %[[ARG3]], %[[ARG4]] : i64
%5 = udiv i64 %arg3, %arg4
; CHECK: llvm.sdiv %[[ARG1]], %[[ARG2]] : i32
%6 = sdiv i32 %arg1, %arg2
; CHECK: llvm.urem %[[ARG3]], %[[ARG4]] : i64
%7 = urem i64 %arg3, %arg4
; CHECK: llvm.srem %[[ARG1]], %[[ARG2]] : i32
%8 = srem i32 %arg1, %arg2
; CHECK: llvm.shl %[[ARG3]], %[[ARG4]] : i64
%9 = shl i64 %arg3, %arg4
; CHECK: llvm.lshr %[[ARG1]], %[[ARG2]] : i32
%10 = lshr i32 %arg1, %arg2
; CHECK: llvm.ashr %[[ARG3]], %[[ARG4]] : i64
%11 = ashr i64 %arg3, %arg4
; CHECK: llvm.and %[[ARG1]], %[[ARG2]] : i32
%12 = and i32 %arg1, %arg2
; CHECK: llvm.or %[[ARG3]], %[[ARG4]] : i64
%13 = or i64 %arg3, %arg4
; CHECK: llvm.xor %[[ARG1]], %[[ARG2]] : i32
%14 = xor i32 %arg1, %arg2
ret void
}
; // -----
; CHECK-LABEL: @integer_compare
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]
define i1 @integer_compare(i32 %arg1, i32 %arg2, <4 x i64> %arg3, <4 x i64> %arg4) {
; CHECK: llvm.icmp "eq" %[[ARG3]], %[[ARG4]] : vector<4xi64>
%1 = icmp eq <4 x i64> %arg3, %arg4
; CHECK: llvm.icmp "slt" %[[ARG1]], %[[ARG2]] : i32
%2 = icmp slt i32 %arg1, %arg2
; CHECK: llvm.icmp "sle" %[[ARG1]], %[[ARG2]] : i32
%3 = icmp sle i32 %arg1, %arg2
; CHECK: llvm.icmp "sgt" %[[ARG1]], %[[ARG2]] : i32
%4 = icmp sgt i32 %arg1, %arg2
; CHECK: llvm.icmp "sge" %[[ARG1]], %[[ARG2]] : i32
%5 = icmp sge i32 %arg1, %arg2
; CHECK: llvm.icmp "ult" %[[ARG1]], %[[ARG2]] : i32
%6 = icmp ult i32 %arg1, %arg2
; CHECK: llvm.icmp "ule" %[[ARG1]], %[[ARG2]] : i32
%7 = icmp ule i32 %arg1, %arg2
; Verify scalar comparisons return a scalar boolean
; CHECK: llvm.icmp "ugt" %[[ARG1]], %[[ARG2]] : i32
%8 = icmp ugt i32 %arg1, %arg2
ret i1 %8
}
; // -----
; CHECK-LABEL: @fp_arith
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]
define void @fp_arith(float %arg1, float %arg2, double %arg3, double %arg4) {
; CHECK: %[[C1:[0-9]+]] = llvm.mlir.constant(3.030000e+01 : f32) : f32
; CHECK: %[[C2:[0-9]+]] = llvm.mlir.constant(3.030000e+01 : f64) : f64
; CHECK: llvm.fadd %[[C1]], %[[ARG1]] : f32
%1 = fadd float 0x403E4CCCC0000000, %arg1
; CHECK: llvm.fadd %[[ARG1]], %[[ARG2]] : f32
%2 = fadd float %arg1, %arg2
; CHECK: llvm.fadd %[[C2]], %[[ARG3]] : f64
%3 = fadd double 3.030000e+01, %arg3
; CHECK: llvm.fsub %[[ARG1]], %[[ARG2]] : f32
%4 = fsub float %arg1, %arg2
; CHECK: llvm.fmul %[[ARG3]], %[[ARG4]] : f64
%5 = fmul double %arg3, %arg4
; CHECK: llvm.fdiv %[[ARG1]], %[[ARG2]] : f32
%6 = fdiv float %arg1, %arg2
; CHECK: llvm.frem %[[ARG3]], %[[ARG4]] : f64
%7 = frem double %arg3, %arg4
; CHECK: llvm.fneg %[[ARG1]] : f32
%8 = fneg float %arg1
ret void
}
; // -----
; CHECK-LABEL: @fp_compare
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]
define <4 x i1> @fp_compare(float %arg1, float %arg2, <4 x double> %arg3, <4 x double> %arg4) {
; CHECK: llvm.fcmp "_false" %[[ARG1]], %[[ARG2]] : f32
%1 = fcmp false float %arg1, %arg2
; CHECK: llvm.fcmp "oeq" %[[ARG1]], %[[ARG2]] : f32
%2 = fcmp oeq float %arg1, %arg2
; CHECK: llvm.fcmp "ogt" %[[ARG1]], %[[ARG2]] : f32
%3 = fcmp ogt float %arg1, %arg2
; CHECK: llvm.fcmp "oge" %[[ARG1]], %[[ARG2]] : f32
%4 = fcmp oge float %arg1, %arg2
; CHECK: llvm.fcmp "olt" %[[ARG1]], %[[ARG2]] : f32
%5 = fcmp olt float %arg1, %arg2
; CHECK: llvm.fcmp "ole" %[[ARG1]], %[[ARG2]] : f32
%6 = fcmp ole float %arg1, %arg2
; CHECK: llvm.fcmp "one" %[[ARG1]], %[[ARG2]] : f32
%7 = fcmp one float %arg1, %arg2
; CHECK: llvm.fcmp "ord" %[[ARG1]], %[[ARG2]] : f32
%8 = fcmp ord float %arg1, %arg2
; CHECK: llvm.fcmp "ueq" %[[ARG1]], %[[ARG2]] : f32
%9 = fcmp ueq float %arg1, %arg2
; CHECK: llvm.fcmp "ugt" %[[ARG1]], %[[ARG2]] : f32
%10 = fcmp ugt float %arg1, %arg2
; CHECK: llvm.fcmp "uge" %[[ARG1]], %[[ARG2]] : f32
%11 = fcmp uge float %arg1, %arg2
; CHECK: llvm.fcmp "ult" %[[ARG1]], %[[ARG2]] : f32
%12 = fcmp ult float %arg1, %arg2
; CHECK: llvm.fcmp "ule" %[[ARG1]], %[[ARG2]] : f32
%13 = fcmp ule float %arg1, %arg2
; CHECK: llvm.fcmp "une" %[[ARG1]], %[[ARG2]] : f32
%14 = fcmp une float %arg1, %arg2
; CHECK: llvm.fcmp "uno" %[[ARG1]], %[[ARG2]] : f32
%15 = fcmp uno float %arg1, %arg2
; Verify vector comparisons return a vector of booleans
; CHECK: llvm.fcmp "_true" %[[ARG3]], %[[ARG4]] : vector<4xf64>
%16 = fcmp true <4 x double> %arg3, %arg4
ret <4 x i1> %16
}
; // -----
; CHECK-LABEL: @fp_casts
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]
define void @fp_casts(float %arg1, double %arg2, i32 %arg3) {
; CHECK: llvm.fptrunc %[[ARG2]] : f64 to f32
; CHECK: llvm.fpext %[[ARG1]] : f32 to f64
; CHECK: llvm.fptosi %[[ARG2]] : f64 to i16
; CHECK: llvm.fptoui %[[ARG1]] : f32 to i32
; CHECK: llvm.sitofp %[[ARG3]] : i32 to f32
; CHECK: llvm.uitofp %[[ARG3]] : i32 to f64
%1 = fptrunc double %arg2 to float
%2 = fpext float %arg1 to double
%3 = fptosi double %arg2 to i16
%4 = fptoui float %arg1 to i32
%5 = sitofp i32 %arg3 to float
%6 = uitofp i32 %arg3 to double
ret void
}
; // -----
; CHECK-LABEL: @integer_extension_and_truncation
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
define void @integer_extension_and_truncation(i32 %arg1) {
; CHECK: llvm.sext %[[ARG1]] : i32 to i64
; CHECK: llvm.zext %[[ARG1]] : i32 to i64
; CHECK: llvm.trunc %[[ARG1]] : i32 to i16
%1 = sext i32 %arg1 to i64
%2 = zext i32 %arg1 to i64
%3 = trunc i32 %arg1 to i16
ret void
}
; // -----
; CHECK-LABEL: @pointer_casts
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
define i32* @pointer_casts(double* %arg1, i64 %arg2) {
; CHECK: %[[NULL:[0-9]+]] = llvm.mlir.null : !llvm.ptr<i32>
; CHECK: llvm.ptrtoint %[[ARG1]] : !llvm.ptr<f64> to i64
; CHECK: llvm.inttoptr %[[ARG2]] : i64 to !llvm.ptr<i64>
; CHECK: llvm.bitcast %[[ARG1]] : !llvm.ptr<f64> to !llvm.ptr<i32>
; CHECK: llvm.return %[[NULL]] : !llvm.ptr<i32>
%1 = ptrtoint double* %arg1 to i64
%2 = inttoptr i64 %arg2 to i64*
%3 = bitcast double* %arg1 to i32*
ret i32* bitcast (double* null to i32*)
}
; // -----
; CHECK-LABEL: @addrspace_casts
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
define ptr addrspace(2) @addrspace_casts(ptr addrspace(1) %arg1) {
; CHECK: llvm.addrspacecast %[[ARG1]] : !llvm.ptr<1> to !llvm.ptr<2>
; CHECK: llvm.return {{.*}} : !llvm.ptr<2>
%1 = addrspacecast ptr addrspace(1) %arg1 to ptr addrspace(2)
ret ptr addrspace(2) %1
}
; // -----
; CHECK-LABEL: @integer_arith
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]
define void @integer_arith(i32 %arg1, i32 %arg2, i64 %arg3, i64 %arg4) {
; CHECK: %[[C1:[0-9]+]] = llvm.mlir.constant(-7 : i32) : i32
; CHECK: %[[C2:[0-9]+]] = llvm.mlir.constant(42 : i32) : i32
; CHECK: llvm.add %[[ARG1]], %[[C1]] : i32
; CHECK: llvm.add %[[C2]], %[[ARG2]] : i32
; CHECK: llvm.sub %[[ARG3]], %[[ARG4]] : i64
; CHECK: llvm.mul %[[ARG1]], %[[ARG2]] : i32
; CHECK: llvm.udiv %[[ARG3]], %[[ARG4]] : i64
; CHECK: llvm.sdiv %[[ARG1]], %[[ARG2]] : i32
; CHECK: llvm.urem %[[ARG3]], %[[ARG4]] : i64
; CHECK: llvm.srem %[[ARG1]], %[[ARG2]] : i32
; CHECK: llvm.shl %[[ARG3]], %[[ARG4]] : i64
; CHECK: llvm.lshr %[[ARG1]], %[[ARG2]] : i32
; CHECK: llvm.ashr %[[ARG3]], %[[ARG4]] : i64
; CHECK: llvm.and %[[ARG1]], %[[ARG2]] : i32
; CHECK: llvm.or %[[ARG3]], %[[ARG4]] : i64
; CHECK: llvm.xor %[[ARG1]], %[[ARG2]] : i32
%1 = add i32 %arg1, -7
%2 = add i32 42, %arg2
%3 = sub i64 %arg3, %arg4
%4 = mul i32 %arg1, %arg2
%5 = udiv i64 %arg3, %arg4
%6 = sdiv i32 %arg1, %arg2
%7 = urem i64 %arg3, %arg4
%8 = srem i32 %arg1, %arg2
%9 = shl i64 %arg3, %arg4
%10 = lshr i32 %arg1, %arg2
%11 = ashr i64 %arg3, %arg4
%12 = and i32 %arg1, %arg2
%13 = or i64 %arg3, %arg4
%14 = xor i32 %arg1, %arg2
ret void
}
; // -----
; CHECK-LABEL: @extract_element
; CHECK-SAME: %[[VEC:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[IDX:[a-zA-Z0-9]+]]
define half @extract_element(<4 x half>* %vec, i32 %idx) {
; CHECK: %[[V1:.+]] = llvm.load %[[VEC]] : !llvm.ptr<vector<4xf16>>
; CHECK: %[[V2:.+]] = llvm.extractelement %[[V1]][%[[IDX]] : i32] : vector<4xf16>
; CHECK: llvm.return %[[V2]]
%1 = load <4 x half>, <4 x half>* %vec
%2 = extractelement <4 x half> %1, i32 %idx
ret half %2
}
; // -----
; CHECK-LABEL: @insert_element
; CHECK-SAME: %[[VEC:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[VAL:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[IDX:[a-zA-Z0-9]+]]
define <4 x half> @insert_element(<4 x half>* %vec, half %val, i32 %idx) {
; CHECK: %[[V1:.+]] = llvm.load %[[VEC]] : !llvm.ptr<vector<4xf16>>
; CHECK: %[[V2:.+]] = llvm.insertelement %[[VAL]], %[[V1]][%[[IDX]] : i32] : vector<4xf16>
; CHECK: llvm.return %[[V2]]
%1 = load <4 x half>, <4 x half>* %vec
%2 = insertelement <4 x half> %1, half %val, i32 %idx
ret <4 x half> %2
}
; // -----
; CHECK-LABEL: @insert_extract_value_struct
; CHECK-SAME: %[[PTR:[a-zA-Z0-9]+]]
define float @insert_extract_value_struct({{i32},{float, double}}* %ptr) {
; CHECK: %[[C0:.+]] = llvm.mlir.constant(2.000000e+00 : f64)
; CHECK: %[[VT:.+]] = llvm.load %[[PTR]]
%1 = load {{i32},{float, double}}, {{i32},{float, double}}* %ptr
; CHECK: %[[EV:.+]] = llvm.extractvalue %[[VT]][1, 0] :
; CHECK-SAME: !llvm.struct<(struct<(i32)>, struct<(f32, f64)>)>
%2 = extractvalue {{i32},{float, double}} %1, 1, 0
; CHECK: %[[IV:.+]] = llvm.insertvalue %[[C0]], %[[VT]][1, 1] :
; CHECK-SAME: !llvm.struct<(struct<(i32)>, struct<(f32, f64)>)>
%3 = insertvalue {{i32},{float, double}} %1, double 2.0, 1, 1
; CHECK: llvm.store %[[IV]], %[[PTR]]
store {{i32},{float, double}} %3, {{i32},{float, double}}* %ptr
; CHECK: llvm.return %[[EV]]
ret float %2
}
; // -----
; CHECK-LABEL: @insert_extract_value_array
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
define void @insert_extract_value_array([4 x [4 x i8]] %arg1) {
; CHECK: %[[C0:.+]] = llvm.mlir.constant(0 : i8)
; CHECK: llvm.insertvalue %[[C0]], %[[ARG1]][0, 0] : !llvm.array<4 x array<4 x i8>>
%1 = insertvalue [4 x [4 x i8 ]] %arg1, i8 0, 0, 0
; CHECK: llvm.extractvalue %[[ARG1]][1] : !llvm.array<4 x array<4 x i8>>
%2 = extractvalue [4 x [4 x i8 ]] %arg1, 1
; CHECK: llvm.extractvalue %[[ARG1]][0, 1] : !llvm.array<4 x array<4 x i8>>
%3 = extractvalue [4 x [4 x i8 ]] %arg1, 0, 1
ret void
}
; // -----
; CHECK-LABEL: @select
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[COND:[a-zA-Z0-9]+]]
define void @select(i32 %arg0, i32 %arg1, i1 %cond) {
; CHECK: llvm.select %[[COND]], %[[ARG1]], %[[ARG2]] : i1, i32
%1 = select i1 %cond, i32 %arg0, i32 %arg1
ret void
}
; // -----
; CHECK-LABEL: func @shuffle_vec
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]
define <4 x half> @shuffle_vec(<4 x half> %arg1, <4 x half> %arg2) {
; CHECK: llvm.shufflevector %[[ARG1]], %[[ARG2]] [2, 3, -1, -1] : vector<4xf16>
%1 = shufflevector <4 x half> %arg1, <4 x half> %arg2, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
ret <4 x half> %1
}
; // -----
; CHECK-LABEL: @alloca
; CHECK-SAME: %[[SIZE:[a-zA-Z0-9]+]]
define double* @alloca(i64 %size) {
; CHECK: %[[C1:[0-9]+]] = llvm.mlir.constant(1 : i32) : i32
; CHECK: llvm.alloca %[[C1]] x f64 {alignment = 8 : i64} : (i32) -> !llvm.ptr<f64>
; CHECK: llvm.alloca %[[SIZE]] x i32 {alignment = 8 : i64} : (i64) -> !llvm.ptr<i32>
; CHECK: llvm.alloca %[[SIZE]] x i32 {alignment = 4 : i64} : (i64) -> !llvm.ptr<i32, 3>
%1 = alloca double
%2 = alloca i32, i64 %size, align 8
%3 = alloca i32, i64 %size, addrspace(3)
ret double* %1
}
; // -----
; CHECK-LABEL: @load_store
; CHECK-SAME: %[[PTR:[a-zA-Z0-9]+]]
define void @load_store(double* %ptr) {
; CHECK: %[[V1:[0-9]+]] = llvm.load %[[PTR]] : !llvm.ptr<f64>
; CHECK: llvm.store %[[V1]], %[[PTR]] : !llvm.ptr<f64>
%1 = load double, double* %ptr
store double %1, double* %ptr
ret void
}
; // -----
; CHECK-LABEL: @atomic_rmw
; CHECK-SAME: %[[PTR1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[VAL1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[PTR2:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[VAL2:[a-zA-Z0-9]+]]
define void @atomic_rmw(i32* %ptr1, i32 %val1, float* %ptr2, float %val2) {
; CHECK: llvm.atomicrmw xchg %[[PTR1]], %[[VAL1]] acquire : i32
%1 = atomicrmw xchg i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw add %[[PTR1]], %[[VAL1]] release : i32
%2 = atomicrmw add i32* %ptr1, i32 %val1 release
; CHECK: llvm.atomicrmw sub %[[PTR1]], %[[VAL1]] acq_rel : i32
%3 = atomicrmw sub i32* %ptr1, i32 %val1 acq_rel
; CHECK: llvm.atomicrmw _and %[[PTR1]], %[[VAL1]] seq_cst : i32
%4 = atomicrmw and i32* %ptr1, i32 %val1 seq_cst
; CHECK: llvm.atomicrmw nand %[[PTR1]], %[[VAL1]] acquire : i32
%5 = atomicrmw nand i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw _or %[[PTR1]], %[[VAL1]] acquire : i32
%6 = atomicrmw or i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw _xor %[[PTR1]], %[[VAL1]] acquire : i32
%7 = atomicrmw xor i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw max %[[PTR1]], %[[VAL1]] acquire : i32
%8 = atomicrmw max i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw min %[[PTR1]], %[[VAL1]] acquire : i32
%9 = atomicrmw min i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw umax %[[PTR1]], %[[VAL1]] acquire : i32
%10 = atomicrmw umax i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw umin %[[PTR1]], %[[VAL1]] acquire : i32
%11 = atomicrmw umin i32* %ptr1, i32 %val1 acquire
; CHECK: llvm.atomicrmw fadd %[[PTR2]], %[[VAL2]] acquire : f32
%12 = atomicrmw fadd float* %ptr2, float %val2 acquire
; CHECK: llvm.atomicrmw fsub %[[PTR2]], %[[VAL2]] acquire : f32
%13 = atomicrmw fsub float* %ptr2, float %val2 acquire
ret void
}
; // -----
; CHECK-LABEL: @atomic_cmpxchg
; CHECK-SAME: %[[PTR1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[VAL1:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[VAL2:[a-zA-Z0-9]+]]
define void @atomic_cmpxchg(i32* %ptr1, i32 %val1, i32 %val2) {
; CHECK: llvm.cmpxchg %[[PTR1]], %[[VAL1]], %[[VAL2]] seq_cst seq_cst : i32
%1 = cmpxchg i32* %ptr1, i32 %val1, i32 %val2 seq_cst seq_cst
; CHECK: llvm.cmpxchg %[[PTR1]], %[[VAL1]], %[[VAL2]] monotonic seq_cst : i32
%2 = cmpxchg i32* %ptr1, i32 %val1, i32 %val2 monotonic seq_cst
ret void
}
; // -----
; CHECK: llvm.func @fn(i32) -> f32
declare float @fn(i32)
; CHECK-LABEL: @call_fn
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
define float @call_fn(i32 %arg1) {
; CHECK: llvm.call @fn(%[[ARG1]])
%1 = call float @fn(i32 %arg1)
ret float %1
}
; // -----
; CHECK-LABEL: @call_fn_ptr
; CHECK-SAME: %[[PTR:[a-zA-Z0-9]+]]
define void @call_fn_ptr(void (i16) *%fn) {
; CHECK: %[[C0:[0-9]+]] = llvm.mlir.constant(0 : i16) : i16
; CHECK: llvm.call %[[PTR]](%[[C0]])
call void %fn(i16 0)
ret void
}
; // -----
; CHECK-LABEL: @gep_static_idx
; CHECK-SAME: %[[PTR:[a-zA-Z0-9]+]]
define void @gep_static_idx(float* %ptr) {
; CHECK: %[[IDX:.+]] = llvm.mlir.constant(7 : i32)
; CHECK: llvm.getelementptr inbounds %[[PTR]][%[[IDX]]] : (!llvm.ptr<f32>, i32) -> !llvm.ptr<f32>
%1 = getelementptr inbounds float, float* %ptr, i32 7
ret void
}
; // -----
%sub_struct = type { i32, i8 }
%my_struct = type { %sub_struct, [4 x i32] }
; CHECK-LABEL: @gep_dynamic_idx
; CHECK-SAME: %[[PTR:[a-zA-Z0-9]+]]
; CHECK-SAME: %[[IDX:[a-zA-Z0-9]+]]
define void @gep_dynamic_idx(%my_struct* %ptr, i32 %idx) {
; CHECK: %[[C0:.+]] = llvm.mlir.constant(0 : i32)
; CHECK: llvm.getelementptr %[[PTR]][%[[C0]], 1, %[[IDX]]]
%1 = getelementptr %my_struct, %my_struct* %ptr, i32 0, i32 1, i32 %idx
ret void
}
; // -----
; CHECK-LABEL: @freeze
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
define void @freeze(i32 %arg1) {
; CHECK: %[[UNDEF:[0-9]+]] = llvm.mlir.undef : i64
; CHECK: llvm.freeze %[[ARG1]] : i32
; CHECK: llvm.freeze %[[UNDEF]] : i64
%1 = freeze i32 %arg1
%2 = freeze i64 undef
ret void
}
; // -----
; CHECK-LABEL: @unreachable
define void @unreachable() {
; CHECK: llvm.unreachable
unreachable
}
; // -----
; CHECK-LABEL: @fence
define void @fence() {
; CHECK: llvm.fence syncscope("agent") seq_cst
; CHECK: llvm.fence release
; CHECK: llvm.fence seq_cst
fence syncscope("agent") seq_cst
fence release
fence syncscope("") seq_cst
ret void
}