}
}
+ // Deopt bundle operands are intended to capture state with minimal
+ // perturbance of the code otherwise. If we can find a constant value for
+ // any such operand and remove a use of the original value, that's
+ // desireable since it may allow further optimization of that value (e.g. via
+ // single use rules in instcombine). Since deopt uses tend to,
+ // idiomatically, appear along rare conditional paths, it's reasonable likely
+ // we may have a conditional fact with which LVI can fold.
+ if (auto DeoptBundle = CS.getOperandBundle(LLVMContext::OB_deopt)) {
+ bool Progress = false;
+ for (const Use &ConstU : DeoptBundle->Inputs) {
+ Use &U = const_cast<Use&>(ConstU);
+ Value *V = U.get();
+ if (V->getType()->isVectorTy()) continue;
+ if (isa<Constant>(V)) continue;
+
+ Constant *C = LVI->getConstant(V, CS.getParent(), CS.getInstruction());
+ if (!C) continue;
+ U.set(C);
+ Progress = true;
+ }
+ if (Progress)
+ return true;
+ }
+
for (Value *V : CS.args()) {
PointerType *Type = dyn_cast<PointerType>(V->getType());
// Try to mark pointer typed parameters as non-null. We skip the
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
-; CHECK-NEXT: call void @use() [ "deopt"(i64 [[SEL2]]) ]
+; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 [[SEL]], i64 0
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
-; CHECK-NEXT: call void @use() [ "deopt"(i64 [[SEL2]]) ]
+; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 -1, i64 1
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 [[SEL]], i64 0
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CMP]]) [ "deopt"(i64 [[SEL2]]) ]
-; CHECK-NEXT: call void @use() [ "deopt"(i64 [[SEL2]]) ]
+; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 -1, i64 1
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
-; CHECK-NEXT: call void @use() [ "deopt"(i64 [[SEL2]]) ]
+; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
-; CHECK-NEXT: call void @use() [ "deopt"(i64 [[SEL2]]) ]
+; CHECK-NEXT: call void @use() [ "deopt"(i64 2) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 0, i64 1
; CHECK-NEXT: [[ADD1:%.*]] = add i64 0, [[SEL]]
; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[ADD1]], [[SEL2]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[ADD2]], 0
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[ADD2]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
-; CHECK-NEXT: call void @use() [ "deopt"(i64 [[ADD2]]) ]
+; CHECK-NEXT: call void @use() [ "deopt"(i64 2) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
%sel2 = select i1 %c2, i64 0, i64 1
%add1 = add i64 0, %sel
%add2 = add i64 %add1, %sel2
- %cmp = icmp sgt i64 %add2, 0
+ %cmp = icmp sgt i64 %add2, 1
br i1 %cmp, label %taken, label %untaken
taken:
call void @use() ["deopt" (i64 %add2)]