Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions llvm/lib/Transforms/Utils/GlobalStatus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -26,6 +28,7 @@
#include <cassert>

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.
Expand Down Expand Up @@ -158,6 +161,17 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
return true;
} else if (isa<CmpInst>(I)) {
GS.IsCompared = true;

const Value *UO = nullptr;
for (Value *Op : I->operands()) {
if (match(Op, m_Zero()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't work when the null pointer is defined. If the function attribute is not suitable, check if AS == 0.

continue;
const Value *OpUO = getUnderlyingObject(Op);
if (!UO)
UO = OpUO;
if (!OpUO || UO != OpUO)
return true;
}
} else if (const MemTransferInst *MTI = dyn_cast<MemTransferInst>(I)) {
if (MTI->isVolatile())
return true;
Expand Down
173 changes: 173 additions & 0 deletions llvm/test/Transforms/GlobalOpt/globals-compares-with-ptrtoint.ll
Original file line number Diff line number Diff line change
@@ -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
}