Nikita Popov 90ba33099c
[InstCombine] Canonicalize constant GEPs to i8 source element type (#68882)
This patch canonicalizes getelementptr instructions with constant
indices to use the `i8` source element type. This makes it easier for
optimizations to recognize that two GEPs are identical, because they
don't need to see past many different ways to express the same offset.

This is a first step towards
https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699.
This is limited to constant GEPs only for now, as they have a clear
canonical form, while we're not yet sure how exactly to deal with
variable indices.

The test llvm/test/Transforms/PhaseOrdering/switch_with_geps.ll gives
two representative examples of the kind of optimization improvement we
expect from this change. In the first test SimplifyCFG can now realize
that all switch branches are actually the same. In the second test it
can convert it into simple arithmetic. These are representative of
common optimization failures we see in Rust.

Fixes https://github.com/llvm/llvm-project/issues/69841.
2024-01-24 15:25:29 +01:00

56 lines
1.8 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -O3 -S < %s | FileCheck %s
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"
target triple = "x86_64-apple-macosx10.6.7"
declare ptr @malloc(i64)
declare void @free(ptr)
; PR2338
define void @test1() nounwind ssp {
; CHECK-LABEL: @test1(
; CHECK-NEXT: ret void
;
%retval = alloca i32, align 4
%i = alloca ptr, align 8
%call = call ptr @malloc(i64 1)
store ptr %call, ptr %i, align 8
%tmp = load ptr, ptr %i, align 8
store i8 1, ptr %tmp
%tmp1 = load ptr, ptr %i, align 8
call void @free(ptr %tmp1)
ret void
}
; This function exposes a phase ordering problem when InstCombine is
; turning %add into a bitmask, making it difficult to spot a 0 return value.
;
; It it also important that %add is expressed as a multiple of %div so scalar
; evolution can recognize it.
define i32 @test2(i32 %a, ptr %p) nounwind uwtable ssp {
; CHECK-LABEL: @test2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[DIV1:%.*]] = lshr i32 [[A:%.*]], 2
; CHECK-NEXT: store i32 [[DIV1]], ptr [[P:%.*]], align 4
; CHECK-NEXT: [[ADD:%.*]] = shl nuw nsw i32 [[DIV1]], 1
; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4
; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX1]], align 4
; CHECK-NEXT: ret i32 0
;
entry:
%div = udiv i32 %a, 4
store i32 %div, ptr %p, align 4
%add = add i32 %div, %div
%arrayidx1 = getelementptr inbounds i32, ptr %p, i64 1
store i32 %add, ptr %arrayidx1, align 4
%arrayidx2 = getelementptr inbounds i32, ptr %p, i64 1
%0 = load i32, ptr %arrayidx2, align 4
%1 = load i32, ptr %p, align 4
%mul = mul i32 2, %1
%sub = sub i32 %0, %mul
ret i32 %sub
}