Jameson Nash 96ab74bf17
[InstCombine] remove undef loads, such as memcpy from undef (#143958)
Extend `isAllocSiteRemovable` to be able to check if the ModRef info
indicates the alloca is only Ref or only Mod, and be able to remove it
accordingly. It seemed that there were a surprising number of
benchmarks with this pattern which weren't getting optimized previously
(due to MemorySSA walk limits). There were somewhat more existing tests
than I'd like to have modified which were simply doing exactly this
pattern (and thus relying on undef memory). Claude code contributed the
new tests (and found an important typo that I'd made).

This implements the discussion in
https://github.com/llvm/llvm-project/pull/143782#discussion_r2142720376.
2025-06-20 10:32:31 -04:00

92 lines
2.9 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-grtev4-linux-gnu"
define i32 @test_plain(i1 %f, ptr %a, ptr %b) {
; CHECK-LABEL: @test_plain(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[B:%.*]] = select i1 [[F:%.*]], ptr [[A:%.*]], ptr [[B1:%.*]]
; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8
; CHECK-NEXT: ret i32 [[B_VAL]]
;
entry:
%sel = select i1 %f, ptr %a, ptr %b
%l = load i32, ptr %sel, align 8
ret i32 %l
}
; Don't speculate as the condition may control which memory is valid from
; sanitizer perspective.
define i32 @test_asan(i1 %f) sanitize_address {
; CHECK-LABEL: @test_asan(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[F:%.*]], ptr [[A]], ptr [[B]]
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SEL]], align 8
; CHECK-NEXT: ret i32 [[L]]
;
entry:
%a = alloca i32, align 8
%b = alloca i32, align 8
%sel = select i1 %f, ptr %a, ptr %b
%l = load i32, ptr %sel, align 8
ret i32 %l
}
; Don't speculate as the condition may control which memory is valid from
; sanitizer perspective.
define i32 @test_hwasan(i1 %f) sanitize_hwaddress {
; CHECK-LABEL: @test_hwasan(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[F:%.*]], ptr [[A]], ptr [[B]]
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SEL]], align 8
; CHECK-NEXT: ret i32 [[L]]
;
entry:
%a = alloca i32, align 8
%b = alloca i32, align 8
%sel = select i1 %f, ptr %a, ptr %b
%l = load i32, ptr %sel, align 8
ret i32 %l
}
; Don't speculate as the condition may control which memory is valid from
; sanitizer perspective.
define i32 @test_tsan(i1 %f) sanitize_thread {
; CHECK-LABEL: @test_tsan(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[F:%.*]], ptr [[A]], ptr [[B]]
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SEL]], align 8
; CHECK-NEXT: ret i32 [[L]]
;
entry:
%a = alloca i32, align 8
%b = alloca i32, align 8
%sel = select i1 %f, ptr %a, ptr %b
%l = load i32, ptr %sel, align 8
ret i32 %l
}
; Msan just propagates shadow, even if speculated load accesses uninitialized
; value, instrumentation will select shadow of the desired value anyway.
define i32 @test_msan(i1 %f, ptr %a, ptr %b) sanitize_memory {
; CHECK-LABEL: @test_msan(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[B:%.*]] = select i1 [[F:%.*]], ptr [[A:%.*]], ptr [[B1:%.*]]
; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8
; CHECK-NEXT: ret i32 [[B_VAL]]
;
entry:
%sel = select i1 %f, ptr %a, ptr %b
%l = load i32, ptr %sel, align 8
ret i32 %l
}