From: Matt Arsenault Date: Wed, 5 Jun 2019 21:15:52 +0000 (+0000) Subject: NewGVN: Handle addrspacecast X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4eeaa82a83dc54693746c0523c11fc9b3416e5a7;p=llvm NewGVN: Handle addrspacecast The AllConstant check needs to be moved out of the if/else if chain to avoid a test regression. The "there is no SimplifyZExt" comment puzzles me, since there is SimplifyCastInst. Additionally, the Simplify* calls seem to not see the operand as constant, so this needs to be tried if the simplify failed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362653 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/NewGVN.cpp b/lib/Transforms/Scalar/NewGVN.cpp index c54da4f72df..412bd235d79 100644 --- a/lib/Transforms/Scalar/NewGVN.cpp +++ b/lib/Transforms/Scalar/NewGVN.cpp @@ -1166,9 +1166,9 @@ const Expression *NewGVN::createExpression(Instruction *I) const { SimplifyBinOp(E->getOpcode(), E->getOperand(0), E->getOperand(1), SQ); if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; - } else if (auto *BI = dyn_cast(I)) { + } else if (auto *CI = dyn_cast(I)) { Value *V = - SimplifyCastInst(BI->getOpcode(), BI->getOperand(0), BI->getType(), SQ); + SimplifyCastInst(CI->getOpcode(), E->getOperand(0), CI->getType(), SQ); if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; } else if (isa(I)) { @@ -1984,6 +1984,7 @@ NewGVN::performSymbolicEvaluation(Value *V, E = performSymbolicLoadEvaluation(I); break; case Instruction::BitCast: + case Instruction::AddrSpaceCast: E = createExpression(I); break; case Instruction::ICmp: diff --git a/test/Transforms/NewGVN/addrspacecast.ll b/test/Transforms/NewGVN/addrspacecast.ll new file mode 100644 index 00000000000..e9cef440cfb --- /dev/null +++ b/test/Transforms/NewGVN/addrspacecast.ll @@ -0,0 +1,108 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -newgvn < %s | FileCheck %s + +define i32 addrspace(1)* @addrspacecast(i32* %ptr) { +; CHECK-LABEL: @addrspacecast( +; CHECK-NEXT: block1: +; CHECK-NEXT: [[Z1:%.*]] = addrspacecast i32* [[PTR:%.*]] to i32 addrspace(1)* +; CHECK-NEXT: br label [[BLOCK2:%.*]] +; CHECK: block2: +; CHECK-NEXT: store i32 addrspace(1)* [[Z1]], i32 addrspace(1)** undef +; CHECK-NEXT: ret i32 addrspace(1)* [[Z1]] +; +block1: + %z1 = addrspacecast i32* %ptr to i32 addrspace(1)* + br label %block2 + +block2: + %z2 = addrspacecast i32* %ptr to i32 addrspace(1)* + store i32 addrspace(1)* %z1, i32 addrspace(1)** undef + ret i32 addrspace(1)* %z2 +} + +; Make sure casts with the same source value but different result +; address spaces aren't incorrectly merged. +define i32 addrspace(1)* @addrspacecast_different_result_types(i32* %ptr) { +; CHECK-LABEL: @addrspacecast_different_result_types( +; CHECK-NEXT: block1: +; CHECK-NEXT: [[Z1:%.*]] = addrspacecast i32* [[PTR:%.*]] to i32 addrspace(2)* +; CHECK-NEXT: br label [[BLOCK2:%.*]] +; CHECK: block2: +; CHECK-NEXT: [[Z2:%.*]] = addrspacecast i32* [[PTR]] to i32 addrspace(1)* +; CHECK-NEXT: store i32 addrspace(2)* [[Z1]], i32 addrspace(2)** undef +; CHECK-NEXT: ret i32 addrspace(1)* [[Z2]] +; +block1: + %z1 = addrspacecast i32* %ptr to i32 addrspace(2)* + br label %block2 + +block2: + %z2 = addrspacecast i32* %ptr to i32 addrspace(1)* + store i32 addrspace(2)* %z1, i32 addrspace(2)** undef + ret i32 addrspace(1)* %z2 +} + +define i32 addrspace(1)* @addrspacecast_simplify(i32 addrspace(1)* %ptr) { +; CHECK-LABEL: @addrspacecast_simplify( +; CHECK-NEXT: block1: +; CHECK-NEXT: [[CAST0:%.*]] = addrspacecast i32 addrspace(1)* [[PTR:%.*]] to i32* +; CHECK-NEXT: br label [[BLOCK2:%.*]] +; CHECK: block2: +; CHECK-NEXT: store i32 addrspace(1)* [[PTR]], i32 addrspace(1)** undef +; CHECK-NEXT: ret i32 addrspace(1)* [[PTR]] +; +block1: + %cast0 = addrspacecast i32 addrspace(1)* %ptr to i32* + %z1 = addrspacecast i32* %cast0 to i32 addrspace(1)* + br label %block2 + +block2: + %z2 = addrspacecast i32* %cast0 to i32 addrspace(1)* + store i32 addrspace(1)* %z1, i32 addrspace(1)** undef + ret i32 addrspace(1)* %z2 +} + +@h = common local_unnamed_addr global i32* null, align 4 + +define i32 addrspace(1)* @addrspacecast_constant() { +; CHECK-LABEL: @addrspacecast_constant( +; CHECK-NEXT: block1: +; CHECK-NEXT: store i32* undef, i32** @h, align 4 +; CHECK-NEXT: br label [[BLOCK2:%.*]] +; CHECK: block2: +; CHECK-NEXT: store i32 addrspace(1)* undef, i32 addrspace(1)** undef +; CHECK-NEXT: ret i32 addrspace(1)* undef +; +block1: + store i32* undef, i32** @h, align 4 + %ptr = load i32*, i32** @h, align 4 + %z1 = addrspacecast i32* %ptr to i32 addrspace(1)* + br label %block2 + +block2: + %z2 = addrspacecast i32* %ptr to i32 addrspace(1)* + store i32 addrspace(1)* %z1, i32 addrspace(1)** undef + ret i32 addrspace(1)* %z2 +} + +define i32 addrspace(1)* @addrspacecast_leader(i32** %arg.ptr) { +; CHECK-LABEL: @addrspacecast_leader( +; CHECK-NEXT: block1: +; CHECK-NEXT: [[LOAD0:%.*]] = load i32*, i32** [[ARG_PTR:%.*]] +; CHECK-NEXT: [[Z1:%.*]] = addrspacecast i32* [[LOAD0]] to i32 addrspace(1)* +; CHECK-NEXT: br label [[BLOCK2:%.*]] +; CHECK: block2: +; CHECK-NEXT: store i32 addrspace(1)* [[Z1]], i32 addrspace(1)** undef +; CHECK-NEXT: ret i32 addrspace(1)* [[Z1]] +; +block1: + %load0 = load i32*, i32** %arg.ptr + %z1 = addrspacecast i32* %load0 to i32 addrspace(1)* + br label %block2 + +block2: + %load1 = load i32*, i32** %arg.ptr + %z2 = addrspacecast i32* %load1 to i32 addrspace(1)* + store i32 addrspace(1)* %z1, i32 addrspace(1)** undef + ret i32 addrspace(1)* %z2 +}