diff --git a/llvm/lib/Transforms/Utils/GlobalStatus.cpp b/llvm/lib/Transforms/Utils/GlobalStatus.cpp index 0b3016a86e287..57f57899b9ff9 100644 --- a/llvm/lib/Transforms/Utils/GlobalStatus.cpp +++ b/llvm/lib/Transforms/Utils/GlobalStatus.cpp @@ -8,6 +8,7 @@ #include "llvm/Transforms/Utils/GlobalStatus.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" @@ -17,6 +18,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/Use.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" @@ -26,6 +28,7 @@ #include using namespace llvm; +using namespace llvm::PatternMatch; /// Return the stronger of the two ordering. If the two orderings are acquire /// and release, then return AcquireRelease. @@ -158,6 +161,17 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS, return true; } else if (isa(I)) { GS.IsCompared = true; + + const Value *UO = nullptr; + for (Value *Op : I->operands()) { + if (match(Op, m_Zero())) + continue; + const Value *OpUO = getUnderlyingObject(Op); + if (!UO) + UO = OpUO; + if (!OpUO || UO != OpUO) + return true; + } } else if (const MemTransferInst *MTI = dyn_cast(I)) { if (MTI->isVolatile()) return true; diff --git a/llvm/test/Transforms/GlobalOpt/globals-compares-with-ptrtoint.ll b/llvm/test/Transforms/GlobalOpt/globals-compares-with-ptrtoint.ll new file mode 100644 index 0000000000000..e3daa2bb26ca3 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/globals-compares-with-ptrtoint.ll @@ -0,0 +1,173 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5 +; RUN: opt -p globalopt -S %s | FileCheck %s + +@A = internal global i64 zeroinitializer +@B = internal global i64 zeroinitializer + +@C = internal global i64 zeroinitializer +@D = internal global i64 zeroinitializer + +@E = internal global i64 zeroinitializer +@F = internal global i64 zeroinitializer + +@G = internal global i64 zeroinitializer +@H = internal global i64 zeroinitializer + +@J = internal global [2 x ptr] zeroinitializer + +;. +; CHECK: @A = internal global i64 0 +; CHECK: @B = internal global i64 0 +; CHECK: @C = internal global i64 0 +; CHECK: @D = internal global i64 0 +; CHECK: @G = internal global i64 0 +; CHECK: @H = internal global i64 0 +; CHECK: @J = internal global [2 x ptr] zeroinitializer +;. +define i64 @A_and_B_cmp_ptrtoint_constant_expr() { +; CHECK-LABEL: define i64 @A_and_B_cmp_ptrtoint_constant_expr() local_unnamed_addr { +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr), @B +; CHECK-NEXT: br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr), align 4 +; CHECK-NEXT: br label %[[EXIT:.*]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[L:%.*]] = load i64, ptr @B, align 4 +; CHECK-NEXT: ret i64 [[L]] +; + %cmp = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr) , @B + br i1 %cmp, label %then, label %else + +then: + store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr) + br label %exit + +else: + br label %exit + +exit: + %l = load i64, ptr @B + ret i64 %l +} + +define i64 @G_and_H_cmp_ptrtoint_constant_expr_cmp_ops_swapped() { +; CHECK-LABEL: define i64 @G_and_H_cmp_ptrtoint_constant_expr_cmp_ops_swapped() local_unnamed_addr { +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @G to i64), i64 8) to ptr), @H +; CHECK-NEXT: br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @G to i64), i64 8) to ptr), align 4 +; CHECK-NEXT: br label %[[EXIT:.*]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[L:%.*]] = load i64, ptr @H, align 4 +; CHECK-NEXT: ret i64 [[L]] +; + %cmp = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @G to i64), i64 8) to ptr) , @H + br i1 %cmp, label %then, label %else + +then: + store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @G to i64), i64 8) to ptr) + br label %exit + +else: + br label %exit + +exit: + %l = load i64, ptr @H + ret i64 %l +} + +define i64 @C_and_D_cmp_ptr_load() { +; CHECK-LABEL: define i64 @C_and_D_cmp_ptr_load() local_unnamed_addr { +; CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: store ptr inttoptr (i64 add (i64 ptrtoint (ptr @C to i64), i64 8) to ptr), ptr [[P]], align 8 +; CHECK-NEXT: [[L_P:%.*]] = load ptr, ptr [[P]], align 8 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[L_P]], @D +; CHECK-NEXT: br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @C to i64), i64 8) to ptr), align 4 +; CHECK-NEXT: br label %[[EXIT:.*]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[L:%.*]] = load i64, ptr @D, align 4 +; CHECK-NEXT: ret i64 [[L]] +; + %p = alloca ptr + store ptr inttoptr (i64 add (i64 ptrtoint (ptr @C to i64), i64 8) to ptr), ptr %p + %l.p = load ptr, ptr %p + %cmp = icmp eq ptr %l.p, @D + br i1 %cmp, label %then, label %else + +then: + store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @C to i64), i64 8) to ptr) + br label %exit + +else: + br label %exit + +exit: + %l = load i64, ptr @D + ret i64 %l +} + +define i64 @D_and_E_cmp_ptrtoint_constant_expr() { +; CHECK-LABEL: define i64 @D_and_E_cmp_ptrtoint_constant_expr() local_unnamed_addr { +; CHECK-NEXT: [[PTR2INT:%.*]] = ptrtoint ptr @A to i64 +; CHECK-NEXT: [[ADD:%.*]] = add i64 [[PTR2INT]], 8 +; CHECK-NEXT: [[INT2PTR:%.*]] = inttoptr i64 [[ADD]] to ptr +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[INT2PTR]], @B +; CHECK-NEXT: br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr), align 4 +; CHECK-NEXT: br label %[[EXIT:.*]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[L:%.*]] = load i64, ptr @B, align 4 +; CHECK-NEXT: ret i64 [[L]] +; + %ptr2int = ptrtoint ptr @A to i64 + %add = add i64 %ptr2int, 8 + %int2ptr = inttoptr i64 %add to ptr + %cmp = icmp eq ptr %int2ptr , @B + br i1 %cmp, label %then, label %else + +then: + store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr) + br label %exit + +else: + br label %exit + +exit: + %l = load i64, ptr @B + ret i64 %l +} + +define ptr @compare_arg(ptr %a) { +; CHECK-LABEL: define ptr @compare_arg( +; CHECK-SAME: ptr [[A:%.*]]) local_unnamed_addr { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[A]], @J +; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: [[L:%.*]] = load ptr, ptr @J, align 8 +; CHECK-NEXT: ret ptr [[L]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: ret ptr null +; +entry: + %c = icmp eq ptr %a, @J + br i1 %c, label %then, label %else + +then: + %l = load ptr, ptr @J, align 8 + ret ptr %l + +else: + ret ptr null +}