llvm.org GIT mirror llvm / 792a173
[msan] Fix handling of multiplication by a constant with a number of trailing zeroes. Multiplication by an integer with a number of trailing zero bits leaves the same number of lower bits of the result initialized to zero. This change makes MSan take this into account in the case of multiplication by a compile-time constant. We don't handle the general, non-constant, case because (a) it's not going to be cheap (computation-wise); (b) multiplication by a partially uninitialized value in user code is a bad idea anyway. Constant case must be handled because it appears from LLVM optimization of a completely valid user code, as the test case in compiler-rt demonstrates. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211092 91177308-0d34-0410-b5e6-96231b3b80d8 Evgeniy Stepanov 5 years ago
2 changed file(s) with 143 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
13961396 SC.Done(&I);
13971397 }
13981398
1399 // \brief Handle multiplication by constant.
1400 //
1401 // Handle a special case of multiplication by constant that may have one or
1402 // more zeros in the lower bits. This makes corresponding number of lower bits
1403 // of the result zero as well. We model it by shifting the other operand
1404 // shadow left by the required number of bits. Effectively, we transform
1405 // (X * (A * 2**B)) to ((X << B) * A) and instrument (X << B) as (Sx << B).
1406 // We use multiplication by 2**N instead of shift to cover the case of
1407 // multiplication by 0, which may occur in some elements of a vector operand.
1408 void handleMulByConstant(BinaryOperator &I, Constant *ConstArg,
1409 Value *OtherArg) {
1410 Constant *ShadowMul;
1411 Type *Ty = ConstArg->getType();
1412 if (Ty->isVectorTy()) {
1413 unsigned NumElements = Ty->getVectorNumElements();
1414 Type *EltTy = Ty->getSequentialElementType();
1415 SmallVector Elements;
1416 for (unsigned Idx = 0; Idx < NumElements; ++Idx) {
1417 ConstantInt *Elt =
1418 dyn_cast(ConstArg->getAggregateElement(Idx));
1419 APInt V = Elt->getValue();
1420 APInt V2 = APInt(V.getBitWidth(), 1) << V.countTrailingZeros();
1421 Elements.push_back(ConstantInt::get(EltTy, V2));
1422 }
1423 ShadowMul = ConstantVector::get(Elements);
1424 } else {
1425 ConstantInt *Elt = dyn_cast(ConstArg);
1426 APInt V = Elt->getValue();
1427 APInt V2 = APInt(V.getBitWidth(), 1) << V.countTrailingZeros();
1428 ShadowMul = ConstantInt::get(Elt->getType(), V2);
1429 }
1430
1431 IRBuilder<> IRB(&I);
1432 setShadow(&I,
1433 IRB.CreateMul(getShadow(OtherArg), ShadowMul, "msprop_mul_cst"));
1434 setOrigin(&I, getOrigin(OtherArg));
1435 }
1436
1437 void visitMul(BinaryOperator &I) {
1438 Constant *constOp0 = dyn_cast(I.getOperand(0));
1439 Constant *constOp1 = dyn_cast(I.getOperand(1));
1440 if (constOp0 && !constOp1)
1441 handleMulByConstant(I, constOp0, I.getOperand(1));
1442 else if (constOp1 && !constOp0)
1443 handleMulByConstant(I, constOp1, I.getOperand(0));
1444 else
1445 handleShadowOr(I);
1446 }
1447
13991448 void visitFAdd(BinaryOperator &I) { handleShadowOr(I); }
14001449 void visitFSub(BinaryOperator &I) { handleShadowOr(I); }
14011450 void visitFMul(BinaryOperator &I) { handleShadowOr(I); }
14021451 void visitAdd(BinaryOperator &I) { handleShadowOr(I); }
14031452 void visitSub(BinaryOperator &I) { handleShadowOr(I); }
14041453 void visitXor(BinaryOperator &I) { handleShadowOr(I); }
1405 void visitMul(BinaryOperator &I) { handleShadowOr(I); }
14061454
14071455 void handleDiv(Instruction &I) {
14081456 IRBuilder<> IRB(&I);
0 ; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
1
2 target 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"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 ; Check instrumentation mul when one of the operands is a constant.
6
7 define i64 @MulConst(i64 %x) sanitize_memory {
8 entry:
9 %y = mul i64 %x, 42949672960000
10 ret i64 %y
11 }
12
13 ; 42949672960000 = 2**32 * 10000
14 ; 36 trailing zero bits
15 ; 68719476736 = 2**36
16
17 ; CHECK-LABEL: @MulConst(
18 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_param_tls
19 ; CHECK: [[B:%.*]] = mul i64 [[A]], 68719476736
20 ; CHECK: store i64 [[B]], i64* {{.*}} @__msan_retval_tls
21
22
23 define i64 @MulZero(i64 %x) sanitize_memory {
24 entry:
25 %y = mul i64 %x, 0
26 ret i64 %y
27 }
28
29 ; CHECK-LABEL: @MulZero(
30 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_param_tls
31 ; CHECK: [[B:%.*]] = mul i64 [[A]], 0{{$}}
32 ; CHECK: store i64 [[B]], i64* {{.*}} @__msan_retval_tls
33
34
35 define i64 @MulNeg(i64 %x) sanitize_memory {
36 entry:
37 %y = mul i64 %x, -16
38 ret i64 %y
39 }
40
41 ; CHECK-LABEL: @MulNeg(
42 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_param_tls
43 ; CHECK: [[B:%.*]] = mul i64 [[A]], 16
44 ; CHECK: store i64 [[B]], i64* {{.*}} @__msan_retval_tls
45
46
47 define i64 @MulNeg2(i64 %x) sanitize_memory {
48 entry:
49 %y = mul i64 %x, -48
50 ret i64 %y
51 }
52
53 ; CHECK-LABEL: @MulNeg2(
54 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_param_tls
55 ; CHECK: [[B:%.*]] = mul i64 [[A]], 16
56 ; CHECK: store i64 [[B]], i64* {{.*}} @__msan_retval_tls
57
58
59 define i64 @MulOdd(i64 %x) sanitize_memory {
60 entry:
61 %y = mul i64 %x, 12345
62 ret i64 %y
63 }
64
65 ; CHECK-LABEL: @MulOdd(
66 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_param_tls
67 ; CHECK: [[B:%.*]] = mul i64 [[A]], 1
68 ; CHECK: store i64 [[B]], i64* {{.*}} @__msan_retval_tls
69
70
71 define i64 @MulLarge(i64 %x) sanitize_memory {
72 entry:
73 %y = mul i64 %x, -9223372036854775808
74 ret i64 %y
75 }
76
77 ; -9223372036854775808 = 0x7000000000000000
78
79 ; CHECK-LABEL: @MulLarge(
80 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_param_tls
81 ; CHECK: [[B:%.*]] = mul i64 [[A]], -9223372036854775808
82 ; CHECK: store i64 [[B]], i64* {{.*}} @__msan_retval_tls
83
84 define <4 x i32> @MulVectorConst(<4 x i32> %x) sanitize_memory {
85 entry:
86 %y = mul <4 x i32> %x,
87 ret <4 x i32> %y
88 }
89
90 ; CHECK-LABEL: @MulVectorConst(
91 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_param_tls
92 ; CHECK: [[B:%.*]] = mul <4 x i32> [[A]],
93 ; CHECK: store <4 x i32> [[B]], <4 x i32>* {{.*}} @__msan_retval_tls