From 967f6ad3e1c4a01a9c1ce2ada91e07e396c7de19 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 28 May 2015 18:39:17 +0000 Subject: [PATCH] [InstCombine] Fold IntToPtr and PtrToInt into preceding loads. Currently we only fold a BitCast into a Load when the BitCast is its only user. Do the same for any no-op cast. Differential Revision: http://reviews.llvm.org/D9152 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238452 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombineLoadStoreAlloca.cpp | 15 ++-- test/Transforms/InstCombine/load-bitcast32.ll | 79 +++++++++++++++++++ test/Transforms/InstCombine/load-bitcast64.ll | 78 ++++++++++++++++++ 3 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 test/Transforms/InstCombine/load-bitcast32.ll create mode 100644 test/Transforms/InstCombine/load-bitcast64.ll diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 5aa59c69f39..e7a45330d95 100644 --- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -483,12 +483,17 @@ static Instruction *combineLoadToOperationType(InstCombiner &IC, LoadInst &LI) { } // Fold away bit casts of the loaded value by loading the desired type. + // We can do this for BitCastInsts as well as casts from and to pointer types, + // as long as those are noops (i.e., the source or dest type have the same + // bitwidth as the target's pointers). if (LI.hasOneUse()) - if (auto *BC = dyn_cast(LI.user_back())) { - LoadInst *NewLoad = combineLoadToNewType(IC, LI, BC->getDestTy()); - BC->replaceAllUsesWith(NewLoad); - IC.EraseInstFromFunction(*BC); - return &LI; + if (auto* CI = dyn_cast(LI.user_back())) { + if (CI->isNoopCast(DL)) { + LoadInst *NewLoad = combineLoadToNewType(IC, LI, CI->getDestTy()); + CI->replaceAllUsesWith(NewLoad); + IC.EraseInstFromFunction(*CI); + return &LI; + } } // FIXME: We should also canonicalize loads of vectors when their elements are diff --git a/test/Transforms/InstCombine/load-bitcast32.ll b/test/Transforms/InstCombine/load-bitcast32.ll new file mode 100644 index 00000000000..b1c78a8a314 --- /dev/null +++ b/test/Transforms/InstCombine/load-bitcast32.ll @@ -0,0 +1,79 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +target datalayout = "p:32:32:32" + + +define i64* @test1(i8* %x) { +entry: +; CHECK-LABEL: @test1( +; CHECK: load i64, i64* +; CHECK: ret + %a = bitcast i8* %x to i64* + %b = load i64, i64* %a + %c = inttoptr i64 %b to i64* + + ret i64* %c +} + +define i32* @test2(i8* %x) { +entry: +; CHECK-LABEL: @test2( +; CHECK: load i32*, i32** +; CHECK: ret + %a = bitcast i8* %x to i32* + %b = load i32, i32* %a + %c = inttoptr i32 %b to i32* + + ret i32* %c +} + +define i64* @test3(i8* %x) { +entry: +; CHECK-LABEL: @test3( +; CHECK: load i64*, i64** +; CHECK: ret + %a = bitcast i8* %x to i32* + %b = load i32, i32* %a + %c = inttoptr i32 %b to i64* + + ret i64* %c +} + +define i64 @test4(i8* %x) { +entry: +; CHECK-LABEL: @test4( +; CHECK: load i32, i32* +; CHECK: zext +; CHECK: ret + %a = bitcast i8* %x to i64** + %b = load i64*, i64** %a + %c = ptrtoint i64* %b to i64 + + ret i64 %c +} + +define i32 @test5(i8* %x) { +entry: +; CHECK-LABEL: @test5( +; CHECK: load i32, i32* +; CHECK: ret + %a = bitcast i8* %x to i32** + %b = load i32*, i32** %a + %c = ptrtoint i32* %b to i32 + + ret i32 %c +} + +define i64 @test6(i8* %x) { +entry: +; CHECK-LABEL: @test6( +; CHECK: load i32, i32* +; CHECK: zext +; CHECK: ret + %a = bitcast i8* %x to i32** + %b = load i32*, i32** %a + %c = ptrtoint i32* %b to i64 + + ret i64 %c +} + diff --git a/test/Transforms/InstCombine/load-bitcast64.ll b/test/Transforms/InstCombine/load-bitcast64.ll new file mode 100644 index 00000000000..d14c686d83e --- /dev/null +++ b/test/Transforms/InstCombine/load-bitcast64.ll @@ -0,0 +1,78 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +target datalayout = "p:64:64:64" + + +define i64* @test1(i8* %x) { +entry: +; CHECK-LABEL: @test1( +; CHECK: load i64*, i64** +; CHECK: ret + %a = bitcast i8* %x to i64* + %b = load i64, i64* %a + %c = inttoptr i64 %b to i64* + + ret i64* %c +} + +define i32* @test2(i8* %x) { +entry: +; CHECK-LABEL: @test2( +; CHECK: load i32, i32* +; CHECK: ret + %a = bitcast i8* %x to i32* + %b = load i32, i32* %a + %c = inttoptr i32 %b to i32* + + ret i32* %c +} + +define i64* @test3(i8* %x) { +entry: +; CHECK-LABEL: @test3( +; CHECK: load i32, i32* +; CHECK: ret + %a = bitcast i8* %x to i32* + %b = load i32, i32* %a + %c = inttoptr i32 %b to i64* + + ret i64* %c +} + +define i64 @test4(i8* %x) { +entry: +; CHECK-LABEL: @test4( +; CHECK: load i64, i64* +; CHECK: ret + %a = bitcast i8* %x to i64** + %b = load i64*, i64** %a + %c = ptrtoint i64* %b to i64 + + ret i64 %c +} + +define i32 @test5(i8* %x) { +entry: +; CHECK-LABEL: @test5( +; CHECK: load i64, i64* +; CHECK: trunc +; CHECK: ret + %a = bitcast i8* %x to i32** + %b = load i32*, i32** %a + %c = ptrtoint i32* %b to i32 + + ret i32 %c +} + +define i64 @test6(i8* %x) { +entry: +; CHECK-LABEL: @test6( +; CHECK: load i64, i64* +; CHECK: ret + %a = bitcast i8* %x to i32** + %b = load i32*, i32** %a + %c = ptrtoint i32* %b to i64 + + ret i64 %c +} + -- 2.34.1