Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV][Clang] Added code to generate clang error if immediate operan… #93

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
3 changes: 2 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -13300,7 +13300,8 @@ class Sema final {
bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum);
bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);

bool CheckRISCVCOREVBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall);
bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
Expand Down
22 changes: 21 additions & 1 deletion clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2019,7 +2019,8 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
return CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall);
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
return CheckRISCVBuiltinFunctionCall(TI, BuiltinID, TheCall);
return CheckRISCVBuiltinFunctionCall(TI, BuiltinID, TheCall) ||
CheckRISCVCOREVBuiltinFunctionCall(BuiltinID, TheCall);
}
}

Expand Down Expand Up @@ -4461,6 +4462,25 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
return false;
}

bool Sema::CheckRISCVCOREVBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
// For intrinsics which take an immediate value as part of the instruction,
// range check them here.
switch (BuiltinID) {
default: return false;
case RISCVCOREV::BI__builtin_riscv_cv_simd_extract_h:
case RISCVCOREV::BI__builtin_riscv_cv_simd_extractu_h:
return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
case RISCVCOREV::BI__builtin_riscv_cv_simd_extract_b:
case RISCVCOREV::BI__builtin_riscv_cv_simd_extractu_b:
return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
case RISCVCOREV::BI__builtin_riscv_cv_simd_insert_h:
return SemaBuiltinConstantArgRange(TheCall, 2, 0, 1);
case RISCVCOREV::BI__builtin_riscv_cv_simd_insert_b:
return SemaBuiltinConstantArgRange(TheCall, 2, 0, 3);
}
}

bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
if (BuiltinID == SystemZ::BI__builtin_tabort) {
Expand Down
50 changes: 50 additions & 0 deletions clang/test/CodeGen/RISCV/corev-intrinsics/simd-errors.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// RUN: %clang_cc1 %s -triple=riscv32 -target-feature +xcvsimd -fsyntax-only -verify
#include <stdint.h>

uint32_t test_extract_h(uint32_t a) {
return __builtin_riscv_cv_simd_extract_h(a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
}

uint32_t test_extract_h_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extract_h(a, -1); // expected-error {{argument value 255 is outside the valid range [0, 1]}}
}

uint32_t test_extractu_h(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_h(a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
}

uint32_t test_extractu_h_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_h(a, -1); // expected-error {{argument value 255 is outside the valid range [0, 1]}}
}

uint32_t test_extract_b(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
}

uint32_t test_extract_b_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, -1); // expected-error {{argument value 255 is outside the valid range [0, 3]}}
}

uint32_t test_extractu_b(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
}

uint32_t test_extractu_b_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, -1); // expected-error {{argument value 255 is outside the valid range [0, 3]}}
}

uint32_t test_insert_h(uint32_t dst, uint8_t a) {
return __builtin_riscv_cv_simd_insert_h(dst, a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
}

uint32_t test_insert_h_negative(uint32_t dst, uint8_t a) {
return __builtin_riscv_cv_simd_insert_h(dst, a, -1); // expected-error {{argument value 255 is outside the valid range [0, 1]}}
}

uint32_t test_insert_b(uint32_t dst, uint8_t a) {
return __builtin_riscv_cv_simd_insert_b(dst, a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
}

uint32_t test_insert_b_negative(uint32_t dst, uint8_t a) {
return __builtin_riscv_cv_simd_insert_b(dst, a, -1); // expected-error {{argument value 255 is outside the valid range [0, 3]}}
}
112 changes: 80 additions & 32 deletions clang/test/CodeGen/RISCV/corev-intrinsics/simd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2256,100 +2256,148 @@ uint32_t test_sdotsp_sci_b_negative(uint32_t a, uint8_t b) {
return __builtin_riscv_cv_simd_sdotsp_sc_b(a, -32, b);
}

// CHECK-LABEL: @test_extract_h(
// CHECK-LABEL: @test_extract_h0(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.h(i32 [[TMP0]], i32 5)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.h(i32 [[TMP0]], i32 0)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extract_h(uint32_t a) {
return __builtin_riscv_cv_simd_extract_h(a, 5);
uint32_t test_extract_h0(uint32_t a) {
return __builtin_riscv_cv_simd_extract_h(a, 0);
}

// CHECK-LABEL: @test_extract_h_negative(
// CHECK-LABEL: @test_extract_h1(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.h(i32 [[TMP0]], i32 224)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.h(i32 [[TMP0]], i32 1)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extract_h_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extract_h(a, -32);
uint32_t test_extract_h1(uint32_t a) {
return __builtin_riscv_cv_simd_extract_h(a, 1);
}

// CHECK-LABEL: @test_extract_b(
// CHECK-LABEL: @test_extract_b0(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 5)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 0)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extract_b(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, 5);
uint32_t test_extract_b0(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, 0);
}

// CHECK-LABEL: @test_extract_b_negative(
// CHECK-LABEL: @test_extract_b1(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 224)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 1)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extract_b_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, -32);
uint32_t test_extract_b1(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, 1);
}

// CHECK-LABEL: @test_extractu_h(
// CHECK-LABEL: @test_extract_b2(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.h(i32 [[TMP0]], i32 5)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 2)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_h(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_h(a, 5);
uint32_t test_extract_b2(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, 2);
}

// CHECK-LABEL: @test_extractu_h_negative(
// CHECK-LABEL: @test_extract_b3(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.h(i32 [[TMP0]], i32 224)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 3)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_h_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_h(a, -32);
uint32_t test_extract_b3(uint32_t a) {
return __builtin_riscv_cv_simd_extract_b(a, 3);
}

// CHECK-LABEL: @test_extractu_b(
// CHECK-LABEL: @test_extractu_h0(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 5)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.h(i32 [[TMP0]], i32 0)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_b(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, 5);
uint32_t test_extractu_h0(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_h(a, 0);
}

// CHECK-LABEL: @test_extractu_b_negative(
// CHECK-LABEL: @test_extractu_h1(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 224)
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.h(i32 [[TMP0]], i32 1)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_b_negative(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, -32);
uint32_t test_extractu_h1(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_h(a, 1);
}

// CHECK-LABEL: @test_extractu_b0(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 0)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_b0(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, 0);
}

// CHECK-LABEL: @test_extractu_b1(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 1)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_b1(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, 1);
}

// CHECK-LABEL: @test_extractu_b2(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 2)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_b2(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, 2);
}

// CHECK-LABEL: @test_extractu_b3(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 3)
// CHECK-NEXT: ret i32 [[TMP1]]
//
uint32_t test_extractu_b3(uint32_t a) {
return __builtin_riscv_cv_simd_extractu_b(a, 3);
}

// CHECK-LABEL: @test_shuffle_h(
Expand Down