1; RUN: opt < %s -passes=dfsan -dfsan-track-origins=1 -S | FileCheck %s 2target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" 3target triple = "x86_64-unknown-linux-gnu" 4 5; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]] 6; CHECK: @__dfsan_retval_tls = external thread_local(initialexec) global [[TLS_ARR]] 7define float @unop(float %f) { 8 ; CHECK: @unop.dfsan 9 ; CHECK: [[FO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 10 ; CHECK: store i32 [[FO]], ptr @__dfsan_retval_origin_tls, align 4 11 12 %r = fneg float %f 13 ret float %r 14} 15 16define i1 @binop(i1 %a, i1 %b) { 17 ; CHECK: @binop.dfsan 18 ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 19 ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 20 ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2 21 ; CHECK: [[NE:%.*]] = icmp ne i8 [[BS]], 0 22 ; CHECK: [[MO:%.*]] = select i1 [[NE]], i32 [[BO]], i32 [[AO]] 23 ; CHECK: store i32 [[MO]], ptr @__dfsan_retval_origin_tls, align 4 24 25 %r = add i1 %a, %b 26 ret i1 %r 27} 28 29define i8 @castop(ptr %p) { 30 ; CHECK: @castop.dfsan 31 ; CHECK: [[PO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 32 ; CHECK: store i32 [[PO]], ptr @__dfsan_retval_origin_tls, align 4 33 34 %r = ptrtoint ptr %p to i8 35 ret i8 %r 36} 37 38define i1 @cmpop(i1 %a, i1 %b) { 39 ; CHECK: @cmpop.dfsan 40 ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 41 ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 42 ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2 43 ; CHECK: [[NE:%.*]] = icmp ne i8 [[BS]], 0 44 ; CHECK: [[MO:%.*]] = select i1 [[NE]], i32 [[BO]], i32 [[AO]] 45 ; CHECK: store i32 [[MO]], ptr @__dfsan_retval_origin_tls, align 4 46 47 %r = icmp eq i1 %a, %b 48 ret i1 %r 49} 50 51define ptr @gepop(ptr %p, i32 %a, i32 %b, i32 %c) { 52 ; CHECK: @gepop.dfsan 53 ; CHECK: [[CO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 3), align 4 54 ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 2), align 4 55 ; CHECK: [[AO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 56 ; CHECK: [[PO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 57 ; CHECK: [[CS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 6) to ptr), align 2 58 ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align 2 59 ; CHECK: [[AS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2 60 ; CHECK: [[AS_NE:%.*]] = icmp ne i8 [[AS]], 0 61 ; CHECK: [[APO:%.*]] = select i1 [[AS_NE]], i32 [[AO]], i32 [[PO]] 62 ; CHECK: [[BS_NE:%.*]] = icmp ne i8 [[BS]], 0 63 ; CHECK: [[ABPO:%.*]] = select i1 [[BS_NE]], i32 [[BO]], i32 [[APO]] 64 ; CHECK: [[CS_NE:%.*]] = icmp ne i8 [[CS]], 0 65 ; CHECK: [[ABCPO:%.*]] = select i1 [[CS_NE]], i32 [[CO]], i32 [[ABPO]] 66 ; CHECK: store i32 [[ABCPO]], ptr @__dfsan_retval_origin_tls, align 4 67 68 %e = getelementptr [10 x [20 x i32]], ptr %p, i32 %a, i32 %b, i32 %c 69 ret ptr %e 70} 71 72define i32 @eeop(<4 x i32> %a, i32 %b) { 73 ; CHECK: @eeop.dfsan 74 ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 75 ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 76 ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2 77 ; CHECK: [[NE:%.*]] = icmp ne i8 [[BS]], 0 78 ; CHECK: [[MO:%.*]] = select i1 [[NE]], i32 [[BO]], i32 [[AO]] 79 ; CHECK: store i32 [[MO]], ptr @__dfsan_retval_origin_tls, align 4 80 81 %e = extractelement <4 x i32> %a, i32 %b 82 ret i32 %e 83} 84 85define <4 x i32> @ieop(<4 x i32> %p, i32 %a, i32 %b) { 86 ; CHECK: @ieop.dfsan 87 ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 2), align 4 88 ; CHECK: [[AO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 89 ; CHECK: [[PO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 90 ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align 2 91 ; CHECK: [[AS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2 92 ; CHECK: [[AS_NE:%.*]] = icmp ne i8 [[AS]], 0 93 ; CHECK: [[APO:%.*]] = select i1 [[AS_NE]], i32 [[AO]], i32 [[PO]] 94 ; CHECK: [[BS_NE:%.*]] = icmp ne i8 [[BS]], 0 95 ; CHECK: [[ABPO:%.*]] = select i1 [[BS_NE]], i32 [[BO]], i32 [[APO]] 96 ; CHECK: store i32 [[ABPO]], ptr @__dfsan_retval_origin_tls, align 4 97 98 %e = insertelement <4 x i32> %p, i32 %a, i32 %b 99 ret <4 x i32> %e 100} 101 102define <4 x i32> @svop(<4 x i32> %a, <4 x i32> %b) { 103 ; CHECK: @svop.dfsan 104 ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 105 ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 106 ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2 107 ; CHECK: [[NE:%.*]] = icmp ne i8 [[BS]], 0 108 ; CHECK: [[MO:%.*]] = select i1 [[NE]], i32 [[BO]], i32 [[AO]] 109 ; CHECK: store i32 [[MO]], ptr @__dfsan_retval_origin_tls, align 4 110 111 %e = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5> 112 ret <4 x i32> %e 113} 114 115define i32 @evop({i32, float} %a) { 116 ; CHECK: @evop.dfsan 117 ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 118 ; CHECK: store i32 [[AO]], ptr @__dfsan_retval_origin_tls, align 4 119 120 %e = extractvalue {i32, float} %a, 0 121 ret i32 %e 122} 123 124define {i32, {float, float}} @ivop({i32, {float, float}} %a, {float, float} %b) { 125 ; CHECK: @ivop.dfsan 126 ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 127 ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4 128 ; COMM: TODO simplify the expression 4 to 129 ; COMM: 6, if shadow-tls-alignment is updated to match shadow 130 ; CHECK: [[BS:%.*]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align 2 131 ; CHECK: [[BS0:%.*]] = extractvalue { i8, i8 } [[BS]], 0 132 ; CHECK: [[BS1:%.*]] = extractvalue { i8, i8 } [[BS]], 1 133 ; CHECK: [[BS01:%.*]] = or i8 [[BS0]], [[BS1]] 134 ; CHECK: [[NE:%.*]] = icmp ne i8 [[BS01]], 0 135 ; CHECK: [[MO:%.*]] = select i1 [[NE]], i32 [[BO]], i32 [[AO]] 136 ; CHECK: store i32 [[MO]], ptr @__dfsan_retval_origin_tls, align 4 137 138 %e = insertvalue {i32, {float, float}} %a, {float, float} %b, 1 139 ret {i32, {float, float}} %e 140} 141