diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index f2cf7a76e54..e9b78acbfe5 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -1744,11 +1744,22 @@ struct MemorySanitizerVisitor : public InstVisitor { void visitSelectInst(SelectInst& I) { IRBuilder<> IRB(&I); // a = select b, c, d - // Sa = (sext Sb) | (select b, Sc, Sd) Value *S = IRB.CreateSelect(I.getCondition(), getShadow(I.getTrueValue()), getShadow(I.getFalseValue())); - Value *S2 = IRB.CreateSExt(getShadow(I.getCondition()), S->getType()); - setShadow(&I, IRB.CreateOr(S, S2, "_msprop")); + if (I.getType()->isAggregateType()) { + // To avoid "sign extending" i1 to an arbitrary aggregate type, we just do + // an extra "select". This results in much more compact IR. + // Sa = select Sb, poisoned, (select b, Sc, Sd) + S = IRB.CreateSelect(getShadow(I.getCondition()), + getPoisonedShadow(getShadowTy(I.getType())), S, + "_msprop_select_agg"); + } else { + // Sa = (sext Sb) | (select b, Sc, Sd) + S = IRB.CreateOr( + S, IRB.CreateSExt(getShadow(I.getCondition()), S->getType()), + "_msprop_select"); + } + setShadow(&I, S); if (MS.TrackOrigins) { // Origins are always i32, so any vector conditions must be flattened. // FIXME: consider tracking vector origins for app vectors? diff --git a/test/Instrumentation/MemorySanitizer/msan_basic.ll b/test/Instrumentation/MemorySanitizer/msan_basic.ll index 466e2528dd9..e87bf530273 100644 --- a/test/Instrumentation/MemorySanitizer/msan_basic.ll +++ b/test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -290,6 +290,19 @@ entry: ; CHECK-ORIGINS: ret <8 x i16> +define { i64, i64 } @SelectStruct(i1 zeroext %x, { i64, i64 } %a, { i64, i64 } %b) readnone sanitize_memory { +entry: + %c = select i1 %x, { i64, i64 } %a, { i64, i64 } %b + ret { i64, i64 } %c +} + +; CHECK: @SelectStruct +; CHECK: select i1 {{.*}}, { i64, i64 } +; CHECK-NEXT: select i1 {{.*}}, { i64, i64 } { i64 -1, i64 -1 }, { i64, i64 } +; CHECK-NEXT: select i1 {{.*}}, { i64, i64 } +; CHECK: ret { i64, i64 } + + define i8* @IntToPtr(i64 %x) nounwind uwtable readnone sanitize_memory { entry: %0 = inttoptr i64 %x to i8*