// RUN: %clang_cc1 %s -O0 -fsanitize=shift-exponent -emit-llvm -std=c2x -triple=x86_64-unknown-linux -o - | FileCheck %s // Checking that the code generation is using the unextended/untruncated // exponent values and capping the values accordingly // CHECK-LABEL: define{{.*}} i32 @test_left_variable int test_left_variable(unsigned _BitInt(5) b, unsigned _BitInt(2) e) { // CHECK: load i8 // CHECK: [[E_REG:%.+]] = trunc i8 {{.*}} to [[E_SIZE:i2]] // CHECK: icmp ule [[E_SIZE]] [[E_REG]], -1, return b << e; } // CHECK-LABEL: define{{.*}} i32 @test_right_variable int test_right_variable(unsigned _BitInt(2) b, unsigned _BitInt(3) e) { // CHECK: load i8 // CHECK: [[E_REG:%.+]] = trunc i8 {{.*}} to [[E_SIZE:i3]] // CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1, return b >> e; } // Old code generation would give false positives on left shifts when: // value(e) > (width(b) - 1 % 2 ** width(e)) // CHECK-LABEL: define{{.*}} i32 @test_left_literal int test_left_literal(unsigned _BitInt(5) b) { // CHECK-NOT: br i1 false, label %cont, label %handler.shift_out_of_bounds // CHECK: br i1 true, label %cont, label %handler.shift_out_of_bounds return b << 3uwb; } // Old code generation would give false positives on right shifts when: // (value(e) % 2 ** width(b)) < width(b) // CHECK-LABEL: define{{.*}} i32 @test_right_literal int test_right_literal(unsigned _BitInt(2) b) { // CHECK-NOT: br i1 true, label %cont, label %handler.shift_out_of_bounds // CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds return b >> 4uwb; } // CHECK-LABEL: define{{.*}} i32 @test_signed_left_variable int test_signed_left_variable(unsigned _BitInt(15) b, _BitInt(2) e) { // CHECK: load i8 // CHECK: [[E_REG:%.+]] = trunc i8 {{.*}} to [[E_SIZE:i2]] // CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1, return b << e; } // CHECK-LABEL: define{{.*}} i32 @test_signed_right_variable int test_signed_right_variable(unsigned _BitInt(32) b, _BitInt(4) e) { // CHECK: load i8 // CHECK: [[E_REG:%.+]] = trunc i8 {{.*}} to [[E_SIZE:i4]] // CHECK: icmp ule [[E_SIZE]] [[E_REG]], 7, return b >> e; } // CHECK-LABEL: define{{.*}} i32 @test_signed_left_literal int test_signed_left_literal(unsigned _BitInt(16) b) { // CHECK-NOT: br i1 true, label %cont, label %handler.shift_out_of_bounds // CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds return b << (_BitInt(4))-2wb; } // CHECK-LABEL: define{{.*}} i32 @test_signed_right_literal int test_signed_right_literal(unsigned _BitInt(16) b) { // CHECK-NOT: br i1 true, label %cont, label %handler.shift_out_of_bounds // CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds return b >> (_BitInt(4))-8wb; }