1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=poison-checking -S < %s | FileCheck %s 3 4; This file contains tests to exercise the UB triggering instructions with 5; a potential source of UB. The UB source is kept simple; we focus on the 6; UB triggering instructions here. 7 8define void @store(i8* %base, i32 %a) { 9; CHECK-LABEL: @store( 10; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 11; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 12; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 13; CHECK-NEXT: [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]] 14; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 15; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 16; CHECK-NEXT: store i8 0, i8* [[P]] 17; CHECK-NEXT: ret void 18; 19 %add = add nsw i32 %a, 1 20 %p = getelementptr i8, i8* %base, i32 %add 21 store i8 0, i8* %p 22 ret void 23} 24 25define void @load(i8* %base, i32 %a) { 26; CHECK-LABEL: @load( 27; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 28; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 29; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 30; CHECK-NEXT: [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]] 31; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 32; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 33; CHECK-NEXT: [[TMP4:%.*]] = load volatile i8, i8* [[P]] 34; CHECK-NEXT: ret void 35; 36 %add = add nsw i32 %a, 1 37 %p = getelementptr i8, i8* %base, i32 %add 38 load volatile i8, i8* %p 39 ret void 40} 41 42define void @atomicrmw(i8* %base, i32 %a) { 43; CHECK-LABEL: @atomicrmw( 44; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 45; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 46; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 47; CHECK-NEXT: [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]] 48; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 49; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 50; CHECK-NEXT: [[TMP4:%.*]] = atomicrmw add i8* [[P]], i8 1 seq_cst 51; CHECK-NEXT: ret void 52; 53 %add = add nsw i32 %a, 1 54 %p = getelementptr i8, i8* %base, i32 %add 55 atomicrmw add i8* %p, i8 1 seq_cst 56 ret void 57} 58 59define void @cmpxchg(i8* %base, i32 %a) { 60; CHECK-LABEL: @cmpxchg( 61; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 62; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 63; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 64; CHECK-NEXT: [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]] 65; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 66; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 67; CHECK-NEXT: [[TMP4:%.*]] = cmpxchg i8* [[P]], i8 1, i8 0 seq_cst seq_cst 68; CHECK-NEXT: ret void 69; 70 %add = add nsw i32 %a, 1 71 %p = getelementptr i8, i8* %base, i32 %add 72 cmpxchg i8* %p, i8 1, i8 0 seq_cst seq_cst 73 ret void 74} 75 76define i32 @udiv(i8* %base, i32 %a) { 77; CHECK-LABEL: @udiv( 78; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 79; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 80; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1 81; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 82; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 83; CHECK-NEXT: [[RES:%.*]] = udiv i32 2048, [[ADD]] 84; CHECK-NEXT: ret i32 [[RES]] 85; 86 %add = add nuw i32 %a, 1 87 %res = udiv i32 2048, %add 88 ret i32 %res 89} 90 91define i32 @sdiv(i8* %base, i32 %a) { 92; CHECK-LABEL: @sdiv( 93; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 94; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 95; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1 96; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 97; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 98; CHECK-NEXT: [[RES:%.*]] = sdiv i32 2048, [[ADD]] 99; CHECK-NEXT: ret i32 [[RES]] 100; 101 %add = add nuw i32 %a, 1 102 %res = sdiv i32 2048, %add 103 ret i32 %res 104} 105 106define i32 @urem(i8* %base, i32 %a) { 107; CHECK-LABEL: @urem( 108; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 109; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 110; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1 111; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 112; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 113; CHECK-NEXT: [[RES:%.*]] = urem i32 2048, [[ADD]] 114; CHECK-NEXT: ret i32 [[RES]] 115; 116 %add = add nuw i32 %a, 1 117 %res = urem i32 2048, %add 118 ret i32 %res 119} 120 121define i32 @srem(i8* %base, i32 %a) { 122; CHECK-LABEL: @srem( 123; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1) 124; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 125; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1 126; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true 127; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]]) 128; CHECK-NEXT: [[RES:%.*]] = srem i32 2048, [[ADD]] 129; CHECK-NEXT: ret i32 [[RES]] 130; 131 %add = add nuw i32 %a, 1 132 %res = srem i32 2048, %add 133 ret i32 %res 134} 135 136 137 138